summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/Kconfig140
-rw-r--r--drivers/net/wireless/Makefile10
-rw-r--r--drivers/net/wireless/ath/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ar9170/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath5k/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c669
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h22
-rw-r--r--drivers/net/wireless/ath/ath9k/initvals.h29
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c58
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.c1100
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h40
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c3
-rw-r--r--drivers/net/wireless/b43/Kconfig2
-rw-r--r--drivers/net/wireless/b43/b43.h2
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43/phy_lp.c783
-rw-r--r--drivers/net/wireless/b43/phy_lp.h11
-rw-r--r--drivers/net/wireless/b43/xmit.c1
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig2
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h2
-rw-r--r--drivers/net/wireless/b43legacy/dma.c17
-rw-r--r--drivers/net/wireless/b43legacy/main.c2
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c1
-rw-r--r--drivers/net/wireless/hostap/Kconfig1
-rw-r--r--drivers/net/wireless/ipw2x00/Kconfig6
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c102
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h35
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c25
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c143
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h161
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c236
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c15
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Kconfig2
-rw-r--r--drivers/net/wireless/libertas/Kconfig2
-rw-r--r--drivers/net/wireless/libertas/if_spi.c136
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c67
-rw-r--r--drivers/net/wireless/mwl8k.c1258
-rw-r--r--drivers/net/wireless/orinoco/Kconfig2
-rw-r--r--drivers/net/wireless/p54/Kconfig2
-rw-r--r--drivers/net/wireless/p54/eeprom.c31
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig18
-rw-r--r--drivers/net/wireless/rt2x00/Makefile1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h1816
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c1817
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h134
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c1908
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.h1780
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c1828
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.h1818
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h43
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h17
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c13
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig3
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.c2
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c5
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c99
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h3
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_conf.h8
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c53
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.h7
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c7
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c19
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c2
-rw-r--r--drivers/net/wireless/zd1211rw/Kconfig2
-rw-r--r--drivers/staging/Kconfig8
-rw-r--r--drivers/staging/Makefile5
-rw-r--r--drivers/staging/arlan/Kconfig15
-rw-r--r--drivers/staging/arlan/Makefile3
-rw-r--r--drivers/staging/arlan/TODO7
-rw-r--r--drivers/staging/arlan/arlan-main.c (renamed from drivers/net/wireless/arlan-main.c)0
-rw-r--r--drivers/staging/arlan/arlan-proc.c (renamed from drivers/net/wireless/arlan-proc.c)0
-rw-r--r--drivers/staging/arlan/arlan.h (renamed from drivers/net/wireless/arlan.h)0
-rw-r--r--drivers/staging/netwave/Kconfig11
-rw-r--r--drivers/staging/netwave/Makefile1
-rw-r--r--drivers/staging/netwave/TODO7
-rw-r--r--drivers/staging/netwave/netwave_cs.c (renamed from drivers/net/wireless/netwave_cs.c)0
-rw-r--r--drivers/staging/strip/Kconfig22
-rw-r--r--drivers/staging/strip/Makefile1
-rw-r--r--drivers/staging/strip/TODO7
-rw-r--r--drivers/staging/strip/strip.c (renamed from drivers/net/wireless/strip.c)0
-rw-r--r--drivers/staging/wavelan/Kconfig38
-rw-r--r--drivers/staging/wavelan/Makefile2
-rw-r--r--drivers/staging/wavelan/TODO7
-rw-r--r--drivers/staging/wavelan/i82586.h (renamed from drivers/net/wireless/i82586.h)0
-rw-r--r--drivers/staging/wavelan/i82593.h (renamed from drivers/net/wireless/i82593.h)0
-rw-r--r--drivers/staging/wavelan/wavelan.c (renamed from drivers/net/wireless/wavelan.c)0
-rw-r--r--drivers/staging/wavelan/wavelan.h (renamed from drivers/net/wireless/wavelan.h)0
-rw-r--r--drivers/staging/wavelan/wavelan.p.h (renamed from drivers/net/wireless/wavelan.p.h)0
-rw-r--r--drivers/staging/wavelan/wavelan_cs.c (renamed from drivers/net/wireless/wavelan_cs.c)0
-rw-r--r--drivers/staging/wavelan/wavelan_cs.h (renamed from drivers/net/wireless/wavelan_cs.h)0
-rw-r--r--drivers/staging/wavelan/wavelan_cs.p.h (renamed from drivers/net/wireless/wavelan_cs.p.h)0
-rw-r--r--include/linux/ieee80211.h12
-rw-r--r--include/net/ieee80211_radiotap.h2
-rw-r--r--include/net/mac80211.h116
-rw-r--r--net/mac80211/cfg.c7
-rw-r--r--net/mac80211/debugfs.c73
-rw-r--r--net/mac80211/debugfs.h2
-rw-r--r--net/mac80211/debugfs_key.c44
-rw-r--r--net/mac80211/debugfs_netdev.c174
-rw-r--r--net/mac80211/debugfs_sta.c38
-rw-r--r--net/mac80211/ibss.c4
-rw-r--r--net/mac80211/ieee80211_i.h123
-rw-r--r--net/mac80211/iface.c8
-rw-r--r--net/mac80211/key.h12
-rw-r--r--net/mac80211/main.c11
-rw-r--r--net/mac80211/rate.c7
-rw-r--r--net/mac80211/rx.c173
-rw-r--r--net/mac80211/scan.c119
-rw-r--r--net/mac80211/sta_info.c136
-rw-r--r--net/mac80211/sta_info.h47
-rw-r--r--net/mac80211/tx.c99
-rw-r--r--net/mac80211/util.c8
-rw-r--r--net/wireless/core.c3
-rw-r--r--net/wireless/core.h11
-rw-r--r--net/wireless/debugfs.c15
-rw-r--r--net/wireless/debugfs.h3
-rw-r--r--net/wireless/mlme.c2
-rw-r--r--net/wireless/nl80211.c34
-rw-r--r--net/wireless/scan.c6
-rw-r--r--net/wireless/wext-compat.c6
147 files changed, 8305 insertions, 9862 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 85f8bf4112c1..56dd6650c97a 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 7a4647e78fd3..5d4ce4d2b32b 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -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
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 6ce86cb37654..4e7a7fd695c8 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig
index 05918f1e685a..d7a4799d20fb 100644
--- a/drivers/net/wireless/ath/ar9170/Kconfig
+++ b/drivers/net/wireless/ath/ar9170/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 06d006675d7d..eb83b7b4d0e3 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -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
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index b767c3b67b24..7ce98bd7c749 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -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) */
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 99ce066392a7..b735fb399fb1 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -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
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 25531f231b67..329e6bc137ab 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -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;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 551f8801459f..238a5744d8e9 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -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);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 58167d861dc6..68db16690abf 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -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,
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index cab17c6c8a37..111ff049f75d 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -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);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index cdaec526db35..c7b0c4d5f75a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -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
diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h
index 3ee6658d809b..8a3bf3ab998d 100644
--- a/drivers/net/wireless/ath/ath9k/initvals.h
+++ b/drivers/net/wireless/ath/ath9k/initvals.h
@@ -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 },
+};
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 69cf702b18c2..9fefc51aec17 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -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;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 63059b6a90da..5321f735e5a0 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -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;
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
index 72a17c43a5a0..13ab4d7eb7aa 100644
--- a/drivers/net/wireless/ath/ath9k/phy.c
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -14,91 +14,70 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/**
+ * DOC: Programming Atheros 802.11n analog front end radios
+ *
+ * AR5416 MAC based PCI devices and AR518 MAC based PCI-Express
+ * devices have either an external AR2133 analog front end radio for single
+ * band 2.4 GHz communication or an AR5133 analog front end radio for dual
+ * band 2.4 GHz / 5 GHz communication.
+ *
+ * All devices after the AR5416 and AR5418 family starting with the AR9280
+ * have their analog front radios, MAC/BB and host PCIe/USB interface embedded
+ * into a single-chip and require less programming.
+ *
+ * The following single-chips exist with a respective embedded radio:
+ *
+ * AR9280 - 11n dual-band 2x2 MIMO for PCIe
+ * AR9281 - 11n single-band 1x2 MIMO for PCIe
+ * AR9285 - 11n single-band 1x1 for PCIe
+ * AR9287 - 11n single-band 2x2 MIMO for PCIe
+ *
+ * AR9220 - 11n dual-band 2x2 MIMO for PCI
+ * AR9223 - 11n single-band 2x2 MIMO for PCI
+ *
+ * AR9287 - 11n single-band 1x1 MIMO for USB
+ */
+
#include "hw.h"
-void
-ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex,
- int regWrites)
+/**
+ * ath9k_hw_write_regs - ??
+ *
+ * @ah: atheros hardware structure
+ * @freqIndex:
+ * @regWrites:
+ *
+ * Used for both the chipsets with an external AR2133/AR5133 radios and
+ * single-chip devices.
+ */
+void ath9k_hw_write_regs(struct ath_hw *ah, u32 freqIndex, int regWrites)
{
REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
}
-bool
-ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
-{
- struct ath_common *common = ath9k_hw_common(ah);
- u32 channelSel = 0;
- u32 bModeSynth = 0;
- u32 aModeRefSel = 0;
- u32 reg32 = 0;
- u16 freq;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
- freq = centers.synth_center;
-
- if (freq < 4800) {
- u32 txctl;
-
- if (((freq - 2192) % 5) == 0) {
- channelSel = ((freq - 672) * 2 - 3040) / 10;
- bModeSynth = 0;
- } else if (((freq - 2224) % 5) == 0) {
- channelSel = ((freq - 704) * 2 - 3040) / 10;
- bModeSynth = 1;
- } else {
- ath_print(common, ATH_DBG_FATAL,
- "Invalid channel %u MHz\n", freq);
- return false;
- }
-
- channelSel = (channelSel << 2) & 0xff;
- channelSel = ath9k_hw_reverse_bits(channelSel, 8);
-
- txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
- if (freq == 2484) {
-
- REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
- txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
- } else {
- REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
- txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
- }
-
- } else if ((freq % 20) == 0 && freq >= 5120) {
- channelSel =
- ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
- aModeRefSel = ath9k_hw_reverse_bits(1, 2);
- } else if ((freq % 10) == 0) {
- channelSel =
- ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
- if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
- aModeRefSel = ath9k_hw_reverse_bits(2, 2);
- else
- aModeRefSel = ath9k_hw_reverse_bits(1, 2);
- } else if ((freq % 5) == 0) {
- channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
- aModeRefSel = ath9k_hw_reverse_bits(1, 2);
- } else {
- ath_print(common, ATH_DBG_FATAL,
- "Invalid channel %u MHz\n", freq);
- return false;
- }
-
- reg32 =
- (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
- (1 << 5) | 0x1;
-
- REG_WRITE(ah, AR_PHY(0x37), reg32);
-
- ah->curchan = chan;
- ah->curchan_rad_index = -1;
-
- return true;
-}
-
-void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
- struct ath9k_channel *chan)
+/**
+ * ath9k_hw_ar9280_set_channel - set channel on single-chip device
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * This is the function to change channel on single-chip devices, that is
+ * all devices after ar9280.
+ *
+ * This function takes the channel value in MHz and sets
+ * hardware channel value. Assumes writes have been enabled to analog bus.
+ *
+ * Actual Expression,
+ *
+ * For 2GHz channel,
+ * Channel Frequency = (3/4) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^17)
+ * (freq_ref = 40MHz)
+ *
+ * For 5GHz channel,
+ * Channel Frequency = (3/2) * freq_ref * (chansel[8:0] + chanfrac[16:0]/2^10)
+ * (freq_ref = 40MHz/(24>>amodeRefSel))
+ */
+int ath9k_hw_ar9280_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
{
u16 bMode, fracMode, aModeRefSel = 0;
u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0;
@@ -111,7 +90,7 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL);
reg32 &= 0xc0000000;
- if (freq < 4800) {
+ if (freq < 4800) { /* 2 GHz, fractional mode */
u32 txctl;
int regWrites = 0;
@@ -122,6 +101,7 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
if (AR_SREV_9287_11_OR_LATER(ah)) {
if (freq == 2484) {
+ /* Enable channel spreading for channel 14 */
REG_WRITE_ARRAY(&ah->iniCckfirJapan2484,
1, regWrites);
} else {
@@ -155,10 +135,15 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
case 1:
default:
aModeRefSel = 0;
+ /*
+ * Enable 2G (fractional) mode for channels
+ * which are 5MHz spaced.
+ */
fracMode = 1;
refDivA = 1;
channelSel = (freq * 0x8000) / 15;
+ /* RefDivA setting */
REG_RMW_FIELD(ah, AR_AN_SYNTH9,
AR_AN_SYNTH9_REFDIVA, refDivA);
@@ -180,12 +165,284 @@ void ath9k_hw_ar9280_set_channel(struct ath_hw *ah,
ah->curchan = chan;
ah->curchan_rad_index = -1;
+
+ return 0;
+}
+
+/**
+ * ath9k_hw_9280_spur_mitigate - convert baseband spur frequency
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+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_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
- u32 numBits, u32 firstBit,
- u32 column)
+/* All code below is for non single-chip solutions */
+
+/**
+ * ath9k_phy_modify_rx_buffer() - perform analog swizzling of parameters
+ * @rfbuf:
+ * @reg32:
+ * @numBits:
+ * @firstBit:
+ * @column:
+ *
+ * Performs analog "swizzling" of parameters into their location.
+ * Used on external AR2133/AR5133 radios.
+ */
+static void ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
+ u32 numBits, u32 firstBit,
+ u32 column)
{
u32 tmp32, mask, arrayEntry, lastBit;
int32_t bitPosition, bitsLeft;
@@ -209,26 +466,556 @@ ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32,
}
}
-bool
-ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
- u16 modesIndex)
+/*
+ * Fix on 2.4 GHz band for orientation sensitivity issue by increasing
+ * rf_pwd_icsyndiv.
+ *
+ * Theoretical Rules:
+ * if 2 GHz band
+ * if forceBiasAuto
+ * if synth_freq < 2412
+ * bias = 0
+ * else if 2412 <= synth_freq <= 2422
+ * bias = 1
+ * else // synth_freq > 2422
+ * bias = 2
+ * else if forceBias > 0
+ * bias = forceBias & 7
+ * else
+ * no change, use value from ini file
+ * else
+ * no change, invalid band
+ *
+ * 1st Mod:
+ * 2422 also uses value of 2
+ * <approved>
+ *
+ * 2nd Mod:
+ * Less than 2412 uses value of 0, 2412 and above uses value of 2
+ */
+static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 tmp_reg;
+ int reg_writes = 0;
+ u32 new_bias = 0;
+
+ if (!AR_SREV_5416(ah) || synth_freq >= 3000) {
+ return;
+ }
+
+ BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+
+ if (synth_freq < 2412)
+ new_bias = 0;
+ else if (synth_freq < 2422)
+ new_bias = 1;
+ else
+ new_bias = 2;
+
+ /* pre-reverse this field */
+ tmp_reg = ath9k_hw_reverse_bits(new_bias, 3);
+
+ ath_print(common, ATH_DBG_CONFIG,
+ "Force rf_pwd_icsyndiv to %1d on %4d\n",
+ new_bias, synth_freq);
+
+ /* swizzle rf_pwd_icsyndiv */
+ ath9k_phy_modify_rx_buffer(ah->analogBank6Data, tmp_reg, 3, 181, 3);
+
+ /* write Bank 6 with new params */
+ REG_WRITE_RF_ARRAY(&ah->iniBank6, ah->analogBank6Data, reg_writes);
+}
+
+/**
+ * ath9k_hw_decrease_chain_power()
+ *
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * Only used on the AR5416 and AR5418 with the external AR2133/AR5133 radios.
+ *
+ * Sets a chain internal RF path to the lowest output power. Any
+ * further writes to bank6 after this setting will override these
+ * changes. Thus this function must be the last function in the
+ * sequence to modify bank 6.
+ *
+ * This function must be called after ar5416SetRfRegs() which is
+ * called from ath9k_hw_process_ini() due to swizzling of bank 6.
+ * Depends on ah->analogBank6Data being initialized by
+ * ath9k_hw_set_rf_regs()
+ *
+ * Additional additive reduction in power -
+ * change chain's switch table so chain's tx state is actually the rx
+ * state value. May produce different results in 2GHz/5GHz as well as
+ * board to board but in general should be a reduction.
+ *
+ * Activated by #ifdef ALTER_SWITCH. Not tried yet. If so, must be
+ * called after ah->eep_ops->set_board_values() due to RMW of
+ * PHY_SWITCH_CHAIN_0.
+ */
+void ath9k_hw_decrease_chain_power(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+{
+ int i, regWrites = 0;
+ u32 bank6SelMask;
+ u32 *bank6Temp = ah->bank6Temp;
+
+ BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+
+ switch (ah->config.diversity_control) {
+ case ATH9K_ANT_FIXED_A:
+ bank6SelMask =
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_0 : /* swapped, reduce chain 0 */
+ REDUCE_CHAIN_1; /* normal, select chain 1/2 to reduce */
+ break;
+ case ATH9K_ANT_FIXED_B:
+ bank6SelMask =
+ (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
+ REDUCE_CHAIN_1 : /* swapped, reduce chain 1/2 */
+ REDUCE_CHAIN_0; /* normal, select chain 0 to reduce */
+ break;
+ case ATH9K_ANT_VARIABLE:
+ return; /* do not change anything */
+ break;
+ default:
+ return; /* do not change anything */
+ break;
+ }
+
+ for (i = 0; i < ah->iniBank6.ia_rows; i++)
+ bank6Temp[i] = ah->analogBank6Data[i];
+
+ /* Write Bank 5 to switch Bank 6 write to selected chain only */
+ REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
+
+ /*
+ * Modify Bank6 selected chain to use lowest amplification.
+ * Modifies the parameters to a value of 1.
+ * Depends on existing bank 6 values to be cached in
+ * ah->analogBank6Data
+ */
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
+ ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
+
+ REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites);
+
+ REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
+#ifdef ALTER_SWITCH
+ REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
+ (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
+ | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
+#endif
+}
+
+/**
+ * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
+ * @ah: atheros hardware stucture
+ * @chan:
+ *
+ * For the external AR2133/AR5133 radios, takes the MHz channel value and set
+ * the channel value. Assumes writes enabled to analog bus and bank6 register
+ * cache in ah->analogBank6Data.
+ */
+int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 channelSel = 0;
+ u32 bModeSynth = 0;
+ u32 aModeRefSel = 0;
+ u32 reg32 = 0;
+ u16 freq;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = centers.synth_center;
+
+ if (freq < 4800) {
+ u32 txctl;
+
+ if (((freq - 2192) % 5) == 0) {
+ channelSel = ((freq - 672) * 2 - 3040) / 10;
+ bModeSynth = 0;
+ } else if (((freq - 2224) % 5) == 0) {
+ channelSel = ((freq - 704) * 2 - 3040) / 10;
+ bModeSynth = 1;
+ } else {
+ ath_print(common, ATH_DBG_FATAL,
+ "Invalid channel %u MHz\n", freq);
+ return -EINVAL;
+ }
+
+ channelSel = (channelSel << 2) & 0xff;
+ channelSel = ath9k_hw_reverse_bits(channelSel, 8);
+
+ txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL);
+ if (freq == 2484) {
+
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl | AR_PHY_CCK_TX_CTRL_JAPAN);
+ } else {
+ REG_WRITE(ah, AR_PHY_CCK_TX_CTRL,
+ txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN);
+ }
+
+ } else if ((freq % 20) == 0 && freq >= 5120) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 10) == 0) {
+ channelSel =
+ ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8);
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah))
+ aModeRefSel = ath9k_hw_reverse_bits(2, 2);
+ else
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else if ((freq % 5) == 0) {
+ channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
+ aModeRefSel = ath9k_hw_reverse_bits(1, 2);
+ } else {
+ ath_print(common, ATH_DBG_FATAL,
+ "Invalid channel %u MHz\n", freq);
+ return -EINVAL;
+ }
+
+ ath9k_hw_force_bias(ah, freq);
+ ath9k_hw_decrease_chain_power(ah, chan);
+
+ reg32 =
+ (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) |
+ (1 << 5) | 0x1;
+
+ REG_WRITE(ah, AR_PHY(0x37), reg32);
+
+ ah->curchan = chan;
+ ah->curchan_rad_index = -1;
+
+ return 0;
+}
+
+/**
+ * ath9k_hw_spur_mitigate - convert baseband spur frequency for external radios
+ * @ah: atheros hardware structure
+ * @chan:
+ *
+ * For non single-chip solutions. Converts to baseband spur frequency given the
+ * input channel frequency and compute register settings below.
+ */
+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);
+}
+
+/**
+ * ath9k_hw_rf_alloc_ext_banks - allocates banks for external radio programming
+ * @ah: atheros hardware structure
+ *
+ * Only required for older devices with external AR2133/AR5133 radios.
+ */
+int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
+{
+#define ATH_ALLOC_BANK(bank, size) do { \
+ bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
+ if (!bank) { \
+ ath_print(common, ATH_DBG_FATAL, \
+ "Cannot allocate RF banks\n"); \
+ return -ENOMEM; \
+ } \
+ } while (0);
+
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+
+ ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank2Data, ah->iniBank2.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank3Data, ah->iniBank3.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank6Data, ah->iniBank6.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank6TPCData, ah->iniBank6TPC.ia_rows);
+ ATH_ALLOC_BANK(ah->analogBank7Data, ah->iniBank7.ia_rows);
+ ATH_ALLOC_BANK(ah->addac5416_21,
+ ah->iniAddac.ia_rows * ah->iniAddac.ia_columns);
+ ATH_ALLOC_BANK(ah->bank6Temp, ah->iniBank6.ia_rows);
+
+ return 0;
+#undef ATH_ALLOC_BANK
+}
+
+
+/**
+ * ath9k_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
+ * @ah: atheros hardware struture
+ * For the external AR2133/AR5133 radios banks.
+ */
+void
+ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
+{
+#define ATH_FREE_BANK(bank) do { \
+ kfree(bank); \
+ bank = NULL; \
+ } while (0);
+
+ BUG_ON(AR_SREV_9280_10_OR_LATER(ah));
+
+ ATH_FREE_BANK(ah->analogBank0Data);
+ ATH_FREE_BANK(ah->analogBank1Data);
+ ATH_FREE_BANK(ah->analogBank2Data);
+ ATH_FREE_BANK(ah->analogBank3Data);
+ ATH_FREE_BANK(ah->analogBank6Data);
+ ATH_FREE_BANK(ah->analogBank6TPCData);
+ ATH_FREE_BANK(ah->analogBank7Data);
+ ATH_FREE_BANK(ah->addac5416_21);
+ ATH_FREE_BANK(ah->bank6Temp);
+
+#undef ATH_FREE_BANK
+}
+
+/* *
+ * ath9k_hw_set_rf_regs - programs rf registers based on EEPROM
+ * @ah: atheros hardware structure
+ * @chan:
+ * @modesIndex:
+ *
+ * Used for the external AR2133/AR5133 radios.
+ *
+ * Reads the EEPROM header info from the device structure and programs
+ * all rf registers. This routine requires access to the analog
+ * rf device. This is not required for single-chip devices.
+ */
+bool ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
+ u16 modesIndex)
{
u32 eepMinorRev;
u32 ob5GHz = 0, db5GHz = 0;
u32 ob2GHz = 0, db2GHz = 0;
int regWrites = 0;
+ /*
+ * Software does not need to program bank data
+ * for single chip devices, that is AR9280 or anything
+ * after that.
+ */
if (AR_SREV_9280_10_OR_LATER(ah))
return true;
+ /* Setup rf parameters */
eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV);
+ /* Setup Bank 0 Write */
RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1);
+ /* Setup Bank 1 Write */
RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1);
+ /* Setup Bank 2 Write */
RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1);
+ /* Setup Bank 6 Write */
RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3,
modesIndex);
{
@@ -239,6 +1026,7 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
}
}
+ /* Only the 5 or 2 GHz OB/DB need to be set for a mode */
if (eepMinorRev >= 2) {
if (IS_CHAN_2GHZ(chan)) {
ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2);
@@ -257,8 +1045,10 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
}
}
+ /* Setup Bank 7 Setup */
RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1);
+ /* Write Analog registers */
REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data,
regWrites);
REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data,
@@ -274,139 +1064,3 @@ ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan,
return true;
}
-
-void
-ath9k_hw_rf_free(struct ath_hw *ah)
-{
-#define ATH_FREE_BANK(bank) do { \
- kfree(bank); \
- bank = NULL; \
- } while (0);
-
- ATH_FREE_BANK(ah->analogBank0Data);
- ATH_FREE_BANK(ah->analogBank1Data);
- ATH_FREE_BANK(ah->analogBank2Data);
- ATH_FREE_BANK(ah->analogBank3Data);
- ATH_FREE_BANK(ah->analogBank6Data);
- ATH_FREE_BANK(ah->analogBank6TPCData);
- ATH_FREE_BANK(ah->analogBank7Data);
- ATH_FREE_BANK(ah->addac5416_21);
- ATH_FREE_BANK(ah->bank6Temp);
-#undef ATH_FREE_BANK
-}
-
-bool ath9k_hw_init_rf(struct ath_hw *ah, int *status)
-{
- struct ath_common *common = ath9k_hw_common(ah);
-
- if (!AR_SREV_9280_10_OR_LATER(ah)) {
- ah->analogBank0Data =
- kzalloc((sizeof(u32) *
- ah->iniBank0.ia_rows), GFP_KERNEL);
- ah->analogBank1Data =
- kzalloc((sizeof(u32) *
- ah->iniBank1.ia_rows), GFP_KERNEL);
- ah->analogBank2Data =
- kzalloc((sizeof(u32) *
- ah->iniBank2.ia_rows), GFP_KERNEL);
- ah->analogBank3Data =
- kzalloc((sizeof(u32) *
- ah->iniBank3.ia_rows), GFP_KERNEL);
- ah->analogBank6Data =
- kzalloc((sizeof(u32) *
- ah->iniBank6.ia_rows), GFP_KERNEL);
- ah->analogBank6TPCData =
- kzalloc((sizeof(u32) *
- ah->iniBank6TPC.ia_rows), GFP_KERNEL);
- ah->analogBank7Data =
- kzalloc((sizeof(u32) *
- ah->iniBank7.ia_rows), GFP_KERNEL);
-
- if (ah->analogBank0Data == NULL
- || ah->analogBank1Data == NULL
- || ah->analogBank2Data == NULL
- || ah->analogBank3Data == NULL
- || ah->analogBank6Data == NULL
- || ah->analogBank6TPCData == NULL
- || ah->analogBank7Data == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Cannot allocate RF banks\n");
- *status = -ENOMEM;
- return false;
- }
-
- ah->addac5416_21 =
- kzalloc((sizeof(u32) *
- ah->iniAddac.ia_rows *
- ah->iniAddac.ia_columns), GFP_KERNEL);
- if (ah->addac5416_21 == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Cannot allocate addac5416_21\n");
- *status = -ENOMEM;
- return false;
- }
-
- ah->bank6Temp =
- kzalloc((sizeof(u32) *
- ah->iniBank6.ia_rows), GFP_KERNEL);
- if (ah->bank6Temp == NULL) {
- ath_print(common, ATH_DBG_FATAL,
- "Cannot allocate bank6Temp\n");
- *status = -ENOMEM;
- return false;
- }
- }
-
- return true;
-}
-
-void
-ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
-{
- int i, regWrites = 0;
- u32 bank6SelMask;
- u32 *bank6Temp = ah->bank6Temp;
-
- switch (ah->config.diversity_control) {
- case ATH9K_ANT_FIXED_A:
- bank6SelMask =
- (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
- REDUCE_CHAIN_0 : REDUCE_CHAIN_1;
- break;
- case ATH9K_ANT_FIXED_B:
- bank6SelMask =
- (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
- REDUCE_CHAIN_1 : REDUCE_CHAIN_0;
- break;
- case ATH9K_ANT_VARIABLE:
- return;
- break;
- default:
- return;
- break;
- }
-
- for (i = 0; i < ah->iniBank6.ia_rows; i++)
- bank6Temp[i] = ah->analogBank6Data[i];
-
- REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask);
-
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0);
- ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0);
-
- REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites);
-
- REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053);
-#ifdef ALTER_SWITCH
- REG_WRITE(ah, PHY_SWITCH_CHAIN_0,
- (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38)
- | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38));
-#endif
-}
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index 140fef74c666..dc145a135dc7 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -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
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index c880a55939bf..355dd1834e1d 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -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 &&
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index ceed0095efac..061e12ce0b24 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -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
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 2a4efcbced60..8e052f406c35 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -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;
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 54ea61c15d8b..64c12e1bced3 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -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---
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 65b23f725a04..fe3bf9491997 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -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
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index ed6e96a34743..c806924c7b5c 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -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) {
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index c6987b147af4..3e046ec1ff86 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -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;
-
- 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
+ u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
- 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,
};
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index c3232c17b60a..62737f700cbc 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -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 {
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 7a5e294be2bc..eda06529ef5f 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -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)
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 94a463478053..1ffa28835c58 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -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---
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index 038baa8869e2..89fe2f972c72 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -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
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 866403415811..0a86bdf53154 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -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. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 0983406f4630..d579bb9035c4 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -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) {
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 103f3c9e7f58..9c8882d9275e 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -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);
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 08f1e989653d..287d82728bc3 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -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
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig
index 59ec9eec5024..2715b101aded 100644
--- a/drivers/net/wireless/ipw2x00/Kconfig
+++ b/drivers/net/wireless/ipw2x00/Kconfig
@@ -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
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index c82c97be7bfa..b16b06c2031f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -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
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 3a645e485dda..1e387b9dce1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -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,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index cbb0585083a9..dc81e19674f7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index ebb999a51b58..2b0d65c5780a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -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 {
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d256fecc6cda..910217f0ad8a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 32466d38d1ae..70e117f8d0c4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -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));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 27d4ece4d467..43edd8fd4405 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -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++)
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index fa1672e99e4b..b5fe8f87aa7e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -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
*****************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 1f801eb9fbff..d994de7438d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -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
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 954bad60355d..b62c90ec9e1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -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;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d2b56baf98fb..e0b5b4aef41d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -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;
-
- spin_lock_irqsave(&priv->lock, flags);
+ int ret = 0;
- /* 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)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index b875dcfca2d6..9574d8f33537 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index e7ce67387662..cb2642c18da4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -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;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 9429cb1c69bd..8a0709e81a9f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -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)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index f2a60dc4109f..905645d15a9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 4fca65a2fe9c..1eb0d0bf1fe4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -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)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index dc74c16d36a8..eba36f737388 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -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;
@@ -1030,6 +1035,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
*
* If new IBSS station, create new entry in station table
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 6deebade6361..1c382de80d49 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 8ae4c9b614e7..05e75109d842 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -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);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index bfd7f497157f..23b31e6dcacd 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -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
* ********************/
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig
index 9606b3100fde..b9d34a766964 100644
--- a/drivers/net/wireless/iwmc3200wifi/Kconfig
+++ b/drivers/net/wireless/iwmc3200wifi/Kconfig
@@ -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
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig
index 8f8d75b61ea9..30aa9d48d67e 100644
--- a/drivers/net/wireless/libertas/Kconfig
+++ b/drivers/net/wireless/libertas/Kconfig
@@ -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
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 30d9d0ea28eb..d6a48dd3652c 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -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... */
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 38cfd79e0590..fc4ec48eda12 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -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 |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 746532ebe5a8..2ebfee4da3fa 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/list.h>
#include <linux/pci.h>
@@ -27,18 +28,6 @@
#define MWL8K_NAME KBUILD_MODNAME
#define MWL8K_VERSION "0.10"
-MODULE_DESCRIPTION(MWL8K_DESC);
-MODULE_VERSION(MWL8K_VERSION);
-MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>");
-MODULE_LICENSE("GPL");
-
-static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = {
- { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, },
- { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, },
- { }
-};
-MODULE_DEVICE_TABLE(pci, mwl8k_table);
-
/* Register definitions */
#define MWL8K_HIU_GEN_PTR 0x00000c10
#define MWL8K_MODE_STA 0x0000005a
@@ -88,72 +77,89 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table);
MWL8K_A2H_INT_RX_READY | \
MWL8K_A2H_INT_TX_DONE)
-/* WME stream classes */
-#define WME_AC_BE 0 /* best effort */
-#define WME_AC_BK 1 /* background */
-#define WME_AC_VI 2 /* video */
-#define WME_AC_VO 3 /* voice */
-
#define MWL8K_RX_QUEUES 1
#define MWL8K_TX_QUEUES 4
+struct rxd_ops {
+ int rxd_size;
+ void (*rxd_init)(void *rxd, dma_addr_t next_dma_addr);
+ void (*rxd_refill)(void *rxd, dma_addr_t addr, int len);
+ int (*rxd_process)(void *rxd, struct ieee80211_rx_status *status);
+};
+
+struct mwl8k_device_info {
+ char *part_name;
+ char *helper_image;
+ char *fw_image;
+ struct rxd_ops *rxd_ops;
+ u16 modes;
+};
+
struct mwl8k_rx_queue {
- int rx_desc_count;
+ int rxd_count;
/* hw receives here */
- int rx_head;
+ int head;
/* refill descs here */
- int rx_tail;
+ int tail;
- struct mwl8k_rx_desc *rx_desc_area;
- dma_addr_t rx_desc_dma;
- struct sk_buff **rx_skb;
+ void *rxd;
+ dma_addr_t rxd_dma;
+ struct {
+ struct sk_buff *skb;
+ DECLARE_PCI_UNMAP_ADDR(dma)
+ } *buf;
};
struct mwl8k_tx_queue {
/* hw transmits here */
- int tx_head;
+ int head;
/* sw appends here */
- int tx_tail;
+ int tail;
- struct ieee80211_tx_queue_stats tx_stats;
- struct mwl8k_tx_desc *tx_desc_area;
- dma_addr_t tx_desc_dma;
- struct sk_buff **tx_skb;
+ struct ieee80211_tx_queue_stats stats;
+ struct mwl8k_tx_desc *txd;
+ dma_addr_t txd_dma;
+ struct sk_buff **skb;
};
/* Pointers to the firmware data and meta information about it. */
struct mwl8k_firmware {
- /* Microcode */
- struct firmware *ucode;
-
/* Boot helper code */
struct firmware *helper;
+
+ /* Microcode */
+ struct firmware *ucode;
};
struct mwl8k_priv {
+ void __iomem *sram;
void __iomem *regs;
struct ieee80211_hw *hw;
struct pci_dev *pdev;
- u8 name[16];
+
+ struct mwl8k_device_info *device_info;
+ bool ap_fw;
+ struct rxd_ops *rxd_ops;
/* firmware files and meta data */
struct mwl8k_firmware fw;
- u32 part_num;
/* firmware access */
struct mutex fw_mutex;
struct task_struct *fw_mutex_owner;
int fw_mutex_depth;
- struct completion *tx_wait;
struct completion *hostcmd_wait;
/* lock held over TX and TX reap */
spinlock_t tx_lock;
+ /* TX quiesce completion, protected by fw_mutex and tx_lock */
+ struct completion *tx_wait;
+
struct ieee80211_vif *vif;
struct ieee80211_channel *current_channel;
@@ -178,10 +184,11 @@ struct mwl8k_priv {
/* PHY parameters */
struct ieee80211_supported_band band;
struct ieee80211_channel channels[14];
- struct ieee80211_rate rates[12];
+ struct ieee80211_rate rates[13];
bool radio_on;
bool radio_short_preamble;
+ bool sniffer_enabled;
bool wmm_enabled;
/* XXX need to convert this to handle multiple interfaces */
@@ -199,9 +206,6 @@ struct mwl8k_priv {
/* Tasklet to reclaim TX descriptors and buffers after tx */
struct tasklet_struct tx_reclaim_task;
-
- /* Work thread to serialize configuration requests */
- struct workqueue_struct *config_wq;
};
/* Per interface specific private data */
@@ -220,7 +224,7 @@ struct mwl8k_vif {
* Subset of supported legacy rates.
* Intersection of AP and STA supported rates.
*/
- struct ieee80211_rate legacy_rates[12];
+ struct ieee80211_rate legacy_rates[13];
/* number of supported legacy rates */
u8 legacy_nrates;
@@ -252,9 +256,10 @@ static const struct ieee80211_rate mwl8k_rates[] = {
{ .bitrate = 10, .hw_value = 2, },
{ .bitrate = 20, .hw_value = 4, },
{ .bitrate = 55, .hw_value = 11, },
+ { .bitrate = 110, .hw_value = 22, },
+ { .bitrate = 220, .hw_value = 44, },
{ .bitrate = 60, .hw_value = 12, },
{ .bitrate = 90, .hw_value = 18, },
- { .bitrate = 110, .hw_value = 22, },
{ .bitrate = 120, .hw_value = 24, },
{ .bitrate = 180, .hw_value = 36, },
{ .bitrate = 240, .hw_value = 48, },
@@ -270,10 +275,12 @@ static const struct ieee80211_rate mwl8k_rates[] = {
/* Firmware command codes */
#define MWL8K_CMD_CODE_DNLD 0x0001
#define MWL8K_CMD_GET_HW_SPEC 0x0003
+#define MWL8K_CMD_SET_HW_SPEC 0x0004
#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010
#define MWL8K_CMD_GET_STAT 0x0014
#define MWL8K_CMD_RADIO_CONTROL 0x001c
#define MWL8K_CMD_RF_TX_POWER 0x001e
+#define MWL8K_CMD_RF_ANTENNA 0x0020
#define MWL8K_CMD_SET_PRE_SCAN 0x0107
#define MWL8K_CMD_SET_POST_SCAN 0x0108
#define MWL8K_CMD_SET_RF_CHANNEL 0x010a
@@ -287,6 +294,7 @@ static const struct ieee80211_rate mwl8k_rates[] = {
#define MWL8K_CMD_MIMO_CONFIG 0x0125
#define MWL8K_CMD_USE_FIXED_RATE 0x0126
#define MWL8K_CMD_ENABLE_SNIFFER 0x0150
+#define MWL8K_CMD_SET_MAC_ADDR 0x0202
#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203
#define MWL8K_CMD_UPDATE_STADB 0x1123
@@ -299,10 +307,12 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
switch (cmd & ~0x8000) {
MWL8K_CMDNAME(CODE_DNLD);
MWL8K_CMDNAME(GET_HW_SPEC);
+ MWL8K_CMDNAME(SET_HW_SPEC);
MWL8K_CMDNAME(MAC_MULTICAST_ADR);
MWL8K_CMDNAME(GET_STAT);
MWL8K_CMDNAME(RADIO_CONTROL);
MWL8K_CMDNAME(RF_TX_POWER);
+ MWL8K_CMDNAME(RF_ANTENNA);
MWL8K_CMDNAME(SET_PRE_SCAN);
MWL8K_CMDNAME(SET_POST_SCAN);
MWL8K_CMDNAME(SET_RF_CHANNEL);
@@ -316,6 +326,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize)
MWL8K_CMDNAME(MIMO_CONFIG);
MWL8K_CMDNAME(USE_FIXED_RATE);
MWL8K_CMDNAME(ENABLE_SNIFFER);
+ MWL8K_CMDNAME(SET_MAC_ADDR);
MWL8K_CMDNAME(SET_RATEADAPT_MODE);
MWL8K_CMDNAME(UPDATE_STADB);
default:
@@ -353,41 +364,35 @@ static void mwl8k_release_firmware(struct mwl8k_priv *priv)
/* Request fw image */
static int mwl8k_request_fw(struct mwl8k_priv *priv,
- const char *fname, struct firmware **fw)
+ const char *fname, struct firmware **fw)
{
/* release current image */
if (*fw != NULL)
mwl8k_release_fw(fw);
return request_firmware((const struct firmware **)fw,
- fname, &priv->pdev->dev);
+ fname, &priv->pdev->dev);
}
-static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num)
+static int mwl8k_request_firmware(struct mwl8k_priv *priv)
{
- u8 filename[64];
+ struct mwl8k_device_info *di = priv->device_info;
int rc;
- priv->part_num = part_num;
-
- snprintf(filename, sizeof(filename),
- "mwl8k/helper_%u.fw", priv->part_num);
-
- rc = mwl8k_request_fw(priv, filename, &priv->fw.helper);
- if (rc) {
- printk(KERN_ERR
- "%s Error requesting helper firmware file %s\n",
- pci_name(priv->pdev), filename);
- return rc;
+ if (di->helper_image != NULL) {
+ rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper);
+ if (rc) {
+ printk(KERN_ERR "%s: Error requesting helper "
+ "firmware file %s\n", pci_name(priv->pdev),
+ di->helper_image);
+ return rc;
+ }
}
- snprintf(filename, sizeof(filename),
- "mwl8k/fmimage_%u.fw", priv->part_num);
-
- rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode);
+ rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode);
if (rc) {
- printk(KERN_ERR "%s Error requesting firmware file %s\n",
- pci_name(priv->pdev), filename);
+ printk(KERN_ERR "%s: Error requesting firmware file %s\n",
+ pci_name(priv->pdev), di->fw_image);
mwl8k_release_fw(&priv->fw.helper);
return rc;
}
@@ -434,6 +439,7 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length)
break;
}
+ cond_resched();
udelay(1);
} while (--loops);
@@ -542,43 +548,62 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv,
return rc;
}
-static int mwl8k_load_firmware(struct mwl8k_priv *priv)
+static int mwl8k_load_firmware(struct ieee80211_hw *hw)
{
- int loops, rc;
+ struct mwl8k_priv *priv = hw->priv;
+ struct firmware *fw = priv->fw.ucode;
+ struct mwl8k_device_info *di = priv->device_info;
+ int rc;
+ int loops;
+
+ if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) {
+ struct firmware *helper = priv->fw.helper;
- const u8 *ucode = priv->fw.ucode->data;
- size_t ucode_len = priv->fw.ucode->size;
- const u8 *helper = priv->fw.helper->data;
- size_t helper_len = priv->fw.helper->size;
+ if (helper == NULL) {
+ printk(KERN_ERR "%s: helper image needed but none "
+ "given\n", pci_name(priv->pdev));
+ return -EINVAL;
+ }
- if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) {
- rc = mwl8k_load_fw_image(priv, helper, helper_len);
+ rc = mwl8k_load_fw_image(priv, helper->data, helper->size);
if (rc) {
printk(KERN_ERR "%s: unable to load firmware "
- "helper image\n", pci_name(priv->pdev));
+ "helper image\n", pci_name(priv->pdev));
return rc;
}
msleep(1);
- rc = mwl8k_feed_fw_image(priv, ucode, ucode_len);
+ rc = mwl8k_feed_fw_image(priv, fw->data, fw->size);
} else {
- rc = mwl8k_load_fw_image(priv, ucode, ucode_len);
+ rc = mwl8k_load_fw_image(priv, fw->data, fw->size);
}
if (rc) {
- printk(KERN_ERR "%s: unable to load firmware data\n",
- pci_name(priv->pdev));
+ printk(KERN_ERR "%s: unable to load firmware image\n",
+ pci_name(priv->pdev));
return rc;
}
- iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
+ if (di->modes & BIT(NL80211_IFTYPE_AP))
+ iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR);
+ else
+ iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR);
msleep(1);
loops = 200000;
do {
- if (ioread32(priv->regs + MWL8K_HIU_INT_CODE)
- == MWL8K_FWSTA_READY)
+ u32 ready_code;
+
+ ready_code = ioread32(priv->regs + MWL8K_HIU_INT_CODE);
+ if (ready_code == MWL8K_FWAP_READY) {
+ priv->ap_fw = 1;
break;
+ } else if (ready_code == MWL8K_FWSTA_READY) {
+ priv->ap_fw = 0;
+ break;
+ }
+
+ cond_resched();
udelay(1);
} while (--loops);
@@ -605,7 +630,7 @@ struct ewc_ht_info {
/* Peer Entry flags - used to define the type of the peer node */
#define MWL8K_PEER_TYPE_ACCESSPOINT 2
-#define MWL8K_IEEE_LEGACY_DATA_RATES 12
+#define MWL8K_IEEE_LEGACY_DATA_RATES 13
#define MWL8K_MCS_BITMAP_SIZE 16
struct peer_capability_info {
@@ -731,16 +756,96 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb)
/*
- * Packet reception.
+ * Packet reception for 88w8366.
*/
-#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02
+struct mwl8k_rxd_8366 {
+ __le16 pkt_len;
+ __u8 sq2;
+ __u8 rate;
+ __le32 pkt_phys_addr;
+ __le32 next_rxd_phys_addr;
+ __le16 qos_control;
+ __le16 htsig2;
+ __le32 hw_rssi_info;
+ __le32 hw_noise_floor_info;
+ __u8 noise_floor;
+ __u8 pad0[3];
+ __u8 rssi;
+ __u8 rx_status;
+ __u8 channel;
+ __u8 rx_ctrl;
+} __attribute__((packed));
-struct mwl8k_rx_desc {
+#define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80
+
+static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr)
+{
+ struct mwl8k_rxd_8366 *rxd = _rxd;
+
+ rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
+ rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST;
+}
+
+static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len)
+{
+ struct mwl8k_rxd_8366 *rxd = _rxd;
+
+ rxd->pkt_len = cpu_to_le16(len);
+ rxd->pkt_phys_addr = cpu_to_le32(addr);
+ wmb();
+ rxd->rx_ctrl = 0;
+}
+
+static int
+mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status)
+{
+ struct mwl8k_rxd_8366 *rxd = _rxd;
+
+ if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST))
+ return -1;
+ rmb();
+
+ memset(status, 0, sizeof(*status));
+
+ status->signal = -rxd->rssi;
+ status->noise = -rxd->noise_floor;
+
+ if (rxd->rate & 0x80) {
+ status->flag |= RX_FLAG_HT;
+ status->rate_idx = rxd->rate & 0x7f;
+ } else {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mwl8k_rates); i++) {
+ if (mwl8k_rates[i].hw_value == rxd->rate) {
+ status->rate_idx = i;
+ break;
+ }
+ }
+ }
+
+ status->band = IEEE80211_BAND_2GHZ;
+ status->freq = ieee80211_channel_to_frequency(rxd->channel);
+
+ return le16_to_cpu(rxd->pkt_len);
+}
+
+static struct rxd_ops rxd_8366_ops = {
+ .rxd_size = sizeof(struct mwl8k_rxd_8366),
+ .rxd_init = mwl8k_rxd_8366_init,
+ .rxd_refill = mwl8k_rxd_8366_refill,
+ .rxd_process = mwl8k_rxd_8366_process,
+};
+
+/*
+ * Packet reception for 88w8687.
+ */
+struct mwl8k_rxd_8687 {
__le16 pkt_len;
__u8 link_quality;
__u8 noise_level;
__le32 pkt_phys_addr;
- __le32 next_rx_desc_phys_addr;
+ __le32 next_rxd_phys_addr;
__le16 qos_control;
__le16 rate_info;
__le32 pad0[4];
@@ -752,6 +857,76 @@ struct mwl8k_rx_desc {
__u8 pad2[2];
} __attribute__((packed));
+#define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000
+#define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3)
+#define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f)
+#define MWL8K_8687_RATE_INFO_40MHZ 0x0004
+#define MWL8K_8687_RATE_INFO_SHORTGI 0x0002
+#define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001
+
+#define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02
+
+static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr)
+{
+ struct mwl8k_rxd_8687 *rxd = _rxd;
+
+ rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr);
+ rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST;
+}
+
+static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len)
+{
+ struct mwl8k_rxd_8687 *rxd = _rxd;
+
+ rxd->pkt_len = cpu_to_le16(len);
+ rxd->pkt_phys_addr = cpu_to_le32(addr);
+ wmb();
+ rxd->rx_ctrl = 0;
+}
+
+static int
+mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status)
+{
+ struct mwl8k_rxd_8687 *rxd = _rxd;
+ u16 rate_info;
+
+ if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST))
+ return -1;
+ rmb();
+
+ rate_info = le16_to_cpu(rxd->rate_info);
+
+ memset(status, 0, sizeof(*status));
+
+ status->signal = -rxd->rssi;
+ status->noise = -rxd->noise_level;
+ status->qual = rxd->link_quality;
+ status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info);
+ status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info);
+
+ if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE)
+ status->flag |= RX_FLAG_SHORTPRE;
+ if (rate_info & MWL8K_8687_RATE_INFO_40MHZ)
+ status->flag |= RX_FLAG_40MHZ;
+ if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI)
+ status->flag |= RX_FLAG_SHORT_GI;
+ if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT)
+ status->flag |= RX_FLAG_HT;
+
+ status->band = IEEE80211_BAND_2GHZ;
+ status->freq = ieee80211_channel_to_frequency(rxd->channel);
+
+ return le16_to_cpu(rxd->pkt_len);
+}
+
+static struct rxd_ops rxd_8687_ops = {
+ .rxd_size = sizeof(struct mwl8k_rxd_8687),
+ .rxd_init = mwl8k_rxd_8687_init,
+ .rxd_refill = mwl8k_rxd_8687_refill,
+ .rxd_process = mwl8k_rxd_8687_process,
+};
+
+
#define MWL8K_RX_DESCS 256
#define MWL8K_RX_MAXSZ 3800
@@ -762,43 +937,44 @@ static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index)
int size;
int i;
- rxq->rx_desc_count = 0;
- rxq->rx_head = 0;
- rxq->rx_tail = 0;
+ rxq->rxd_count = 0;
+ rxq->head = 0;
+ rxq->tail = 0;
- size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc);
+ size = MWL8K_RX_DESCS * priv->rxd_ops->rxd_size;
- rxq->rx_desc_area =
- pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma);
- if (rxq->rx_desc_area == NULL) {
+ rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
+ if (rxq->rxd == NULL) {
printk(KERN_ERR "%s: failed to alloc RX descriptors\n",
- priv->name);
+ wiphy_name(hw->wiphy));
return -ENOMEM;
}
- memset(rxq->rx_desc_area, 0, size);
+ memset(rxq->rxd, 0, size);
- rxq->rx_skb = kmalloc(MWL8K_RX_DESCS *
- sizeof(*rxq->rx_skb), GFP_KERNEL);
- if (rxq->rx_skb == NULL) {
+ rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
+ if (rxq->buf == NULL) {
printk(KERN_ERR "%s: failed to alloc RX skbuff list\n",
- priv->name);
- pci_free_consistent(priv->pdev, size,
- rxq->rx_desc_area, rxq->rx_desc_dma);
+ wiphy_name(hw->wiphy));
+ pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
return -ENOMEM;
}
- memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb));
+ memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf));
for (i = 0; i < MWL8K_RX_DESCS; i++) {
- struct mwl8k_rx_desc *rx_desc;
+ int desc_size;
+ void *rxd;
int nexti;
+ dma_addr_t next_dma_addr;
- rx_desc = rxq->rx_desc_area + i;
- nexti = (i + 1) % MWL8K_RX_DESCS;
+ desc_size = priv->rxd_ops->rxd_size;
+ rxd = rxq->rxd + (i * priv->rxd_ops->rxd_size);
- rx_desc->next_rx_desc_phys_addr =
- cpu_to_le32(rxq->rx_desc_dma
- + nexti * sizeof(*rx_desc));
- rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST;
+ nexti = i + 1;
+ if (nexti == MWL8K_RX_DESCS)
+ nexti = 0;
+ next_dma_addr = rxq->rxd_dma + (nexti * desc_size);
+
+ priv->rxd_ops->rxd_init(rxd, next_dma_addr);
}
return 0;
@@ -811,27 +987,28 @@ static int rxq_refill(struct ieee80211_hw *hw, int index, int limit)
int refilled;
refilled = 0;
- while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) {
+ while (rxq->rxd_count < MWL8K_RX_DESCS && limit--) {
struct sk_buff *skb;
+ dma_addr_t addr;
int rx;
+ void *rxd;
skb = dev_alloc_skb(MWL8K_RX_MAXSZ);
if (skb == NULL)
break;
- rxq->rx_desc_count++;
-
- rx = rxq->rx_tail;
- rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS;
+ addr = pci_map_single(priv->pdev, skb->data,
+ MWL8K_RX_MAXSZ, DMA_FROM_DEVICE);
- rxq->rx_desc_area[rx].pkt_phys_addr =
- cpu_to_le32(pci_map_single(priv->pdev, skb->data,
- MWL8K_RX_MAXSZ, DMA_FROM_DEVICE));
+ rxq->rxd_count++;
+ rx = rxq->tail++;
+ if (rxq->tail == MWL8K_RX_DESCS)
+ rxq->tail = 0;
+ rxq->buf[rx].skb = skb;
+ pci_unmap_addr_set(&rxq->buf[rx], dma, addr);
- rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ);
- rxq->rx_skb[rx] = skb;
- wmb();
- rxq->rx_desc_area[rx].rx_ctrl = 0;
+ rxd = rxq->rxd + (rx * priv->rxd_ops->rxd_size);
+ priv->rxd_ops->rxd_refill(rxd, addr, MWL8K_RX_MAXSZ);
refilled++;
}
@@ -847,24 +1024,24 @@ static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index)
int i;
for (i = 0; i < MWL8K_RX_DESCS; i++) {
- if (rxq->rx_skb[i] != NULL) {
- unsigned long addr;
-
- addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr);
- pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ,
- PCI_DMA_FROMDEVICE);
- kfree_skb(rxq->rx_skb[i]);
- rxq->rx_skb[i] = NULL;
+ if (rxq->buf[i].skb != NULL) {
+ pci_unmap_single(priv->pdev,
+ pci_unmap_addr(&rxq->buf[i], dma),
+ MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
+ pci_unmap_addr_set(&rxq->buf[i], dma, 0);
+
+ kfree_skb(rxq->buf[i].skb);
+ rxq->buf[i].skb = NULL;
}
}
- kfree(rxq->rx_skb);
- rxq->rx_skb = NULL;
+ kfree(rxq->buf);
+ rxq->buf = NULL;
pci_free_consistent(priv->pdev,
- MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc),
- rxq->rx_desc_area, rxq->rx_desc_dma);
- rxq->rx_desc_area = NULL;
+ MWL8K_RX_DESCS * priv->rxd_ops->rxd_size,
+ rxq->rxd, rxq->rxd_dma);
+ rxq->rxd = NULL;
}
@@ -880,9 +1057,11 @@ mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh)
!compare_ether_addr(wh->addr3, priv->capture_bssid);
}
-static inline void mwl8k_save_beacon(struct mwl8k_priv *priv,
- struct sk_buff *skb)
+static inline void mwl8k_save_beacon(struct ieee80211_hw *hw,
+ struct sk_buff *skb)
{
+ struct mwl8k_priv *priv = hw->priv;
+
priv->capture_beacon = false;
memset(priv->capture_bssid, 0, ETH_ALEN);
@@ -893,8 +1072,7 @@ static inline void mwl8k_save_beacon(struct mwl8k_priv *priv,
*/
priv->beacon_skb = skb_copy(skb, GFP_ATOMIC);
if (priv->beacon_skb != NULL)
- queue_work(priv->config_wq,
- &priv->finalize_join_worker);
+ ieee80211_queue_work(hw, &priv->finalize_join_worker);
}
static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
@@ -904,53 +1082,46 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
int processed;
processed = 0;
- while (rxq->rx_desc_count && limit--) {
- struct mwl8k_rx_desc *rx_desc;
+ while (rxq->rxd_count && limit--) {
struct sk_buff *skb;
+ void *rxd;
+ int pkt_len;
struct ieee80211_rx_status status;
- unsigned long addr;
- struct ieee80211_hdr *wh;
- rx_desc = rxq->rx_desc_area + rxq->rx_head;
- if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST))
+ skb = rxq->buf[rxq->head].skb;
+ if (skb == NULL)
break;
- rmb();
- skb = rxq->rx_skb[rxq->rx_head];
- if (skb == NULL)
+ rxd = rxq->rxd + (rxq->head * priv->rxd_ops->rxd_size);
+
+ pkt_len = priv->rxd_ops->rxd_process(rxd, &status);
+ if (pkt_len < 0)
break;
- rxq->rx_skb[rxq->rx_head] = NULL;
- rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS;
- rxq->rx_desc_count--;
+ rxq->buf[rxq->head].skb = NULL;
- addr = le32_to_cpu(rx_desc->pkt_phys_addr);
- pci_unmap_single(priv->pdev, addr,
- MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
+ pci_unmap_single(priv->pdev,
+ pci_unmap_addr(&rxq->buf[rxq->head], dma),
+ MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE);
+ pci_unmap_addr_set(&rxq->buf[rxq->head], dma, 0);
- skb_put(skb, le16_to_cpu(rx_desc->pkt_len));
- mwl8k_remove_dma_header(skb);
+ rxq->head++;
+ if (rxq->head == MWL8K_RX_DESCS)
+ rxq->head = 0;
+
+ rxq->rxd_count--;
- wh = (struct ieee80211_hdr *)skb->data;
+ skb_put(skb, pkt_len);
+ mwl8k_remove_dma_header(skb);
/*
- * Check for pending join operation. save a copy of
- * the beacon and schedule a tasklet to send finalize
- * join command to the firmware.
+ * Check for a pending join operation. Save a
+ * copy of the beacon and schedule a tasklet to
+ * send a FINALIZE_JOIN command to the firmware.
*/
- if (mwl8k_capture_bssid(priv, wh))
- mwl8k_save_beacon(priv, skb);
-
- memset(&status, 0, sizeof(status));
- status.mactime = 0;
- status.signal = -rx_desc->rssi;
- status.noise = -rx_desc->noise_level;
- status.qual = rx_desc->link_quality;
- status.antenna = 1;
- status.rate_idx = 1;
- status.flag = 0;
- status.band = IEEE80211_BAND_2GHZ;
- status.freq = ieee80211_channel_to_frequency(rx_desc->channel);
+ if (mwl8k_capture_bssid(priv, (void *)skb->data))
+ mwl8k_save_beacon(hw, skb);
+
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
ieee80211_rx_irqsafe(hw, skb);
@@ -965,24 +1136,10 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
* Packet transmission.
*/
-/* Transmit queue assignment. */
-enum {
- MWL8K_WME_AC_BK = 0, /* background access */
- MWL8K_WME_AC_BE = 1, /* best effort access */
- MWL8K_WME_AC_VI = 2, /* video access */
- MWL8K_WME_AC_VO = 3, /* voice access */
-};
-
/* Transmit packet ACK policy */
#define MWL8K_TXD_ACK_POLICY_NORMAL 0
#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3
-#define GET_TXQ(_ac) (\
- ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \
- ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \
- ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \
- MWL8K_WME_AC_BE)
-
#define MWL8K_TXD_STATUS_OK 0x00000001
#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002
#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004
@@ -997,7 +1154,7 @@ struct mwl8k_tx_desc {
__le32 pkt_phys_addr;
__le16 pkt_len;
__u8 dest_MAC_addr[ETH_ALEN];
- __le32 next_tx_desc_phys_addr;
+ __le32 next_txd_phys_addr;
__le32 reserved;
__le16 rate_info;
__u8 peer_id;
@@ -1013,44 +1170,40 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
int size;
int i;
- memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats));
- txq->tx_stats.limit = MWL8K_TX_DESCS;
- txq->tx_head = 0;
- txq->tx_tail = 0;
+ memset(&txq->stats, 0, sizeof(struct ieee80211_tx_queue_stats));
+ txq->stats.limit = MWL8K_TX_DESCS;
+ txq->head = 0;
+ txq->tail = 0;
size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc);
- txq->tx_desc_area =
- pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma);
- if (txq->tx_desc_area == NULL) {
+ txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
+ if (txq->txd == NULL) {
printk(KERN_ERR "%s: failed to alloc TX descriptors\n",
- priv->name);
+ wiphy_name(hw->wiphy));
return -ENOMEM;
}
- memset(txq->tx_desc_area, 0, size);
+ memset(txq->txd, 0, size);
- txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb),
- GFP_KERNEL);
- if (txq->tx_skb == NULL) {
+ txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
+ if (txq->skb == NULL) {
printk(KERN_ERR "%s: failed to alloc TX skbuff list\n",
- priv->name);
- pci_free_consistent(priv->pdev, size,
- txq->tx_desc_area, txq->tx_desc_dma);
+ wiphy_name(hw->wiphy));
+ pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
return -ENOMEM;
}
- memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb));
+ memset(txq->skb, 0, MWL8K_TX_DESCS * sizeof(*txq->skb));
for (i = 0; i < MWL8K_TX_DESCS; i++) {
struct mwl8k_tx_desc *tx_desc;
int nexti;
- tx_desc = txq->tx_desc_area + i;
+ tx_desc = txq->txd + i;
nexti = (i + 1) % MWL8K_TX_DESCS;
tx_desc->status = 0;
- tx_desc->next_tx_desc_phys_addr =
- cpu_to_le32(txq->tx_desc_dma +
- nexti * sizeof(*tx_desc));
+ tx_desc->next_txd_phys_addr =
+ cpu_to_le32(txq->txd_dma + nexti * sizeof(*tx_desc));
}
return 0;
@@ -1065,11 +1218,6 @@ static inline void mwl8k_tx_start(struct mwl8k_priv *priv)
ioread32(priv->regs + MWL8K_HIU_INT_CODE);
}
-static inline int mwl8k_txq_busy(struct mwl8k_priv *priv)
-{
- return priv->pending_tx_pkts;
-}
-
struct mwl8k_txq_info {
u32 fw_owned;
u32 drv_owned;
@@ -1089,14 +1237,13 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info));
- spin_lock_bh(&priv->tx_lock);
for (count = 0; count < MWL8K_TX_QUEUES; count++) {
txq = priv->txq + count;
- txinfo[count].len = txq->tx_stats.len;
- txinfo[count].head = txq->tx_head;
- txinfo[count].tail = txq->tx_tail;
+ txinfo[count].len = txq->stats.len;
+ txinfo[count].head = txq->head;
+ txinfo[count].tail = txq->tail;
for (desc = 0; desc < MWL8K_TX_DESCS; desc++) {
- tx_desc = txq->tx_desc_area + desc;
+ tx_desc = txq->txd + desc;
status = le32_to_cpu(tx_desc->status);
if (status & MWL8K_TXD_STATUS_FW_OWNED)
@@ -1108,30 +1255,26 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv,
txinfo[count].unused++;
}
}
- spin_unlock_bh(&priv->tx_lock);
return ndescs;
}
/*
- * Must be called with hw->fw_mutex held and tx queues stopped.
+ * Must be called with priv->fw_mutex held and tx queues stopped.
*/
static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
- DECLARE_COMPLETION_ONSTACK(cmd_wait);
+ DECLARE_COMPLETION_ONSTACK(tx_wait);
u32 count;
unsigned long timeout;
might_sleep();
spin_lock_bh(&priv->tx_lock);
- count = mwl8k_txq_busy(priv);
- if (count) {
- priv->tx_wait = &cmd_wait;
- if (priv->radio_on)
- mwl8k_tx_start(priv);
- }
+ count = priv->pending_tx_pkts;
+ if (count)
+ priv->tx_wait = &tx_wait;
spin_unlock_bh(&priv->tx_lock);
if (count) {
@@ -1139,23 +1282,23 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw)
int index;
int newcount;
- timeout = wait_for_completion_timeout(&cmd_wait,
+ timeout = wait_for_completion_timeout(&tx_wait,
msecs_to_jiffies(5000));
if (timeout)
return 0;
spin_lock_bh(&priv->tx_lock);
priv->tx_wait = NULL;
- newcount = mwl8k_txq_busy(priv);
+ newcount = priv->pending_tx_pkts;
+ mwl8k_scan_tx_ring(priv, txinfo);
spin_unlock_bh(&priv->tx_lock);
printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n",
__func__, __LINE__, count, newcount);
- mwl8k_scan_tx_ring(priv, txinfo);
for (index = 0; index < MWL8K_TX_QUEUES; index++)
- printk(KERN_ERR
- "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n",
+ printk(KERN_ERR "TXQ:%u L:%u H:%u T:%u FW:%u "
+ "DRV:%u U:%u\n",
index,
txinfo[index].len,
txinfo[index].head,
@@ -1181,7 +1324,7 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
struct mwl8k_tx_queue *txq = priv->txq + index;
int wake = 0;
- while (txq->tx_stats.len > 0) {
+ while (txq->stats.len > 0) {
int tx;
struct mwl8k_tx_desc *tx_desc;
unsigned long addr;
@@ -1190,8 +1333,8 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
struct ieee80211_tx_info *info;
u32 status;
- tx = txq->tx_head;
- tx_desc = txq->tx_desc_area + tx;
+ tx = txq->head;
+ tx_desc = txq->txd + tx;
status = le32_to_cpu(tx_desc->status);
@@ -1202,15 +1345,15 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force)
~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED);
}
- txq->tx_head = (tx + 1) % MWL8K_TX_DESCS;
- BUG_ON(txq->tx_stats.len == 0);
- txq->tx_stats.len--;
+ txq->head = (tx + 1) % MWL8K_TX_DESCS;
+ BUG_ON(txq->stats.len == 0);
+ txq->stats.len--;
priv->pending_tx_pkts--;
addr = le32_to_cpu(tx_desc->pkt_phys_addr);
size = le16_to_cpu(tx_desc->pkt_len);
- skb = txq->tx_skb[tx];
- txq->tx_skb[tx] = NULL;
+ skb = txq->skb[tx];
+ txq->skb[tx] = NULL;
BUG_ON(skb == NULL);
pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE);
@@ -1243,13 +1386,13 @@ static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index)
mwl8k_txq_reclaim(hw, index, 1);
- kfree(txq->tx_skb);
- txq->tx_skb = NULL;
+ kfree(txq->skb);
+ txq->skb = NULL;
pci_free_consistent(priv->pdev,
MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc),
- txq->tx_desc_area, txq->tx_desc_dma);
- txq->tx_desc_area = NULL;
+ txq->txd, txq->txd_dma);
+ txq->txd = NULL;
}
static int
@@ -1317,7 +1460,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
if (pci_dma_mapping_error(priv->pdev, dma)) {
printk(KERN_DEBUG "%s: failed to dma map skb, "
- "dropping TX frame.\n", priv->name);
+ "dropping TX frame.\n", wiphy_name(hw->wiphy));
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -1326,10 +1469,10 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
txq = priv->txq + index;
- BUG_ON(txq->tx_skb[txq->tx_tail] != NULL);
- txq->tx_skb[txq->tx_tail] = skb;
+ BUG_ON(txq->skb[txq->tail] != NULL);
+ txq->skb[txq->tail] = skb;
- tx = txq->tx_desc_area + txq->tx_tail;
+ tx = txq->txd + txq->tail;
tx->data_rate = txdatarate;
tx->tx_priority = index;
tx->qos_control = cpu_to_le16(qos);
@@ -1340,15 +1483,15 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
wmb();
tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
- txq->tx_stats.count++;
- txq->tx_stats.len++;
+ txq->stats.count++;
+ txq->stats.len++;
priv->pending_tx_pkts++;
- txq->tx_tail++;
- if (txq->tx_tail == MWL8K_TX_DESCS)
- txq->tx_tail = 0;
+ txq->tail++;
+ if (txq->tail == MWL8K_TX_DESCS)
+ txq->tail = 0;
- if (txq->tx_head == txq->tx_tail)
+ if (txq->head == txq->tail)
ieee80211_stop_queue(hw, index);
mwl8k_tx_start(priv);
@@ -1431,7 +1574,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
unsigned long timeout = 0;
u8 buf[32];
- cmd->result = 0xFFFF;
+ cmd->result = 0xffff;
dma_size = le16_to_cpu(cmd->length);
dma_addr = pci_map_single(priv->pdev, cmd, dma_size,
PCI_DMA_BIDIRECTIONAL);
@@ -1464,7 +1607,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
if (!timeout) {
printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
- priv->name,
+ wiphy_name(hw->wiphy),
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
MWL8K_CMD_TIMEOUT_MS);
rc = -ETIMEDOUT;
@@ -1472,7 +1615,7 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
rc = cmd->result ? -EINVAL : 0;
if (rc)
printk(KERN_ERR "%s: Command %s error 0x%x\n",
- priv->name,
+ wiphy_name(hw->wiphy),
mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
le16_to_cpu(cmd->result));
}
@@ -1481,9 +1624,9 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd)
}
/*
- * GET_HW_SPEC.
+ * CMD_GET_HW_SPEC (STA version).
*/
-struct mwl8k_cmd_get_hw_spec {
+struct mwl8k_cmd_get_hw_spec_sta {
struct mwl8k_cmd_pkt header;
__u8 hw_rev;
__u8 host_interface;
@@ -1499,13 +1642,13 @@ struct mwl8k_cmd_get_hw_spec {
__le32 tx_queue_ptrs[MWL8K_TX_QUEUES];
__le32 caps2;
__le32 num_tx_desc_per_queue;
- __le32 total_rx_desc;
+ __le32 total_rxd;
} __attribute__((packed));
-static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
+static int mwl8k_cmd_get_hw_spec_sta(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_cmd_get_hw_spec *cmd;
+ struct mwl8k_cmd_get_hw_spec_sta *cmd;
int rc;
int i;
@@ -1518,12 +1661,12 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
- cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma);
+ cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
for (i = 0; i < MWL8K_TX_QUEUES; i++)
- cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma);
+ cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
- cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS);
+ cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
rc = mwl8k_post_cmd(hw, &cmd->header);
@@ -1539,6 +1682,129 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw)
}
/*
+ * CMD_GET_HW_SPEC (AP version).
+ */
+struct mwl8k_cmd_get_hw_spec_ap {
+ struct mwl8k_cmd_pkt header;
+ __u8 hw_rev;
+ __u8 host_interface;
+ __le16 num_wcb;
+ __le16 num_mcaddrs;
+ __u8 perm_addr[ETH_ALEN];
+ __le16 region_code;
+ __le16 num_antenna;
+ __le32 fw_rev;
+ __le32 wcbbase0;
+ __le32 rxwrptr;
+ __le32 rxrdptr;
+ __le32 ps_cookie;
+ __le32 wcbbase1;
+ __le32 wcbbase2;
+ __le32 wcbbase3;
+} __attribute__((packed));
+
+static int mwl8k_cmd_get_hw_spec_ap(struct ieee80211_hw *hw)
+{
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_cmd_get_hw_spec_ap *cmd;
+ int rc;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+
+ memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr));
+ cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+
+ if (!rc) {
+ int off;
+
+ SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr);
+ priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs);
+ priv->fw_rev = le32_to_cpu(cmd->fw_rev);
+ priv->hw_rev = cmd->hw_rev;
+
+ off = le32_to_cpu(cmd->wcbbase0) & 0xffff;
+ iowrite32(cpu_to_le32(priv->txq[0].txd_dma), priv->sram + off);
+
+ off = le32_to_cpu(cmd->rxwrptr) & 0xffff;
+ iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off);
+
+ off = le32_to_cpu(cmd->rxrdptr) & 0xffff;
+ iowrite32(cpu_to_le32(priv->rxq[0].rxd_dma), priv->sram + off);
+
+ off = le32_to_cpu(cmd->wcbbase1) & 0xffff;
+ iowrite32(cpu_to_le32(priv->txq[1].txd_dma), priv->sram + off);
+
+ off = le32_to_cpu(cmd->wcbbase2) & 0xffff;
+ iowrite32(cpu_to_le32(priv->txq[2].txd_dma), priv->sram + off);
+
+ off = le32_to_cpu(cmd->wcbbase3) & 0xffff;
+ iowrite32(cpu_to_le32(priv->txq[3].txd_dma), priv->sram + off);
+ }
+
+ kfree(cmd);
+ return rc;
+}
+
+/*
+ * CMD_SET_HW_SPEC.
+ */
+struct mwl8k_cmd_set_hw_spec {
+ struct mwl8k_cmd_pkt header;
+ __u8 hw_rev;
+ __u8 host_interface;
+ __le16 num_mcaddrs;
+ __u8 perm_addr[ETH_ALEN];
+ __le16 region_code;
+ __le32 fw_rev;
+ __le32 ps_cookie;
+ __le32 caps;
+ __le32 rx_queue_ptr;
+ __le32 num_tx_queues;
+ __le32 tx_queue_ptrs[MWL8K_TX_QUEUES];
+ __le32 flags;
+ __le32 num_tx_desc_per_queue;
+ __le32 total_rxd;
+} __attribute__((packed));
+
+#define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT 0x00000080
+
+static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
+{
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_cmd_set_hw_spec *cmd;
+ int rc;
+ int i;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_HW_SPEC);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+
+ cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
+ cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
+ cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES);
+ for (i = 0; i < MWL8K_TX_QUEUES; i++)
+ cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].txd_dma);
+ cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT);
+ cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
+ cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ kfree(cmd);
+
+ return rc;
+}
+
+/*
* CMD_MAC_MULTICAST_ADR.
*/
struct mwl8k_cmd_mac_multicast_adr {
@@ -1548,19 +1814,23 @@ struct mwl8k_cmd_mac_multicast_adr {
__u8 addr[0][ETH_ALEN];
};
-#define MWL8K_ENABLE_RX_MULTICAST 0x000F
+#define MWL8K_ENABLE_RX_DIRECTED 0x0001
+#define MWL8K_ENABLE_RX_MULTICAST 0x0002
+#define MWL8K_ENABLE_RX_ALL_MULTICAST 0x0004
+#define MWL8K_ENABLE_RX_BROADCAST 0x0008
static struct mwl8k_cmd_pkt *
-__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
+__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti,
int mc_count, struct dev_addr_list *mclist)
{
struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_mac_multicast_adr *cmd;
int size;
- int i;
- if (mc_count > priv->num_mcaddrs)
- mc_count = priv->num_mcaddrs;
+ if (allmulti || mc_count > priv->num_mcaddrs) {
+ allmulti = 1;
+ mc_count = 0;
+ }
size = sizeof(*cmd) + mc_count * ETH_ALEN;
@@ -1570,16 +1840,24 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR);
cmd->header.length = cpu_to_le16(size);
- cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
- cmd->numaddr = cpu_to_le16(mc_count);
-
- for (i = 0; i < mc_count && mclist; i++) {
- if (mclist->da_addrlen != ETH_ALEN) {
- kfree(cmd);
- return NULL;
+ cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_DIRECTED |
+ MWL8K_ENABLE_RX_BROADCAST);
+
+ if (allmulti) {
+ cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_ALL_MULTICAST);
+ } else if (mc_count) {
+ int i;
+
+ cmd->action |= cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST);
+ cmd->numaddr = cpu_to_le16(mc_count);
+ for (i = 0; i < mc_count && mclist; i++) {
+ if (mclist->da_addrlen != ETH_ALEN) {
+ kfree(cmd);
+ return NULL;
+ }
+ memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
+ mclist = mclist->next;
}
- memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN);
- mclist = mclist->next;
}
return &cmd->header;
@@ -1590,7 +1868,6 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw,
*/
struct mwl8k_cmd_802_11_get_stat {
struct mwl8k_cmd_pkt header;
- __le16 action;
__le32 stats[64];
} __attribute__((packed));
@@ -1611,7 +1888,6 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw,
cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
- cmd->action = cpu_to_le16(MWL8K_CMD_GET);
rc = mwl8k_post_cmd(hw, &cmd->header);
if (!rc) {
@@ -1727,6 +2003,39 @@ static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm)
}
/*
+ * CMD_RF_ANTENNA.
+ */
+struct mwl8k_cmd_rf_antenna {
+ struct mwl8k_cmd_pkt header;
+ __le16 antenna;
+ __le16 mode;
+} __attribute__((packed));
+
+#define MWL8K_RF_ANTENNA_RX 1
+#define MWL8K_RF_ANTENNA_TX 2
+
+static int
+mwl8k_cmd_rf_antenna(struct ieee80211_hw *hw, int antenna, int mask)
+{
+ struct mwl8k_cmd_rf_antenna *cmd;
+ int rc;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_ANTENNA);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+ cmd->antenna = cpu_to_le16(antenna);
+ cmd->mode = cpu_to_le16(mask);
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ kfree(cmd);
+
+ return rc;
+}
+
+/*
* CMD_SET_PRE_SCAN.
*/
struct mwl8k_cmd_set_pre_scan {
@@ -1904,6 +2213,46 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable)
}
/*
+ * CMD_SET_MAC_ADDR.
+ */
+struct mwl8k_cmd_set_mac_addr {
+ struct mwl8k_cmd_pkt header;
+ union {
+ struct {
+ __le16 mac_type;
+ __u8 mac_addr[ETH_ALEN];
+ } mbss;
+ __u8 mac_addr[ETH_ALEN];
+ };
+} __attribute__((packed));
+
+static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac)
+{
+ struct mwl8k_priv *priv = hw->priv;
+ struct mwl8k_cmd_set_mac_addr *cmd;
+ int rc;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (cmd == NULL)
+ return -ENOMEM;
+
+ cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR);
+ cmd->header.length = cpu_to_le16(sizeof(*cmd));
+ if (priv->ap_fw) {
+ cmd->mbss.mac_type = 0;
+ memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN);
+ } else {
+ memcpy(cmd->mac_addr, mac, ETH_ALEN);
+ }
+
+ rc = mwl8k_post_cmd(hw, &cmd->header);
+ kfree(cmd);
+
+ return rc;
+}
+
+
+/*
* CMD_SET_RATEADAPT_MODE.
*/
struct mwl8k_cmd_set_rate_adapt_mode {
@@ -2005,17 +2354,34 @@ struct mwl8k_cmd_set_edca_params {
/* TX opportunity in units of 32 us */
__le16 txop;
- /* Log exponent of max contention period: 0...15*/
- __u8 log_cw_max;
+ union {
+ struct {
+ /* Log exponent of max contention period: 0...15 */
+ __le32 log_cw_max;
+
+ /* Log exponent of min contention period: 0...15 */
+ __le32 log_cw_min;
+
+ /* Adaptive interframe spacing in units of 32us */
+ __u8 aifs;
+
+ /* TX queue to configure */
+ __u8 txq;
+ } ap;
+ struct {
+ /* Log exponent of max contention period: 0...15 */
+ __u8 log_cw_max;
- /* Log exponent of min contention period: 0...15 */
- __u8 log_cw_min;
+ /* Log exponent of min contention period: 0...15 */
+ __u8 log_cw_min;
- /* Adaptive interframe spacing in units of 32us */
- __u8 aifs;
+ /* Adaptive interframe spacing in units of 32us */
+ __u8 aifs;
- /* TX queue to configure */
- __u8 txq;
+ /* TX queue to configure */
+ __u8 txq;
+ } sta;
+ };
} __attribute__((packed));
#define MWL8K_SET_EDCA_CW 0x01
@@ -2031,6 +2397,7 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
__u16 cw_min, __u16 cw_max,
__u8 aifs, __u16 txop)
{
+ struct mwl8k_priv *priv = hw->priv;
struct mwl8k_cmd_set_edca_params *cmd;
int rc;
@@ -2038,14 +2405,27 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum,
if (cmd == NULL)
return -ENOMEM;
+ /*
+ * Queues 0 (BE) and 1 (BK) are swapped in hardware for
+ * this call.
+ */
+ qnum ^= !(qnum >> 1);
+
cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS);
cmd->header.length = cpu_to_le16(sizeof(*cmd));
cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL);
cmd->txop = cpu_to_le16(txop);
- cmd->log_cw_max = (u8)ilog2(cw_max + 1);
- cmd->log_cw_min = (u8)ilog2(cw_min + 1);
- cmd->aifs = aifs;
- cmd->txq = qnum;
+ if (priv->ap_fw) {
+ cmd->ap.log_cw_max = cpu_to_le32(ilog2(cw_max + 1));
+ cmd->ap.log_cw_min = cpu_to_le32(ilog2(cw_min + 1));
+ cmd->ap.aifs = aifs;
+ cmd->ap.txq = qnum;
+ } else {
+ cmd->sta.log_cw_max = (u8)ilog2(cw_max + 1);
+ cmd->sta.log_cw_min = (u8)ilog2(cw_min + 1);
+ cmd->sta.aifs = aifs;
+ cmd->sta.txq = qnum;
+ }
rc = mwl8k_post_cmd(hw, &cmd->header);
kfree(cmd);
@@ -2093,8 +2473,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame,
/* XXX TBD Might just have to abort and return an error */
if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
printk(KERN_ERR "%s(): WARNING: Incomplete beacon "
- "sent to firmware. Sz=%u MAX=%u\n", __func__,
- payload_len, MWL8K_FJ_BEACON_MAXLEN);
+ "sent to firmware. Sz=%u MAX=%u\n", __func__,
+ payload_len, MWL8K_FJ_BEACON_MAXLEN);
if (payload_len > MWL8K_FJ_BEACON_MAXLEN)
payload_len = MWL8K_FJ_BEACON_MAXLEN;
@@ -2341,9 +2721,10 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw,
cmd->rate_type = cpu_to_le32(rate_type);
if (rate_table != NULL) {
- /* Copy over each field manually so
- * that bitflipping can be done
- */
+ /*
+ * Copy over each field manually so that endian
+ * conversion can be done.
+ */
cmd->rate_table.allow_rate_drop =
cpu_to_le32(rate_table->allow_rate_drop);
cmd->rate_table.num_rates =
@@ -2399,7 +2780,7 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id)
if (status & MWL8K_A2H_INT_QUEUE_EMPTY) {
if (!mutex_is_locked(&priv->fw_mutex) &&
- priv->radio_on && mwl8k_txq_busy(priv))
+ priv->radio_on && priv->pending_tx_pkts)
mwl8k_tx_start(priv);
}
@@ -2418,7 +2799,7 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (priv->current_channel == NULL) {
printk(KERN_DEBUG "%s: dropped TX frame since radio "
- "disabled\n", priv->name);
+ "disabled\n", wiphy_name(hw->wiphy));
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
@@ -2437,7 +2818,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
IRQF_SHARED, MWL8K_NAME, hw);
if (rc) {
printk(KERN_ERR "%s: failed to register IRQ handler\n",
- priv->name);
+ wiphy_name(hw->wiphy));
return -EIO;
}
@@ -2451,12 +2832,17 @@ static int mwl8k_start(struct ieee80211_hw *hw)
if (!rc) {
rc = mwl8k_cmd_802_11_radio_enable(hw);
- if (!rc)
- rc = mwl8k_cmd_set_pre_scan(hw);
+ if (!priv->ap_fw) {
+ if (!rc)
+ rc = mwl8k_enable_sniffer(hw, 0);
- if (!rc)
- rc = mwl8k_cmd_set_post_scan(hw,
- "\x00\x00\x00\x00\x00\x00");
+ if (!rc)
+ rc = mwl8k_cmd_set_pre_scan(hw);
+
+ if (!rc)
+ rc = mwl8k_cmd_set_post_scan(hw,
+ "\x00\x00\x00\x00\x00\x00");
+ }
if (!rc)
rc = mwl8k_cmd_setrateadaptmode(hw, 0);
@@ -2464,9 +2850,6 @@ static int mwl8k_start(struct ieee80211_hw *hw)
if (!rc)
rc = mwl8k_set_wmm(hw, 0);
- if (!rc)
- rc = mwl8k_enable_sniffer(hw, 0);
-
mwl8k_fw_unlock(hw);
}
@@ -2500,9 +2883,6 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
/* Stop tx reclaim tasklet */
tasklet_disable(&priv->tx_reclaim_task);
- /* Stop config thread */
- flush_workqueue(priv->config_wq);
-
/* Return all skbs to mac80211 */
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_reclaim(hw, i, 1);
@@ -2526,11 +2906,24 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw,
if (conf->type != NL80211_IFTYPE_STATION)
return -EINVAL;
+ /*
+ * Reject interface creation if sniffer mode is active, as
+ * STA operation is mutually exclusive with hardware sniffer
+ * mode.
+ */
+ if (priv->sniffer_enabled) {
+ printk(KERN_INFO "%s: unable to create STA "
+ "interface due to sniffer mode being enabled\n",
+ wiphy_name(hw->wiphy));
+ return -EINVAL;
+ }
+
/* Clean out driver private area */
mwl8k_vif = MWL8K_VIF(conf->vif);
memset(mwl8k_vif, 0, sizeof(*mwl8k_vif));
- /* Save the mac address */
+ /* Set and save the mac address */
+ mwl8k_set_mac_addr(hw, conf->mac_addr);
memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN);
/* Back pointer to parent config block */
@@ -2558,6 +2951,8 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw,
if (priv->vif == NULL)
return;
+ mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00");
+
priv->vif = NULL;
}
@@ -2593,8 +2988,13 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed)
if (rc)
goto out;
- if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7))
- rc = -EINVAL;
+ if (priv->ap_fw) {
+ rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7);
+ if (!rc)
+ rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
+ } else {
+ rc = mwl8k_cmd_mimo_config(hw, 0x7, 0x7);
+ }
out:
mwl8k_fw_unlock(hw);
@@ -2681,32 +3081,108 @@ static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw,
{
struct mwl8k_cmd_pkt *cmd;
- cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist);
+ /*
+ * Synthesize and return a command packet that programs the
+ * hardware multicast address filter. At this point we don't
+ * know whether FIF_ALLMULTI is being requested, but if it is,
+ * we'll end up throwing this packet away and creating a new
+ * one in mwl8k_configure_filter().
+ */
+ cmd = __mwl8k_cmd_mac_multicast_adr(hw, 0, mc_count, mclist);
return (unsigned long)cmd;
}
+static int
+mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *total_flags)
+{
+ struct mwl8k_priv *priv = hw->priv;
+
+ /*
+ * Hardware sniffer mode is mutually exclusive with STA
+ * operation, so refuse to enable sniffer mode if a STA
+ * interface is active.
+ */
+ if (priv->vif != NULL) {
+ if (net_ratelimit())
+ printk(KERN_INFO "%s: not enabling sniffer "
+ "mode because STA interface is active\n",
+ wiphy_name(hw->wiphy));
+ return 0;
+ }
+
+ if (!priv->sniffer_enabled) {
+ if (mwl8k_enable_sniffer(hw, 1))
+ return 0;
+ priv->sniffer_enabled = true;
+ }
+
+ *total_flags &= FIF_PROMISC_IN_BSS | FIF_ALLMULTI |
+ FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL |
+ FIF_OTHER_BSS;
+
+ return 1;
+}
+
static void mwl8k_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
u64 multicast)
{
struct mwl8k_priv *priv = hw->priv;
- struct mwl8k_cmd_pkt *multicast_adr_cmd;
+ struct mwl8k_cmd_pkt *cmd = (void *)(unsigned long)multicast;
+
+ /*
+ * AP firmware doesn't allow fine-grained control over
+ * the receive filter.
+ */
+ if (priv->ap_fw) {
+ *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
+ kfree(cmd);
+ return;
+ }
+
+ /*
+ * Enable hardware sniffer mode if FIF_CONTROL or
+ * FIF_OTHER_BSS is requested.
+ */
+ if (*total_flags & (FIF_CONTROL | FIF_OTHER_BSS) &&
+ mwl8k_configure_filter_sniffer(hw, changed_flags, total_flags)) {
+ kfree(cmd);
+ return;
+ }
/* Clear unsupported feature flags */
- *total_flags &= FIF_BCN_PRBRESP_PROMISC;
+ *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
if (mwl8k_fw_lock(hw))
return;
+ if (priv->sniffer_enabled) {
+ mwl8k_enable_sniffer(hw, 0);
+ priv->sniffer_enabled = false;
+ }
+
if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC) {
+ /*
+ * Disable the BSS filter.
+ */
mwl8k_cmd_set_pre_scan(hw);
- else {
+ } else {
u8 *bssid;
- bssid = "\x00\x00\x00\x00\x00\x00";
+ /*
+ * Enable the BSS filter.
+ *
+ * If there is an active STA interface, use that
+ * interface's BSSID, otherwise use a dummy one
+ * (where the OUI part needs to be nonzero for
+ * the BSSID to be accepted by POST_SCAN).
+ */
+ bssid = "\x01\x00\x00\x00\x00\x00";
if (priv->vif != NULL)
bssid = MWL8K_VIF(priv->vif)->bssid;
@@ -2714,10 +3190,20 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw,
}
}
- multicast_adr_cmd = (void *)(unsigned long)multicast;
- if (multicast_adr_cmd != NULL) {
- mwl8k_post_cmd(hw, multicast_adr_cmd);
- kfree(multicast_adr_cmd);
+ /*
+ * If FIF_ALLMULTI is being requested, throw away the command
+ * packet that ->prepare_multicast() built and replace it with
+ * a command packet that enables reception of all multicast
+ * packets.
+ */
+ if (*total_flags & FIF_ALLMULTI) {
+ kfree(cmd);
+ cmd = __mwl8k_cmd_mac_multicast_adr(hw, 1, 0, NULL);
+ }
+
+ if (cmd != NULL) {
+ mwl8k_post_cmd(hw, cmd);
+ kfree(cmd);
}
mwl8k_fw_unlock(hw);
@@ -2762,7 +3248,7 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw,
spin_lock_bh(&priv->tx_lock);
for (index = 0; index < MWL8K_TX_QUEUES; index++) {
txq = priv->txq + index;
- memcpy(&stats[index], &txq->tx_stats,
+ memcpy(&stats[index], &txq->stats,
sizeof(struct ieee80211_tx_queue_stats));
}
spin_unlock_bh(&priv->tx_lock);
@@ -2802,7 +3288,7 @@ static void mwl8k_tx_reclaim_handler(unsigned long data)
for (i = 0; i < MWL8K_TX_QUEUES; i++)
mwl8k_txq_reclaim(hw, i, 0);
- if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) {
+ if (priv->tx_wait != NULL && !priv->pending_tx_pkts) {
complete(priv->tx_wait);
priv->tx_wait = NULL;
}
@@ -2822,6 +3308,36 @@ static void mwl8k_finalize_join_worker(struct work_struct *work)
priv->beacon_skb = NULL;
}
+enum {
+ MWL8687 = 0,
+ MWL8366,
+};
+
+static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = {
+ {
+ .part_name = "88w8687",
+ .helper_image = "mwl8k/helper_8687.fw",
+ .fw_image = "mwl8k/fmimage_8687.fw",
+ .rxd_ops = &rxd_8687_ops,
+ .modes = BIT(NL80211_IFTYPE_STATION),
+ },
+ {
+ .part_name = "88w8366",
+ .helper_image = "mwl8k/helper_8366.fw",
+ .fw_image = "mwl8k/fmimage_8366.fw",
+ .rxd_ops = &rxd_8366_ops,
+ .modes = 0,
+ },
+};
+
+static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
+ { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = MWL8687, },
+ { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = MWL8687, },
+ { PCI_VDEVICE(MARVELL, 0x2a40), .driver_data = MWL8366, },
+ { },
+};
+MODULE_DEVICE_TABLE(pci, mwl8k_pci_id_table);
+
static int __devinit mwl8k_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -2862,17 +3378,34 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
priv = hw->priv;
priv->hw = hw;
priv->pdev = pdev;
+ priv->device_info = &mwl8k_info_tbl[id->driver_data];
+ priv->rxd_ops = priv->device_info->rxd_ops;
+ priv->sniffer_enabled = false;
priv->wmm_enabled = false;
priv->pending_tx_pkts = 0;
- strncpy(priv->name, MWL8K_NAME, sizeof(priv->name));
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
+ priv->sram = pci_iomap(pdev, 0, 0x10000);
+ if (priv->sram == NULL) {
+ printk(KERN_ERR "%s: Cannot map device SRAM\n",
+ wiphy_name(hw->wiphy));
+ goto err_iounmap;
+ }
+
+ /*
+ * If BAR0 is a 32 bit BAR, the register BAR will be BAR1.
+ * If BAR0 is a 64 bit BAR, the register BAR will be BAR2.
+ */
priv->regs = pci_iomap(pdev, 1, 0x10000);
if (priv->regs == NULL) {
- printk(KERN_ERR "%s: Cannot map device memory\n", priv->name);
- goto err_iounmap;
+ priv->regs = pci_iomap(pdev, 2, 0x10000);
+ if (priv->regs == NULL) {
+ printk(KERN_ERR "%s: Cannot map device registers\n",
+ wiphy_name(hw->wiphy));
+ goto err_iounmap;
+ }
}
memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels));
@@ -2897,7 +3430,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
hw->queues = MWL8K_TX_QUEUES;
- hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ hw->wiphy->interface_modes = priv->device_info->modes;
/* Set rssi and noise values to dBm */
hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
@@ -2916,11 +3449,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
mwl8k_tx_reclaim_handler, (unsigned long)hw);
tasklet_disable(&priv->tx_reclaim_task);
- /* Config workthread */
- priv->config_wq = create_singlethread_workqueue("mwl8k_config");
- if (priv->config_wq == NULL)
- goto err_iounmap;
-
/* Power management cookie */
priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma);
if (priv->cookie == NULL)
@@ -2934,11 +3462,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
mutex_init(&priv->fw_mutex);
priv->fw_mutex_owner = NULL;
priv->fw_mutex_depth = 0;
- priv->tx_wait = NULL;
priv->hostcmd_wait = NULL;
spin_lock_init(&priv->tx_lock);
+ priv->tx_wait = NULL;
+
for (i = 0; i < MWL8K_TX_QUEUES; i++) {
rc = mwl8k_txq_init(hw, i);
if (rc)
@@ -2954,7 +3483,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
IRQF_SHARED, MWL8K_NAME, hw);
if (rc) {
printk(KERN_ERR "%s: failed to register IRQ handler\n",
- priv->name);
+ wiphy_name(hw->wiphy));
goto err_free_queues;
}
@@ -2962,16 +3491,18 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
mwl8k_hw_reset(priv);
/* Ask userland hotplug daemon for the device firmware */
- rc = mwl8k_request_firmware(priv, (u32)id->driver_data);
+ rc = mwl8k_request_firmware(priv);
if (rc) {
- printk(KERN_ERR "%s: Firmware files not found\n", priv->name);
+ printk(KERN_ERR "%s: Firmware files not found\n",
+ wiphy_name(hw->wiphy));
goto err_free_irq;
}
/* Load firmware into hardware */
- rc = mwl8k_load_firmware(priv);
+ rc = mwl8k_load_firmware(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot start firmware\n", priv->name);
+ printk(KERN_ERR "%s: Cannot start firmware\n",
+ wiphy_name(hw->wiphy));
goto err_stop_firmware;
}
@@ -2986,16 +3517,31 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
/* Get config data, mac addrs etc */
- rc = mwl8k_cmd_get_hw_spec(hw);
+ if (priv->ap_fw) {
+ rc = mwl8k_cmd_get_hw_spec_ap(hw);
+ if (!rc)
+ rc = mwl8k_cmd_set_hw_spec(hw);
+ } else {
+ rc = mwl8k_cmd_get_hw_spec_sta(hw);
+ }
if (rc) {
- printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name);
+ printk(KERN_ERR "%s: Cannot initialise firmware\n",
+ wiphy_name(hw->wiphy));
goto err_stop_firmware;
}
/* Turn radio off */
rc = mwl8k_cmd_802_11_radio_disable(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot disable\n", priv->name);
+ printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy));
+ goto err_stop_firmware;
+ }
+
+ /* Clear MAC address */
+ rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00");
+ if (rc) {
+ printk(KERN_ERR "%s: Cannot clear MAC address\n",
+ wiphy_name(hw->wiphy));
goto err_stop_firmware;
}
@@ -3005,13 +3551,15 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
rc = ieee80211_register_hw(hw);
if (rc) {
- printk(KERN_ERR "%s: Cannot register device\n", priv->name);
+ printk(KERN_ERR "%s: Cannot register device\n",
+ wiphy_name(hw->wiphy));
goto err_stop_firmware;
}
- printk(KERN_INFO "%s: 88w%u v%d, %pM, firmware version %u.%u.%u.%u\n",
- wiphy_name(hw->wiphy), priv->part_num, priv->hw_rev,
- hw->wiphy->perm_addr,
+ printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n",
+ wiphy_name(hw->wiphy), priv->device_info->part_name,
+ priv->hw_rev, hw->wiphy->perm_addr,
+ priv->ap_fw ? "AP" : "STA",
(priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
(priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
@@ -3038,8 +3586,8 @@ err_iounmap:
if (priv->regs != NULL)
pci_iounmap(pdev, priv->regs);
- if (priv->config_wq != NULL)
- destroy_workqueue(priv->config_wq);
+ if (priv->sram != NULL)
+ pci_iounmap(pdev, priv->sram);
pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
@@ -3073,9 +3621,6 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
/* Remove tx reclaim tasklet */
tasklet_kill(&priv->tx_reclaim_task);
- /* Stop config thread */
- destroy_workqueue(priv->config_wq);
-
/* Stop hardware */
mwl8k_hw_reset(priv);
@@ -3088,10 +3633,10 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
mwl8k_rxq_deinit(hw, 0);
- pci_free_consistent(priv->pdev, 4,
- priv->cookie, priv->cookie_dma);
+ pci_free_consistent(priv->pdev, 4, priv->cookie, priv->cookie_dma);
pci_iounmap(pdev, priv->regs);
+ pci_iounmap(pdev, priv->sram);
pci_set_drvdata(pdev, NULL);
ieee80211_free_hw(hw);
pci_release_regions(pdev);
@@ -3100,7 +3645,7 @@ static void __devexit mwl8k_remove(struct pci_dev *pdev)
static struct pci_driver mwl8k_driver = {
.name = MWL8K_NAME,
- .id_table = mwl8k_table,
+ .id_table = mwl8k_pci_id_table,
.probe = mwl8k_probe,
.remove = __devexit_p(mwl8k_remove),
.shutdown = __devexit_p(mwl8k_shutdown),
@@ -3118,3 +3663,8 @@ static void __exit mwl8k_exit(void)
module_init(mwl8k_init);
module_exit(mwl8k_exit);
+
+MODULE_DESCRIPTION(MWL8K_DESC);
+MODULE_VERSION(MWL8K_VERSION);
+MODULE_AUTHOR("Lennert Buytenhek <buytenh@marvell.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig
index dce652054afd..e2a2c18920aa 100644
--- a/drivers/net/wireless/orinoco/Kconfig
+++ b/drivers/net/wireless/orinoco/Kconfig
@@ -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
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index b45d6a4ed1e8..b0342a520bf1 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index 0efe67deedee..8e3818f6832e 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -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. */
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 390c0c7b3ac2..bf60689aaabb 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -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
diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile
index 912f5f67e159..971339858297 100644
--- a/drivers/net/wireless/rt2x00/Makefile
+++ b/drivers/net/wireless/rt2x00/Makefile
@@ -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
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
new file mode 100644
index 000000000000..d9b6a72e6d27
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -0,0 +1,1816 @@
+/*
+ Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ 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.
+ */
+
+/*
+ Module: rt2800
+ Abstract: Data structures and registers for the rt2800 modules.
+ Supported chipsets: RT2800E, RT2800ED & RT2800U.
+ */
+
+#ifndef RT2800_H
+#define RT2800_H
+
+/*
+ * RF chip defines.
+ *
+ * RF2820 2.4G 2T3R
+ * RF2850 2.4G/5G 2T3R
+ * RF2720 2.4G 1T2R
+ * RF2750 2.4G/5G 1T2R
+ * RF3020 2.4G 1T1R
+ * RF2020 2.4G B/G
+ * RF3021 2.4G 1T2R
+ * RF3022 2.4G 2T2R
+ * RF3052 2.4G 2T2R
+ */
+#define RF2820 0x0001
+#define RF2850 0x0002
+#define RF2720 0x0003
+#define RF2750 0x0004
+#define RF3020 0x0005
+#define RF2020 0x0006
+#define RF3021 0x0007
+#define RF3022 0x0008
+#define RF3052 0x0009
+
+/*
+ * Chipset version.
+ */
+#define RT2860C_VERSION 0x28600100
+#define RT2860D_VERSION 0x28600101
+#define RT2880E_VERSION 0x28720200
+#define RT2883_VERSION 0x28830300
+#define RT3070_VERSION 0x30700200
+
+/*
+ * Signal information.
+ * Default offset is required for RSSI <-> dBm conversion.
+ */
+#define DEFAULT_RSSI_OFFSET 120 /* FIXME */
+
+/*
+ * Register layout information.
+ */
+#define CSR_REG_BASE 0x1000
+#define CSR_REG_SIZE 0x0800
+#define EEPROM_BASE 0x0000
+#define EEPROM_SIZE 0x0110
+#define BBP_BASE 0x0000
+#define BBP_SIZE 0x0080
+#define RF_BASE 0x0004
+#define RF_SIZE 0x0010
+
+/*
+ * Number of TX queues.
+ */
+#define NUM_TX_QUEUES 4
+
+/*
+ * USB registers.
+ */
+
+/*
+ * INT_SOURCE_CSR: Interrupt source register.
+ * Write one to clear corresponding bit.
+ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
+ */
+#define INT_SOURCE_CSR 0x0200
+#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001)
+#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002)
+#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004)
+#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008)
+#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010)
+#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020)
+#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040)
+#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
+#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
+#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200)
+#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400)
+#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800)
+#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000)
+#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
+#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000)
+#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000)
+#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000)
+#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000)
+
+/*
+ * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
+ */
+#define INT_MASK_CSR 0x0204
+#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001)
+#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002)
+#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004)
+#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008)
+#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010)
+#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020)
+#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040)
+#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
+#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
+#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200)
+#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400)
+#define INT_MASK_CSR_TBTT FIELD32(0x00000800)
+#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000)
+#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
+#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000)
+#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000)
+#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000)
+#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000)
+
+/*
+ * WPDMA_GLO_CFG
+ */
+#define WPDMA_GLO_CFG 0x0208
+#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001)
+#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002)
+#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004)
+#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008)
+#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030)
+#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040)
+#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080)
+#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00)
+#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000)
+
+/*
+ * WPDMA_RST_IDX
+ */
+#define WPDMA_RST_IDX 0x020c
+#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001)
+#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002)
+#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004)
+#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008)
+#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010)
+#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020)
+#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000)
+
+/*
+ * DELAY_INT_CFG
+ */
+#define DELAY_INT_CFG 0x0210
+#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff)
+#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00)
+#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000)
+#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000)
+#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000)
+#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000)
+
+/*
+ * WMM_AIFSN_CFG: Aifsn for each EDCA AC
+ * AIFSN0: AC_BE
+ * AIFSN1: AC_BK
+ * AIFSN2: AC_VI
+ * AIFSN3: AC_VO
+ */
+#define WMM_AIFSN_CFG 0x0214
+#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f)
+#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0)
+#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00)
+#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMIN_CSR: CWmin for each EDCA AC
+ * CWMIN0: AC_BE
+ * CWMIN1: AC_BK
+ * CWMIN2: AC_VI
+ * CWMIN3: AC_VO
+ */
+#define WMM_CWMIN_CFG 0x0218
+#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f)
+#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0)
+#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00)
+#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000)
+
+/*
+ * WMM_CWMAX_CSR: CWmax for each EDCA AC
+ * CWMAX0: AC_BE
+ * CWMAX1: AC_BK
+ * CWMAX2: AC_VI
+ * CWMAX3: AC_VO
+ */
+#define WMM_CWMAX_CFG 0x021c
+#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f)
+#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0)
+#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00)
+#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000)
+
+/*
+ * AC_TXOP0: AC_BK/AC_BE TXOP register
+ * AC0TXOP: AC_BK in unit of 32us
+ * AC1TXOP: AC_BE in unit of 32us
+ */
+#define WMM_TXOP0_CFG 0x0220
+#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff)
+#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000)
+
+/*
+ * AC_TXOP1: AC_VO/AC_VI TXOP register
+ * AC2TXOP: AC_VI in unit of 32us
+ * AC3TXOP: AC_VO in unit of 32us
+ */
+#define WMM_TXOP1_CFG 0x0224
+#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff)
+#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000)
+
+/*
+ * GPIO_CTRL_CFG:
+ */
+#define GPIO_CTRL_CFG 0x0228
+#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001)
+#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002)
+#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004)
+#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008)
+#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010)
+#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020)
+#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040)
+#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080)
+#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100)
+
+/*
+ * MCU_CMD_CFG
+ */
+#define MCU_CMD_CFG 0x022c
+
+/*
+ * AC_BK register offsets
+ */
+#define TX_BASE_PTR0 0x0230
+#define TX_MAX_CNT0 0x0234
+#define TX_CTX_IDX0 0x0238
+#define TX_DTX_IDX0 0x023c
+
+/*
+ * AC_BE register offsets
+ */
+#define TX_BASE_PTR1 0x0240
+#define TX_MAX_CNT1 0x0244
+#define TX_CTX_IDX1 0x0248
+#define TX_DTX_IDX1 0x024c
+
+/*
+ * AC_VI register offsets
+ */
+#define TX_BASE_PTR2 0x0250
+#define TX_MAX_CNT2 0x0254
+#define TX_CTX_IDX2 0x0258
+#define TX_DTX_IDX2 0x025c
+
+/*
+ * AC_VO register offsets
+ */
+#define TX_BASE_PTR3 0x0260
+#define TX_MAX_CNT3 0x0264
+#define TX_CTX_IDX3 0x0268
+#define TX_DTX_IDX3 0x026c
+
+/*
+ * HCCA register offsets
+ */
+#define TX_BASE_PTR4 0x0270
+#define TX_MAX_CNT4 0x0274
+#define TX_CTX_IDX4 0x0278
+#define TX_DTX_IDX4 0x027c
+
+/*
+ * MGMT register offsets
+ */
+#define TX_BASE_PTR5 0x0280
+#define TX_MAX_CNT5 0x0284
+#define TX_CTX_IDX5 0x0288
+#define TX_DTX_IDX5 0x028c
+
+/*
+ * RX register offsets
+ */
+#define RX_BASE_PTR 0x0290
+#define RX_MAX_CNT 0x0294
+#define RX_CRX_IDX 0x0298
+#define RX_DRX_IDX 0x029c
+
+/*
+ * PBF_SYS_CTRL
+ * HOST_RAM_WRITE: enable Host program ram write selection
+ */
+#define PBF_SYS_CTRL 0x0400
+#define PBF_SYS_CTRL_READY FIELD32(0x00000080)
+#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
+
+/*
+ * HOST-MCU shared memory
+ */
+#define HOST_CMD_CSR 0x0404
+#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff)
+
+/*
+ * PBF registers
+ * Most are for debug. Driver doesn't touch PBF register.
+ */
+#define PBF_CFG 0x0408
+#define PBF_MAX_PCNT 0x040c
+#define PBF_CTRL 0x0410
+#define PBF_INT_STA 0x0414
+#define PBF_INT_ENA 0x0418
+
+/*
+ * BCN_OFFSET0:
+ */
+#define BCN_OFFSET0 0x042c
+#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff)
+#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00)
+#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000)
+#define BCN_OFFSET0_BCN3 FIELD32(0xff000000)
+
+/*
+ * BCN_OFFSET1:
+ */
+#define BCN_OFFSET1 0x0430
+#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff)
+#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00)
+#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000)
+#define BCN_OFFSET1_BCN7 FIELD32(0xff000000)
+
+/*
+ * PBF registers
+ * Most are for debug. Driver doesn't touch PBF register.
+ */
+#define TXRXQ_PCNT 0x0438
+#define PBF_DBG 0x043c
+
+/*
+ * RF registers
+ */
+#define RF_CSR_CFG 0x0500
+#define RF_CSR_CFG_DATA FIELD32(0x000000ff)
+#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00)
+#define RF_CSR_CFG_WRITE FIELD32(0x00010000)
+#define RF_CSR_CFG_BUSY FIELD32(0x00020000)
+
+/*
+ * MAC Control/Status Registers(CSR).
+ * Some values are set in TU, whereas 1 TU == 1024 us.
+ */
+
+/*
+ * MAC_CSR0: ASIC revision number.
+ * ASIC_REV: 0
+ * ASIC_VER: 2860 or 2870
+ */
+#define MAC_CSR0 0x1000
+#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff)
+#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000)
+
+/*
+ * MAC_SYS_CTRL:
+ */
+#define MAC_SYS_CTRL 0x1004
+#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001)
+#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002)
+#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004)
+#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008)
+#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010)
+#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020)
+#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040)
+#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080)
+
+/*
+ * MAC_ADDR_DW0: STA MAC register 0
+ */
+#define MAC_ADDR_DW0 0x1008
+#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff)
+#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00)
+#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000)
+#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000)
+
+/*
+ * MAC_ADDR_DW1: STA MAC register 1
+ * UNICAST_TO_ME_MASK:
+ * Used to mask off bits from byte 5 of the MAC address
+ * to determine the UNICAST_TO_ME bit for RX frames.
+ * The full mask is complemented by BSS_ID_MASK:
+ * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
+ */
+#define MAC_ADDR_DW1 0x100c
+#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff)
+#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00)
+#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000)
+
+/*
+ * MAC_BSSID_DW0: BSSID register 0
+ */
+#define MAC_BSSID_DW0 0x1010
+#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff)
+#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00)
+#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000)
+#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000)
+
+/*
+ * MAC_BSSID_DW1: BSSID register 1
+ * BSS_ID_MASK:
+ * 0: 1-BSSID mode (BSS index = 0)
+ * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
+ * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
+ * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
+ * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
+ * BSSID. This will make sure that those bits will be ignored
+ * when determining the MY_BSS of RX frames.
+ */
+#define MAC_BSSID_DW1 0x1014
+#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff)
+#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00)
+#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000)
+#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000)
+
+/*
+ * MAX_LEN_CFG: Maximum frame length register.
+ * MAX_MPDU: rt2860b max 16k bytes
+ * MAX_PSDU: Maximum PSDU length
+ * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
+ */
+#define MAX_LEN_CFG 0x1018
+#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff)
+#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000)
+#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000)
+#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000)
+
+/*
+ * BBP_CSR_CFG: BBP serial control register
+ * VALUE: Register value to program into BBP
+ * REG_NUM: Selected BBP register
+ * READ_CONTROL: 0 write BBP, 1 read BBP
+ * BUSY: ASIC is busy executing BBP commands
+ * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
+ * BBP_RW_MODE: 0 serial, 1 paralell
+ */
+#define BBP_CSR_CFG 0x101c
+#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff)
+#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00)
+#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000)
+#define BBP_CSR_CFG_BUSY FIELD32(0x00020000)
+#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000)
+#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000)
+
+/*
+ * RF_CSR_CFG0: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * BITWIDTH: Selected RF register
+ * STANDBYMODE: 0 high when standby, 1 low when standby
+ * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
+ * BUSY: ASIC is busy executing RF commands
+ */
+#define RF_CSR_CFG0 0x1020
+#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff)
+#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000)
+#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff)
+#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000)
+#define RF_CSR_CFG0_SEL FIELD32(0x40000000)
+#define RF_CSR_CFG0_BUSY FIELD32(0x80000000)
+
+/*
+ * RF_CSR_CFG1: RF control register
+ * REGID_AND_VALUE: Register value to program into RF
+ * RFGAP: Gap between BB_CONTROL_RF and RF_LE
+ * 0: 3 system clock cycle (37.5usec)
+ * 1: 5 system clock cycle (62.5usec)
+ */
+#define RF_CSR_CFG1 0x1024
+#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff)
+#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000)
+
+/*
+ * RF_CSR_CFG2: RF control register
+ * VALUE: Register value to program into RF
+ */
+#define RF_CSR_CFG2 0x1028
+#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff)
+
+/*
+ * LED_CFG: LED control
+ * color LED's:
+ * 0: off
+ * 1: blinking upon TX2
+ * 2: periodic slow blinking
+ * 3: always on
+ * LED polarity:
+ * 0: active low
+ * 1: active high
+ */
+#define LED_CFG 0x102c
+#define LED_CFG_ON_PERIOD FIELD32(0x000000ff)
+#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00)
+#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000)
+#define LED_CFG_R_LED_MODE FIELD32(0x03000000)
+#define LED_CFG_G_LED_MODE FIELD32(0x0c000000)
+#define LED_CFG_Y_LED_MODE FIELD32(0x30000000)
+#define LED_CFG_LED_POLAR FIELD32(0x40000000)
+
+/*
+ * XIFS_TIME_CFG: MAC timing
+ * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
+ * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
+ * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
+ * when MAC doesn't reference BBP signal BBRXEND
+ * EIFS: unit 1us
+ * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
+ *
+ */
+#define XIFS_TIME_CFG 0x1100
+#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff)
+#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00)
+#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000)
+#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000)
+#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000)
+
+/*
+ * BKOFF_SLOT_CFG:
+ */
+#define BKOFF_SLOT_CFG 0x1104
+#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff)
+#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00)
+
+/*
+ * NAV_TIME_CFG:
+ */
+#define NAV_TIME_CFG 0x1108
+#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff)
+#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00)
+#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000)
+#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000)
+
+/*
+ * CH_TIME_CFG: count as channel busy
+ */
+#define CH_TIME_CFG 0x110c
+
+/*
+ * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
+ */
+#define PBF_LIFE_TIMER 0x1110
+
+/*
+ * BCN_TIME_CFG:
+ * BEACON_INTERVAL: in unit of 1/16 TU
+ * TSF_TICKING: Enable TSF auto counting
+ * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
+ * BEACON_GEN: Enable beacon generator
+ */
+#define BCN_TIME_CFG 0x1114
+#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff)
+#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000)
+#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000)
+#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000)
+#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000)
+#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000)
+
+/*
+ * TBTT_SYNC_CFG:
+ */
+#define TBTT_SYNC_CFG 0x1118
+
+/*
+ * TSF_TIMER_DW0: Local lsb TSF timer, read-only
+ */
+#define TSF_TIMER_DW0 0x111c
+#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff)
+
+/*
+ * TSF_TIMER_DW1: Local msb TSF timer, read-only
+ */
+#define TSF_TIMER_DW1 0x1120
+#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff)
+
+/*
+ * TBTT_TIMER: TImer remains till next TBTT, read-only
+ */
+#define TBTT_TIMER 0x1124
+
+/*
+ * INT_TIMER_CFG:
+ */
+#define INT_TIMER_CFG 0x1128
+
+/*
+ * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
+ */
+#define INT_TIMER_EN 0x112c
+
+/*
+ * CH_IDLE_STA: channel idle time
+ */
+#define CH_IDLE_STA 0x1130
+
+/*
+ * CH_BUSY_STA: channel busy time
+ */
+#define CH_BUSY_STA 0x1134
+
+/*
+ * MAC_STATUS_CFG:
+ * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
+ * if 1 or higher one of the 2 registers is busy.
+ */
+#define MAC_STATUS_CFG 0x1200
+#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003)
+
+/*
+ * PWR_PIN_CFG:
+ */
+#define PWR_PIN_CFG 0x1204
+
+/*
+ * AUTOWAKEUP_CFG: Manual power control / status register
+ * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
+ * AUTOWAKE: 0:sleep, 1:awake
+ */
+#define AUTOWAKEUP_CFG 0x1208
+#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff)
+#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00)
+#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000)
+
+/*
+ * EDCA_AC0_CFG:
+ */
+#define EDCA_AC0_CFG 0x1300
+#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff)
+#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00)
+#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000)
+#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC1_CFG:
+ */
+#define EDCA_AC1_CFG 0x1304
+#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff)
+#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00)
+#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000)
+#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC2_CFG:
+ */
+#define EDCA_AC2_CFG 0x1308
+#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff)
+#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00)
+#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000)
+#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000)
+
+/*
+ * EDCA_AC3_CFG:
+ */
+#define EDCA_AC3_CFG 0x130c
+#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff)
+#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00)
+#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000)
+#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000)
+
+/*
+ * EDCA_TID_AC_MAP:
+ */
+#define EDCA_TID_AC_MAP 0x1310
+
+/*
+ * TX_PWR_CFG_0:
+ */
+#define TX_PWR_CFG_0 0x1314
+#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f)
+#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0)
+#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00)
+#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000)
+#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000)
+#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000)
+#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000)
+#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_1:
+ */
+#define TX_PWR_CFG_1 0x1318
+#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f)
+#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0)
+#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00)
+#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000)
+#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000)
+#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000)
+#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000)
+#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_2:
+ */
+#define TX_PWR_CFG_2 0x131c
+#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f)
+#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0)
+#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00)
+#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000)
+#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000)
+#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000)
+#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000)
+#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_3:
+ */
+#define TX_PWR_CFG_3 0x1320
+#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f)
+#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0)
+#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00)
+#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000)
+#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000)
+#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000)
+#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000)
+#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000)
+
+/*
+ * TX_PWR_CFG_4:
+ */
+#define TX_PWR_CFG_4 0x1324
+#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f)
+#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0)
+#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00)
+#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000)
+
+/*
+ * TX_PIN_CFG:
+ */
+#define TX_PIN_CFG 0x1328
+#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001)
+#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002)
+#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004)
+#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008)
+#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010)
+#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020)
+#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040)
+#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080)
+#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100)
+#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200)
+#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400)
+#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800)
+#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000)
+#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000)
+#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000)
+#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000)
+#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000)
+#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000)
+#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000)
+#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000)
+
+/*
+ * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
+ */
+#define TX_BAND_CFG 0x132c
+#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001)
+#define TX_BAND_CFG_A FIELD32(0x00000002)
+#define TX_BAND_CFG_BG FIELD32(0x00000004)
+
+/*
+ * TX_SW_CFG0:
+ */
+#define TX_SW_CFG0 0x1330
+
+/*
+ * TX_SW_CFG1:
+ */
+#define TX_SW_CFG1 0x1334
+
+/*
+ * TX_SW_CFG2:
+ */
+#define TX_SW_CFG2 0x1338
+
+/*
+ * TXOP_THRES_CFG:
+ */
+#define TXOP_THRES_CFG 0x133c
+
+/*
+ * TXOP_CTRL_CFG:
+ */
+#define TXOP_CTRL_CFG 0x1340
+
+/*
+ * TX_RTS_CFG:
+ * RTS_THRES: unit:byte
+ * RTS_FBK_EN: enable rts rate fallback
+ */
+#define TX_RTS_CFG 0x1344
+#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff)
+#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00)
+#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000)
+
+/*
+ * TX_TIMEOUT_CFG:
+ * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
+ * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
+ * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
+ * it is recommended that:
+ * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
+ */
+#define TX_TIMEOUT_CFG 0x1348
+#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0)
+#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00)
+#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000)
+
+/*
+ * TX_RTY_CFG:
+ * SHORT_RTY_LIMIT: short retry limit
+ * LONG_RTY_LIMIT: long retry limit
+ * LONG_RTY_THRE: Long retry threshoold
+ * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
+ * 0:expired by retry limit, 1: expired by mpdu life timer
+ * AGG_RTY_MODE: Aggregate MPDU retry mode
+ * 0:expired by retry limit, 1: expired by mpdu life timer
+ * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
+ */
+#define TX_RTY_CFG 0x134c
+#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff)
+#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00)
+#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000)
+#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000)
+#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000)
+#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000)
+
+/*
+ * TX_LINK_CFG:
+ * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
+ * MFB_ENABLE: TX apply remote MFB 1:enable
+ * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable
+ * 0: not apply remote remote unsolicit (MFS=7)
+ * TX_MRQ_EN: MCS request TX enable
+ * TX_RDG_EN: RDG TX enable
+ * TX_CF_ACK_EN: Piggyback CF-ACK enable
+ * REMOTE_MFB: remote MCS feedback
+ * REMOTE_MFS: remote MCS feedback sequence number
+ */
+#define TX_LINK_CFG 0x1350
+#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff)
+#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100)
+#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200)
+#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400)
+#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800)
+#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000)
+#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000)
+#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000)
+
+/*
+ * HT_FBK_CFG0:
+ */
+#define HT_FBK_CFG0 0x1354
+#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f)
+#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0)
+#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00)
+#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000)
+#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000)
+#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000)
+#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000)
+#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000)
+
+/*
+ * HT_FBK_CFG1:
+ */
+#define HT_FBK_CFG1 0x1358
+#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f)
+#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0)
+#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00)
+#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000)
+#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000)
+#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000)
+#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000)
+#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG0:
+ */
+#define LG_FBK_CFG0 0x135c
+#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f)
+#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0)
+#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00)
+#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000)
+#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000)
+#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000)
+#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000)
+#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000)
+
+/*
+ * LG_FBK_CFG1:
+ */
+#define LG_FBK_CFG1 0x1360
+#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f)
+#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0)
+#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00)
+#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000)
+
+/*
+ * CCK_PROT_CFG: CCK Protection
+ * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
+ * PROTECT_CTRL: Protection control frame type for CCK TX
+ * 0:none, 1:RTS/CTS, 2:CTS-to-self
+ * PROTECT_NAV: TXOP protection type for CCK TX
+ * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect
+ * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
+ * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
+ * RTS_TH_EN: RTS threshold enable on CCK TX
+ */
+#define CCK_PROT_CFG 0x1364
+#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * OFDM_PROT_CFG: OFDM Protection
+ */
+#define OFDM_PROT_CFG 0x1368
+#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * MM20_PROT_CFG: MM20 Protection
+ */
+#define MM20_PROT_CFG 0x136c
+#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * MM40_PROT_CFG: MM40 Protection
+ */
+#define MM40_PROT_CFG 0x1370
+#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * GF20_PROT_CFG: GF20 Protection
+ */
+#define GF20_PROT_CFG 0x1374
+#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * GF40_PROT_CFG: GF40 Protection
+ */
+#define GF40_PROT_CFG 0x1378
+#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
+#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
+#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
+#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
+#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
+
+/*
+ * EXP_CTS_TIME:
+ */
+#define EXP_CTS_TIME 0x137c
+
+/*
+ * EXP_ACK_TIME:
+ */
+#define EXP_ACK_TIME 0x1380
+
+/*
+ * RX_FILTER_CFG: RX configuration register.
+ */
+#define RX_FILTER_CFG 0x1400
+#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001)
+#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002)
+#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004)
+#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008)
+#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010)
+#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020)
+#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040)
+#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080)
+#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100)
+#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200)
+#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400)
+#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800)
+#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000)
+#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000)
+#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000)
+#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000)
+#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000)
+
+/*
+ * AUTO_RSP_CFG:
+ * AUTORESPONDER: 0: disable, 1: enable
+ * BAC_ACK_POLICY: 0:long, 1:short preamble
+ * CTS_40_MMODE: Response CTS 40MHz duplicate mode
+ * CTS_40_MREF: Response CTS 40MHz duplicate mode
+ * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
+ * DUAL_CTS_EN: Power bit value in control frame
+ * ACK_CTS_PSM_BIT:Power bit value in control frame
+ */
+#define AUTO_RSP_CFG 0x1404
+#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001)
+#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002)
+#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004)
+#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008)
+#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010)
+#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040)
+#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080)
+
+/*
+ * LEGACY_BASIC_RATE:
+ */
+#define LEGACY_BASIC_RATE 0x1408
+
+/*
+ * HT_BASIC_RATE:
+ */
+#define HT_BASIC_RATE 0x140c
+
+/*
+ * HT_CTRL_CFG:
+ */
+#define HT_CTRL_CFG 0x1410
+
+/*
+ * SIFS_COST_CFG:
+ */
+#define SIFS_COST_CFG 0x1414
+
+/*
+ * RX_PARSER_CFG:
+ * Set NAV for all received frames
+ */
+#define RX_PARSER_CFG 0x1418
+
+/*
+ * TX_SEC_CNT0:
+ */
+#define TX_SEC_CNT0 0x1500
+
+/*
+ * RX_SEC_CNT0:
+ */
+#define RX_SEC_CNT0 0x1504
+
+/*
+ * CCMP_FC_MUTE:
+ */
+#define CCMP_FC_MUTE 0x1508
+
+/*
+ * TXOP_HLDR_ADDR0:
+ */
+#define TXOP_HLDR_ADDR0 0x1600
+
+/*
+ * TXOP_HLDR_ADDR1:
+ */
+#define TXOP_HLDR_ADDR1 0x1604
+
+/*
+ * TXOP_HLDR_ET:
+ */
+#define TXOP_HLDR_ET 0x1608
+
+/*
+ * QOS_CFPOLL_RA_DW0:
+ */
+#define QOS_CFPOLL_RA_DW0 0x160c
+
+/*
+ * QOS_CFPOLL_RA_DW1:
+ */
+#define QOS_CFPOLL_RA_DW1 0x1610
+
+/*
+ * QOS_CFPOLL_QC:
+ */
+#define QOS_CFPOLL_QC 0x1614
+
+/*
+ * RX_STA_CNT0: RX PLCP error count & RX CRC error count
+ */
+#define RX_STA_CNT0 0x1700
+#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff)
+#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT1: RX False CCA count & RX LONG frame count
+ */
+#define RX_STA_CNT1 0x1704
+#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff)
+#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000)
+
+/*
+ * RX_STA_CNT2:
+ */
+#define RX_STA_CNT2 0x1708
+#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff)
+#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT0: TX Beacon count
+ */
+#define TX_STA_CNT0 0x170c
+#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff)
+#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT1: TX tx count
+ */
+#define TX_STA_CNT1 0x1710
+#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff)
+#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000)
+
+/*
+ * TX_STA_CNT2: TX tx count
+ */
+#define TX_STA_CNT2 0x1714
+#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff)
+#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_STA_FIFO: TX Result for specific PID status fifo register
+ */
+#define TX_STA_FIFO 0x1718
+#define TX_STA_FIFO_VALID FIELD32(0x00000001)
+#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e)
+#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020)
+#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040)
+#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080)
+#define TX_STA_FIFO_WCID FIELD32(0x0000ff00)
+#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000)
+#define TX_STA_FIFO_MCS FIELD32(0x007f0000)
+#define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000)
+
+/*
+ * TX_AGG_CNT: Debug counter
+ */
+#define TX_AGG_CNT 0x171c
+#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT0:
+ */
+#define TX_AGG_CNT0 0x1720
+#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT1:
+ */
+#define TX_AGG_CNT1 0x1724
+#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT2:
+ */
+#define TX_AGG_CNT2 0x1728
+#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT3:
+ */
+#define TX_AGG_CNT3 0x172c
+#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT4:
+ */
+#define TX_AGG_CNT4 0x1730
+#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT5:
+ */
+#define TX_AGG_CNT5 0x1734
+#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT6:
+ */
+#define TX_AGG_CNT6 0x1738
+#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000)
+
+/*
+ * TX_AGG_CNT7:
+ */
+#define TX_AGG_CNT7 0x173c
+#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff)
+#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000)
+
+/*
+ * MPDU_DENSITY_CNT:
+ * TX_ZERO_DEL: TX zero length delimiter count
+ * RX_ZERO_DEL: RX zero length delimiter count
+ */
+#define MPDU_DENSITY_CNT 0x1740
+#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff)
+#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000)
+
+/*
+ * Security key table memory.
+ * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
+ * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
+ * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
+ * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
+ * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry
+ * SHARED_KEY_MODE_BASE: 4-byte * 16-entry
+ */
+#define MAC_WCID_BASE 0x1800
+#define PAIRWISE_KEY_TABLE_BASE 0x4000
+#define MAC_IVEIV_TABLE_BASE 0x6000
+#define MAC_WCID_ATTRIBUTE_BASE 0x6800
+#define SHARED_KEY_TABLE_BASE 0x6c00
+#define SHARED_KEY_MODE_BASE 0x7000
+
+#define MAC_WCID_ENTRY(__idx) \
+ ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
+#define PAIRWISE_KEY_ENTRY(__idx) \
+ ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+#define MAC_IVEIV_ENTRY(__idx) \
+ ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) )
+#define MAC_WCID_ATTR_ENTRY(__idx) \
+ ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
+#define SHARED_KEY_ENTRY(__idx) \
+ ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+#define SHARED_KEY_MODE_ENTRY(__idx) \
+ ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
+
+struct mac_wcid_entry {
+ u8 mac[6];
+ u8 reserved[2];
+} __attribute__ ((packed));
+
+struct hw_key_entry {
+ u8 key[16];
+ u8 tx_mic[8];
+ u8 rx_mic[8];
+} __attribute__ ((packed));
+
+struct mac_iveiv_entry {
+ u8 iv[8];
+} __attribute__ ((packed));
+
+/*
+ * MAC_WCID_ATTRIBUTE:
+ */
+#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001)
+#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e)
+#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070)
+#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380)
+
+/*
+ * SHARED_KEY_MODE:
+ */
+#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007)
+#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070)
+#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700)
+#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000)
+#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000)
+#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000)
+#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000)
+#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000)
+
+/*
+ * HOST-MCU communication
+ */
+
+/*
+ * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
+ */
+#define H2M_MAILBOX_CSR 0x7010
+#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff)
+#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_CID:
+ */
+#define H2M_MAILBOX_CID 0x7014
+#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff)
+#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00)
+#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000)
+#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000)
+
+/*
+ * H2M_MAILBOX_STATUS:
+ */
+#define H2M_MAILBOX_STATUS 0x701c
+
+/*
+ * H2M_INT_SRC:
+ */
+#define H2M_INT_SRC 0x7024
+
+/*
+ * H2M_BBP_AGENT:
+ */
+#define H2M_BBP_AGENT 0x7028
+
+/*
+ * MCU_LEDCS: LED control for MCU Mailbox.
+ */
+#define MCU_LEDCS_LED_MODE FIELD8(0x1f)
+#define MCU_LEDCS_POLARITY FIELD8(0x01)
+
+/*
+ * HW_CS_CTS_BASE:
+ * Carrier-sense CTS frame base address.
+ * It's where mac stores carrier-sense frame for carrier-sense function.
+ */
+#define HW_CS_CTS_BASE 0x7700
+
+/*
+ * HW_DFS_CTS_BASE:
+ * DFS CTS frame base address. It's where mac stores CTS frame for DFS.
+ */
+#define HW_DFS_CTS_BASE 0x7780
+
+/*
+ * TXRX control registers - base address 0x3000
+ */
+
+/*
+ * TXRX_CSR1:
+ * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first..
+ */
+#define TXRX_CSR1 0x77d0
+
+/*
+ * HW_DEBUG_SETTING_BASE:
+ * since NULL frame won't be that long (256 byte)
+ * We steal 16 tail bytes to save debugging settings
+ */
+#define HW_DEBUG_SETTING_BASE 0x77f0
+#define HW_DEBUG_SETTING_BASE2 0x7770
+
+/*
+ * HW_BEACON_BASE
+ * In order to support maximum 8 MBSS and its maximum length
+ * is 512 bytes for each beacon
+ * Three section discontinue memory segments will be used.
+ * 1. The original region for BCN 0~3
+ * 2. Extract memory from FCE table for BCN 4~5
+ * 3. Extract memory from Pair-wise key table for BCN 6~7
+ * It occupied those memory of wcid 238~253 for BCN 6
+ * and wcid 222~237 for BCN 7
+ *
+ * IMPORTANT NOTE: Not sure why legacy driver does this,
+ * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
+ */
+#define HW_BEACON_BASE0 0x7800
+#define HW_BEACON_BASE1 0x7a00
+#define HW_BEACON_BASE2 0x7c00
+#define HW_BEACON_BASE3 0x7e00
+#define HW_BEACON_BASE4 0x7200
+#define HW_BEACON_BASE5 0x7400
+#define HW_BEACON_BASE6 0x5dc0
+#define HW_BEACON_BASE7 0x5bc0
+
+#define HW_BEACON_OFFSET(__index) \
+ ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
+ (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
+ (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
+
+/*
+ * BBP registers.
+ * The wordsize of the BBP is 8 bits.
+ */
+
+/*
+ * BBP 1: TX Antenna
+ */
+#define BBP1_TX_POWER FIELD8(0x07)
+#define BBP1_TX_ANTENNA FIELD8(0x18)
+
+/*
+ * BBP 3: RX Antenna
+ */
+#define BBP3_RX_ANTENNA FIELD8(0x18)
+#define BBP3_HT40_PLUS FIELD8(0x20)
+
+/*
+ * BBP 4: Bandwidth
+ */
+#define BBP4_TX_BF FIELD8(0x01)
+#define BBP4_BANDWIDTH FIELD8(0x18)
+
+/*
+ * RFCSR registers
+ * The wordsize of the RFCSR is 8 bits.
+ */
+
+/*
+ * RFCSR 6:
+ */
+#define RFCSR6_R FIELD8(0x03)
+
+/*
+ * RFCSR 7:
+ */
+#define RFCSR7_RF_TUNING FIELD8(0x01)
+
+/*
+ * RFCSR 12:
+ */
+#define RFCSR12_TX_POWER FIELD8(0x1f)
+
+/*
+ * RFCSR 22:
+ */
+#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01)
+
+/*
+ * RFCSR 23:
+ */
+#define RFCSR23_FREQ_OFFSET FIELD8(0x7f)
+
+/*
+ * RFCSR 30:
+ */
+#define RFCSR30_RF_CALIBRATION FIELD8(0x80)
+
+/*
+ * RF registers
+ */
+
+/*
+ * RF 2
+ */
+#define RF2_ANTENNA_RX2 FIELD32(0x00000040)
+#define RF2_ANTENNA_TX1 FIELD32(0x00004000)
+#define RF2_ANTENNA_RX1 FIELD32(0x00020000)
+
+/*
+ * RF 3
+ */
+#define RF3_TXPOWER_G FIELD32(0x00003e00)
+#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200)
+#define RF3_TXPOWER_A FIELD32(0x00003c00)
+
+/*
+ * RF 4
+ */
+#define RF4_TXPOWER_G FIELD32(0x000007c0)
+#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040)
+#define RF4_TXPOWER_A FIELD32(0x00000780)
+#define RF4_FREQ_OFFSET FIELD32(0x001f8000)
+#define RF4_HT40 FIELD32(0x00200000)
+
+/*
+ * EEPROM content.
+ * The wordsize of the EEPROM is 16 bits.
+ */
+
+/*
+ * EEPROM Version
+ */
+#define EEPROM_VERSION 0x0001
+#define EEPROM_VERSION_FAE FIELD16(0x00ff)
+#define EEPROM_VERSION_VERSION FIELD16(0xff00)
+
+/*
+ * HW MAC address.
+ */
+#define EEPROM_MAC_ADDR_0 0x0002
+#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_1 0x0003
+#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
+#define EEPROM_MAC_ADDR_2 0x0004
+#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
+#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
+
+/*
+ * EEPROM ANTENNA config
+ * RXPATH: 1: 1R, 2: 2R, 3: 3R
+ * TXPATH: 1: 1T, 2: 2T
+ */
+#define EEPROM_ANTENNA 0x001a
+#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f)
+#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0)
+#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00)
+
+/*
+ * EEPROM NIC config
+ * CARDBUS_ACCEL: 0 - enable, 1 - disable
+ */
+#define EEPROM_NIC 0x001b
+#define EEPROM_NIC_HW_RADIO FIELD16(0x0001)
+#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002)
+#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004)
+#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008)
+#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010)
+#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020)
+#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040)
+#define EEPROM_NIC_WPS_PBC FIELD16(0x0080)
+#define EEPROM_NIC_BW40M_BG FIELD16(0x0100)
+#define EEPROM_NIC_BW40M_A FIELD16(0x0200)
+
+/*
+ * EEPROM frequency
+ */
+#define EEPROM_FREQ 0x001d
+#define EEPROM_FREQ_OFFSET FIELD16(0x00ff)
+#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00)
+#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000)
+
+/*
+ * EEPROM LED
+ * POLARITY_RDY_G: Polarity RDY_G setting.
+ * POLARITY_RDY_A: Polarity RDY_A setting.
+ * POLARITY_ACT: Polarity ACT setting.
+ * POLARITY_GPIO_0: Polarity GPIO0 setting.
+ * POLARITY_GPIO_1: Polarity GPIO1 setting.
+ * POLARITY_GPIO_2: Polarity GPIO2 setting.
+ * POLARITY_GPIO_3: Polarity GPIO3 setting.
+ * POLARITY_GPIO_4: Polarity GPIO4 setting.
+ * LED_MODE: Led mode.
+ */
+#define EEPROM_LED1 0x001e
+#define EEPROM_LED2 0x001f
+#define EEPROM_LED3 0x0020
+#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001)
+#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002)
+#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004)
+#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008)
+#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010)
+#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020)
+#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040)
+#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080)
+#define EEPROM_LED_LED_MODE FIELD16(0x1f00)
+
+/*
+ * EEPROM LNA
+ */
+#define EEPROM_LNA 0x0022
+#define EEPROM_LNA_BG FIELD16(0x00ff)
+#define EEPROM_LNA_A0 FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG offset
+ */
+#define EEPROM_RSSI_BG 0x0023
+#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff)
+#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI BG2 offset
+ */
+#define EEPROM_RSSI_BG2 0x0024
+#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff)
+#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI A offset
+ */
+#define EEPROM_RSSI_A 0x0025
+#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff)
+#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00)
+
+/*
+ * EEPROM RSSI A2 offset
+ */
+#define EEPROM_RSSI_A2 0x0026
+#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff)
+#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00)
+
+/*
+ * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
+ * This is delta in 40MHZ.
+ * VALUE: Tx Power dalta value (MAX=4)
+ * TYPE: 1: Plus the delta value, 0: minus the delta value
+ * TXPOWER: Enable:
+ */
+#define EEPROM_TXPOWER_DELTA 0x0028
+#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f)
+#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040)
+#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080)
+
+/*
+ * EEPROM TXPOWER 802.11BG
+ */
+#define EEPROM_TXPOWER_BG1 0x0029
+#define EEPROM_TXPOWER_BG2 0x0030
+#define EEPROM_TXPOWER_BG_SIZE 7
+#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff)
+#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00)
+
+/*
+ * EEPROM TXPOWER 802.11A
+ */
+#define EEPROM_TXPOWER_A1 0x003c
+#define EEPROM_TXPOWER_A2 0x0053
+#define EEPROM_TXPOWER_A_SIZE 6
+#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff)
+#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
+
+/*
+ * EEPROM TXpower byrate: 20MHZ power
+ */
+#define EEPROM_TXPOWER_BYRATE 0x006f
+
+/*
+ * EEPROM BBP.
+ */
+#define EEPROM_BBP_START 0x0078
+#define EEPROM_BBP_SIZE 16
+#define EEPROM_BBP_VALUE FIELD16(0x00ff)
+#define EEPROM_BBP_REG_ID FIELD16(0xff00)
+
+/*
+ * MCU mailbox commands.
+ */
+#define MCU_SLEEP 0x30
+#define MCU_WAKEUP 0x31
+#define MCU_RADIO_OFF 0x35
+#define MCU_CURRENT 0x36
+#define MCU_LED 0x50
+#define MCU_LED_STRENGTH 0x51
+#define MCU_LED_1 0x52
+#define MCU_LED_2 0x53
+#define MCU_LED_3 0x54
+#define MCU_RADAR 0x60
+#define MCU_BOOT_SIGNAL 0x72
+#define MCU_BBP_SIGNAL 0x80
+#define MCU_POWER_SAVE 0x83
+
+/*
+ * MCU mailbox tokens
+ */
+#define TOKEN_WAKUP 3
+
+/*
+ * DMA descriptor defines.
+ */
+#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) )
+#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
+
+/*
+ * TX WI structure
+ */
+
+/*
+ * Word0
+ * FRAG: 1 To inform TKIP engine this is a fragment.
+ * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
+ * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
+ * BW: Channel bandwidth 20MHz or 40 MHz
+ * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
+ */
+#define TXWI_W0_FRAG FIELD32(0x00000001)
+#define TXWI_W0_MIMO_PS FIELD32(0x00000002)
+#define TXWI_W0_CF_ACK FIELD32(0x00000004)
+#define TXWI_W0_TS FIELD32(0x00000008)
+#define TXWI_W0_AMPDU FIELD32(0x00000010)
+#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0)
+#define TXWI_W0_TX_OP FIELD32(0x00000300)
+#define TXWI_W0_MCS FIELD32(0x007f0000)
+#define TXWI_W0_BW FIELD32(0x00800000)
+#define TXWI_W0_SHORT_GI FIELD32(0x01000000)
+#define TXWI_W0_STBC FIELD32(0x06000000)
+#define TXWI_W0_IFS FIELD32(0x08000000)
+#define TXWI_W0_PHYMODE FIELD32(0xc0000000)
+
+/*
+ * Word1
+ */
+#define TXWI_W1_ACK FIELD32(0x00000001)
+#define TXWI_W1_NSEQ FIELD32(0x00000002)
+#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc)
+#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00)
+#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
+#define TXWI_W1_PACKETID FIELD32(0xf0000000)
+
+/*
+ * Word2
+ */
+#define TXWI_W2_IV FIELD32(0xffffffff)
+
+/*
+ * Word3
+ */
+#define TXWI_W3_EIV FIELD32(0xffffffff)
+
+/*
+ * RX WI structure
+ */
+
+/*
+ * Word0
+ */
+#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff)
+#define RXWI_W0_KEY_INDEX FIELD32(0x00000300)
+#define RXWI_W0_BSSID FIELD32(0x00001c00)
+#define RXWI_W0_UDF FIELD32(0x0000e000)
+#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
+#define RXWI_W0_TID FIELD32(0xf0000000)
+
+/*
+ * Word1
+ */
+#define RXWI_W1_FRAG FIELD32(0x0000000f)
+#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0)
+#define RXWI_W1_MCS FIELD32(0x007f0000)
+#define RXWI_W1_BW FIELD32(0x00800000)
+#define RXWI_W1_SHORT_GI FIELD32(0x01000000)
+#define RXWI_W1_STBC FIELD32(0x06000000)
+#define RXWI_W1_PHYMODE FIELD32(0xc0000000)
+
+/*
+ * Word2
+ */
+#define RXWI_W2_RSSI0 FIELD32(0x000000ff)
+#define RXWI_W2_RSSI1 FIELD32(0x0000ff00)
+#define RXWI_W2_RSSI2 FIELD32(0x00ff0000)
+
+/*
+ * Word3
+ */
+#define RXWI_W3_SNR0 FIELD32(0x000000ff)
+#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
+
+/*
+ * Macros for converting txpower from EEPROM to mac80211 value
+ * and from mac80211 value to register value.
+ */
+#define MIN_G_TXPOWER 0
+#define MIN_A_TXPOWER -7
+#define MAX_G_TXPOWER 31
+#define MAX_A_TXPOWER 15
+#define DEFAULT_TXPOWER 5
+
+#define TXPOWER_G_FROM_DEV(__txpower) \
+ ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_G_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
+
+#define TXPOWER_A_FROM_DEV(__txpower) \
+ ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
+
+#define TXPOWER_A_TO_DEV(__txpower) \
+ clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
+
+#endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
new file mode 100644
index 000000000000..5c7d74a6f16e
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -0,0 +1,1817 @@
+/*
+ Copyright (C) 2009 Bartlomiej Zolnierkiewicz
+
+ Based on the original rt2800pci.c and rt2800usb.c:
+
+ Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+ <http://rt2x00.serialmonkey.com>
+
+ 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.
+ */
+
+/*
+ Module: rt2800lib
+ Abstract: rt2800 generic device routines.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "rt2x00.h"
+#ifdef CONFIG_RT2800USB
+#include "rt2x00usb.h"
+#endif
+#include "rt2800lib.h"
+#include "rt2800.h"
+#include "rt2800usb.h"
+
+MODULE_AUTHOR("Bartlomiej Zolnierkiewicz");
+MODULE_DESCRIPTION("rt2800 library");
+MODULE_LICENSE("GPL");
+
+/*
+ * Register access.
+ * All access to the CSR registers will go through the methods
+ * rt2800_register_read and rt2800_register_write.
+ * BBP and RF register require indirect register access,
+ * and use the CSR registers BBPCSR and RFCSR to achieve this.
+ * These indirect registers work with busy bits,
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
+ * the register while taking a REGISTER_BUSY_DELAY us delay
+ * between each attampt. When the busy bit is still set at that time,
+ * the access attempt is considered to have failed,
+ * and we will print an error.
+ * The _lock versions must be used if you already hold the csr_mutex
+ */
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2800_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RFCSR(__dev, __reg) \
+ rt2800_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2800_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+ rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+ H2M_MAILBOX_CSR_OWNER, (__reg))
+
+static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, const u8 value)
+{
+ u32 reg;
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
+ if (rt2x00_intf_is_pci(rt2x00dev))
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+
+ rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, u8 *value)
+{
+ u32 reg;
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
+ */
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
+ if (rt2x00_intf_is_pci(rt2x00dev))
+ rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+
+ rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
+
+ WAIT_FOR_BBP(rt2x00dev, &reg);
+ }
+
+ *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rfcsr_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, const u8 value)
+{
+ u32 reg;
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the RFCSR becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
+ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
+ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rfcsr_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, u8 *value)
+{
+ u32 reg;
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the RFCSR becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
+ */
+ if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
+ rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
+ rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
+
+ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
+
+ WAIT_FOR_RFCSR(rt2x00dev, &reg);
+ }
+
+ *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+static void rt2800_rf_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int word, const u32 value)
+{
+ u32 reg;
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
+ rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
+ rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
+ rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
+
+ rt2800_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
+ const u8 command, const u8 token,
+ const u8 arg0, const u8 arg1)
+{
+ u32 reg;
+
+ if (rt2x00_intf_is_pci(rt2x00dev)) {
+ /*
+ * RT2880 and RT3052 don't support MCU requests.
+ */
+ if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
+ rt2x00_rt(&rt2x00dev->chip, RT3052))
+ return;
+ }
+
+ mutex_lock(&rt2x00dev->csr_mutex);
+
+ /*
+ * Wait until the MCU becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+ rt2800_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+ reg = 0;
+ rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+ rt2800_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
+ }
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
+}
+EXPORT_SYMBOL_GPL(rt2800_mcu_request);
+
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
+const struct rt2x00debug rt2800_rt2x00debug = {
+ .owner = THIS_MODULE,
+ .csr = {
+ .read = rt2800_register_read,
+ .write = rt2800_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
+ .word_size = sizeof(u32),
+ .word_count = CSR_REG_SIZE / sizeof(u32),
+ },
+ .eeprom = {
+ .read = rt2x00_eeprom_read,
+ .write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
+ .word_size = sizeof(u16),
+ .word_count = EEPROM_SIZE / sizeof(u16),
+ },
+ .bbp = {
+ .read = rt2800_bbp_read,
+ .write = rt2800_bbp_write,
+ .word_base = BBP_BASE,
+ .word_size = sizeof(u8),
+ .word_count = BBP_SIZE / sizeof(u8),
+ },
+ .rf = {
+ .read = rt2x00_rf_read,
+ .write = rt2800_rf_write,
+ .word_base = RF_BASE,
+ .word_size = sizeof(u32),
+ .word_count = RF_SIZE / sizeof(u32),
+ },
+};
+EXPORT_SYMBOL_GPL(rt2800_rt2x00debug);
+#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
+
+int rt2800_rfkill_poll(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+ return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
+}
+EXPORT_SYMBOL_GPL(rt2800_rfkill_poll);
+
+#ifdef CONFIG_RT2X00_LIB_LEDS
+static void rt2800_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ struct rt2x00_led *led =
+ container_of(led_cdev, struct rt2x00_led, led_dev);
+ unsigned int enabled = brightness != LED_OFF;
+ unsigned int bg_mode =
+ (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
+ unsigned int polarity =
+ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+ EEPROM_FREQ_LED_POLARITY);
+ unsigned int ledmode =
+ rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
+ EEPROM_FREQ_LED_MODE);
+
+ if (led->type == LED_TYPE_RADIO) {
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+ enabled ? 0x20 : 0);
+ } else if (led->type == LED_TYPE_ASSOC) {
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
+ enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
+ } else if (led->type == LED_TYPE_QUALITY) {
+ /*
+ * The brightness is divided into 6 levels (0 - 5),
+ * The specs tell us the following levels:
+ * 0, 1 ,3, 7, 15, 31
+ * to determine the level in a simple way we can simply
+ * work with bitshifting:
+ * (1 << level) - 1
+ */
+ rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
+ (1 << brightness / (LED_FULL / 6)) - 1,
+ polarity);
+ }
+}
+
+static int rt2800_blink_set(struct led_classdev *led_cdev,
+ unsigned long *delay_on, unsigned long *delay_off)
+{
+ struct rt2x00_led *led =
+ container_of(led_cdev, struct rt2x00_led, led_dev);
+ u32 reg;
+
+ rt2800_register_read(led->rt2x00dev, LED_CFG, &reg);
+ rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
+ rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
+ rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
+ rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
+ rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 12);
+ rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
+ rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
+ rt2800_register_write(led->rt2x00dev, LED_CFG, reg);
+
+ return 0;
+}
+
+void rt2800_init_led(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00_led *led, enum led_type type)
+{
+ led->rt2x00dev = rt2x00dev;
+ led->type = type;
+ led->led_dev.brightness_set = rt2800_brightness_set;
+ led->led_dev.blink_set = rt2800_blink_set;
+ led->flags = LED_INITIALIZED;
+}
+EXPORT_SYMBOL_GPL(rt2800_init_led);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+/*
+ * Configuration handlers.
+ */
+static void rt2800_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct mac_wcid_entry wcid_entry;
+ struct mac_iveiv_entry iveiv_entry;
+ u32 offset;
+ u32 reg;
+
+ offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
+
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
+ !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
+ (crypto->cmd == SET_KEY) * crypto->cipher);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
+ (crypto->cmd == SET_KEY) * crypto->bssidx);
+ rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
+ rt2800_register_write(rt2x00dev, offset, reg);
+
+ offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
+
+ memset(&iveiv_entry, 0, sizeof(iveiv_entry));
+ if ((crypto->cipher == CIPHER_TKIP) ||
+ (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
+ (crypto->cipher == CIPHER_AES))
+ iveiv_entry.iv[3] |= 0x20;
+ iveiv_entry.iv[3] |= key->keyidx << 6;
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
+
+ offset = MAC_WCID_ENTRY(key->hw_key_idx);
+
+ memset(&wcid_entry, 0, sizeof(wcid_entry));
+ if (crypto->cmd == SET_KEY)
+ memcpy(&wcid_entry, crypto->address, ETH_ALEN);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &wcid_entry, sizeof(wcid_entry));
+}
+
+int rt2800_config_shared_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_key_entry key_entry;
+ struct rt2x00_field32 field;
+ u32 offset;
+ u32 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
+
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ offset = SHARED_KEY_ENTRY(key->hw_key_idx);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &key_entry, sizeof(key_entry));
+ }
+
+ /*
+ * The cipher types are stored over multiple registers
+ * starting with SHARED_KEY_MODE_BASE each word will have
+ * 32 bits and contains the cipher types for 2 bssidx each.
+ * Using the correct defines correctly will cause overhead,
+ * so just calculate the correct offset.
+ */
+ field.bit_offset = 4 * (key->hw_key_idx % 8);
+ field.bit_mask = 0x7 << field.bit_offset;
+
+ offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
+
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, field,
+ (crypto->cmd == SET_KEY) * crypto->cipher);
+ rt2800_register_write(rt2x00dev, offset, reg);
+
+ /*
+ * Update WCID information
+ */
+ rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
+
+int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ struct hw_key_entry key_entry;
+ u32 offset;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * 1 pairwise key is possible per AID, this means that the AID
+ * equals our hw_key_idx. Make sure the WCID starts _after_ the
+ * last possible shared key entry.
+ */
+ if (crypto->aid > (256 - 32))
+ return -ENOSPC;
+
+ key->hw_key_idx = 32 + crypto->aid;
+
+ memcpy(key_entry.key, crypto->key,
+ sizeof(key_entry.key));
+ memcpy(key_entry.tx_mic, crypto->tx_mic,
+ sizeof(key_entry.tx_mic));
+ memcpy(key_entry.rx_mic, crypto->rx_mic,
+ sizeof(key_entry.rx_mic));
+
+ offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
+ rt2800_register_multiwrite(rt2x00dev, offset,
+ &key_entry, sizeof(key_entry));
+ }
+
+ /*
+ * Update WCID information
+ */
+ rt2800_config_wcid_attr(rt2x00dev, crypto, key);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_config_pairwise_key);
+
+void rt2800_config_filter(struct rt2x00_dev *rt2x00dev,
+ const unsigned int filter_flags)
+{
+ u32 reg;
+
+ /*
+ * Start configuration steps.
+ * Note that the version error will always be dropped
+ * and broadcast frames will always be accepted since
+ * there is no filter for it at this time.
+ */
+ rt2800_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
+ !(filter_flags & FIF_FCSFAIL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
+ !(filter_flags & FIF_PLCPFAIL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME,
+ !(filter_flags & FIF_PROMISC_IN_BSS));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
+ !(filter_flags & FIF_ALLMULTI));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
+ !(filter_flags & FIF_CONTROL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
+ !(filter_flags & FIF_CONTROL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
+ !(filter_flags & FIF_CONTROL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
+ !(filter_flags & FIF_CONTROL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
+ !(filter_flags & FIF_CONTROL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
+ !(filter_flags & FIF_PSPOLL));
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
+ rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
+ !(filter_flags & FIF_CONTROL));
+ rt2800_register_write(rt2x00dev, RX_FILTER_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_config_filter);
+
+void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
+ struct rt2x00intf_conf *conf, const unsigned int flags)
+{
+ unsigned int beacon_base;
+ u32 reg;
+
+ if (flags & CONFIG_UPDATE_TYPE) {
+ /*
+ * Clear current synchronisation setup.
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
+ rt2800_register_write(rt2x00dev, beacon_base, 0);
+
+ /*
+ * Enable synchronisation.
+ */
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ }
+
+ if (flags & CONFIG_UPDATE_MAC) {
+ reg = le32_to_cpu(conf->mac[1]);
+ rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
+ conf->mac[1] = cpu_to_le32(reg);
+
+ rt2800_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
+ conf->mac, sizeof(conf->mac));
+ }
+
+ if (flags & CONFIG_UPDATE_BSSID) {
+ reg = le32_to_cpu(conf->bssid[1]);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
+ rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
+ conf->bssid[1] = cpu_to_le32(reg);
+
+ rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
+ conf->bssid, sizeof(conf->bssid));
+ }
+}
+EXPORT_SYMBOL_GPL(rt2800_config_intf);
+
+void rt2800_config_erp(struct rt2x00_dev *rt2x00dev, struct rt2x00lib_erp *erp)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20);
+ rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
+ !!erp->short_preamble);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
+ !!erp->short_preamble);
+ rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
+ erp->cts_protection ? 2 : 0);
+ rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE,
+ erp->basic_rates);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+ rt2800_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
+ rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
+ rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
+ rt2800_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
+ rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
+ rt2800_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
+ erp->beacon_int * 16);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_config_erp);
+
+void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
+{
+ u8 r1;
+ u8 r3;
+
+ rt2800_bbp_read(rt2x00dev, 1, &r1);
+ rt2800_bbp_read(rt2x00dev, 3, &r3);
+
+ /*
+ * Configure the TX antenna.
+ */
+ switch ((int)ant->tx) {
+ case 1:
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
+ if (rt2x00_intf_is_pci(rt2x00dev))
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
+ break;
+ case 2:
+ rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
+ break;
+ case 3:
+ /* Do nothing */
+ break;
+ }
+
+ /*
+ * Configure the RX antenna.
+ */
+ switch ((int)ant->rx) {
+ case 1:
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
+ break;
+ case 2:
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
+ break;
+ case 3:
+ rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
+ break;
+ }
+
+ rt2800_bbp_write(rt2x00dev, 3, r3);
+ rt2800_bbp_write(rt2x00dev, 1, r1);
+}
+EXPORT_SYMBOL_GPL(rt2800_config_ant);
+
+static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u16 eeprom;
+ short lna_gain;
+
+ if (libconf->rf.channel <= 14) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
+ } else if (libconf->rf.channel <= 64) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
+ } else if (libconf->rf.channel <= 128) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
+ } else {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
+ lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
+ }
+
+ rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt2800_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+ if (rt2x00dev->default_ant.tx == 1)
+ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
+
+ if (rt2x00dev->default_ant.rx == 1) {
+ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
+ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+ } else if (rt2x00dev->default_ant.rx == 2)
+ rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
+
+ if (rf->channel > 14) {
+ /*
+ * When TX power is below 0, we should increase it by 7 to
+ * make it a positive value (Minumum value is -7).
+ * However this means that values between 0 and 7 have
+ * double meaning, and we should set a 7DBm boost flag.
+ */
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
+ (info->tx_power1 >= 0));
+
+ if (info->tx_power1 < 0)
+ info->tx_power1 += 7;
+
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
+ TXPOWER_A_TO_DEV(info->tx_power1));
+
+ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
+ (info->tx_power2 >= 0));
+
+ if (info->tx_power2 < 0)
+ info->tx_power2 += 7;
+
+ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
+ TXPOWER_A_TO_DEV(info->tx_power2));
+ } else {
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
+ TXPOWER_G_TO_DEV(info->tx_power1));
+ rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
+ TXPOWER_G_TO_DEV(info->tx_power2));
+ }
+
+ rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
+
+ rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+
+ udelay(200);
+
+ rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2800_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+ rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+
+ udelay(200);
+
+ rt2800_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2800_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2800_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt2800_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u8 rfcsr;
+
+ rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
+ rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3);
+
+ rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
+ rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
+ TXPOWER_G_TO_DEV(info->tx_power1));
+ rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
+
+ rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
+ rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+
+ rt2800_rfcsr_write(rt2x00dev, 24,
+ rt2x00dev->calibration[conf_is_ht40(conf)]);
+
+ rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
+ rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
+}
+
+static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct ieee80211_conf *conf,
+ struct rf_channel *rf,
+ struct channel_info *info)
+{
+ u32 reg;
+ unsigned int tx_pin;
+ u8 bbp;
+
+ if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
+ rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
+ else
+ rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
+
+ /*
+ * Change BBP settings
+ */
+ rt2800_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
+ rt2800_bbp_write(rt2x00dev, 86, 0);
+
+ if (rf->channel <= 14) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
+ rt2800_bbp_write(rt2x00dev, 75, 0x46);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 82, 0x84);
+ rt2800_bbp_write(rt2x00dev, 75, 0x50);
+ }
+ } else {
+ rt2800_bbp_write(rt2x00dev, 82, 0xf2);
+
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ rt2800_bbp_write(rt2x00dev, 75, 0x46);
+ else
+ rt2800_bbp_write(rt2x00dev, 75, 0x50);
+ }
+
+ rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
+ rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
+ rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
+ rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
+
+ tx_pin = 0;
+
+ /* Turn on unused PA or LNA when not using 1T or 1R */
+ if (rt2x00dev->default_ant.tx != 1) {
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
+ }
+
+ /* Turn on unused PA or LNA when not using 1T or 1R */
+ if (rt2x00dev->default_ant.rx != 1) {
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
+ }
+
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
+ rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
+
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
+
+ rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+
+ rt2800_bbp_read(rt2x00dev, 3, &bbp);
+ rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
+ rt2800_bbp_write(rt2x00dev, 3, bbp);
+
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
+ if (conf_is_ht40(conf)) {
+ rt2800_bbp_write(rt2x00dev, 69, 0x1a);
+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+ rt2800_bbp_write(rt2x00dev, 73, 0x16);
+ } else {
+ rt2800_bbp_write(rt2x00dev, 69, 0x16);
+ rt2800_bbp_write(rt2x00dev, 70, 0x08);
+ rt2800_bbp_write(rt2x00dev, 73, 0x11);
+ }
+ }
+
+ msleep(1);
+}
+
+static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
+ const int txpower)
+{
+ u32 reg;
+ u32 value = TXPOWER_G_TO_DEV(txpower);
+ u8 r1;
+
+ rt2800_bbp_read(rt2x00dev, 1, &r1);
+ rt2x00_set_field8(&reg, BBP1_TX_POWER, 0);
+ rt2800_bbp_write(rt2x00dev, 1, r1);
+
+ rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_1MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_2MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_55MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_11MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_6MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_9MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_12MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_0_18MBS, value);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_0, reg);
+
+ rt2800_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_24MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_36MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_48MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_54MBS, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS0, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS1, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS2, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS3, value);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_1, reg);
+
+ rt2800_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS4, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS5, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS6, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS7, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS8, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS9, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS10, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS11, value);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_2, reg);
+
+ rt2800_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS12, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS13, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS14, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS15, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN1, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN2, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN3, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN4, value);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_3, reg);
+
+ rt2800_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN5, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN6, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN7, value);
+ rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN8, value);
+ rt2800_register_write(rt2x00dev, TX_PWR_CFG_4, reg);
+}
+
+static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, TX_RTY_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
+ libconf->conf->short_frame_max_tx_count);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
+ libconf->conf->long_frame_max_tx_count);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
+ rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
+ rt2800_register_write(rt2x00dev, TX_RTY_CFG, reg);
+}
+
+static void rt2800_config_ps(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ enum dev_state state =
+ (libconf->conf->flags & IEEE80211_CONF_PS) ?
+ STATE_SLEEP : STATE_AWAKE;
+ u32 reg;
+
+ if (state == STATE_SLEEP) {
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
+
+ rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
+ libconf->conf->listen_interval - 1);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+ } else {
+ rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
+
+ rt2800_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
+ rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
+ }
+}
+
+void rt2800_config(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf,
+ const unsigned int flags)
+{
+ /* Always recalculate LNA gain before changing configuration */
+ rt2800_config_lna_gain(rt2x00dev, libconf);
+
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+ rt2800_config_channel(rt2x00dev, libconf->conf,
+ &libconf->rf, &libconf->channel);
+ if (flags & IEEE80211_CONF_CHANGE_POWER)
+ rt2800_config_txpower(rt2x00dev, libconf->conf->power_level);
+ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ rt2800_config_retry_limit(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_PS)
+ rt2800_config_ps(rt2x00dev, libconf);
+}
+EXPORT_SYMBOL_GPL(rt2800_config);
+
+/*
+ * Link tuning
+ */
+void rt2800_link_stats(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
+{
+ u32 reg;
+
+ /*
+ * Update FCS error count from register.
+ */
+ rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+ qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
+}
+EXPORT_SYMBOL_GPL(rt2800_link_stats);
+
+static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev)
+{
+ if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
+ return 0x1c + (2 * rt2x00dev->lna_gain);
+ else
+ return 0x2e + rt2x00dev->lna_gain;
+ }
+
+ if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+ return 0x32 + (rt2x00dev->lna_gain * 5) / 3;
+ else
+ return 0x3a + (rt2x00dev->lna_gain * 5) / 3;
+}
+
+static inline void rt2800_set_vgc(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual, u8 vgc_level)
+{
+ if (qual->vgc_level != vgc_level) {
+ rt2800_bbp_write(rt2x00dev, 66, vgc_level);
+ qual->vgc_level = vgc_level;
+ qual->vgc_level_reg = vgc_level;
+ }
+}
+
+void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual)
+{
+ rt2800_set_vgc(rt2x00dev, qual, rt2800_get_default_vgc(rt2x00dev));
+}
+EXPORT_SYMBOL_GPL(rt2800_reset_tuner);
+
+void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
+ const u32 count)
+{
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
+ return;
+
+ /*
+ * When RSSI is better then -80 increase VGC level with 0x10
+ */
+ rt2800_set_vgc(rt2x00dev, qual,
+ rt2800_get_default_vgc(rt2x00dev) +
+ ((qual->rssi > -80) * 0x10));
+}
+EXPORT_SYMBOL_GPL(rt2800_link_tuner);
+
+/*
+ * Initialization functions.
+ */
+int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
+{
+ u32 reg;
+ unsigned int i;
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ /*
+ * Wait untill BBP and RF are ready.
+ */
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+ if (reg && reg != ~0)
+ break;
+ msleep(1);
+ }
+
+ if (i == REGISTER_BUSY_COUNT) {
+ ERROR(rt2x00dev, "Unstable hardware.\n");
+ return -EBUSY;
+ }
+
+ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL,
+ reg & ~0x00002000);
+ } else if (rt2x00_intf_is_pci(rt2x00dev))
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
+ rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
+#ifdef CONFIG_RT2800USB
+ rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
+ USB_MODE_RESET, REGISTER_TIMEOUT);
+#endif
+ }
+
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+ rt2800_register_read(rt2x00dev, BCN_OFFSET0, &reg);
+ rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */
+ rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */
+ rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */
+ rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */
+ rt2800_register_write(rt2x00dev, BCN_OFFSET0, reg);
+
+ rt2800_register_read(rt2x00dev, BCN_OFFSET1, &reg);
+ rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */
+ rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */
+ rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */
+ rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */
+ rt2800_register_write(rt2x00dev, BCN_OFFSET1, reg);
+
+ rt2800_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
+ rt2800_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
+
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
+
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 0);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+ rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
+ } else {
+ rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
+ rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+ }
+
+ rt2800_register_read(rt2x00dev, TX_LINK_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
+ rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
+ rt2800_register_write(rt2x00dev, TX_LINK_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
+ rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
+ rt2800_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
+ if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
+ rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
+ else
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
+ rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
+ rt2800_register_write(rt2x00dev, MAX_LEN_CFG, reg);
+
+ rt2800_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
+
+ rt2800_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
+ rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
+ rt2800_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 8);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+ rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 8);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+ rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+ rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+ rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
+ rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
+ rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
+ rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ }
+
+ rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
+ rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
+
+ rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
+ IEEE80211_MAX_RTS_THRESHOLD);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
+ rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+ rt2800_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
+
+ /*
+ * ASIC will keep garbage value after boot, clear encryption keys.
+ */
+ for (i = 0; i < 4; i++)
+ rt2800_register_write(rt2x00dev,
+ SHARED_KEY_MODE_ENTRY(i), 0);
+
+ for (i = 0; i < 256; i++) {
+ u32 wcid[2] = { 0xffffffff, 0x00ffffff };
+ rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
+ wcid, sizeof(wcid));
+
+ rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
+ rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
+ }
+
+ /*
+ * Clear all beacons
+ * For the Beacon base registers we only need to clear
+ * the first byte since that byte contains the VALID and OWNER
+ * bits which (when set to 0) will invalidate the entire beacon.
+ */
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
+ rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ rt2800_register_read(rt2x00dev, USB_CYC_CFG, &reg);
+ rt2x00_set_field32(&reg, USB_CYC_CFG_CLOCK_CYCLE, 30);
+ rt2800_register_write(rt2x00dev, USB_CYC_CFG, reg);
+ }
+
+ rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
+ rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
+ rt2800_register_write(rt2x00dev, HT_FBK_CFG0, reg);
+
+ rt2800_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
+ rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
+ rt2800_register_write(rt2x00dev, HT_FBK_CFG1, reg);
+
+ rt2800_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
+ rt2800_register_write(rt2x00dev, LG_FBK_CFG0, reg);
+
+ rt2800_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
+ rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
+ rt2800_register_write(rt2x00dev, LG_FBK_CFG1, reg);
+
+ /*
+ * We must clear the error counters.
+ * These registers are cleared on read,
+ * so we may pass a useless variable to store the value.
+ */
+ rt2800_register_read(rt2x00dev, RX_STA_CNT0, &reg);
+ rt2800_register_read(rt2x00dev, RX_STA_CNT1, &reg);
+ rt2800_register_read(rt2x00dev, RX_STA_CNT2, &reg);
+ rt2800_register_read(rt2x00dev, TX_STA_CNT0, &reg);
+ rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
+ rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_init_registers);
+
+static int rt2800_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i;
+ u32 reg;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
+ if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
+ return 0;
+
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
+ return -EACCES;
+}
+
+static int rt2800_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i;
+ u8 value;
+
+ /*
+ * BBP was enabled after firmware was loaded,
+ * but we need to reactivate it now.
+ */
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ msleep(1);
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2800_bbp_read(rt2x00dev, 0, &value);
+ if ((value != 0xff) && (value != 0x00))
+ return 0;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
+ return -EACCES;
+}
+
+int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
+{
+ unsigned int i;
+ u16 eeprom;
+ u8 reg_id;
+ u8 value;
+
+ if (unlikely(rt2800_wait_bbp_rf_ready(rt2x00dev) ||
+ rt2800_wait_bbp_ready(rt2x00dev)))
+ return -EACCES;
+
+ rt2800_bbp_write(rt2x00dev, 65, 0x2c);
+ rt2800_bbp_write(rt2x00dev, 66, 0x38);
+ rt2800_bbp_write(rt2x00dev, 69, 0x12);
+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+ rt2800_bbp_write(rt2x00dev, 73, 0x10);
+ rt2800_bbp_write(rt2x00dev, 81, 0x37);
+ rt2800_bbp_write(rt2x00dev, 82, 0x62);
+ rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+ rt2800_bbp_write(rt2x00dev, 84, 0x99);
+ rt2800_bbp_write(rt2x00dev, 86, 0x00);
+ rt2800_bbp_write(rt2x00dev, 91, 0x04);
+ rt2800_bbp_write(rt2x00dev, 92, 0x00);
+ rt2800_bbp_write(rt2x00dev, 103, 0x00);
+ rt2800_bbp_write(rt2x00dev, 105, 0x05);
+
+ if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
+ rt2800_bbp_write(rt2x00dev, 69, 0x16);
+ rt2800_bbp_write(rt2x00dev, 73, 0x12);
+ }
+
+ if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION)
+ rt2800_bbp_write(rt2x00dev, 84, 0x19);
+
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
+ rt2800_bbp_write(rt2x00dev, 70, 0x0a);
+ rt2800_bbp_write(rt2x00dev, 84, 0x99);
+ rt2800_bbp_write(rt2x00dev, 105, 0x05);
+ }
+
+ if (rt2x00_intf_is_pci(rt2x00dev) &&
+ rt2x00_rt(&rt2x00dev->chip, RT3052)) {
+ rt2800_bbp_write(rt2x00dev, 31, 0x08);
+ rt2800_bbp_write(rt2x00dev, 78, 0x0e);
+ rt2800_bbp_write(rt2x00dev, 80, 0x08);
+ }
+
+ for (i = 0; i < EEPROM_BBP_SIZE; i++) {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
+
+ if (eeprom != 0xffff && eeprom != 0x0000) {
+ reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
+ value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
+ rt2800_bbp_write(rt2x00dev, reg_id, value);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_init_bbp);
+
+static u8 rt2800_init_rx_filter(struct rt2x00_dev *rt2x00dev,
+ bool bw40, u8 rfcsr24, u8 filter_target)
+{
+ unsigned int i;
+ u8 bbp;
+ u8 rfcsr;
+ u8 passband;
+ u8 stopband;
+ u8 overtuned = 0;
+
+ rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+
+ rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+
+ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+ /*
+ * Set power & frequency of passband test tone
+ */
+ rt2800_bbp_write(rt2x00dev, 24, 0);
+
+ for (i = 0; i < 100; i++) {
+ rt2800_bbp_write(rt2x00dev, 25, 0x90);
+ msleep(1);
+
+ rt2800_bbp_read(rt2x00dev, 55, &passband);
+ if (passband)
+ break;
+ }
+
+ /*
+ * Set power & frequency of stopband test tone
+ */
+ rt2800_bbp_write(rt2x00dev, 24, 0x06);
+
+ for (i = 0; i < 100; i++) {
+ rt2800_bbp_write(rt2x00dev, 25, 0x90);
+ msleep(1);
+
+ rt2800_bbp_read(rt2x00dev, 55, &stopband);
+
+ if ((passband - stopband) <= filter_target) {
+ rfcsr24++;
+ overtuned += ((passband - stopband) == filter_target);
+ } else
+ break;
+
+ rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+ }
+
+ rfcsr24 -= !!overtuned;
+
+ rt2800_rfcsr_write(rt2x00dev, 24, rfcsr24);
+ return rfcsr24;
+}
+
+int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
+{
+ u8 rfcsr;
+ u8 bbp;
+
+ if (rt2x00_intf_is_usb(rt2x00dev) &&
+ rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
+ return 0;
+
+ if (rt2x00_intf_is_pci(rt2x00dev)) {
+ if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
+ !rt2x00_rf(&rt2x00dev->chip, RF3022))
+ return 0;
+ }
+
+ /*
+ * Init RF calibration.
+ */
+ rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+ msleep(1);
+ rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
+ rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+ if (rt2x00_intf_is_usb(rt2x00dev)) {
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x70);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0x71);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x7b);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x16);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x1f);
+ } else if (rt2x00_intf_is_pci(rt2x00dev)) {
+ rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
+ rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
+ rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
+ rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+ rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
+ rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
+ rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
+ rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
+ rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
+ rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+ rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
+ rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
+ rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+ rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
+ rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
+ rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
+ rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
+ rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+ rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
+ rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+ rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+ rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
+ rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
+ rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+ rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
+ rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
+ rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
+ rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
+ }
+
+ /*
+ * Set RX Filter calibration for 20MHz and 40MHz
+ */
+ rt2x00dev->calibration[0] =
+ rt2800_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
+ rt2x00dev->calibration[1] =
+ rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
+
+ /*
+ * Set back to initial state
+ */
+ rt2800_bbp_write(rt2x00dev, 24, 0);
+
+ rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+ rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+ rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+
+ /*
+ * set BBP back to BW20
+ */
+ rt2800_bbp_read(rt2x00dev, 4, &bbp);
+ rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+ rt2800_bbp_write(rt2x00dev, 4, bbp);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
+
+/*
+ * IEEE80211 stack callback functions.
+ */
+static void rt2800_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
+ u32 *iv32, u16 *iv16)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct mac_iveiv_entry iveiv_entry;
+ u32 offset;
+
+ offset = MAC_IVEIV_ENTRY(hw_key_idx);
+ rt2800_register_multiread(rt2x00dev, offset,
+ &iveiv_entry, sizeof(iveiv_entry));
+
+ memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16));
+ memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32));
+}
+
+static int rt2800_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ u32 reg;
+ bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
+
+ rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
+ rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
+ rt2800_register_write(rt2x00dev, TX_RTS_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, CCK_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, MM20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, MM40_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, GF20_PROT_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
+ rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
+ rt2800_register_write(rt2x00dev, GF40_PROT_CFG, reg);
+
+ return 0;
+}
+
+static int rt2800_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct data_queue *queue;
+ struct rt2x00_field32 field;
+ int retval;
+ u32 reg;
+ u32 offset;
+
+ /*
+ * First pass the configuration through rt2x00lib, that will
+ * update the queue settings and validate the input. After that
+ * we are free to update the registers based on the value
+ * in the queue parameter.
+ */
+ retval = rt2x00mac_conf_tx(hw, queue_idx, params);
+ if (retval)
+ return retval;
+
+ /*
+ * We only need to perform additional register initialization
+ * for WMM queues/
+ */
+ if (queue_idx >= 4)
+ return 0;
+
+ queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+
+ /* Update WMM TXOP register */
+ offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
+ field.bit_offset = (queue_idx & 1) * 16;
+ field.bit_mask = 0xffff << field.bit_offset;
+
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, field, queue->txop);
+ rt2800_register_write(rt2x00dev, offset, reg);
+
+ /* Update WMM registers */
+ field.bit_offset = queue_idx * 4;
+ field.bit_mask = 0xf << field.bit_offset;
+
+ rt2800_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
+ rt2x00_set_field32(&reg, field, queue->aifs);
+ rt2800_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_min);
+ rt2800_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
+
+ rt2800_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
+ rt2x00_set_field32(&reg, field, queue->cw_max);
+ rt2800_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
+
+ /* Update EDCA registers */
+ offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
+
+ rt2800_register_read(rt2x00dev, offset, &reg);
+ rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
+ rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
+ rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
+ rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
+ rt2800_register_write(rt2x00dev, offset, reg);
+
+ return 0;
+}
+
+static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
+{
+ struct rt2x00_dev *rt2x00dev = hw->priv;
+ u64 tsf;
+ u32 reg;
+
+ rt2800_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
+ tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
+ rt2800_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
+ tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
+
+ return tsf;
+}
+
+const struct ieee80211_ops rt2800_mac80211_ops = {
+ .tx = rt2x00mac_tx,
+ .start = rt2x00mac_start,
+ .stop = rt2x00mac_stop,
+ .add_interface = rt2x00mac_add_interface,
+ .remove_interface = rt2x00mac_remove_interface,
+ .config = rt2x00mac_config,
+ .configure_filter = rt2x00mac_configure_filter,
+ .set_tim = rt2x00mac_set_tim,
+ .set_key = rt2x00mac_set_key,
+ .get_stats = rt2x00mac_get_stats,
+ .get_tkip_seq = rt2800_get_tkip_seq,
+ .set_rts_threshold = rt2800_set_rts_threshold,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
+ .conf_tx = rt2800_conf_tx,
+ .get_tx_stats = rt2x00mac_get_tx_stats,
+ .get_tsf = rt2800_get_tsf,
+ .rfkill_poll = rt2x00mac_rfkill_poll,
+};
+EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
new file mode 100644
index 000000000000..5eea8fcba6cc
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -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 */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index be81788b80c7..3c5b875cdee8 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -37,6 +37,8 @@
#include "rt2x00.h"
#include "rt2x00pci.h"
#include "rt2x00soc.h"
+#include "rt2800lib.h"
+#include "rt2800.h"
#include "rt2800pci.h"
#ifdef CONFIG_RT2800PCI_PCI_MODULE
@@ -54,205 +56,13 @@ static int modparam_nohwcrypt = 1;
module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
-/*
- * Register access.
- * BBP and RF register require indirect register access,
- * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RFCSR(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
-#define WAIT_FOR_MCU(__dev, __reg) \
- rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
- H2M_MAILBOX_CSR_OWNER, (__reg))
-
-static void rt2800pci_bbp_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u8 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the BBP becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
-
- rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800pci_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the BBP becomes available, afterwards we
- * can safely write the read request into the register.
- * After the data has been written, we wait until hardware
- * returns the correct value, if at any time the register
- * doesn't become available in time, reg will be 0xffffffff
- * which means we return 0xff to the caller.
- */
- if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
-
- rt2x00pci_register_write(rt2x00dev, BBP_CSR_CFG, reg);
-
- WAIT_FOR_BBP(rt2x00dev, &reg);
- }
-
- *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800pci_rfcsr_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u8 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RFCSR becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
- rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800pci_rfcsr_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RFCSR becomes available, afterwards we
- * can safely write the read request into the register.
- * After the data has been written, we wait until hardware
- * returns the correct value, if at any time the register
- * doesn't become available in time, reg will be 0xffffffff
- * which means we return 0xff to the caller.
- */
- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
- rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG, reg);
-
- WAIT_FOR_RFCSR(rt2x00dev, &reg);
- }
-
- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800pci_rf_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u32 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RF becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_RF(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
-
- rt2x00pci_register_write(rt2x00dev, RF_CSR_CFG0, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800pci_mcu_request(struct rt2x00_dev *rt2x00dev,
- const u8 command, const u8 token,
- const u8 arg0, const u8 arg1)
-{
- u32 reg;
-
- /*
- * RT2880 and RT3052 don't support MCU requests.
- */
- if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
- rt2x00_rt(&rt2x00dev->chip, RT3052))
- return;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the MCU becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
-
- reg = 0;
- rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
{
unsigned int i;
u32 reg;
for (i = 0; i < 200; i++) {
- rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
+ rt2800_register_read(rt2x00dev, H2M_MAILBOX_CID, &reg);
if ((rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD0) == token) ||
(rt2x00_get_field32(reg, H2M_MAILBOX_CID_CMD1) == token) ||
@@ -266,8 +76,8 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
if (i == 200)
ERROR(rt2x00dev, "MCU request failed, no response from hardware\n");
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
}
#ifdef CONFIG_RT2800PCI_WISOC
@@ -289,7 +99,7 @@ static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
struct rt2x00_dev *rt2x00dev = eeprom->data;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN);
eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT);
@@ -311,7 +121,7 @@ static void rt2800pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
rt2x00_set_field32(&reg, E2PROM_CSR_CHIP_SELECT,
!!eeprom->reg_chip_select);
- rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg);
+ rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
}
static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
@@ -319,7 +129,7 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
struct eeprom_93cx6 eeprom;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, &reg);
+ rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
eeprom.data = rt2x00dev;
eeprom.register_read = rt2800pci_eepromregister_read;
@@ -340,23 +150,23 @@ static void rt2800pci_efuse_read(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
- rt2x00pci_register_write(rt2x00dev, EFUSE_CTRL, reg);
+ rt2800_register_write(rt2x00dev, EFUSE_CTRL, reg);
/* Wait until the EEPROM has been loaded */
- rt2x00pci_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
+ rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
/* Apparently the data is read from end to start */
- rt2x00pci_register_read(rt2x00dev, EFUSE_DATA3,
+ rt2800_register_read(rt2x00dev, EFUSE_DATA3,
(u32 *)&rt2x00dev->eeprom[i]);
- rt2x00pci_register_read(rt2x00dev, EFUSE_DATA2,
+ rt2800_register_read(rt2x00dev, EFUSE_DATA2,
(u32 *)&rt2x00dev->eeprom[i + 2]);
- rt2x00pci_register_read(rt2x00dev, EFUSE_DATA1,
+ rt2800_register_read(rt2x00dev, EFUSE_DATA1,
(u32 *)&rt2x00dev->eeprom[i + 4]);
- rt2x00pci_register_read(rt2x00dev, EFUSE_DATA0,
+ rt2800_register_read(rt2x00dev, EFUSE_DATA0,
(u32 *)&rt2x00dev->eeprom[i + 6]);
}
@@ -377,829 +187,6 @@ static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
}
#endif /* CONFIG_RT2800PCI_PCI */
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt2800pci_rt2x00debug = {
- .owner = THIS_MODULE,
- .csr = {
- .read = rt2x00pci_register_read,
- .write = rt2x00pci_register_write,
- .flags = RT2X00DEBUGFS_OFFSET,
- .word_base = CSR_REG_BASE,
- .word_size = sizeof(u32),
- .word_count = CSR_REG_SIZE / sizeof(u32),
- },
- .eeprom = {
- .read = rt2x00_eeprom_read,
- .write = rt2x00_eeprom_write,
- .word_base = EEPROM_BASE,
- .word_size = sizeof(u16),
- .word_count = EEPROM_SIZE / sizeof(u16),
- },
- .bbp = {
- .read = rt2800pci_bbp_read,
- .write = rt2800pci_bbp_write,
- .word_base = BBP_BASE,
- .word_size = sizeof(u8),
- .word_count = BBP_SIZE / sizeof(u8),
- },
- .rf = {
- .read = rt2x00_rf_read,
- .write = rt2800pci_rf_write,
- .word_base = RF_BASE,
- .word_size = sizeof(u32),
- .word_count = RF_SIZE / sizeof(u32),
- },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt2800pci_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
- return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2800pci_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- unsigned int enabled = brightness != LED_OFF;
- unsigned int bg_mode =
- (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
- unsigned int polarity =
- rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
- EEPROM_FREQ_LED_POLARITY);
- unsigned int ledmode =
- rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
- EEPROM_FREQ_LED_MODE);
-
- if (led->type == LED_TYPE_RADIO) {
- rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? 0x20 : 0);
- } else if (led->type == LED_TYPE_ASSOC) {
- rt2800pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
- } else if (led->type == LED_TYPE_QUALITY) {
- /*
- * The brightness is divided into 6 levels (0 - 5),
- * The specs tell us the following levels:
- * 0, 1 ,3, 7, 15, 31
- * to determine the level in a simple way we can simply
- * work with bitshifting:
- * (1 << level) - 1
- */
- rt2800pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
- (1 << brightness / (LED_FULL / 6)) - 1,
- polarity);
- }
-}
-
-static int rt2800pci_blink_set(struct led_classdev *led_cdev,
- unsigned long *delay_on,
- unsigned long *delay_off)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- u32 reg;
-
- rt2x00pci_register_read(led->rt2x00dev, LED_CFG, &reg);
- rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
- rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
- rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
- rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
- rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 12);
- rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
- rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
- rt2x00pci_register_write(led->rt2x00dev, LED_CFG, reg);
-
- return 0;
-}
-
-static void rt2800pci_init_led(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_led *led,
- enum led_type type)
-{
- led->rt2x00dev = rt2x00dev;
- led->type = type;
- led->led_dev.brightness_set = rt2800pci_brightness_set;
- led->led_dev.blink_set = rt2800pci_blink_set;
- led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static void rt2800pci_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct mac_wcid_entry wcid_entry;
- struct mac_iveiv_entry iveiv_entry;
- u32 offset;
- u32 reg;
-
- offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
-
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
- !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
- (crypto->cmd == SET_KEY) * crypto->cipher);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
- (crypto->cmd == SET_KEY) * crypto->bssidx);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
-
- offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
-
- memset(&iveiv_entry, 0, sizeof(iveiv_entry));
- if ((crypto->cipher == CIPHER_TKIP) ||
- (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
- (crypto->cipher == CIPHER_AES))
- iveiv_entry.iv[3] |= 0x20;
- iveiv_entry.iv[3] |= key->keyidx << 6;
- rt2x00pci_register_multiwrite(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
-
- offset = MAC_WCID_ENTRY(key->hw_key_idx);
-
- memset(&wcid_entry, 0, sizeof(wcid_entry));
- if (crypto->cmd == SET_KEY)
- memcpy(&wcid_entry, crypto->address, ETH_ALEN);
- rt2x00pci_register_multiwrite(rt2x00dev, offset,
- &wcid_entry, sizeof(wcid_entry));
-}
-
-static int rt2800pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct hw_key_entry key_entry;
- struct rt2x00_field32 field;
- u32 offset;
- u32 reg;
-
- if (crypto->cmd == SET_KEY) {
- key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
-
- memcpy(key_entry.key, crypto->key,
- sizeof(key_entry.key));
- memcpy(key_entry.tx_mic, crypto->tx_mic,
- sizeof(key_entry.tx_mic));
- memcpy(key_entry.rx_mic, crypto->rx_mic,
- sizeof(key_entry.rx_mic));
-
- offset = SHARED_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, offset,
- &key_entry, sizeof(key_entry));
- }
-
- /*
- * The cipher types are stored over multiple registers
- * starting with SHARED_KEY_MODE_BASE each word will have
- * 32 bits and contains the cipher types for 2 bssidx each.
- * Using the correct defines correctly will cause overhead,
- * so just calculate the correct offset.
- */
- field.bit_offset = 4 * (key->hw_key_idx % 8);
- field.bit_mask = 0x7 << field.bit_offset;
-
- offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
-
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, field,
- (crypto->cmd == SET_KEY) * crypto->cipher);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
-
- /*
- * Update WCID information
- */
- rt2800pci_config_wcid_attr(rt2x00dev, crypto, key);
-
- return 0;
-}
-
-static int rt2800pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct hw_key_entry key_entry;
- u32 offset;
-
- if (crypto->cmd == SET_KEY) {
- /*
- * 1 pairwise key is possible per AID, this means that the AID
- * equals our hw_key_idx. Make sure the WCID starts _after_ the
- * last possible shared key entry.
- */
- if (crypto->aid > (256 - 32))
- return -ENOSPC;
-
- key->hw_key_idx = 32 + crypto->aid;
-
-
- memcpy(key_entry.key, crypto->key,
- sizeof(key_entry.key));
- memcpy(key_entry.tx_mic, crypto->tx_mic,
- sizeof(key_entry.tx_mic));
- memcpy(key_entry.rx_mic, crypto->rx_mic,
- sizeof(key_entry.rx_mic));
-
- offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
- rt2x00pci_register_multiwrite(rt2x00dev, offset,
- &key_entry, sizeof(key_entry));
- }
-
- /*
- * Update WCID information
- */
- rt2800pci_config_wcid_attr(rt2x00dev, crypto, key);
-
- return 0;
-}
-
-static void rt2800pci_config_filter(struct rt2x00_dev *rt2x00dev,
- const unsigned int filter_flags)
-{
- u32 reg;
-
- /*
- * Start configuration steps.
- * Note that the version error will always be dropped
- * and broadcast frames will always be accepted since
- * there is no filter for it at this time.
- */
- rt2x00pci_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
- !(filter_flags & FIF_FCSFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
- !(filter_flags & FIF_PLCPFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME,
- !(filter_flags & FIF_PROMISC_IN_BSS));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
- !(filter_flags & FIF_ALLMULTI));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
- !(filter_flags & FIF_PSPOLL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
- !(filter_flags & FIF_CONTROL));
- rt2x00pci_register_write(rt2x00dev, RX_FILTER_CFG, reg);
-}
-
-static void rt2800pci_config_intf(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_intf *intf,
- struct rt2x00intf_conf *conf,
- const unsigned int flags)
-{
- unsigned int beacon_base;
- u32 reg;
-
- if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
- rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
-
- /*
- * Enable synchronisation.
- */
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- }
-
- if (flags & CONFIG_UPDATE_MAC) {
- reg = le32_to_cpu(conf->mac[1]);
- rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
- conf->mac[1] = cpu_to_le32(reg);
-
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
- conf->mac, sizeof(conf->mac));
- }
-
- if (flags & CONFIG_UPDATE_BSSID) {
- reg = le32_to_cpu(conf->bssid[1]);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
- conf->bssid[1] = cpu_to_le32(reg);
-
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
- conf->bssid, sizeof(conf->bssid));
- }
-}
-
-static void rt2800pci_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
-{
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20);
- rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
- !!erp->short_preamble);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
- !!erp->short_preamble);
- rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
- erp->cts_protection ? 2 : 0);
- rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE,
- erp->basic_rates);
- rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-
- rt2x00pci_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
- rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
- rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
- rt2x00pci_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
- rt2x00pci_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
- erp->beacon_int * 16);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-}
-
-static void rt2800pci_config_ant(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
-{
- u8 r1;
- u8 r3;
-
- rt2800pci_bbp_read(rt2x00dev, 1, &r1);
- rt2800pci_bbp_read(rt2x00dev, 3, &r3);
-
- /*
- * Configure the TX antenna.
- */
- switch ((int)ant->tx) {
- case 1:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
- break;
- case 2:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
- break;
- case 3:
- /* Do nothing */
- break;
- }
-
- /*
- * Configure the RX antenna.
- */
- switch ((int)ant->rx) {
- case 1:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
- break;
- case 2:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
- break;
- case 3:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
- break;
- }
-
- rt2800pci_bbp_write(rt2x00dev, 3, r3);
- rt2800pci_bbp_write(rt2x00dev, 1, r1);
-}
-
-static void rt2800pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u16 eeprom;
- short lna_gain;
-
- if (libconf->rf.channel <= 14) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
- } else if (libconf->rf.channel <= 64) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
- } else if (libconf->rf.channel <= 128) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
- } else {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
- }
-
- rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt2800pci_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
- if (rt2x00dev->default_ant.tx == 1)
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
-
- if (rt2x00dev->default_ant.rx == 1) {
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
- } else if (rt2x00dev->default_ant.rx == 2)
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
-
- if (rf->channel > 14) {
- /*
- * When TX power is below 0, we should increase it by 7 to
- * make it a positive value (Minumum value is -7).
- * However this means that values between 0 and 7 have
- * double meaning, and we should set a 7DBm boost flag.
- */
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
- (info->tx_power1 >= 0));
-
- if (info->tx_power1 < 0)
- info->tx_power1 += 7;
-
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power1));
-
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
- (info->tx_power2 >= 0));
-
- if (info->tx_power2 < 0)
- info->tx_power2 += 7;
-
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power2));
- } else {
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power1));
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power2));
- }
-
- rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
-
- rt2800pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt2800pci_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt2800pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
- rt2800pci_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt2800pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt2800pci_rf_write(rt2x00dev, 4, rf->rf4);
-}
-
-static void rt2800pci_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- u8 rfcsr;
-
- rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf1);
- rt2800pci_rfcsr_write(rt2x00dev, 2, rf->rf3);
-
- rt2800pci_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
- rt2800pci_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800pci_rfcsr_read(rt2x00dev, 12, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
- TXPOWER_G_TO_DEV(info->tx_power1));
- rt2800pci_rfcsr_write(rt2x00dev, 12, rfcsr);
-
- rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
- rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr);
-
- rt2800pci_rfcsr_write(rt2x00dev, 24,
- rt2x00dev->calibration[conf_is_ht40(conf)]);
-
- rt2800pci_rfcsr_read(rt2x00dev, 23, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
- rt2800pci_rfcsr_write(rt2x00dev, 23, rfcsr);
-}
-
-static void rt2800pci_config_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- u32 reg;
- unsigned int tx_pin;
- u8 bbp;
-
- if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
- rt2800pci_config_channel_rt2x(rt2x00dev, conf, rf, info);
- else
- rt2800pci_config_channel_rt3x(rt2x00dev, conf, rf, info);
-
- /*
- * Change BBP settings
- */
- rt2800pci_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
- rt2800pci_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
- rt2800pci_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
- rt2800pci_bbp_write(rt2x00dev, 86, 0);
-
- if (rf->channel <= 14) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
- rt2800pci_bbp_write(rt2x00dev, 82, 0x62);
- rt2800pci_bbp_write(rt2x00dev, 75, 0x46);
- } else {
- rt2800pci_bbp_write(rt2x00dev, 82, 0x84);
- rt2800pci_bbp_write(rt2x00dev, 75, 0x50);
- }
- } else {
- rt2800pci_bbp_write(rt2x00dev, 82, 0xf2);
-
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
- rt2800pci_bbp_write(rt2x00dev, 75, 0x46);
- else
- rt2800pci_bbp_write(rt2x00dev, 75, 0x50);
- }
-
- rt2x00pci_register_read(rt2x00dev, TX_BAND_CFG, &reg);
- rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
- rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
- rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
- rt2x00pci_register_write(rt2x00dev, TX_BAND_CFG, reg);
-
- tx_pin = 0;
-
- /* Turn on unused PA or LNA when not using 1T or 1R */
- if (rt2x00dev->default_ant.tx != 1) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
- }
-
- /* Turn on unused PA or LNA when not using 1T or 1R */
- if (rt2x00dev->default_ant.rx != 1) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
- }
-
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
-
- rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
-
- rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
- rt2800pci_bbp_write(rt2x00dev, 4, bbp);
-
- rt2800pci_bbp_read(rt2x00dev, 3, &bbp);
- rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
- rt2800pci_bbp_write(rt2x00dev, 3, bbp);
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
- if (conf_is_ht40(conf)) {
- rt2800pci_bbp_write(rt2x00dev, 69, 0x1a);
- rt2800pci_bbp_write(rt2x00dev, 70, 0x0a);
- rt2800pci_bbp_write(rt2x00dev, 73, 0x16);
- } else {
- rt2800pci_bbp_write(rt2x00dev, 69, 0x16);
- rt2800pci_bbp_write(rt2x00dev, 70, 0x08);
- rt2800pci_bbp_write(rt2x00dev, 73, 0x11);
- }
- }
-
- msleep(1);
-}
-
-static void rt2800pci_config_txpower(struct rt2x00_dev *rt2x00dev,
- const int txpower)
-{
- u32 reg;
- u32 value = TXPOWER_G_TO_DEV(txpower);
- u8 r1;
-
- rt2800pci_bbp_read(rt2x00dev, 1, &r1);
- rt2x00_set_field8(&reg, BBP1_TX_POWER, 0);
- rt2800pci_bbp_write(rt2x00dev, 1, r1);
-
- rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_1MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_2MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_55MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_11MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_6MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_9MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_12MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_18MBS, value);
- rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_0, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_24MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_36MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_48MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_54MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS0, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS1, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS2, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS3, value);
- rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_1, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS4, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS5, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS6, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS7, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS8, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS9, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS10, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS11, value);
- rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_2, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS12, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS13, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS14, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS15, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN1, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN2, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN3, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN4, value);
- rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_3, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN5, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN6, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN7, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN8, value);
- rt2x00pci_register_write(rt2x00dev, TX_PWR_CFG_4, reg);
-}
-
-static void rt2800pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, TX_RTY_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
- libconf->conf->short_frame_max_tx_count);
- rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
- libconf->conf->long_frame_max_tx_count);
- rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
- rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
- rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
- rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
- rt2x00pci_register_write(rt2x00dev, TX_RTY_CFG, reg);
-}
-
-static void rt2800pci_config_ps(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- enum dev_state state =
- (libconf->conf->flags & IEEE80211_CONF_PS) ?
- STATE_SLEEP : STATE_AWAKE;
- u32 reg;
-
- if (state == STATE_SLEEP) {
- rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
-
- rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
- libconf->conf->listen_interval - 1);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
- rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
-
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
- } else {
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-
- rt2x00pci_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
- rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
- }
-}
-
-static void rt2800pci_config(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf,
- const unsigned int flags)
-{
- /* Always recalculate LNA gain before changing configuration */
- rt2800pci_config_lna_gain(rt2x00dev, libconf);
-
- if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
- rt2800pci_config_channel(rt2x00dev, libconf->conf,
- &libconf->rf, &libconf->channel);
- if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800pci_config_txpower(rt2x00dev, libconf->conf->power_level);
- if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
- rt2800pci_config_retry_limit(rt2x00dev, libconf);
- if (flags & IEEE80211_CONF_CHANGE_PS)
- rt2800pci_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt2800pci_link_stats(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual)
-{
- u32 reg;
-
- /*
- * Update FCS error count from register.
- */
- rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, &reg);
- qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
-}
-
-static u8 rt2800pci_get_default_vgc(struct rt2x00_dev *rt2x00dev)
-{
- if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)
- return 0x2e + rt2x00dev->lna_gain;
-
- if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
- return 0x32 + (rt2x00dev->lna_gain * 5) / 3;
- else
- return 0x3a + (rt2x00dev->lna_gain * 5) / 3;
-}
-
-static inline void rt2800pci_set_vgc(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual, u8 vgc_level)
-{
- if (qual->vgc_level != vgc_level) {
- rt2800pci_bbp_write(rt2x00dev, 66, vgc_level);
- qual->vgc_level = vgc_level;
- qual->vgc_level_reg = vgc_level;
- }
-}
-
-static void rt2800pci_reset_tuner(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual)
-{
- rt2800pci_set_vgc(rt2x00dev, qual,
- rt2800pci_get_default_vgc(rt2x00dev));
-}
-
-static void rt2800pci_link_tuner(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual, const u32 count)
-{
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
- return;
-
- /*
- * When RSSI is better then -80 increase VGC level with 0x10
- */
- rt2800pci_set_vgc(rt2x00dev, qual,
- rt2800pci_get_default_vgc(rt2x00dev) +
- ((qual->rssi > -80) * 0x10));
-}
-
/*
* Firmware functions
*/
@@ -1257,7 +244,7 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
if (reg && reg != ~0)
break;
msleep(1);
@@ -1268,42 +255,42 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev,
return -EBUSY;
}
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
- rt2x00pci_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
+ rt2800_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0x00000000);
/*
* Disable DMA, will be reenabled later when enabling
* the radio.
*/
- rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
/*
* enable Host program ram write selection
*/
reg = 0;
rt2x00_set_field32(&reg, PBF_SYS_CTRL_HOST_RAM_WRITE, 1);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, reg);
/*
* Write firmware to device.
*/
- rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ rt2800_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
data, len);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001);
/*
* Wait for device to stabilize.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
break;
msleep(1);
@@ -1322,8 +309,8 @@ static int rt2800pci_load_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Initialize BBP R/W access agent
*/
- rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
return 0;
}
@@ -1373,7 +360,7 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
struct queue_entry_priv_pci *entry_priv;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -1381,539 +368,54 @@ static int rt2800pci_init_queues(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
/*
* Initialize registers.
*/
entry_priv = rt2x00dev->tx[0].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX0, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX0, 0);
+ rt2800_register_write(rt2x00dev, TX_BASE_PTR0, entry_priv->desc_dma);
+ rt2800_register_write(rt2x00dev, TX_MAX_CNT0, rt2x00dev->tx[0].limit);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX0, 0);
+ rt2800_register_write(rt2x00dev, TX_DTX_IDX0, 0);
entry_priv = rt2x00dev->tx[1].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX1, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX1, 0);
+ rt2800_register_write(rt2x00dev, TX_BASE_PTR1, entry_priv->desc_dma);
+ rt2800_register_write(rt2x00dev, TX_MAX_CNT1, rt2x00dev->tx[1].limit);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX1, 0);
+ rt2800_register_write(rt2x00dev, TX_DTX_IDX1, 0);
entry_priv = rt2x00dev->tx[2].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX2, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX2, 0);
+ rt2800_register_write(rt2x00dev, TX_BASE_PTR2, entry_priv->desc_dma);
+ rt2800_register_write(rt2x00dev, TX_MAX_CNT2, rt2x00dev->tx[2].limit);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX2, 0);
+ rt2800_register_write(rt2x00dev, TX_DTX_IDX2, 0);
entry_priv = rt2x00dev->tx[3].entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX3, 0);
- rt2x00pci_register_write(rt2x00dev, TX_DTX_IDX3, 0);
+ rt2800_register_write(rt2x00dev, TX_BASE_PTR3, entry_priv->desc_dma);
+ rt2800_register_write(rt2x00dev, TX_MAX_CNT3, rt2x00dev->tx[3].limit);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX3, 0);
+ rt2800_register_write(rt2x00dev, TX_DTX_IDX3, 0);
entry_priv = rt2x00dev->rx->entries[0].priv_data;
- rt2x00pci_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
- rt2x00pci_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
- rt2x00pci_register_write(rt2x00dev, RX_DRX_IDX, 0);
+ rt2800_register_write(rt2x00dev, RX_BASE_PTR, entry_priv->desc_dma);
+ rt2800_register_write(rt2x00dev, RX_MAX_CNT, rt2x00dev->rx[0].limit);
+ rt2800_register_write(rt2x00dev, RX_CRX_IDX, rt2x00dev->rx[0].limit - 1);
+ rt2800_register_write(rt2x00dev, RX_DRX_IDX, 0);
/*
* Enable global DMA configuration
*/
- rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, DELAY_INT_CFG, 0);
-
- return 0;
-}
-
-static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
-
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
- rt2x00pci_register_read(rt2x00dev, BCN_OFFSET0, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */
- rt2x00pci_register_write(rt2x00dev, BCN_OFFSET0, reg);
-
- rt2x00pci_register_read(rt2x00dev, BCN_OFFSET1, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */
- rt2x00pci_register_write(rt2x00dev, BCN_OFFSET1, reg);
-
- rt2x00pci_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
- rt2x00pci_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
- rt2x00pci_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
-
- rt2x00pci_register_read(rt2x00dev, TX_LINK_CFG, &reg);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
- rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
- rt2x00pci_register_write(rt2x00dev, TX_LINK_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
- rt2x00pci_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
- if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
- rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
- else
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
- rt2x00pci_register_write(rt2x00dev, MAX_LEN_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
-
- rt2x00pci_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
- rt2x00pci_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 8);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 8);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
- rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
- rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
- rt2x00pci_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
-
- rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
- IEEE80211_MAX_RTS_THRESHOLD);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
- rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
- rt2x00pci_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
-
- /*
- * ASIC will keep garbage value after boot, clear encryption keys.
- */
- for (i = 0; i < 4; i++)
- rt2x00pci_register_write(rt2x00dev,
- SHARED_KEY_MODE_ENTRY(i), 0);
-
- for (i = 0; i < 256; i++) {
- u32 wcid[2] = { 0xffffffff, 0x00ffffff };
- rt2x00pci_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
- wcid, sizeof(wcid));
-
- rt2x00pci_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
- rt2x00pci_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
- }
-
- /*
- * Clear all beacons
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
- rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
-
- rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
- rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG0, reg);
-
- rt2x00pci_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
- rt2x00pci_register_write(rt2x00dev, HT_FBK_CFG1, reg);
-
- rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
- rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG0, reg);
-
- rt2x00pci_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
- rt2x00pci_register_write(rt2x00dev, LG_FBK_CFG1, reg);
-
- /*
- * We must clear the error counters.
- * These registers are cleared on read,
- * so we may pass a useless variable to store the value.
- */
- rt2x00pci_register_read(rt2x00dev, RX_STA_CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, RX_STA_CNT1, &reg);
- rt2x00pci_register_read(rt2x00dev, RX_STA_CNT2, &reg);
- rt2x00pci_register_read(rt2x00dev, TX_STA_CNT0, &reg);
- rt2x00pci_register_read(rt2x00dev, TX_STA_CNT1, &reg);
- rt2x00pci_register_read(rt2x00dev, TX_STA_CNT2, &reg);
-
- return 0;
-}
-
-static int rt2800pci_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u32 reg;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
- if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
- return 0;
-
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
- return -EACCES;
-}
-
-static int rt2800pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u8 value;
-
- /*
- * BBP was enabled after firmware was loaded,
- * but we need to reactivate it now.
- */
- rt2x00pci_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- msleep(1);
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800pci_bbp_read(rt2x00dev, 0, &value);
- if ((value != 0xff) && (value != 0x00))
- return 0;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
- return -EACCES;
-}
-
-static int rt2800pci_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u16 eeprom;
- u8 reg_id;
- u8 value;
-
- if (unlikely(rt2800pci_wait_bbp_rf_ready(rt2x00dev) ||
- rt2800pci_wait_bbp_ready(rt2x00dev)))
- return -EACCES;
-
- rt2800pci_bbp_write(rt2x00dev, 65, 0x2c);
- rt2800pci_bbp_write(rt2x00dev, 66, 0x38);
- rt2800pci_bbp_write(rt2x00dev, 69, 0x12);
- rt2800pci_bbp_write(rt2x00dev, 70, 0x0a);
- rt2800pci_bbp_write(rt2x00dev, 73, 0x10);
- rt2800pci_bbp_write(rt2x00dev, 81, 0x37);
- rt2800pci_bbp_write(rt2x00dev, 82, 0x62);
- rt2800pci_bbp_write(rt2x00dev, 83, 0x6a);
- rt2800pci_bbp_write(rt2x00dev, 84, 0x99);
- rt2800pci_bbp_write(rt2x00dev, 86, 0x00);
- rt2800pci_bbp_write(rt2x00dev, 91, 0x04);
- rt2800pci_bbp_write(rt2x00dev, 92, 0x00);
- rt2800pci_bbp_write(rt2x00dev, 103, 0x00);
- rt2800pci_bbp_write(rt2x00dev, 105, 0x05);
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
- rt2800pci_bbp_write(rt2x00dev, 69, 0x16);
- rt2800pci_bbp_write(rt2x00dev, 73, 0x12);
- }
-
- if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION)
- rt2800pci_bbp_write(rt2x00dev, 84, 0x19);
-
- if (rt2x00_rt(&rt2x00dev->chip, RT3052)) {
- rt2800pci_bbp_write(rt2x00dev, 31, 0x08);
- rt2800pci_bbp_write(rt2x00dev, 78, 0x0e);
- rt2800pci_bbp_write(rt2x00dev, 80, 0x08);
- }
-
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
- rt2800pci_bbp_write(rt2x00dev, reg_id, value);
- }
- }
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- return 0;
-}
-
-static u8 rt2800pci_init_rx_filter(struct rt2x00_dev *rt2x00dev,
- bool bw40, u8 rfcsr24, u8 filter_target)
-{
- unsigned int i;
- u8 bbp;
- u8 rfcsr;
- u8 passband;
- u8 stopband;
- u8 overtuned = 0;
-
- rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
-
- rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
- rt2800pci_bbp_write(rt2x00dev, 4, bbp);
-
- rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
- rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * Set power & frequency of passband test tone
- */
- rt2800pci_bbp_write(rt2x00dev, 24, 0);
-
- for (i = 0; i < 100; i++) {
- rt2800pci_bbp_write(rt2x00dev, 25, 0x90);
- msleep(1);
-
- rt2800pci_bbp_read(rt2x00dev, 55, &passband);
- if (passband)
- break;
- }
-
- /*
- * Set power & frequency of stopband test tone
- */
- rt2800pci_bbp_write(rt2x00dev, 24, 0x06);
-
- for (i = 0; i < 100; i++) {
- rt2800pci_bbp_write(rt2x00dev, 25, 0x90);
- msleep(1);
-
- rt2800pci_bbp_read(rt2x00dev, 55, &stopband);
-
- if ((passband - stopband) <= filter_target) {
- rfcsr24++;
- overtuned += ((passband - stopband) == filter_target);
- } else
- break;
-
- rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
- }
-
- rfcsr24 -= !!overtuned;
-
- rt2800pci_rfcsr_write(rt2x00dev, 24, rfcsr24);
- return rfcsr24;
-}
-
-static int rt2800pci_init_rfcsr(struct rt2x00_dev *rt2x00dev)
-{
- u8 rfcsr;
- u8 bbp;
-
- if (!rt2x00_rf(&rt2x00dev->chip, RF3020) &&
- !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
- !rt2x00_rf(&rt2x00dev->chip, RF3022))
- return 0;
-
- /*
- * Init RF calibration.
- */
- rt2800pci_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
- rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
- rt2800pci_rfcsr_write(rt2x00dev, 30, rfcsr);
-
- rt2800pci_rfcsr_write(rt2x00dev, 0, 0x50);
- rt2800pci_rfcsr_write(rt2x00dev, 1, 0x01);
- rt2800pci_rfcsr_write(rt2x00dev, 2, 0xf7);
- rt2800pci_rfcsr_write(rt2x00dev, 3, 0x75);
- rt2800pci_rfcsr_write(rt2x00dev, 4, 0x40);
- rt2800pci_rfcsr_write(rt2x00dev, 5, 0x03);
- rt2800pci_rfcsr_write(rt2x00dev, 6, 0x02);
- rt2800pci_rfcsr_write(rt2x00dev, 7, 0x50);
- rt2800pci_rfcsr_write(rt2x00dev, 8, 0x39);
- rt2800pci_rfcsr_write(rt2x00dev, 9, 0x0f);
- rt2800pci_rfcsr_write(rt2x00dev, 10, 0x60);
- rt2800pci_rfcsr_write(rt2x00dev, 11, 0x21);
- rt2800pci_rfcsr_write(rt2x00dev, 12, 0x75);
- rt2800pci_rfcsr_write(rt2x00dev, 13, 0x75);
- rt2800pci_rfcsr_write(rt2x00dev, 14, 0x90);
- rt2800pci_rfcsr_write(rt2x00dev, 15, 0x58);
- rt2800pci_rfcsr_write(rt2x00dev, 16, 0xb3);
- rt2800pci_rfcsr_write(rt2x00dev, 17, 0x92);
- rt2800pci_rfcsr_write(rt2x00dev, 18, 0x2c);
- rt2800pci_rfcsr_write(rt2x00dev, 19, 0x02);
- rt2800pci_rfcsr_write(rt2x00dev, 20, 0xba);
- rt2800pci_rfcsr_write(rt2x00dev, 21, 0xdb);
- rt2800pci_rfcsr_write(rt2x00dev, 22, 0x00);
- rt2800pci_rfcsr_write(rt2x00dev, 23, 0x31);
- rt2800pci_rfcsr_write(rt2x00dev, 24, 0x08);
- rt2800pci_rfcsr_write(rt2x00dev, 25, 0x01);
- rt2800pci_rfcsr_write(rt2x00dev, 26, 0x25);
- rt2800pci_rfcsr_write(rt2x00dev, 27, 0x23);
- rt2800pci_rfcsr_write(rt2x00dev, 28, 0x13);
- rt2800pci_rfcsr_write(rt2x00dev, 29, 0x83);
-
- /*
- * Set RX Filter calibration for 20MHz and 40MHz
- */
- rt2x00dev->calibration[0] =
- rt2800pci_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
- rt2x00dev->calibration[1] =
- rt2800pci_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
-
- /*
- * Set back to initial state
- */
- rt2800pci_bbp_write(rt2x00dev, 24, 0);
-
- rt2800pci_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
- rt2800pci_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * set BBP back to BW20
- */
- rt2800pci_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
- rt2800pci_bbp_write(rt2x00dev, 4, bbp);
+ rt2800_register_write(rt2x00dev, DELAY_INT_CFG, 0);
return 0;
}
@@ -1926,11 +428,11 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
(state == STATE_RADIO_RX_ON) ||
(state == STATE_RADIO_RX_ON_LINK));
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
}
static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
@@ -1944,11 +446,11 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
* should clear the register to assure a clean state.
*/
if (state == STATE_RADIO_IRQ_ON) {
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
}
- rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+ rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_DONE, mask);
@@ -1967,7 +469,7 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, INT_MASK_CSR_GPTIMER, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, mask);
rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, mask);
- rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+ rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
}
static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
@@ -1976,7 +478,7 @@ static int rt2800pci_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
u32 reg;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
!rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
return 0;
@@ -1998,50 +500,50 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
*/
if (unlikely(rt2800pci_wait_wpdma_ready(rt2x00dev) ||
rt2800pci_init_queues(rt2x00dev) ||
- rt2800pci_init_registers(rt2x00dev) ||
+ rt2800_init_registers(rt2x00dev) ||
rt2800pci_wait_wpdma_ready(rt2x00dev) ||
- rt2800pci_init_bbp(rt2x00dev) ||
- rt2800pci_init_rfcsr(rt2x00dev)))
+ rt2800_init_bbp(rt2x00dev) ||
+ rt2800_init_rfcsr(rt2x00dev)))
return -EIO;
/*
* Send signal to firmware during boot time.
*/
- rt2800pci_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
/*
* Enable RX.
*/
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
- rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 2);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- rt2x00pci_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
/*
* Initialize LED control
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
- rt2800pci_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
- rt2800pci_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
- rt2800pci_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
word & 0xff, (word >> 8) & 0xff);
return 0;
@@ -2051,21 +553,21 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
- rt2x00pci_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00pci_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
@@ -2073,10 +575,10 @@ static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
- rt2x00pci_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
+ rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
/* Wait for DMA, ignore error */
rt2800pci_wait_wpdma_ready(rt2x00dev);
@@ -2090,10 +592,10 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
* if the device is booting and wasn't asleep it will return
* failure when attempting to wakeup.
*/
- rt2800pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
if (state == STATE_AWAKE) {
- rt2800pci_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
}
@@ -2195,7 +697,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- (skbdesc->entry->entry_idx + 1) : 0xff);
+ txdesc->key_idx : 0xff);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
skb->len - txdesc->l2pad);
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
@@ -2204,8 +706,8 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
/*
* Always write 0 to IV/EIV fields, hardware will insert the IV
- * from the IVEIV register when ENTRY_TXD_ENCRYPT_IV is set to 0.
- * When ENTRY_TXD_ENCRYPT_IV is set to 1 it will use the IV data
+ * from the IVEIV register when TXD_W3_WIV is set to 0.
+ * When TXD_W3_WIV is set to 1 it will use the IV data
* from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which
* crypto entry in the registers should be used to encrypt the frame.
*/
@@ -2265,18 +767,18 @@ static void rt2800pci_write_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
/*
* Write entire beacon with descriptor to register.
*/
beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
- rt2x00pci_register_multiwrite(rt2x00dev,
+ rt2800_register_multiwrite(rt2x00dev,
beacon_base,
skbdesc->desc, skbdesc->desc_len);
- rt2x00pci_register_multiwrite(rt2x00dev,
+ rt2800_register_multiwrite(rt2x00dev,
beacon_base + skbdesc->desc_len,
entry->skb->data, entry->skb->len);
@@ -2295,12 +797,12 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (queue_idx == QID_BEACON) {
- rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
}
return;
}
@@ -2316,7 +818,7 @@ static void rt2800pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
else
qidx = queue_idx;
- rt2x00pci_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx);
+ rt2800_register_write(rt2x00dev, TX_CTX_IDX(qidx), idx);
}
static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
@@ -2325,16 +827,16 @@ static void rt2800pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev,
u32 reg;
if (qid == QID_BEACON) {
- rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, 0);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, 0);
return;
}
- rt2x00pci_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, (qid == QID_AC_BE));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, (qid == QID_AC_BK));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, (qid == QID_AC_VI));
rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, (qid == QID_AC_VO));
- rt2x00pci_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
}
/*
@@ -2430,7 +932,7 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
* Set RX IDX in register to inform hardware that we have handled
* this entry and it is available for reuse again.
*/
- rt2x00pci_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
+ rt2800_register_write(rt2x00dev, RX_CRX_IDX, entry->entry_idx);
/*
* Remove TXWI descriptor from start of buffer.
@@ -2467,7 +969,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
old_reg = 0;
while (1) {
- rt2x00pci_register_read(rt2x00dev, TX_STA_FIFO, &reg);
+ rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
break;
@@ -2551,8 +1053,8 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
u32 reg;
/* Read status and ACK all interrupts */
- rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
- rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+ rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
+ rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
if (!reg)
return IRQ_NONE;
@@ -2709,7 +1211,7 @@ static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip_rf(rt2x00dev, value, reg);
if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
@@ -2758,9 +1260,9 @@ static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Store led settings, for correct led behaviour.
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
- rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
- rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
- rt2800pci_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
#endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -2948,10 +1450,25 @@ static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
return 0;
}
+static const struct rt2800_ops rt2800pci_rt2800_ops = {
+ .register_read = rt2x00pci_register_read,
+ .register_write = rt2x00pci_register_write,
+ .register_write_lock = rt2x00pci_register_write, /* same for PCI */
+
+ .register_multiread = rt2x00pci_register_multiread,
+ .register_multiwrite = rt2x00pci_register_multiwrite,
+
+ .regbusy_read = rt2x00pci_regbusy_read,
+};
+
static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+
+ rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops;
+
/*
* Allocate eeprom data.
*/
@@ -2996,161 +1513,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
return 0;
}
-/*
- * IEEE80211 stack callback functions.
- */
-static void rt2800pci_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
- u32 *iv32, u16 *iv16)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct mac_iveiv_entry iveiv_entry;
- u32 offset;
-
- offset = MAC_IVEIV_ENTRY(hw_key_idx);
- rt2x00pci_register_multiread(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
-
- memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16));
- memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32));
-}
-
-static int rt2800pci_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
- bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
-
- rt2x00pci_register_read(rt2x00dev, TX_RTS_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
- rt2x00pci_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00pci_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
- return 0;
-}
-
-static int rt2800pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
- const struct ieee80211_tx_queue_params *params)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct data_queue *queue;
- struct rt2x00_field32 field;
- int retval;
- u32 reg;
- u32 offset;
-
- /*
- * First pass the configuration through rt2x00lib, that will
- * update the queue settings and validate the input. After that
- * we are free to update the registers based on the value
- * in the queue parameter.
- */
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
- if (retval)
- return retval;
-
- /*
- * We only need to perform additional register initialization
- * for WMM queues/
- */
- if (queue_idx >= 4)
- return 0;
-
- queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-
- /* Update WMM TXOP register */
- offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
- field.bit_offset = (queue_idx & 1) * 16;
- field.bit_mask = 0xffff << field.bit_offset;
-
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, field, queue->txop);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
-
- /* Update WMM registers */
- field.bit_offset = queue_idx * 4;
- field.bit_mask = 0xf << field.bit_offset;
-
- rt2x00pci_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->aifs);
- rt2x00pci_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->cw_min);
- rt2x00pci_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
-
- rt2x00pci_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->cw_max);
- rt2x00pci_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
-
- /* Update EDCA registers */
- offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
-
- rt2x00pci_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
- rt2x00pci_register_write(rt2x00dev, offset, reg);
-
- return 0;
-}
-
-static u64 rt2800pci_get_tsf(struct ieee80211_hw *hw)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u64 tsf;
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
- tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
- rt2x00pci_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
- tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
-
- return tsf;
-}
-
-static const struct ieee80211_ops rt2800pci_mac80211_ops = {
- .tx = rt2x00mac_tx,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .configure_filter = rt2x00mac_configure_filter,
- .set_key = rt2x00mac_set_key,
- .get_stats = rt2x00mac_get_stats,
- .get_tkip_seq = rt2800pci_get_tkip_seq,
- .set_rts_threshold = rt2800pci_set_rts_threshold,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2800pci_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt2800pci_get_tsf,
- .rfkill_poll = rt2x00mac_rfkill_poll,
-};
-
static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.irq_handler = rt2800pci_interrupt,
.probe_hw = rt2800pci_probe_hw,
@@ -3162,23 +1524,23 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
.get_entry_state = rt2800pci_get_entry_state,
.clear_entry = rt2800pci_clear_entry,
.set_device_state = rt2800pci_set_device_state,
- .rfkill_poll = rt2800pci_rfkill_poll,
- .link_stats = rt2800pci_link_stats,
- .reset_tuner = rt2800pci_reset_tuner,
- .link_tuner = rt2800pci_link_tuner,
+ .rfkill_poll = rt2800_rfkill_poll,
+ .link_stats = rt2800_link_stats,
+ .reset_tuner = rt2800_reset_tuner,
+ .link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800pci_write_tx_desc,
.write_tx_data = rt2x00pci_write_tx_data,
.write_beacon = rt2800pci_write_beacon,
.kick_tx_queue = rt2800pci_kick_tx_queue,
.kill_tx_queue = rt2800pci_kill_tx_queue,
.fill_rxdone = rt2800pci_fill_rxdone,
- .config_shared_key = rt2800pci_config_shared_key,
- .config_pairwise_key = rt2800pci_config_pairwise_key,
- .config_filter = rt2800pci_config_filter,
- .config_intf = rt2800pci_config_intf,
- .config_erp = rt2800pci_config_erp,
- .config_ant = rt2800pci_config_ant,
- .config = rt2800pci_config,
+ .config_shared_key = rt2800_config_shared_key,
+ .config_pairwise_key = rt2800_config_pairwise_key,
+ .config_filter = rt2800_config_filter,
+ .config_intf = rt2800_config_intf,
+ .config_erp = rt2800_config_erp,
+ .config_ant = rt2800_config_ant,
+ .config = rt2800_config,
};
static const struct data_queue_desc rt2800pci_queue_rx = {
@@ -3213,9 +1575,9 @@ static const struct rt2x00_ops rt2800pci_ops = {
.tx = &rt2800pci_queue_tx,
.bcn = &rt2800pci_queue_bcn,
.lib = &rt2800pci_rt2x00_ops,
- .hw = &rt2800pci_mac80211_ops,
+ .hw = &rt2800_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
- .debugfs = &rt2800pci_rt2x00debug,
+ .debugfs = &rt2800_rt2x00debug,
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
};
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.h b/drivers/net/wireless/rt2x00/rt2800pci.h
index 856908815221..1dbf13270cda 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.h
+++ b/drivers/net/wireless/rt2x00/rt2800pci.h
@@ -28,61 +28,6 @@
#define RT2800PCI_H
/*
- * RF chip defines.
- *
- * RF2820 2.4G 2T3R
- * RF2850 2.4G/5G 2T3R
- * RF2720 2.4G 1T2R
- * RF2750 2.4G/5G 1T2R
- * RF3020 2.4G 1T1R
- * RF2020 2.4G B/G
- * RF3021 2.4G 1T2R
- * RF3022 2.4G 2T2R
- * RF3052 2.4G 2T2R
- */
-#define RF2820 0x0001
-#define RF2850 0x0002
-#define RF2720 0x0003
-#define RF2750 0x0004
-#define RF3020 0x0005
-#define RF2020 0x0006
-#define RF3021 0x0007
-#define RF3022 0x0008
-#define RF3052 0x0009
-
-/*
- * RT2860 version
- */
-#define RT2860C_VERSION 0x28600100
-#define RT2860D_VERSION 0x28600101
-#define RT2880E_VERSION 0x28720200
-#define RT2883_VERSION 0x28830300
-#define RT3070_VERSION 0x30700200
-
-/*
- * Signal information.
- * Default offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET 120 /* FIXME */
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE 0x1000
-#define CSR_REG_SIZE 0x0800
-#define EEPROM_BASE 0x0000
-#define EEPROM_SIZE 0x0110
-#define BBP_BASE 0x0000
-#define BBP_SIZE 0x0080
-#define RF_BASE 0x0004
-#define RF_SIZE 0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES 4
-
-/*
* PCI registers.
*/
@@ -102,215 +47,6 @@
#define E2PROM_CSR_RELOAD FIELD32(0x00000080)
/*
- * INT_SOURCE_CSR: Interrupt source register.
- * Write one to clear corresponding bit.
- * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
- */
-#define INT_SOURCE_CSR 0x0200
-#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001)
-#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002)
-#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004)
-#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008)
-#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010)
-#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020)
-#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040)
-#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
-#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
-#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200)
-#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400)
-#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800)
-#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000)
-#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
-#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000)
-#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000)
-#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000)
-#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000)
-
-/*
- * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
- */
-#define INT_MASK_CSR 0x0204
-#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001)
-#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002)
-#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004)
-#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008)
-#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010)
-#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020)
-#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040)
-#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
-#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
-#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200)
-#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400)
-#define INT_MASK_CSR_TBTT FIELD32(0x00000800)
-#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000)
-#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
-#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000)
-#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000)
-#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000)
-#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000)
-
-/*
- * WPDMA_GLO_CFG
- */
-#define WPDMA_GLO_CFG 0x0208
-#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001)
-#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002)
-#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004)
-#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008)
-#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030)
-#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040)
-#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080)
-#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00)
-#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000)
-
-/*
- * WPDMA_RST_IDX
- */
-#define WPDMA_RST_IDX 0x020c
-#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001)
-#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002)
-#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004)
-#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008)
-#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010)
-#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020)
-#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000)
-
-/*
- * DELAY_INT_CFG
- */
-#define DELAY_INT_CFG 0x0210
-#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff)
-#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00)
-#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000)
-#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000)
-#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000)
-#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000)
-
-/*
- * WMM_AIFSN_CFG: Aifsn for each EDCA AC
- * AIFSN0: AC_BE
- * AIFSN1: AC_BK
- * AIFSN1: AC_VI
- * AIFSN1: AC_VO
- */
-#define WMM_AIFSN_CFG 0x0214
-#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f)
-#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0)
-#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00)
-#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000)
-
-/*
- * WMM_CWMIN_CSR: CWmin for each EDCA AC
- * CWMIN0: AC_BE
- * CWMIN1: AC_BK
- * CWMIN1: AC_VI
- * CWMIN1: AC_VO
- */
-#define WMM_CWMIN_CFG 0x0218
-#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f)
-#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0)
-#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00)
-#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000)
-
-/*
- * WMM_CWMAX_CSR: CWmax for each EDCA AC
- * CWMAX0: AC_BE
- * CWMAX1: AC_BK
- * CWMAX1: AC_VI
- * CWMAX1: AC_VO
- */
-#define WMM_CWMAX_CFG 0x021c
-#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f)
-#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0)
-#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00)
-#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000)
-
-/*
- * AC_TXOP0: AC_BK/AC_BE TXOP register
- * AC0TXOP: AC_BK in unit of 32us
- * AC1TXOP: AC_BE in unit of 32us
- */
-#define WMM_TXOP0_CFG 0x0220
-#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff)
-#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000)
-
-/*
- * AC_TXOP1: AC_VO/AC_VI TXOP register
- * AC2TXOP: AC_VI in unit of 32us
- * AC3TXOP: AC_VO in unit of 32us
- */
-#define WMM_TXOP1_CFG 0x0224
-#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff)
-#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000)
-
-/*
- * GPIO_CTRL_CFG:
- */
-#define GPIO_CTRL_CFG 0x0228
-#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001)
-#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002)
-#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004)
-#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008)
-#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010)
-#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020)
-#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040)
-#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080)
-#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100)
-
-/*
- * MCU_CMD_CFG
- */
-#define MCU_CMD_CFG 0x022c
-
-/*
- * AC_BK register offsets
- */
-#define TX_BASE_PTR0 0x0230
-#define TX_MAX_CNT0 0x0234
-#define TX_CTX_IDX0 0x0238
-#define TX_DTX_IDX0 0x023c
-
-/*
- * AC_BE register offsets
- */
-#define TX_BASE_PTR1 0x0240
-#define TX_MAX_CNT1 0x0244
-#define TX_CTX_IDX1 0x0248
-#define TX_DTX_IDX1 0x024c
-
-/*
- * AC_VI register offsets
- */
-#define TX_BASE_PTR2 0x0250
-#define TX_MAX_CNT2 0x0254
-#define TX_CTX_IDX2 0x0258
-#define TX_DTX_IDX2 0x025c
-
-/*
- * AC_VO register offsets
- */
-#define TX_BASE_PTR3 0x0260
-#define TX_MAX_CNT3 0x0264
-#define TX_CTX_IDX3 0x0268
-#define TX_DTX_IDX3 0x026c
-
-/*
- * HCCA register offsets
- */
-#define TX_BASE_PTR4 0x0270
-#define TX_MAX_CNT4 0x0274
-#define TX_CTX_IDX4 0x0278
-#define TX_DTX_IDX4 0x027c
-
-/*
- * MGMT register offsets
- */
-#define TX_BASE_PTR5 0x0280
-#define TX_MAX_CNT5 0x0284
-#define TX_CTX_IDX5 0x0288
-#define TX_DTX_IDX5 0x028c
-
-/*
* Queue register offset macros
*/
#define TX_QUEUE_REG_OFFSET 0x10
@@ -320,72 +56,6 @@
#define TX_DTX_IDX(__x) TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
/*
- * RX register offsets
- */
-#define RX_BASE_PTR 0x0290
-#define RX_MAX_CNT 0x0294
-#define RX_CRX_IDX 0x0298
-#define RX_DRX_IDX 0x029c
-
-/*
- * PBF_SYS_CTRL
- * HOST_RAM_WRITE: enable Host program ram write selection
- */
-#define PBF_SYS_CTRL 0x0400
-#define PBF_SYS_CTRL_READY FIELD32(0x00000080)
-#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
-
-/*
- * HOST-MCU shared memory
- */
-#define HOST_CMD_CSR 0x0404
-#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff)
-
-/*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
- */
-#define PBF_CFG 0x0408
-#define PBF_MAX_PCNT 0x040c
-#define PBF_CTRL 0x0410
-#define PBF_INT_STA 0x0414
-#define PBF_INT_ENA 0x0418
-
-/*
- * BCN_OFFSET0:
- */
-#define BCN_OFFSET0 0x042c
-#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff)
-#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00)
-#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000)
-#define BCN_OFFSET0_BCN3 FIELD32(0xff000000)
-
-/*
- * BCN_OFFSET1:
- */
-#define BCN_OFFSET1 0x0430
-#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff)
-#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00)
-#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000)
-#define BCN_OFFSET1_BCN7 FIELD32(0xff000000)
-
-/*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
- */
-#define TXRXQ_PCNT 0x0438
-#define PBF_DBG 0x043c
-
-/*
- * RF registers
- */
-#define RF_CSR_CFG 0x0500
-#define RF_CSR_CFG_DATA FIELD32(0x000000ff)
-#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00)
-#define RF_CSR_CFG_WRITE FIELD32(0x00010000)
-#define RF_CSR_CFG_BUSY FIELD32(0x00020000)
-
-/*
* EFUSE_CSR: RT3090 EEPROM
*/
#define EFUSE_CTRL 0x0580
@@ -414,1360 +84,16 @@
#define EFUSE_DATA3 0x059c
/*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- * ASIC_REV: 0
- * ASIC_VER: 2860
- */
-#define MAC_CSR0 0x1000
-#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff)
-#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000)
-
-/*
- * MAC_SYS_CTRL:
- */
-#define MAC_SYS_CTRL 0x1004
-#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001)
-#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002)
-#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004)
-#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008)
-#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010)
-#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020)
-#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040)
-#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080)
-
-/*
- * MAC_ADDR_DW0: STA MAC register 0
- */
-#define MAC_ADDR_DW0 0x1008
-#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff)
-#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00)
-#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000)
-#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000)
-
-/*
- * MAC_ADDR_DW1: STA MAC register 1
- * UNICAST_TO_ME_MASK:
- * Used to mask off bits from byte 5 of the MAC address
- * to determine the UNICAST_TO_ME bit for RX frames.
- * The full mask is complemented by BSS_ID_MASK:
- * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
-#define MAC_ADDR_DW1 0x100c
-#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff)
-#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00)
-#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000)
-
-/*
- * MAC_BSSID_DW0: BSSID register 0
- */
-#define MAC_BSSID_DW0 0x1010
-#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff)
-#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00)
-#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000)
-#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000)
-
-/*
- * MAC_BSSID_DW1: BSSID register 1
- * BSS_ID_MASK:
- * 0: 1-BSSID mode (BSS index = 0)
- * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
- * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
- * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
- * BSSID. This will make sure that those bits will be ignored
- * when determining the MY_BSS of RX frames.
- */
-#define MAC_BSSID_DW1 0x1014
-#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff)
-#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00)
-#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000)
-#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000)
-
-/*
- * MAX_LEN_CFG: Maximum frame length register.
- * MAX_MPDU: rt2860b max 16k bytes
- * MAX_PSDU: Maximum PSDU length
- * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
- */
-#define MAX_LEN_CFG 0x1018
-#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff)
-#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000)
-#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000)
-#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000)
-
-/*
- * BBP_CSR_CFG: BBP serial control register
- * VALUE: Register value to program into BBP
- * REG_NUM: Selected BBP register
- * READ_CONTROL: 0 write BBP, 1 read BBP
- * BUSY: ASIC is busy executing BBP commands
- * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
- * BBP_RW_MODE: 0 serial, 1 paralell
- */
-#define BBP_CSR_CFG 0x101c
-#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff)
-#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00)
-#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000)
-#define BBP_CSR_CFG_BUSY FIELD32(0x00020000)
-#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000)
-#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000)
-
-/*
- * RF_CSR_CFG0: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * BITWIDTH: Selected RF register
- * STANDBYMODE: 0 high when standby, 1 low when standby
- * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
- * BUSY: ASIC is busy executing RF commands
- */
-#define RF_CSR_CFG0 0x1020
-#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff)
-#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000)
-#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff)
-#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000)
-#define RF_CSR_CFG0_SEL FIELD32(0x40000000)
-#define RF_CSR_CFG0_BUSY FIELD32(0x80000000)
-
-/*
- * RF_CSR_CFG1: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * RFGAP: Gap between BB_CONTROL_RF and RF_LE
- * 0: 3 system clock cycle (37.5usec)
- * 1: 5 system clock cycle (62.5usec)
- */
-#define RF_CSR_CFG1 0x1024
-#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff)
-#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000)
-
-/*
- * RF_CSR_CFG2: RF control register
- * VALUE: Register value to program into RF
- * RFGAP: Gap between BB_CONTROL_RF and RF_LE
- * 0: 3 system clock cycle (37.5usec)
- * 1: 5 system clock cycle (62.5usec)
- */
-#define RF_CSR_CFG2 0x1028
-#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff)
-
-/*
- * LED_CFG: LED control
- * color LED's:
- * 0: off
- * 1: blinking upon TX2
- * 2: periodic slow blinking
- * 3: always on
- * LED polarity:
- * 0: active low
- * 1: active high
- */
-#define LED_CFG 0x102c
-#define LED_CFG_ON_PERIOD FIELD32(0x000000ff)
-#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00)
-#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000)
-#define LED_CFG_R_LED_MODE FIELD32(0x03000000)
-#define LED_CFG_G_LED_MODE FIELD32(0x0c000000)
-#define LED_CFG_Y_LED_MODE FIELD32(0x30000000)
-#define LED_CFG_LED_POLAR FIELD32(0x40000000)
-
-/*
- * XIFS_TIME_CFG: MAC timing
- * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
- * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
- * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
- * when MAC doesn't reference BBP signal BBRXEND
- * EIFS: unit 1us
- * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
- *
- */
-#define XIFS_TIME_CFG 0x1100
-#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff)
-#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00)
-#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000)
-#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000)
-#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000)
-
-/*
- * BKOFF_SLOT_CFG:
- */
-#define BKOFF_SLOT_CFG 0x1104
-#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff)
-#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00)
-
-/*
- * NAV_TIME_CFG:
- */
-#define NAV_TIME_CFG 0x1108
-#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff)
-#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00)
-#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000)
-#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000)
-
-/*
- * CH_TIME_CFG: count as channel busy
- */
-#define CH_TIME_CFG 0x110c
-
-/*
- * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
- */
-#define PBF_LIFE_TIMER 0x1110
-
-/*
- * BCN_TIME_CFG:
- * BEACON_INTERVAL: in unit of 1/16 TU
- * TSF_TICKING: Enable TSF auto counting
- * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
- * BEACON_GEN: Enable beacon generator
- */
-#define BCN_TIME_CFG 0x1114
-#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff)
-#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000)
-#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000)
-#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000)
-#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000)
-#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000)
-
-/*
- * TBTT_SYNC_CFG:
- */
-#define TBTT_SYNC_CFG 0x1118
-
-/*
- * TSF_TIMER_DW0: Local lsb TSF timer, read-only
- */
-#define TSF_TIMER_DW0 0x111c
-#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff)
-
-/*
- * TSF_TIMER_DW1: Local msb TSF timer, read-only
- */
-#define TSF_TIMER_DW1 0x1120
-#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff)
-
-/*
- * TBTT_TIMER: TImer remains till next TBTT, read-only
- */
-#define TBTT_TIMER 0x1124
-
-/*
- * INT_TIMER_CFG:
- */
-#define INT_TIMER_CFG 0x1128
-
-/*
- * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
- */
-#define INT_TIMER_EN 0x112c
-
-/*
- * CH_IDLE_STA: channel idle time
- */
-#define CH_IDLE_STA 0x1130
-
-/*
- * CH_BUSY_STA: channel busy time
- */
-#define CH_BUSY_STA 0x1134
-
-/*
- * MAC_STATUS_CFG:
- * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
- * if 1 or higher one of the 2 registers is busy.
- */
-#define MAC_STATUS_CFG 0x1200
-#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003)
-
-/*
- * PWR_PIN_CFG:
- */
-#define PWR_PIN_CFG 0x1204
-
-/*
- * AUTOWAKEUP_CFG: Manual power control / status register
- * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
- * AUTOWAKE: 0:sleep, 1:awake
- */
-#define AUTOWAKEUP_CFG 0x1208
-#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff)
-#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00)
-#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000)
-
-/*
- * EDCA_AC0_CFG:
- */
-#define EDCA_AC0_CFG 0x1300
-#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC1_CFG:
- */
-#define EDCA_AC1_CFG 0x1304
-#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC2_CFG:
- */
-#define EDCA_AC2_CFG 0x1308
-#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC3_CFG:
- */
-#define EDCA_AC3_CFG 0x130c
-#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_TID_AC_MAP:
- */
-#define EDCA_TID_AC_MAP 0x1310
-
-/*
- * TX_PWR_CFG_0:
- */
-#define TX_PWR_CFG_0 0x1314
-#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f)
-#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0)
-#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00)
-#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000)
-#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000)
-#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000)
-#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000)
-#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_1:
- */
-#define TX_PWR_CFG_1 0x1318
-#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f)
-#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0)
-#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00)
-#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000)
-#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000)
-#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000)
-#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000)
-#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_2:
- */
-#define TX_PWR_CFG_2 0x131c
-#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f)
-#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0)
-#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00)
-#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000)
-#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000)
-#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000)
-#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000)
-#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_3:
- */
-#define TX_PWR_CFG_3 0x1320
-#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0)
-#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000)
-#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000)
-#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000)
-#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000)
-#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_4:
- */
-#define TX_PWR_CFG_4 0x1324
-#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f)
-#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0)
-#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00)
-#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000)
-
-/*
- * TX_PIN_CFG:
- */
-#define TX_PIN_CFG 0x1328
-#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001)
-#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002)
-#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004)
-#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008)
-#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010)
-#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020)
-#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040)
-#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080)
-#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100)
-#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200)
-#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400)
-#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800)
-#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000)
-#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000)
-#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000)
-#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000)
-#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000)
-#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000)
-#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000)
-#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000)
-
-/*
- * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
- */
-#define TX_BAND_CFG 0x132c
-#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001)
-#define TX_BAND_CFG_A FIELD32(0x00000002)
-#define TX_BAND_CFG_BG FIELD32(0x00000004)
-
-/*
- * TX_SW_CFG0:
- */
-#define TX_SW_CFG0 0x1330
-
-/*
- * TX_SW_CFG1:
- */
-#define TX_SW_CFG1 0x1334
-
-/*
- * TX_SW_CFG2:
- */
-#define TX_SW_CFG2 0x1338
-
-/*
- * TXOP_THRES_CFG:
- */
-#define TXOP_THRES_CFG 0x133c
-
-/*
- * TXOP_CTRL_CFG:
- */
-#define TXOP_CTRL_CFG 0x1340
-
-/*
- * TX_RTS_CFG:
- * RTS_THRES: unit:byte
- * RTS_FBK_EN: enable rts rate fallback
- */
-#define TX_RTS_CFG 0x1344
-#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff)
-#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00)
-#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000)
-
-/*
- * TX_TIMEOUT_CFG:
- * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
- * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
- * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
- * it is recommended that:
- * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
- */
-#define TX_TIMEOUT_CFG 0x1348
-#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0)
-#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00)
-#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000)
-
-/*
- * TX_RTY_CFG:
- * SHORT_RTY_LIMIT: short retry limit
- * LONG_RTY_LIMIT: long retry limit
- * LONG_RTY_THRE: Long retry threshoold
- * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
- * 0:expired by retry limit, 1: expired by mpdu life timer
- * AGG_RTY_MODE: Aggregate MPDU retry mode
- * 0:expired by retry limit, 1: expired by mpdu life timer
- * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
- */
-#define TX_RTY_CFG 0x134c
-#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff)
-#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00)
-#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000)
-#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000)
-#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000)
-#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000)
-
-/*
- * TX_LINK_CFG:
- * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
- * MFB_ENABLE: TX apply remote MFB 1:enable
- * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable
- * 0: not apply remote remote unsolicit (MFS=7)
- * TX_MRQ_EN: MCS request TX enable
- * TX_RDG_EN: RDG TX enable
- * TX_CF_ACK_EN: Piggyback CF-ACK enable
- * REMOTE_MFB: remote MCS feedback
- * REMOTE_MFS: remote MCS feedback sequence number
- */
-#define TX_LINK_CFG 0x1350
-#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff)
-#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100)
-#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200)
-#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400)
-#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800)
-#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000)
-#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000)
-#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000)
-
-/*
- * HT_FBK_CFG0:
- */
-#define HT_FBK_CFG0 0x1354
-#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f)
-#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0)
-#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00)
-#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000)
-#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000)
-#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000)
-#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000)
-#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000)
-
-/*
- * HT_FBK_CFG1:
- */
-#define HT_FBK_CFG1 0x1358
-#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f)
-#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0)
-#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00)
-#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000)
-#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000)
-#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000)
-#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000)
-#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG0:
- */
-#define LG_FBK_CFG0 0x135c
-#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f)
-#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0)
-#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00)
-#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000)
-#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000)
-#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000)
-#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000)
-#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG1:
- */
-#define LG_FBK_CFG1 0x1360
-#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f)
-#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0)
-#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00)
-#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000)
-
-/*
- * CCK_PROT_CFG: CCK Protection
- * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
- * PROTECT_CTRL: Protection control frame type for CCK TX
- * 0:none, 1:RTS/CTS, 2:CTS-to-self
- * PROTECT_NAV: TXOP protection type for CCK TX
- * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect
- * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
- * RTS_TH_EN: RTS threshold enable on CCK TX
- */
-#define CCK_PROT_CFG 0x1364
-#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * OFDM_PROT_CFG: OFDM Protection
- */
-#define OFDM_PROT_CFG 0x1368
-#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * MM20_PROT_CFG: MM20 Protection
- */
-#define MM20_PROT_CFG 0x136c
-#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * MM40_PROT_CFG: MM40 Protection
- */
-#define MM40_PROT_CFG 0x1370
-#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * GF20_PROT_CFG: GF20 Protection
- */
-#define GF20_PROT_CFG 0x1374
-#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * GF40_PROT_CFG: GF40 Protection
- */
-#define GF40_PROT_CFG 0x1378
-#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * EXP_CTS_TIME:
- */
-#define EXP_CTS_TIME 0x137c
-
-/*
- * EXP_ACK_TIME:
- */
-#define EXP_ACK_TIME 0x1380
-
-/*
- * RX_FILTER_CFG: RX configuration register.
- */
-#define RX_FILTER_CFG 0x1400
-#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001)
-#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002)
-#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004)
-#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008)
-#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010)
-#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020)
-#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040)
-#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080)
-#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100)
-#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200)
-#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400)
-#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800)
-#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000)
-#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000)
-#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000)
-#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000)
-#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000)
-
-/*
- * AUTO_RSP_CFG:
- * AUTORESPONDER: 0: disable, 1: enable
- * BAC_ACK_POLICY: 0:long, 1:short preamble
- * CTS_40_MMODE: Response CTS 40MHz duplicate mode
- * CTS_40_MREF: Response CTS 40MHz duplicate mode
- * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
- * DUAL_CTS_EN: Power bit value in control frame
- * ACK_CTS_PSM_BIT:Power bit value in control frame
- */
-#define AUTO_RSP_CFG 0x1404
-#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001)
-#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002)
-#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004)
-#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008)
-#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010)
-#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040)
-#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080)
-
-/*
- * LEGACY_BASIC_RATE:
- */
-#define LEGACY_BASIC_RATE 0x1408
-
-/*
- * HT_BASIC_RATE:
- */
-#define HT_BASIC_RATE 0x140c
-
-/*
- * HT_CTRL_CFG:
- */
-#define HT_CTRL_CFG 0x1410
-
-/*
- * SIFS_COST_CFG:
- */
-#define SIFS_COST_CFG 0x1414
-
-/*
- * RX_PARSER_CFG:
- * Set NAV for all received frames
- */
-#define RX_PARSER_CFG 0x1418
-
-/*
- * TX_SEC_CNT0:
- */
-#define TX_SEC_CNT0 0x1500
-
-/*
- * RX_SEC_CNT0:
- */
-#define RX_SEC_CNT0 0x1504
-
-/*
- * CCMP_FC_MUTE:
- */
-#define CCMP_FC_MUTE 0x1508
-
-/*
- * TXOP_HLDR_ADDR0:
- */
-#define TXOP_HLDR_ADDR0 0x1600
-
-/*
- * TXOP_HLDR_ADDR1:
- */
-#define TXOP_HLDR_ADDR1 0x1604
-
-/*
- * TXOP_HLDR_ET:
- */
-#define TXOP_HLDR_ET 0x1608
-
-/*
- * QOS_CFPOLL_RA_DW0:
- */
-#define QOS_CFPOLL_RA_DW0 0x160c
-
-/*
- * QOS_CFPOLL_RA_DW1:
- */
-#define QOS_CFPOLL_RA_DW1 0x1610
-
-/*
- * QOS_CFPOLL_QC:
- */
-#define QOS_CFPOLL_QC 0x1614
-
-/*
- * RX_STA_CNT0: RX PLCP error count & RX CRC error count
- */
-#define RX_STA_CNT0 0x1700
-#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff)
-#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT1: RX False CCA count & RX LONG frame count
- */
-#define RX_STA_CNT1 0x1704
-#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff)
-#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT2:
- */
-#define RX_STA_CNT2 0x1708
-#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff)
-#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT0: TX Beacon count
- */
-#define TX_STA_CNT0 0x170c
-#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff)
-#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT1: TX tx count
- */
-#define TX_STA_CNT1 0x1710
-#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff)
-#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT2: TX tx count
- */
-#define TX_STA_CNT2 0x1714
-#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff)
-#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_STA_FIFO: TX Result for specific PID status fifo register
- */
-#define TX_STA_FIFO 0x1718
-#define TX_STA_FIFO_VALID FIELD32(0x00000001)
-#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e)
-#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020)
-#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040)
-#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080)
-#define TX_STA_FIFO_WCID FIELD32(0x0000ff00)
-#define TX_STA_FIFO_MCS FIELD32(0x007f0000)
-#define TX_STA_FIFO_PHYMODE FIELD32(0xc0000000)
-
-/*
- * TX_AGG_CNT: Debug counter
- */
-#define TX_AGG_CNT 0x171c
-#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT0:
- */
-#define TX_AGG_CNT0 0x1720
-#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT1:
- */
-#define TX_AGG_CNT1 0x1724
-#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT2:
- */
-#define TX_AGG_CNT2 0x1728
-#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT3:
- */
-#define TX_AGG_CNT3 0x172c
-#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT4:
- */
-#define TX_AGG_CNT4 0x1730
-#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT5:
- */
-#define TX_AGG_CNT5 0x1734
-#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT6:
- */
-#define TX_AGG_CNT6 0x1738
-#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT7:
- */
-#define TX_AGG_CNT7 0x173c
-#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000)
-
-/*
- * MPDU_DENSITY_CNT:
- * TX_ZERO_DEL: TX zero length delimiter count
- * RX_ZERO_DEL: RX zero length delimiter count
- */
-#define MPDU_DENSITY_CNT 0x1740
-#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff)
-#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000)
-
-/*
- * Security key table memory.
- * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
- * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
- * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
- * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
- * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry
- * SHARED_KEY_MODE_BASE: 4 bits * 32-entry
- */
-#define MAC_WCID_BASE 0x1800
-#define PAIRWISE_KEY_TABLE_BASE 0x4000
-#define MAC_IVEIV_TABLE_BASE 0x6000
-#define MAC_WCID_ATTRIBUTE_BASE 0x6800
-#define SHARED_KEY_TABLE_BASE 0x6c00
-#define SHARED_KEY_MODE_BASE 0x7000
-
-#define MAC_WCID_ENTRY(__idx) \
- ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
-#define PAIRWISE_KEY_ENTRY(__idx) \
- ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
-#define MAC_IVEIV_ENTRY(__idx) \
- ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) )
-#define MAC_WCID_ATTR_ENTRY(__idx) \
- ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
-#define SHARED_KEY_ENTRY(__idx) \
- ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
-#define SHARED_KEY_MODE_ENTRY(__idx) \
- ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
-
-struct mac_wcid_entry {
- u8 mac[6];
- u8 reserved[2];
-} __attribute__ ((packed));
-
-struct hw_key_entry {
- u8 key[16];
- u8 tx_mic[8];
- u8 rx_mic[8];
-} __attribute__ ((packed));
-
-struct mac_iveiv_entry {
- u8 iv[8];
-} __attribute__ ((packed));
-
-/*
- * MAC_WCID_ATTRIBUTE:
- */
-#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001)
-#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e)
-#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070)
-#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380)
-
-/*
- * SHARED_KEY_MODE:
- */
-#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007)
-#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070)
-#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700)
-#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000)
-#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000)
-#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000)
-#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000)
-#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000)
-
-/*
- * HOST-MCU communication
- */
-
-/*
- * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
- */
-#define H2M_MAILBOX_CSR 0x7010
-#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff)
-#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_CID:
- */
-#define H2M_MAILBOX_CID 0x7014
-#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff)
-#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_STATUS:
- */
-#define H2M_MAILBOX_STATUS 0x701c
-
-/*
- * H2M_INT_SRC:
- */
-#define H2M_INT_SRC 0x7024
-
-/*
- * H2M_BBP_AGENT:
- */
-#define H2M_BBP_AGENT 0x7028
-
-/*
- * MCU_LEDCS: LED control for MCU Mailbox.
- */
-#define MCU_LEDCS_LED_MODE FIELD8(0x1f)
-#define MCU_LEDCS_POLARITY FIELD8(0x01)
-
-/*
- * HW_CS_CTS_BASE:
- * Carrier-sense CTS frame base address.
- * It's where mac stores carrier-sense frame for carrier-sense function.
- */
-#define HW_CS_CTS_BASE 0x7700
-
-/*
- * HW_DFS_CTS_BASE:
- * FS CTS frame base address. It's where mac stores CTS frame for DFS.
- */
-#define HW_DFS_CTS_BASE 0x7780
-
-/*
- * TXRX control registers - base address 0x3000
- */
-
-/*
- * TXRX_CSR1:
- * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first..
- */
-#define TXRX_CSR1 0x77d0
-
-/*
- * HW_DEBUG_SETTING_BASE:
- * since NULL frame won't be that long (256 byte)
- * We steal 16 tail bytes to save debugging settings
- */
-#define HW_DEBUG_SETTING_BASE 0x77f0
-#define HW_DEBUG_SETTING_BASE2 0x7770
-
-/*
- * HW_BEACON_BASE
- * In order to support maximum 8 MBSS and its maximum length
- * is 512 bytes for each beacon
- * Three section discontinue memory segments will be used.
- * 1. The original region for BCN 0~3
- * 2. Extract memory from FCE table for BCN 4~5
- * 3. Extract memory from Pair-wise key table for BCN 6~7
- * It occupied those memory of wcid 238~253 for BCN 6
- * and wcid 222~237 for BCN 7
- *
- * IMPORTANT NOTE: Not sure why legacy driver does this,
- * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
- */
-#define HW_BEACON_BASE0 0x7800
-#define HW_BEACON_BASE1 0x7a00
-#define HW_BEACON_BASE2 0x7c00
-#define HW_BEACON_BASE3 0x7e00
-#define HW_BEACON_BASE4 0x7200
-#define HW_BEACON_BASE5 0x7400
-#define HW_BEACON_BASE6 0x5dc0
-#define HW_BEACON_BASE7 0x5bc0
-
-#define HW_BEACON_OFFSET(__index) \
- ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
- (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
- (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
-
-/*
* 8051 firmware image.
*/
#define FIRMWARE_RT2860 "rt2860.bin"
#define FIRMWARE_IMAGE_BASE 0x2000
/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP 1: TX Antenna
- */
-#define BBP1_TX_POWER FIELD8(0x07)
-#define BBP1_TX_ANTENNA FIELD8(0x18)
-
-/*
- * BBP 3: RX Antenna
- */
-#define BBP3_RX_ANTENNA FIELD8(0x18)
-#define BBP3_HT40_PLUS FIELD8(0x20)
-
-/*
- * BBP 4: Bandwidth
- */
-#define BBP4_TX_BF FIELD8(0x01)
-#define BBP4_BANDWIDTH FIELD8(0x18)
-
-/*
- * RFCSR registers
- * The wordsize of the RFCSR is 8 bits.
- */
-
-/*
- * RFCSR 6:
- */
-#define RFCSR6_R FIELD8(0x03)
-
-/*
- * RFCSR 7:
- */
-#define RFCSR7_RF_TUNING FIELD8(0x01)
-
-/*
- * RFCSR 12:
- */
-#define RFCSR12_TX_POWER FIELD8(0x1f)
-
-/*
- * RFCSR 22:
- */
-#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01)
-
-/*
- * RFCSR 23:
- */
-#define RFCSR23_FREQ_OFFSET FIELD8(0x7f)
-
-/*
- * RFCSR 30:
- */
-#define RFCSR30_RF_CALIBRATION FIELD8(0x80)
-
-/*
- * RF registers
- */
-
-/*
- * RF 2
- */
-#define RF2_ANTENNA_RX2 FIELD32(0x00000040)
-#define RF2_ANTENNA_TX1 FIELD32(0x00004000)
-#define RF2_ANTENNA_RX1 FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TXPOWER_G FIELD32(0x00003e00)
-#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200)
-#define RF3_TXPOWER_A FIELD32(0x00003c00)
-
-/*
- * RF 4
- */
-#define RF4_TXPOWER_G FIELD32(0x000007c0)
-#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040)
-#define RF4_TXPOWER_A FIELD32(0x00000780)
-#define RF4_FREQ_OFFSET FIELD32(0x001f8000)
-#define RF4_HT40 FIELD32(0x00200000)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * EEPROM Version
- */
-#define EEPROM_VERSION 0x0001
-#define EEPROM_VERSION_FAE FIELD16(0x00ff)
-#define EEPROM_VERSION_VERSION FIELD16(0xff00)
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0 0x0002
-#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_1 0x0003
-#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2 0x0004
-#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
-
-/*
- * EEPROM ANTENNA config
- * RXPATH: 1: 1R, 2: 2R, 3: 3R
- * TXPATH: 1: 1T, 2: 2T
- */
-#define EEPROM_ANTENNA 0x001a
-#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f)
-#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0)
-#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00)
-
-/*
- * EEPROM NIC config
- * CARDBUS_ACCEL: 0 - enable, 1 - disable
- */
-#define EEPROM_NIC 0x001b
-#define EEPROM_NIC_HW_RADIO FIELD16(0x0001)
-#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002)
-#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004)
-#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008)
-#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010)
-#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020)
-#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040)
-#define EEPROM_NIC_WPS_PBC FIELD16(0x0080)
-#define EEPROM_NIC_BW40M_BG FIELD16(0x0100)
-#define EEPROM_NIC_BW40M_A FIELD16(0x0200)
-
-/*
- * EEPROM frequency
- */
-#define EEPROM_FREQ 0x001d
-#define EEPROM_FREQ_OFFSET FIELD16(0x00ff)
-#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00)
-#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000)
-
-/*
- * EEPROM LED
- * POLARITY_RDY_G: Polarity RDY_G setting.
- * POLARITY_RDY_A: Polarity RDY_A setting.
- * POLARITY_ACT: Polarity ACT setting.
- * POLARITY_GPIO_0: Polarity GPIO0 setting.
- * POLARITY_GPIO_1: Polarity GPIO1 setting.
- * POLARITY_GPIO_2: Polarity GPIO2 setting.
- * POLARITY_GPIO_3: Polarity GPIO3 setting.
- * POLARITY_GPIO_4: Polarity GPIO4 setting.
- * LED_MODE: Led mode.
- */
-#define EEPROM_LED1 0x001e
-#define EEPROM_LED2 0x001f
-#define EEPROM_LED3 0x0020
-#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001)
-#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002)
-#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004)
-#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008)
-#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010)
-#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020)
-#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040)
-#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080)
-#define EEPROM_LED_LED_MODE FIELD16(0x1f00)
-
-/*
- * EEPROM LNA
- */
-#define EEPROM_LNA 0x0022
-#define EEPROM_LNA_BG FIELD16(0x00ff)
-#define EEPROM_LNA_A0 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG offset
- */
-#define EEPROM_RSSI_BG 0x0023
-#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff)
-#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG2 offset
- */
-#define EEPROM_RSSI_BG2 0x0024
-#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff)
-#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI A offset
- */
-#define EEPROM_RSSI_A 0x0025
-#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff)
-#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI A2 offset
- */
-#define EEPROM_RSSI_A2 0x0026
-#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff)
-#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00)
-
-/*
- * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
- * This is delta in 40MHZ.
- * VALUE: Tx Power dalta value (MAX=4)
- * TYPE: 1: Plus the delta value, 0: minus the delta value
- * TXPOWER: Enable:
- */
-#define EEPROM_TXPOWER_DELTA 0x0028
-#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f)
-#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040)
-#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080)
-
-/*
- * EEPROM TXPOWER 802.11BG
- */
-#define EEPROM_TXPOWER_BG1 0x0029
-#define EEPROM_TXPOWER_BG2 0x0030
-#define EEPROM_TXPOWER_BG_SIZE 7
-#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff)
-#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER 802.11A
- */
-#define EEPROM_TXPOWER_A1 0x003c
-#define EEPROM_TXPOWER_A2 0x0053
-#define EEPROM_TXPOWER_A_SIZE 6
-#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff)
-#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
-
-/*
- * EEPROM TXpower byrate: 20MHZ power
- */
-#define EEPROM_TXPOWER_BYRATE 0x006f
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START 0x0078
-#define EEPROM_BBP_SIZE 16
-#define EEPROM_BBP_VALUE FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID FIELD16(0xff00)
-
-/*
- * MCU mailbox commands.
- */
-#define MCU_SLEEP 0x30
-#define MCU_WAKEUP 0x31
-#define MCU_RADIO_OFF 0x35
-#define MCU_CURRENT 0x36
-#define MCU_LED 0x50
-#define MCU_LED_STRENGTH 0x51
-#define MCU_LED_1 0x52
-#define MCU_LED_2 0x53
-#define MCU_LED_3 0x54
-#define MCU_RADAR 0x60
-#define MCU_BOOT_SIGNAL 0x72
-#define MCU_BBP_SIGNAL 0x80
-#define MCU_POWER_SAVE 0x83
-
-/*
- * MCU mailbox tokens
- */
-#define TOKEN_WAKUP 3
-
-/*
* DMA descriptor defines.
*/
#define TXD_DESC_SIZE ( 4 * sizeof(__le32) )
-#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) )
#define RXD_DESC_SIZE ( 4 * sizeof(__le32) )
-#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO and Beacon Ring.
@@ -1806,52 +132,6 @@ struct mac_iveiv_entry {
#define TXD_W3_ICO FIELD32(0x80000000)
/*
- * TX WI structure
- */
-
-/*
- * Word0
- * FRAG: 1 To inform TKIP engine this is a fragment.
- * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
- * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
- * BW: Channel bandwidth 20MHz or 40 MHz
- * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
- */
-#define TXWI_W0_FRAG FIELD32(0x00000001)
-#define TXWI_W0_MIMO_PS FIELD32(0x00000002)
-#define TXWI_W0_CF_ACK FIELD32(0x00000004)
-#define TXWI_W0_TS FIELD32(0x00000008)
-#define TXWI_W0_AMPDU FIELD32(0x00000010)
-#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0)
-#define TXWI_W0_TX_OP FIELD32(0x00000300)
-#define TXWI_W0_MCS FIELD32(0x007f0000)
-#define TXWI_W0_BW FIELD32(0x00800000)
-#define TXWI_W0_SHORT_GI FIELD32(0x01000000)
-#define TXWI_W0_STBC FIELD32(0x06000000)
-#define TXWI_W0_IFS FIELD32(0x08000000)
-#define TXWI_W0_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word1
- */
-#define TXWI_W1_ACK FIELD32(0x00000001)
-#define TXWI_W1_NSEQ FIELD32(0x00000002)
-#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc)
-#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00)
-#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define TXWI_W1_PACKETID FIELD32(0xf0000000)
-
-/*
- * Word2
- */
-#define TXWI_W2_IV FIELD32(0xffffffff)
-
-/*
- * Word3
- */
-#define TXWI_W3_EIV FIELD32(0xffffffff)
-
-/*
* RX descriptor format for RX Ring.
*/
@@ -1897,64 +177,4 @@ struct mac_iveiv_entry {
#define RXD_W3_PLCP_SIGNAL FIELD32(0x00020000)
#define RXD_W3_PLCP_RSSI FIELD32(0x00040000)
-/*
- * RX WI structure
- */
-
-/*
- * Word0
- */
-#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff)
-#define RXWI_W0_KEY_INDEX FIELD32(0x00000300)
-#define RXWI_W0_BSSID FIELD32(0x00001c00)
-#define RXWI_W0_UDF FIELD32(0x0000e000)
-#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define RXWI_W0_TID FIELD32(0xf0000000)
-
-/*
- * Word1
- */
-#define RXWI_W1_FRAG FIELD32(0x0000000f)
-#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0)
-#define RXWI_W1_MCS FIELD32(0x007f0000)
-#define RXWI_W1_BW FIELD32(0x00800000)
-#define RXWI_W1_SHORT_GI FIELD32(0x01000000)
-#define RXWI_W1_STBC FIELD32(0x06000000)
-#define RXWI_W1_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define RXWI_W2_RSSI0 FIELD32(0x000000ff)
-#define RXWI_W2_RSSI1 FIELD32(0x0000ff00)
-#define RXWI_W2_RSSI2 FIELD32(0x00ff0000)
-
-/*
- * Word3
- */
-#define RXWI_W3_SNR0 FIELD32(0x000000ff)
-#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_G_TXPOWER 0
-#define MIN_A_TXPOWER -7
-#define MAX_G_TXPOWER 31
-#define MAX_A_TXPOWER 15
-#define DEFAULT_TXPOWER 5
-
-#define TXPOWER_G_FROM_DEV(__txpower) \
- ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_G_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
-
-#define TXPOWER_A_FROM_DEV(__txpower) \
- ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_A_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
-
#endif /* RT2800PCI_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 9fe770f7d7bb..ce2e893856c1 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -34,6 +34,8 @@
#include "rt2x00.h"
#include "rt2x00usb.h"
+#include "rt2800lib.h"
+#include "rt2800.h"
#include "rt2800usb.h"
/*
@@ -44,1027 +46,6 @@ module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
/*
- * Register access.
- * All access to the CSR registers will go through the methods
- * rt2x00usb_register_read and rt2x00usb_register_write.
- * BBP and RF register require indirect register access,
- * and use the CSR registers BBPCSR and RFCSR to achieve this.
- * These indirect registers work with busy bits,
- * and we will try maximal REGISTER_BUSY_COUNT times to access
- * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
- * the access attempt is considered to have failed,
- * and we will print an error.
- * The _lock versions must be used if you already hold the csr_mutex
- */
-#define WAIT_FOR_BBP(__dev, __reg) \
- rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RFCSR(__dev, __reg) \
- rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg))
-#define WAIT_FOR_RF(__dev, __reg) \
- rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg))
-#define WAIT_FOR_MCU(__dev, __reg) \
- rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \
- H2M_MAILBOX_CSR_OWNER, (__reg))
-
-static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u8 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the BBP becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, BBP_CSR_CFG_VALUE, value);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
-
- rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the BBP becomes available, afterwards we
- * can safely write the read request into the register.
- * After the data has been written, we wait until hardware
- * returns the correct value, if at any time the register
- * doesn't become available in time, reg will be 0xffffffff
- * which means we return 0xff to the caller.
- */
- if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
- rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
-
- rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
-
- WAIT_FOR_BBP(rt2x00dev, &reg);
- }
-
- *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u8 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RFCSR becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG_DATA, value);
- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 1);
- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
- rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u8 *value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RFCSR becomes available, afterwards we
- * can safely write the read request into the register.
- * After the data has been written, we wait until hardware
- * returns the correct value, if at any time the register
- * doesn't become available in time, reg will be 0xffffffff
- * which means we return 0xff to the caller.
- */
- if (WAIT_FOR_RFCSR(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG_REGNUM, word);
- rt2x00_set_field32(&reg, RF_CSR_CFG_WRITE, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG_BUSY, 1);
-
- rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
-
- WAIT_FOR_RFCSR(rt2x00dev, &reg);
- }
-
- *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA);
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, const u32 value)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the RF becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_RF(rt2x00dev, &reg)) {
- reg = 0;
- rt2x00_set_field32(&reg, RF_CSR_CFG0_REG_VALUE_BW, value);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_STANDBYMODE, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_SEL, 0);
- rt2x00_set_field32(&reg, RF_CSR_CFG0_BUSY, 1);
-
- rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev,
- const u8 command, const u8 token,
- const u8 arg0, const u8 arg1)
-{
- u32 reg;
-
- mutex_lock(&rt2x00dev->csr_mutex);
-
- /*
- * Wait until the MCU becomes available, afterwards we
- * can safely write the new data into the register.
- */
- if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg);
-
- reg = 0;
- rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
- rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg);
- }
-
- mutex_unlock(&rt2x00dev->csr_mutex);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-static const struct rt2x00debug rt2800usb_rt2x00debug = {
- .owner = THIS_MODULE,
- .csr = {
- .read = rt2x00usb_register_read,
- .write = rt2x00usb_register_write,
- .flags = RT2X00DEBUGFS_OFFSET,
- .word_base = CSR_REG_BASE,
- .word_size = sizeof(u32),
- .word_count = CSR_REG_SIZE / sizeof(u32),
- },
- .eeprom = {
- .read = rt2x00_eeprom_read,
- .write = rt2x00_eeprom_write,
- .word_base = EEPROM_BASE,
- .word_size = sizeof(u16),
- .word_count = EEPROM_SIZE / sizeof(u16),
- },
- .bbp = {
- .read = rt2800usb_bbp_read,
- .write = rt2800usb_bbp_write,
- .word_base = BBP_BASE,
- .word_size = sizeof(u8),
- .word_count = BBP_SIZE / sizeof(u8),
- },
- .rf = {
- .read = rt2x00_rf_read,
- .write = rt2800usb_rf_write,
- .word_base = RF_BASE,
- .word_size = sizeof(u32),
- .word_count = RF_SIZE / sizeof(u32),
- },
-};
-#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
-
-static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
-
- rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
- return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2);
-}
-
-#ifdef CONFIG_RT2X00_LIB_LEDS
-static void rt2800usb_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- unsigned int enabled = brightness != LED_OFF;
- unsigned int bg_mode =
- (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ);
- unsigned int polarity =
- rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
- EEPROM_FREQ_LED_POLARITY);
- unsigned int ledmode =
- rt2x00_get_field16(led->rt2x00dev->led_mcu_reg,
- EEPROM_FREQ_LED_MODE);
-
- if (led->type == LED_TYPE_RADIO) {
- rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? 0x20 : 0);
- } else if (led->type == LED_TYPE_ASSOC) {
- rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode,
- enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20);
- } else if (led->type == LED_TYPE_QUALITY) {
- /*
- * The brightness is divided into 6 levels (0 - 5),
- * The specs tell us the following levels:
- * 0, 1 ,3, 7, 15, 31
- * to determine the level in a simple way we can simply
- * work with bitshifting:
- * (1 << level) - 1
- */
- rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff,
- (1 << brightness / (LED_FULL / 6)) - 1,
- polarity);
- }
-}
-
-static int rt2800usb_blink_set(struct led_classdev *led_cdev,
- unsigned long *delay_on,
- unsigned long *delay_off)
-{
- struct rt2x00_led *led =
- container_of(led_cdev, struct rt2x00_led, led_dev);
- u32 reg;
-
- rt2x00usb_register_read(led->rt2x00dev, LED_CFG, &reg);
- rt2x00_set_field32(&reg, LED_CFG_ON_PERIOD, *delay_on);
- rt2x00_set_field32(&reg, LED_CFG_OFF_PERIOD, *delay_off);
- rt2x00_set_field32(&reg, LED_CFG_SLOW_BLINK_PERIOD, 3);
- rt2x00_set_field32(&reg, LED_CFG_R_LED_MODE, 3);
- rt2x00_set_field32(&reg, LED_CFG_G_LED_MODE, 12);
- rt2x00_set_field32(&reg, LED_CFG_Y_LED_MODE, 3);
- rt2x00_set_field32(&reg, LED_CFG_LED_POLAR, 1);
- rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg);
-
- return 0;
-}
-
-static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_led *led,
- enum led_type type)
-{
- led->rt2x00dev = rt2x00dev;
- led->type = type;
- led->led_dev.brightness_set = rt2800usb_brightness_set;
- led->led_dev.blink_set = rt2800usb_blink_set;
- led->flags = LED_INITIALIZED;
-}
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-/*
- * Configuration handlers.
- */
-static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct mac_wcid_entry wcid_entry;
- struct mac_iveiv_entry iveiv_entry;
- u32 offset;
- u32 reg;
-
- offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx);
-
- rt2x00usb_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_KEYTAB,
- !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE));
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_CIPHER,
- (crypto->cmd == SET_KEY) * crypto->cipher);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_BSS_IDX,
- (crypto->cmd == SET_KEY) * crypto->bssidx);
- rt2x00_set_field32(&reg, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher);
- rt2x00usb_register_write(rt2x00dev, offset, reg);
-
- offset = MAC_IVEIV_ENTRY(key->hw_key_idx);
-
- memset(&iveiv_entry, 0, sizeof(iveiv_entry));
- if ((crypto->cipher == CIPHER_TKIP) ||
- (crypto->cipher == CIPHER_TKIP_NO_MIC) ||
- (crypto->cipher == CIPHER_AES))
- iveiv_entry.iv[3] |= 0x20;
- iveiv_entry.iv[3] |= key->keyidx << 6;
- rt2x00usb_register_multiwrite(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
-
- offset = MAC_WCID_ENTRY(key->hw_key_idx);
-
- memset(&wcid_entry, 0, sizeof(wcid_entry));
- if (crypto->cmd == SET_KEY)
- memcpy(&wcid_entry, crypto->address, ETH_ALEN);
- rt2x00usb_register_multiwrite(rt2x00dev, offset,
- &wcid_entry, sizeof(wcid_entry));
-}
-
-static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct hw_key_entry key_entry;
- struct rt2x00_field32 field;
- int timeout;
- u32 offset;
- u32 reg;
-
- if (crypto->cmd == SET_KEY) {
- key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx;
-
- memcpy(key_entry.key, crypto->key,
- sizeof(key_entry.key));
- memcpy(key_entry.tx_mic, crypto->tx_mic,
- sizeof(key_entry.tx_mic));
- memcpy(key_entry.rx_mic, crypto->rx_mic,
- sizeof(key_entry.rx_mic));
-
- offset = SHARED_KEY_ENTRY(key->hw_key_idx);
- timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
- rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT,
- offset, &key_entry,
- sizeof(key_entry),
- timeout);
- }
-
- /*
- * The cipher types are stored over multiple registers
- * starting with SHARED_KEY_MODE_BASE each word will have
- * 32 bits and contains the cipher types for 2 bssidx each.
- * Using the correct defines correctly will cause overhead,
- * so just calculate the correct offset.
- */
- field.bit_offset = 4 * (key->hw_key_idx % 8);
- field.bit_mask = 0x7 << field.bit_offset;
-
- offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8);
-
- rt2x00usb_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, field,
- (crypto->cmd == SET_KEY) * crypto->cipher);
- rt2x00usb_register_write(rt2x00dev, offset, reg);
-
- /*
- * Update WCID information
- */
- rt2800usb_config_wcid_attr(rt2x00dev, crypto, key);
-
- return 0;
-}
-
-static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_crypto *crypto,
- struct ieee80211_key_conf *key)
-{
- struct hw_key_entry key_entry;
- int timeout;
- u32 offset;
-
- if (crypto->cmd == SET_KEY) {
- /*
- * 1 pairwise key is possible per AID, this means that the AID
- * equals our hw_key_idx. Make sure the WCID starts _after_ the
- * last possible shared key entry.
- */
- if (crypto->aid > (256 - 32))
- return -ENOSPC;
-
- key->hw_key_idx = 32 + crypto->aid;
-
- memcpy(key_entry.key, crypto->key,
- sizeof(key_entry.key));
- memcpy(key_entry.tx_mic, crypto->tx_mic,
- sizeof(key_entry.tx_mic));
- memcpy(key_entry.rx_mic, crypto->rx_mic,
- sizeof(key_entry.rx_mic));
-
- offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx);
- timeout = REGISTER_TIMEOUT32(sizeof(key_entry));
- rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT,
- offset, &key_entry,
- sizeof(key_entry),
- timeout);
- }
-
- /*
- * Update WCID information
- */
- rt2800usb_config_wcid_attr(rt2x00dev, crypto, key);
-
- return 0;
-}
-
-static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev,
- const unsigned int filter_flags)
-{
- u32 reg;
-
- /*
- * Start configuration steps.
- * Note that the version error will always be dropped
- * and broadcast frames will always be accepted since
- * there is no filter for it at this time.
- */
- rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, &reg);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CRC_ERROR,
- !(filter_flags & FIF_FCSFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PHY_ERROR,
- !(filter_flags & FIF_PLCPFAIL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_TO_ME,
- !(filter_flags & FIF_PROMISC_IN_BSS));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_VER_ERROR, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_MULTICAST,
- !(filter_flags & FIF_ALLMULTI));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BROADCAST, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_DUPLICATE, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END_ACK,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CF_END,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_ACK,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CTS,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
- !(filter_flags & FIF_CONTROL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
- !(filter_flags & FIF_PSPOLL));
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
- rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
- !(filter_flags & FIF_CONTROL));
- rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg);
-}
-
-static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev,
- struct rt2x00_intf *intf,
- struct rt2x00intf_conf *conf,
- const unsigned int flags)
-{
- unsigned int beacon_base;
- u32 reg;
-
- if (flags & CONFIG_UPDATE_TYPE) {
- /*
- * Clear current synchronisation setup.
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
- rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
-
- /*
- * Enable synchronisation.
- */
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
- rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
- }
-
- if (flags & CONFIG_UPDATE_MAC) {
- reg = le32_to_cpu(conf->mac[1]);
- rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
- conf->mac[1] = cpu_to_le32(reg);
-
- rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0,
- conf->mac, sizeof(conf->mac));
- }
-
- if (flags & CONFIG_UPDATE_BSSID) {
- reg = le32_to_cpu(conf->bssid[1]);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
- rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
- conf->bssid[1] = cpu_to_le32(reg);
-
- rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
- conf->bssid, sizeof(conf->bssid));
- }
-}
-
-static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_erp *erp)
-{
- u32 reg;
-
- rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20);
- rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_BAC_ACK_POLICY,
- !!erp->short_preamble);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AR_PREAMBLE,
- !!erp->short_preamble);
- rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL,
- erp->cts_protection ? 2 : 0);
- rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE,
- erp->basic_rates);
- rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-
- rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, &reg);
- rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time);
- rt2x00_set_field32(&reg, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2);
- rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
- rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
- rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
- erp->beacon_int * 16);
- rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-}
-
-static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
-{
- u8 r1;
- u8 r3;
-
- rt2800usb_bbp_read(rt2x00dev, 1, &r1);
- rt2800usb_bbp_read(rt2x00dev, 3, &r3);
-
- /*
- * Configure the TX antenna.
- */
- switch ((int)ant->tx) {
- case 1:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
- break;
- case 2:
- rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
- break;
- case 3:
- /* Do nothing */
- break;
- }
-
- /*
- * Configure the RX antenna.
- */
- switch ((int)ant->rx) {
- case 1:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
- break;
- case 2:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1);
- break;
- case 3:
- rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2);
- break;
- }
-
- rt2800usb_bbp_write(rt2x00dev, 3, r3);
- rt2800usb_bbp_write(rt2x00dev, 1, r1);
-}
-
-static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u16 eeprom;
- short lna_gain;
-
- if (libconf->rf.channel <= 14) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG);
- } else if (libconf->rf.channel <= 64) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0);
- } else if (libconf->rf.channel <= 128) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1);
- } else {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom);
- lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2);
- }
-
- rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
- if (rt2x00dev->default_ant.tx == 1)
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
-
- if (rt2x00dev->default_ant.rx == 1) {
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1);
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
- } else if (rt2x00dev->default_ant.rx == 2)
- rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
-
- if (rf->channel > 14) {
- /*
- * When TX power is below 0, we should increase it by 7 to
- * make it a positive value (Minumum value is -7).
- * However this means that values between 0 and 7 have
- * double meaning, and we should set a 7DBm boost flag.
- */
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
- (info->tx_power1 >= 0));
-
- if (info->tx_power1 < 0)
- info->tx_power1 += 7;
-
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power1));
-
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
- (info->tx_power2 >= 0));
-
- if (info->tx_power2 < 0)
- info->tx_power2 += 7;
-
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
- TXPOWER_A_TO_DEV(info->tx_power2));
- } else {
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power1));
- rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
- TXPOWER_G_TO_DEV(info->tx_power2));
- }
-
- rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
-
- rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
- rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt2800usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt2800usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt2800usb_rf_write(rt2x00dev, 4, rf->rf4);
-}
-
-static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- u8 rfcsr;
-
- rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1);
- rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3);
-
- rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
- rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr);
-
- rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER,
- TXPOWER_G_TO_DEV(info->tx_power1));
- rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr);
-
- rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
- rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr);
-
- rt2800usb_rfcsr_write(rt2x00dev, 24,
- rt2x00dev->calibration[conf_is_ht40(conf)]);
-
- rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
- rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr);
-}
-
-static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf,
- struct rf_channel *rf,
- struct channel_info *info)
-{
- u32 reg;
- unsigned int tx_pin;
- u8 bbp;
-
- if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
- rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info);
- else
- rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info);
-
- /*
- * Change BBP settings
- */
- rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain);
- rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain);
- rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain);
- rt2800usb_bbp_write(rt2x00dev, 86, 0);
-
- if (rf->channel <= 14) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
- rt2800usb_bbp_write(rt2x00dev, 82, 0x62);
- rt2800usb_bbp_write(rt2x00dev, 75, 0x46);
- } else {
- rt2800usb_bbp_write(rt2x00dev, 82, 0x84);
- rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
- }
- } else {
- rt2800usb_bbp_write(rt2x00dev, 82, 0xf2);
-
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
- rt2800usb_bbp_write(rt2x00dev, 75, 0x46);
- else
- rt2800usb_bbp_write(rt2x00dev, 75, 0x50);
- }
-
- rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, &reg);
- rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
- rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
- rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
- rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg);
-
- tx_pin = 0;
-
- /* Turn on unused PA or LNA when not using 1T or 1R */
- if (rt2x00dev->default_ant.tx != 1) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
- }
-
- /* Turn on unused PA or LNA when not using 1T or 1R */
- if (rt2x00dev->default_ant.rx != 1) {
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1);
- }
-
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14);
- rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14);
-
- rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
-
- rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf));
- rt2800usb_bbp_write(rt2x00dev, 4, bbp);
-
- rt2800usb_bbp_read(rt2x00dev, 3, &bbp);
- rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
- rt2800usb_bbp_write(rt2x00dev, 3, bbp);
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
- if (conf_is_ht40(conf)) {
- rt2800usb_bbp_write(rt2x00dev, 69, 0x1a);
- rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
- rt2800usb_bbp_write(rt2x00dev, 73, 0x16);
- } else {
- rt2800usb_bbp_write(rt2x00dev, 69, 0x16);
- rt2800usb_bbp_write(rt2x00dev, 70, 0x08);
- rt2800usb_bbp_write(rt2x00dev, 73, 0x11);
- }
- }
-
- msleep(1);
-}
-
-static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev,
- const int txpower)
-{
- u32 reg;
- u32 value = TXPOWER_G_TO_DEV(txpower);
- u8 r1;
-
- rt2800usb_bbp_read(rt2x00dev, 1, &r1);
- rt2x00_set_field8(&reg, BBP1_TX_POWER, 0);
- rt2800usb_bbp_write(rt2x00dev, 1, r1);
-
- rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_1MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_2MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_55MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_11MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_6MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_9MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_12MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_0_18MBS, value);
- rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg);
-
- rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_24MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_36MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_48MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_54MBS, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS0, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS1, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS2, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_1_MCS3, value);
- rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg);
-
- rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS4, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS5, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS6, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS7, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS8, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS9, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS10, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_2_MCS11, value);
- rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg);
-
- rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS12, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS13, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS14, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_MCS15, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN1, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN2, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN3, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_3_UKNOWN4, value);
- rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg);
-
- rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, &reg);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN5, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN6, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN7, value);
- rt2x00_set_field32(&reg, TX_PWR_CFG_4_UKNOWN8, value);
- rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg);
-}
-
-static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u32 reg;
-
- rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTY_CFG_SHORT_RTY_LIMIT,
- libconf->conf->short_frame_max_tx_count);
- rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_LIMIT,
- libconf->conf->long_frame_max_tx_count);
- rt2x00_set_field32(&reg, TX_RTY_CFG_LONG_RTY_THRE, 2000);
- rt2x00_set_field32(&reg, TX_RTY_CFG_NON_AGG_RTY_MODE, 0);
- rt2x00_set_field32(&reg, TX_RTY_CFG_AGG_RTY_MODE, 0);
- rt2x00_set_field32(&reg, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1);
- rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg);
-}
-
-static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- enum dev_state state =
- (libconf->conf->flags & IEEE80211_CONF_PS) ?
- STATE_SLEEP : STATE_AWAKE;
- u32 reg;
-
- if (state == STATE_SLEEP) {
- rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0);
-
- rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE,
- libconf->conf->listen_interval - 1);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 1);
- rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
-
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
- } else {
- rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-
- rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0);
- rt2x00_set_field32(&reg, AUTOWAKEUP_CFG_AUTOWAKE, 0);
- rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg);
- }
-}
-
-static void rt2800usb_config(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf,
- const unsigned int flags)
-{
- /* Always recalculate LNA gain before changing configuration */
- rt2800usb_config_lna_gain(rt2x00dev, libconf);
-
- if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
- rt2800usb_config_channel(rt2x00dev, libconf->conf,
- &libconf->rf, &libconf->channel);
- if (flags & IEEE80211_CONF_CHANGE_POWER)
- rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level);
- if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
- rt2800usb_config_retry_limit(rt2x00dev, libconf);
- if (flags & IEEE80211_CONF_CHANGE_PS)
- rt2800usb_config_ps(rt2x00dev, libconf);
-}
-
-/*
- * Link tuning
- */
-static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual)
-{
- u32 reg;
-
- /*
- * Update FCS error count from register.
- */
- rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, &reg);
- qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR);
-}
-
-static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev)
-{
- if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) {
- if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION)
- return 0x1c + (2 * rt2x00dev->lna_gain);
- else
- return 0x2e + rt2x00dev->lna_gain;
- }
-
- if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
- return 0x32 + (rt2x00dev->lna_gain * 5) / 3;
- else
- return 0x3a + (rt2x00dev->lna_gain * 5) / 3;
-}
-
-static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual, u8 vgc_level)
-{
- if (qual->vgc_level != vgc_level) {
- rt2800usb_bbp_write(rt2x00dev, 66, vgc_level);
- qual->vgc_level = vgc_level;
- qual->vgc_level_reg = vgc_level;
- }
-}
-
-static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual)
-{
- rt2800usb_set_vgc(rt2x00dev, qual,
- rt2800usb_get_default_vgc(rt2x00dev));
-}
-
-static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev,
- struct link_qual *qual, const u32 count)
-{
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION)
- return;
-
- /*
- * When RSSI is better then -80 increase VGC level with 0x10
- */
- rt2800usb_set_vgc(rt2x00dev, qual,
- rt2800usb_get_default_vgc(rt2x00dev) +
- ((qual->rssi > -80) * 0x10));
-}
-
-/*
* Firmware functions
*/
static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
@@ -1172,7 +153,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for stable hardware.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
if (reg && reg != ~0)
break;
msleep(1);
@@ -1192,8 +173,8 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
data + offset, length,
REGISTER_TIMEOUT32(length));
- rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
- rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
/*
* Send firmware request to device to load firmware,
@@ -1208,18 +189,18 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
}
msleep(10);
- rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
/*
* Send signal to firmware during boot time.
*/
- rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0);
if ((chipset == 0x3070) ||
(chipset == 0x3071) ||
(chipset == 0x3572)) {
udelay(200);
- rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0);
udelay(10);
}
@@ -1227,7 +208,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
* Wait for device to stabilize.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY))
break;
msleep(1);
@@ -1241,536 +222,14 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Initialize firmware.
*/
- rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
+ rt2800_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
msleep(1);
return 0;
}
/*
- * Initialization functions.
- */
-static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- /*
- * Wait untill BBP and RF are ready.
- */
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
- if (reg && reg != ~0)
- break;
- msleep(1);
- }
-
- if (i == REGISTER_BUSY_COUNT) {
- ERROR(rt2x00dev, "Unstable hardware.\n");
- return -EBUSY;
- }
-
- rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, &reg);
- rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000);
-
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_CSR, 1);
- rt2x00_set_field32(&reg, MAC_SYS_CTRL_RESET_BBP, 1);
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
- rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000);
-
- rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0,
- USB_MODE_RESET, REGISTER_TIMEOUT);
-
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
- rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */
- rt2x00_set_field32(&reg, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */
- rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg);
-
- rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, &reg);
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */
- rt2x00_set_field32(&reg, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */
- rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg);
-
- rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f);
- rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003);
-
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000);
-
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00_set_field32(&reg, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0);
- rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
- rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
- rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
- rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
- } else {
- rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
- rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
- }
-
- rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, &reg);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32);
- rt2x00_set_field32(&reg, TX_LINK_CFG_MFB_ENABLE, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_MRQ_EN, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_RDG_EN, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_TX_CF_ACK_EN, 1);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFB, 0);
- rt2x00_set_field32(&reg, TX_LINK_CFG_REMOTE_MFS, 0);
- rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, &reg);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9);
- rt2x00_set_field32(&reg, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10);
- rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, &reg);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE);
- if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION &&
- rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION)
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 2);
- else
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MAX_PSDU, 1);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_PSDU, 0);
- rt2x00_set_field32(&reg, MAX_LEN_CFG_MIN_MPDU, 0);
- rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg);
-
- rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f);
-
- rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, &reg);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_AUTORESPONDER, 1);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MMODE, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_CTS_40_MREF, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_DUAL_CTS_EN, 0);
- rt2x00_set_field32(&reg, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0);
- rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 8);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 8);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
- rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_RATE, 0x4004);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0);
- rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_RATE, 0x4084);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_CTRL, 0);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_PROTECT_NAV, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1);
- rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
- rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006);
-
- rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_BIG_ENDIAN, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0);
- rt2x00_set_field32(&reg, WPDMA_GLO_CFG_HDR_SEG_LEN, 0);
- rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
-
- rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
- rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
-
- rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES,
- IEEE80211_MAX_RTS_THRESHOLD);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_FBK_EN, 0);
- rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
- rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca);
- rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
-
- /*
- * ASIC will keep garbage value after boot, clear encryption keys.
- */
- for (i = 0; i < 4; i++)
- rt2x00usb_register_write(rt2x00dev,
- SHARED_KEY_MODE_ENTRY(i), 0);
-
- for (i = 0; i < 256; i++) {
- u32 wcid[2] = { 0xffffffff, 0x00ffffff };
- rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
- wcid, sizeof(wcid));
-
- rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
- rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
- }
-
- /*
- * Clear all beacons
- * For the Beacon base registers we only need to clear
- * the first byte since that byte contains the VALID and OWNER
- * bits which (when set to 0) will invalidate the entire beacon.
- */
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
- rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
-
- rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, &reg);
- rt2x00_set_field32(&reg, USB_CYC_CFG_CLOCK_CYCLE, 30);
- rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS0FBK, 0);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS1FBK, 0);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS2FBK, 1);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS3FBK, 2);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS4FBK, 3);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS5FBK, 4);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS6FBK, 5);
- rt2x00_set_field32(&reg, HT_FBK_CFG0_HTMCS7FBK, 6);
- rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg);
-
- rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, &reg);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS8FBK, 8);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS9FBK, 8);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS10FBK, 9);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS11FBK, 10);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS12FBK, 11);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS13FBK, 12);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS14FBK, 13);
- rt2x00_set_field32(&reg, HT_FBK_CFG1_HTMCS15FBK, 14);
- rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg);
-
- rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, &reg);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS0FBK, 8);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS1FBK, 8);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS2FBK, 9);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS3FBK, 10);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS4FBK, 11);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS5FBK, 12);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS6FBK, 13);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_OFDMMCS7FBK, 14);
- rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg);
-
- rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, &reg);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS0FBK, 0);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS1FBK, 0);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS2FBK, 1);
- rt2x00_set_field32(&reg, LG_FBK_CFG0_CCKMCS3FBK, 2);
- rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg);
-
- /*
- * We must clear the error counters.
- * These registers are cleared on read,
- * so we may pass a useless variable to store the value.
- */
- rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, &reg);
- rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, &reg);
- rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, &reg);
- rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, &reg);
- rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, &reg);
- rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, &reg);
-
- return 0;
-}
-
-static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u32 reg;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, &reg);
- if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY))
- return 0;
-
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n");
- return -EACCES;
-}
-
-static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u8 value;
-
- /*
- * BBP was enabled after firmware was loaded,
- * but we need to reactivate it now.
- */
- rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0);
- rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0);
- msleep(1);
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2800usb_bbp_read(rt2x00dev, 0, &value);
- if ((value != 0xff) && (value != 0x00))
- return 0;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "BBP register access failed, aborting.\n");
- return -EACCES;
-}
-
-static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev)
-{
- unsigned int i;
- u16 eeprom;
- u8 reg_id;
- u8 value;
-
- if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) ||
- rt2800usb_wait_bbp_ready(rt2x00dev)))
- return -EACCES;
-
- rt2800usb_bbp_write(rt2x00dev, 65, 0x2c);
- rt2800usb_bbp_write(rt2x00dev, 66, 0x38);
- rt2800usb_bbp_write(rt2x00dev, 69, 0x12);
- rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
- rt2800usb_bbp_write(rt2x00dev, 73, 0x10);
- rt2800usb_bbp_write(rt2x00dev, 81, 0x37);
- rt2800usb_bbp_write(rt2x00dev, 82, 0x62);
- rt2800usb_bbp_write(rt2x00dev, 83, 0x6a);
- rt2800usb_bbp_write(rt2x00dev, 84, 0x99);
- rt2800usb_bbp_write(rt2x00dev, 86, 0x00);
- rt2800usb_bbp_write(rt2x00dev, 91, 0x04);
- rt2800usb_bbp_write(rt2x00dev, 92, 0x00);
- rt2800usb_bbp_write(rt2x00dev, 103, 0x00);
- rt2800usb_bbp_write(rt2x00dev, 105, 0x05);
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) {
- rt2800usb_bbp_write(rt2x00dev, 69, 0x16);
- rt2800usb_bbp_write(rt2x00dev, 73, 0x12);
- }
-
- if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) {
- rt2800usb_bbp_write(rt2x00dev, 84, 0x19);
- }
-
- if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) {
- rt2800usb_bbp_write(rt2x00dev, 70, 0x0a);
- rt2800usb_bbp_write(rt2x00dev, 84, 0x99);
- rt2800usb_bbp_write(rt2x00dev, 105, 0x05);
- }
-
- for (i = 0; i < EEPROM_BBP_SIZE; i++) {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
-
- if (eeprom != 0xffff && eeprom != 0x0000) {
- reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID);
- value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE);
- rt2800usb_bbp_write(rt2x00dev, reg_id, value);
- }
- }
-
- return 0;
-}
-
-static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev,
- bool bw40, u8 rfcsr24, u8 filter_target)
-{
- unsigned int i;
- u8 bbp;
- u8 rfcsr;
- u8 passband;
- u8 stopband;
- u8 overtuned = 0;
-
- rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
-
- rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
- rt2800usb_bbp_write(rt2x00dev, 4, bbp);
-
- rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
- rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * Set power & frequency of passband test tone
- */
- rt2800usb_bbp_write(rt2x00dev, 24, 0);
-
- for (i = 0; i < 100; i++) {
- rt2800usb_bbp_write(rt2x00dev, 25, 0x90);
- msleep(1);
-
- rt2800usb_bbp_read(rt2x00dev, 55, &passband);
- if (passband)
- break;
- }
-
- /*
- * Set power & frequency of stopband test tone
- */
- rt2800usb_bbp_write(rt2x00dev, 24, 0x06);
-
- for (i = 0; i < 100; i++) {
- rt2800usb_bbp_write(rt2x00dev, 25, 0x90);
- msleep(1);
-
- rt2800usb_bbp_read(rt2x00dev, 55, &stopband);
-
- if ((passband - stopband) <= filter_target) {
- rfcsr24++;
- overtuned += ((passband - stopband) == filter_target);
- } else
- break;
-
- rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
- }
-
- rfcsr24 -= !!overtuned;
-
- rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24);
- return rfcsr24;
-}
-
-static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev)
-{
- u8 rfcsr;
- u8 bbp;
-
- if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
- return 0;
-
- /*
- * Init RF calibration.
- */
- rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
- rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr);
- msleep(1);
- rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
- rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr);
-
- rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40);
- rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03);
- rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02);
- rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70);
- rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f);
- rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71);
- rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21);
- rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b);
- rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90);
- rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58);
- rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3);
- rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92);
- rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c);
- rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02);
- rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba);
- rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb);
- rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16);
- rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01);
- rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03);
- rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f);
-
- /*
- * Set RX Filter calibration for 20MHz and 40MHz
- */
- rt2x00dev->calibration[0] =
- rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16);
- rt2x00dev->calibration[1] =
- rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19);
-
- /*
- * Set back to initial state
- */
- rt2800usb_bbp_write(rt2x00dev, 24, 0);
-
- rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr);
- rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
- rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr);
-
- /*
- * set BBP back to BW20
- */
- rt2800usb_bbp_read(rt2x00dev, 4, &bbp);
- rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
- rt2800usb_bbp_write(rt2x00dev, 4, bbp);
-
- return 0;
-}
-
-/*
* Device state switch handlers.
*/
static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
@@ -1778,11 +237,11 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
(state == STATE_RADIO_RX_ON) ||
(state == STATE_RADIO_RX_ON_LINK));
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
}
static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
@@ -1791,7 +250,7 @@ static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
u32 reg;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
!rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
return 0;
@@ -1812,25 +271,25 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
* Initialize all registers.
*/
if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) ||
- rt2800usb_init_registers(rt2x00dev) ||
- rt2800usb_init_bbp(rt2x00dev) ||
- rt2800usb_init_rfcsr(rt2x00dev)))
+ rt2800_init_registers(rt2x00dev) ||
+ rt2800_init_bbp(rt2x00dev) ||
+ rt2800_init_rfcsr(rt2x00dev)))
return -EIO;
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
udelay(50);
- rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1);
- rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, &reg);
+ rt2800_register_read(rt2x00dev, USB_DMA_CFG, &reg);
rt2x00_set_field32(&reg, USB_DMA_CFG_PHY_CLEAR, 0);
/* Don't use bulk in aggregation when working with USB 1.1 */
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_EN,
@@ -1844,26 +303,26 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3);
rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
- rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg);
+ rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
- rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
+ rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 1);
rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 1);
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
/*
* Initialize LED control
*/
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word);
- rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_1, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word);
- rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_2, 0xff,
word & 0xff, (word >> 8) & 0xff);
rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word);
- rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
+ rt2800_mcu_request(rt2x00dev, MCU_LED_3, 0xff,
word & 0xff, (word >> 8) & 0xff);
return 0;
@@ -1873,14 +332,14 @@ static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
+ rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
rt2x00_set_field32(&reg, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
- rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
+ rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
- rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
- rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0);
- rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0);
+ rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, 0);
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
/* Wait for DMA, ignore error */
rt2800usb_wait_wpdma_ready(rt2x00dev);
@@ -1892,9 +351,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
enum dev_state state)
{
if (state == STATE_AWAKE)
- rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
else
- rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
return 0;
}
@@ -2048,9 +507,9 @@ static void rt2800usb_write_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
- rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
/*
* Write entire beacon with descriptor to register.
@@ -2093,12 +552,12 @@ static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
return;
}
- rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+ rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) {
rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
- rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+ rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
}
}
@@ -2124,7 +583,7 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
*/
memcpy(skbdesc->desc, rxd, skbdesc->desc_len);
rxd = (__le32 *)skbdesc->desc;
- rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)];
+ rxwi = &rxd[RXINFO_DESC_SIZE / sizeof(__le32)];
/*
* It is now safe to read the descriptor on all architectures.
@@ -2326,7 +785,7 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2870, value, reg);
/*
@@ -2385,9 +844,9 @@ static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Store led settings, for correct led behaviour.
*/
#ifdef CONFIG_RT2X00_LIB_LEDS
- rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
- rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
- rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+ rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ,
&rt2x00dev->led_mcu_reg);
@@ -2600,10 +1059,25 @@ static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
return 0;
}
+static const struct rt2800_ops rt2800usb_rt2800_ops = {
+ .register_read = rt2x00usb_register_read,
+ .register_write = rt2x00usb_register_write,
+ .register_write_lock = rt2x00usb_register_write_lock,
+
+ .register_multiread = rt2x00usb_register_multiread,
+ .register_multiwrite = rt2x00usb_register_multiwrite,
+
+ .regbusy_read = rt2x00usb_regbusy_read,
+};
+
static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
{
int retval;
+ rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+
+ rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops;
+
/*
* Allocate eeprom data.
*/
@@ -2645,162 +1119,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
return 0;
}
-/*
- * IEEE80211 stack callback functions.
- */
-static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx,
- u32 *iv32, u16 *iv16)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct mac_iveiv_entry iveiv_entry;
- u32 offset;
-
- offset = MAC_IVEIV_ENTRY(hw_key_idx);
- rt2x00usb_register_multiread(rt2x00dev, offset,
- &iveiv_entry, sizeof(iveiv_entry));
-
- memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16));
- memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32));
-}
-
-static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
- bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD);
-
- rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, &reg);
- rt2x00_set_field32(&reg, TX_RTS_CFG_RTS_THRES, value);
- rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, CCK_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, OFDM_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM20_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, MM40_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF20_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, &reg);
- rt2x00_set_field32(&reg, GF40_PROT_CFG_RTS_TH_EN, enabled);
- rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg);
-
- return 0;
-}
-
-static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
- const struct ieee80211_tx_queue_params *params)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- struct data_queue *queue;
- struct rt2x00_field32 field;
- int retval;
- u32 reg;
- u32 offset;
-
- /*
- * First pass the configuration through rt2x00lib, that will
- * update the queue settings and validate the input. After that
- * we are free to update the registers based on the value
- * in the queue parameter.
- */
- retval = rt2x00mac_conf_tx(hw, queue_idx, params);
- if (retval)
- return retval;
-
- /*
- * We only need to perform additional register initialization
- * for WMM queues/
- */
- if (queue_idx >= 4)
- return 0;
-
- queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
-
- /* Update WMM TXOP register */
- offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
- field.bit_offset = (queue_idx & 1) * 16;
- field.bit_mask = 0xffff << field.bit_offset;
-
- rt2x00usb_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, field, queue->txop);
- rt2x00usb_register_write(rt2x00dev, offset, reg);
-
- /* Update WMM registers */
- field.bit_offset = queue_idx * 4;
- field.bit_mask = 0xf << field.bit_offset;
-
- rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->aifs);
- rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->cw_min);
- rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg);
-
- rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, &reg);
- rt2x00_set_field32(&reg, field, queue->cw_max);
- rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg);
-
- /* Update EDCA registers */
- offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx);
-
- rt2x00usb_register_read(rt2x00dev, offset, &reg);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_TX_OP, queue->txop);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_AIFSN, queue->aifs);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMIN, queue->cw_min);
- rt2x00_set_field32(&reg, EDCA_AC0_CFG_CWMAX, queue->cw_max);
- rt2x00usb_register_write(rt2x00dev, offset, reg);
-
- return 0;
-}
-
-static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u64 tsf;
- u32 reg;
-
- rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, &reg);
- tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32;
- rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, &reg);
- tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD);
-
- return tsf;
-}
-
-static const struct ieee80211_ops rt2800usb_mac80211_ops = {
- .tx = rt2x00mac_tx,
- .start = rt2x00mac_start,
- .stop = rt2x00mac_stop,
- .add_interface = rt2x00mac_add_interface,
- .remove_interface = rt2x00mac_remove_interface,
- .config = rt2x00mac_config,
- .configure_filter = rt2x00mac_configure_filter,
- .set_tim = rt2x00mac_set_tim,
- .set_key = rt2x00mac_set_key,
- .get_stats = rt2x00mac_get_stats,
- .get_tkip_seq = rt2800usb_get_tkip_seq,
- .set_rts_threshold = rt2800usb_set_rts_threshold,
- .bss_info_changed = rt2x00mac_bss_info_changed,
- .conf_tx = rt2800usb_conf_tx,
- .get_tx_stats = rt2x00mac_get_tx_stats,
- .get_tsf = rt2800usb_get_tsf,
- .rfkill_poll = rt2x00mac_rfkill_poll,
-};
-
static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.probe_hw = rt2800usb_probe_hw,
.get_firmware_name = rt2800usb_get_firmware_name,
@@ -2810,10 +1128,10 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.uninitialize = rt2x00usb_uninitialize,
.clear_entry = rt2x00usb_clear_entry,
.set_device_state = rt2800usb_set_device_state,
- .rfkill_poll = rt2800usb_rfkill_poll,
- .link_stats = rt2800usb_link_stats,
- .reset_tuner = rt2800usb_reset_tuner,
- .link_tuner = rt2800usb_link_tuner,
+ .rfkill_poll = rt2800_rfkill_poll,
+ .link_stats = rt2800_link_stats,
+ .reset_tuner = rt2800_reset_tuner,
+ .link_tuner = rt2800_link_tuner,
.write_tx_desc = rt2800usb_write_tx_desc,
.write_tx_data = rt2x00usb_write_tx_data,
.write_beacon = rt2800usb_write_beacon,
@@ -2821,19 +1139,19 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
.kick_tx_queue = rt2800usb_kick_tx_queue,
.kill_tx_queue = rt2x00usb_kill_tx_queue,
.fill_rxdone = rt2800usb_fill_rxdone,
- .config_shared_key = rt2800usb_config_shared_key,
- .config_pairwise_key = rt2800usb_config_pairwise_key,
- .config_filter = rt2800usb_config_filter,
- .config_intf = rt2800usb_config_intf,
- .config_erp = rt2800usb_config_erp,
- .config_ant = rt2800usb_config_ant,
- .config = rt2800usb_config,
+ .config_shared_key = rt2800_config_shared_key,
+ .config_pairwise_key = rt2800_config_pairwise_key,
+ .config_filter = rt2800_config_filter,
+ .config_intf = rt2800_config_intf,
+ .config_erp = rt2800_config_erp,
+ .config_ant = rt2800_config_ant,
+ .config = rt2800_config,
};
static const struct data_queue_desc rt2800usb_queue_rx = {
.entry_num = RX_ENTRIES,
.data_size = AGGREGATION_SIZE,
- .desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE,
+ .desc_size = RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
.priv_size = sizeof(struct queue_entry_priv_usb),
};
@@ -2862,9 +1180,9 @@ static const struct rt2x00_ops rt2800usb_ops = {
.tx = &rt2800usb_queue_tx,
.bcn = &rt2800usb_queue_bcn,
.lib = &rt2800usb_rt2x00_ops,
- .hw = &rt2800usb_mac80211_ops,
+ .hw = &rt2800_mac80211_ops,
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
- .debugfs = &rt2800usb_rt2x00debug,
+ .debugfs = &rt2800_rt2x00debug,
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
};
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h
index 4d9991c9a51c..c9d7d40ee5fb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.h
+++ b/drivers/net/wireless/rt2x00/rt2800usb.h
@@ -28,288 +28,10 @@
#define RT2800USB_H
/*
- * RF chip defines.
- *
- * RF2820 2.4G 2T3R
- * RF2850 2.4G/5G 2T3R
- * RF2720 2.4G 1T2R
- * RF2750 2.4G/5G 1T2R
- * RF3020 2.4G 1T1R
- * RF2020 2.4G B/G
- * RF3021 2.4G 1T2R
- * RF3022 2.4G 2T2R
- * RF3052 2.4G 2T2R
- */
-#define RF2820 0x0001
-#define RF2850 0x0002
-#define RF2720 0x0003
-#define RF2750 0x0004
-#define RF3020 0x0005
-#define RF2020 0x0006
-#define RF3021 0x0007
-#define RF3022 0x0008
-#define RF3052 0x0009
-
-/*
- * RT2870 version
- */
-#define RT2860C_VERSION 0x28600100
-#define RT2860D_VERSION 0x28600101
-#define RT2880E_VERSION 0x28720200
-#define RT2883_VERSION 0x28830300
-#define RT3070_VERSION 0x30700200
-
-/*
- * Signal information.
- * Defaul offset is required for RSSI <-> dBm conversion.
- */
-#define DEFAULT_RSSI_OFFSET 120 /* FIXME */
-
-/*
- * Register layout information.
- */
-#define CSR_REG_BASE 0x1000
-#define CSR_REG_SIZE 0x0800
-#define EEPROM_BASE 0x0000
-#define EEPROM_SIZE 0x0110
-#define BBP_BASE 0x0000
-#define BBP_SIZE 0x0080
-#define RF_BASE 0x0004
-#define RF_SIZE 0x0010
-
-/*
- * Number of TX queues.
- */
-#define NUM_TX_QUEUES 4
-
-/*
* USB registers.
*/
/*
- * HOST-MCU shared memory
- */
-#define HOST_CMD_CSR 0x0404
-#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff)
-
-/*
- * INT_SOURCE_CSR: Interrupt source register.
- * Write one to clear corresponding bit.
- * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
- */
-#define INT_SOURCE_CSR 0x0200
-#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001)
-#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002)
-#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004)
-#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008)
-#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010)
-#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020)
-#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040)
-#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
-#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
-#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200)
-#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400)
-#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800)
-#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000)
-#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
-#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000)
-#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000)
-#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000)
-#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000)
-
-/*
- * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF.
- */
-#define INT_MASK_CSR 0x0204
-#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001)
-#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002)
-#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004)
-#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008)
-#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010)
-#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020)
-#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040)
-#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080)
-#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100)
-#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200)
-#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400)
-#define INT_MASK_CSR_TBTT FIELD32(0x00000800)
-#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000)
-#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000)
-#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000)
-#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000)
-#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000)
-#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000)
-
-/*
- * WPDMA_GLO_CFG
- */
-#define WPDMA_GLO_CFG 0x0208
-#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001)
-#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002)
-#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004)
-#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008)
-#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030)
-#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040)
-#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080)
-#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00)
-#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000)
-
-/*
- * WPDMA_RST_IDX
- */
-#define WPDMA_RST_IDX 0x020c
-#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001)
-#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002)
-#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004)
-#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008)
-#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010)
-#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020)
-#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000)
-
-/*
- * DELAY_INT_CFG
- */
-#define DELAY_INT_CFG 0x0210
-#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff)
-#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00)
-#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000)
-#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000)
-#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000)
-#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000)
-
-/*
- * WMM_AIFSN_CFG: Aifsn for each EDCA AC
- * AIFSN0: AC_BE
- * AIFSN1: AC_BK
- * AIFSN1: AC_VI
- * AIFSN1: AC_VO
- */
-#define WMM_AIFSN_CFG 0x0214
-#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f)
-#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0)
-#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00)
-#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000)
-
-/*
- * WMM_CWMIN_CSR: CWmin for each EDCA AC
- * CWMIN0: AC_BE
- * CWMIN1: AC_BK
- * CWMIN1: AC_VI
- * CWMIN1: AC_VO
- */
-#define WMM_CWMIN_CFG 0x0218
-#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f)
-#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0)
-#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00)
-#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000)
-
-/*
- * WMM_CWMAX_CSR: CWmax for each EDCA AC
- * CWMAX0: AC_BE
- * CWMAX1: AC_BK
- * CWMAX1: AC_VI
- * CWMAX1: AC_VO
- */
-#define WMM_CWMAX_CFG 0x021c
-#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f)
-#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0)
-#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00)
-#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000)
-
-/*
- * AC_TXOP0: AC_BK/AC_BE TXOP register
- * AC0TXOP: AC_BK in unit of 32us
- * AC1TXOP: AC_BE in unit of 32us
- */
-#define WMM_TXOP0_CFG 0x0220
-#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff)
-#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000)
-
-/*
- * AC_TXOP1: AC_VO/AC_VI TXOP register
- * AC2TXOP: AC_VI in unit of 32us
- * AC3TXOP: AC_VO in unit of 32us
- */
-#define WMM_TXOP1_CFG 0x0224
-#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff)
-#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000)
-
-/*
- * GPIO_CTRL_CFG:
- */
-#define GPIO_CTRL_CFG 0x0228
-#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001)
-#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002)
-#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004)
-#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008)
-#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010)
-#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020)
-#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040)
-#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080)
-#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100)
-
-/*
- * MCU_CMD_CFG
- */
-#define MCU_CMD_CFG 0x022c
-
-/*
- * AC_BK register offsets
- */
-#define TX_BASE_PTR0 0x0230
-#define TX_MAX_CNT0 0x0234
-#define TX_CTX_IDX0 0x0238
-#define TX_DTX_IDX0 0x023c
-
-/*
- * AC_BE register offsets
- */
-#define TX_BASE_PTR1 0x0240
-#define TX_MAX_CNT1 0x0244
-#define TX_CTX_IDX1 0x0248
-#define TX_DTX_IDX1 0x024c
-
-/*
- * AC_VI register offsets
- */
-#define TX_BASE_PTR2 0x0250
-#define TX_MAX_CNT2 0x0254
-#define TX_CTX_IDX2 0x0258
-#define TX_DTX_IDX2 0x025c
-
-/*
- * AC_VO register offsets
- */
-#define TX_BASE_PTR3 0x0260
-#define TX_MAX_CNT3 0x0264
-#define TX_CTX_IDX3 0x0268
-#define TX_DTX_IDX3 0x026c
-
-/*
- * HCCA register offsets
- */
-#define TX_BASE_PTR4 0x0270
-#define TX_MAX_CNT4 0x0274
-#define TX_CTX_IDX4 0x0278
-#define TX_DTX_IDX4 0x027c
-
-/*
- * MGMT register offsets
- */
-#define TX_BASE_PTR5 0x0280
-#define TX_MAX_CNT5 0x0284
-#define TX_CTX_IDX5 0x0288
-#define TX_DTX_IDX5 0x028c
-
-/*
- * RX register offsets
- */
-#define RX_BASE_PTR 0x0290
-#define RX_MAX_CNT 0x0294
-#define RX_CRX_IDX 0x0298
-#define RX_DRX_IDX 0x029c
-
-/*
* USB_DMA_CFG
* RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns.
* RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes.
@@ -343,1448 +65,16 @@
#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff)
/*
- * PBF_SYS_CTRL
- * HOST_RAM_WRITE: enable Host program ram write selection
- */
-#define PBF_SYS_CTRL 0x0400
-#define PBF_SYS_CTRL_READY FIELD32(0x00000080)
-#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000)
-
-/*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
- */
-#define PBF_CFG 0x0408
-#define PBF_MAX_PCNT 0x040c
-#define PBF_CTRL 0x0410
-#define PBF_INT_STA 0x0414
-#define PBF_INT_ENA 0x0418
-
-/*
- * BCN_OFFSET0:
- */
-#define BCN_OFFSET0 0x042c
-#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff)
-#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00)
-#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000)
-#define BCN_OFFSET0_BCN3 FIELD32(0xff000000)
-
-/*
- * BCN_OFFSET1:
- */
-#define BCN_OFFSET1 0x0430
-#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff)
-#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00)
-#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000)
-#define BCN_OFFSET1_BCN7 FIELD32(0xff000000)
-
-/*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
- */
-#define TXRXQ_PCNT 0x0438
-#define PBF_DBG 0x043c
-
-/*
- * RF registers
- */
-#define RF_CSR_CFG 0x0500
-#define RF_CSR_CFG_DATA FIELD32(0x000000ff)
-#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00)
-#define RF_CSR_CFG_WRITE FIELD32(0x00010000)
-#define RF_CSR_CFG_BUSY FIELD32(0x00020000)
-
-/*
- * MAC Control/Status Registers(CSR).
- * Some values are set in TU, whereas 1 TU == 1024 us.
- */
-
-/*
- * MAC_CSR0: ASIC revision number.
- * ASIC_REV: 0
- * ASIC_VER: 2870
- */
-#define MAC_CSR0 0x1000
-#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff)
-#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000)
-
-/*
- * MAC_SYS_CTRL:
- */
-#define MAC_SYS_CTRL 0x1004
-#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001)
-#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002)
-#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004)
-#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008)
-#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010)
-#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020)
-#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040)
-#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080)
-
-/*
- * MAC_ADDR_DW0: STA MAC register 0
- */
-#define MAC_ADDR_DW0 0x1008
-#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff)
-#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00)
-#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000)
-#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000)
-
-/*
- * MAC_ADDR_DW1: STA MAC register 1
- * UNICAST_TO_ME_MASK:
- * Used to mask off bits from byte 5 of the MAC address
- * to determine the UNICAST_TO_ME bit for RX frames.
- * The full mask is complemented by BSS_ID_MASK:
- * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK
- */
-#define MAC_ADDR_DW1 0x100c
-#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff)
-#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00)
-#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000)
-
-/*
- * MAC_BSSID_DW0: BSSID register 0
- */
-#define MAC_BSSID_DW0 0x1010
-#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff)
-#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00)
-#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000)
-#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000)
-
-/*
- * MAC_BSSID_DW1: BSSID register 1
- * BSS_ID_MASK:
- * 0: 1-BSSID mode (BSS index = 0)
- * 1: 2-BSSID mode (BSS index: Byte5, bit 0)
- * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1)
- * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2)
- * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the
- * BSSID. This will make sure that those bits will be ignored
- * when determining the MY_BSS of RX frames.
- */
-#define MAC_BSSID_DW1 0x1014
-#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff)
-#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00)
-#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000)
-#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000)
-
-/*
- * MAX_LEN_CFG: Maximum frame length register.
- * MAX_MPDU: rt2860b max 16k bytes
- * MAX_PSDU: Maximum PSDU length
- * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16
- */
-#define MAX_LEN_CFG 0x1018
-#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff)
-#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000)
-#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000)
-#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000)
-
-/*
- * BBP_CSR_CFG: BBP serial control register
- * VALUE: Register value to program into BBP
- * REG_NUM: Selected BBP register
- * READ_CONTROL: 0 write BBP, 1 read BBP
- * BUSY: ASIC is busy executing BBP commands
- * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks
- * BBP_RW_MODE: 0 serial, 1 paralell
- */
-#define BBP_CSR_CFG 0x101c
-#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff)
-#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00)
-#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000)
-#define BBP_CSR_CFG_BUSY FIELD32(0x00020000)
-#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000)
-#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000)
-
-/*
- * RF_CSR_CFG0: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * BITWIDTH: Selected RF register
- * STANDBYMODE: 0 high when standby, 1 low when standby
- * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate
- * BUSY: ASIC is busy executing RF commands
- */
-#define RF_CSR_CFG0 0x1020
-#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff)
-#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000)
-#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff)
-#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000)
-#define RF_CSR_CFG0_SEL FIELD32(0x40000000)
-#define RF_CSR_CFG0_BUSY FIELD32(0x80000000)
-
-/*
- * RF_CSR_CFG1: RF control register
- * REGID_AND_VALUE: Register value to program into RF
- * RFGAP: Gap between BB_CONTROL_RF and RF_LE
- * 0: 3 system clock cycle (37.5usec)
- * 1: 5 system clock cycle (62.5usec)
- */
-#define RF_CSR_CFG1 0x1024
-#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff)
-#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000)
-
-/*
- * RF_CSR_CFG2: RF control register
- * VALUE: Register value to program into RF
- * RFGAP: Gap between BB_CONTROL_RF and RF_LE
- * 0: 3 system clock cycle (37.5usec)
- * 1: 5 system clock cycle (62.5usec)
- */
-#define RF_CSR_CFG2 0x1028
-#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff)
-
-/*
- * LED_CFG: LED control
- * color LED's:
- * 0: off
- * 1: blinking upon TX2
- * 2: periodic slow blinking
- * 3: always on
- * LED polarity:
- * 0: active low
- * 1: active high
- */
-#define LED_CFG 0x102c
-#define LED_CFG_ON_PERIOD FIELD32(0x000000ff)
-#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00)
-#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000)
-#define LED_CFG_R_LED_MODE FIELD32(0x03000000)
-#define LED_CFG_G_LED_MODE FIELD32(0x0c000000)
-#define LED_CFG_Y_LED_MODE FIELD32(0x30000000)
-#define LED_CFG_LED_POLAR FIELD32(0x40000000)
-
-/*
- * XIFS_TIME_CFG: MAC timing
- * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX
- * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX
- * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX
- * when MAC doesn't reference BBP signal BBRXEND
- * EIFS: unit 1us
- * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer
- *
- */
-#define XIFS_TIME_CFG 0x1100
-#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff)
-#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00)
-#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000)
-#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000)
-#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000)
-
-/*
- * BKOFF_SLOT_CFG:
- */
-#define BKOFF_SLOT_CFG 0x1104
-#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff)
-#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00)
-
-/*
- * NAV_TIME_CFG:
- */
-#define NAV_TIME_CFG 0x1108
-#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff)
-#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00)
-#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000)
-#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000)
-
-/*
- * CH_TIME_CFG: count as channel busy
- */
-#define CH_TIME_CFG 0x110c
-
-/*
- * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us
- */
-#define PBF_LIFE_TIMER 0x1110
-
-/*
- * BCN_TIME_CFG:
- * BEACON_INTERVAL: in unit of 1/16 TU
- * TSF_TICKING: Enable TSF auto counting
- * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode
- * BEACON_GEN: Enable beacon generator
- */
-#define BCN_TIME_CFG 0x1114
-#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff)
-#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000)
-#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000)
-#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000)
-#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000)
-#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000)
-
-/*
- * TBTT_SYNC_CFG:
- */
-#define TBTT_SYNC_CFG 0x1118
-
-/*
- * TSF_TIMER_DW0: Local lsb TSF timer, read-only
- */
-#define TSF_TIMER_DW0 0x111c
-#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff)
-
-/*
- * TSF_TIMER_DW1: Local msb TSF timer, read-only
- */
-#define TSF_TIMER_DW1 0x1120
-#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff)
-
-/*
- * TBTT_TIMER: TImer remains till next TBTT, read-only
- */
-#define TBTT_TIMER 0x1124
-
-/*
- * INT_TIMER_CFG:
- */
-#define INT_TIMER_CFG 0x1128
-
-/*
- * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
- */
-#define INT_TIMER_EN 0x112c
-
-/*
- * CH_IDLE_STA: channel idle time
- */
-#define CH_IDLE_STA 0x1130
-
-/*
- * CH_BUSY_STA: channel busy time
- */
-#define CH_BUSY_STA 0x1134
-
-/*
- * MAC_STATUS_CFG:
- * BBP_RF_BUSY: When set to 0, BBP and RF are stable.
- * if 1 or higher one of the 2 registers is busy.
- */
-#define MAC_STATUS_CFG 0x1200
-#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003)
-
-/*
- * PWR_PIN_CFG:
- */
-#define PWR_PIN_CFG 0x1204
-
-/*
- * AUTOWAKEUP_CFG: Manual power control / status register
- * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set
- * AUTOWAKE: 0:sleep, 1:awake
- */
-#define AUTOWAKEUP_CFG 0x1208
-#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff)
-#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00)
-#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000)
-
-/*
- * EDCA_AC0_CFG:
- */
-#define EDCA_AC0_CFG 0x1300
-#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC1_CFG:
- */
-#define EDCA_AC1_CFG 0x1304
-#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC2_CFG:
- */
-#define EDCA_AC2_CFG 0x1308
-#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_AC3_CFG:
- */
-#define EDCA_AC3_CFG 0x130c
-#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff)
-#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00)
-#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000)
-#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000)
-
-/*
- * EDCA_TID_AC_MAP:
- */
-#define EDCA_TID_AC_MAP 0x1310
-
-/*
- * TX_PWR_CFG_0:
- */
-#define TX_PWR_CFG_0 0x1314
-#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f)
-#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0)
-#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00)
-#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000)
-#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000)
-#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000)
-#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000)
-#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_1:
- */
-#define TX_PWR_CFG_1 0x1318
-#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f)
-#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0)
-#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00)
-#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000)
-#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000)
-#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000)
-#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000)
-#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_2:
- */
-#define TX_PWR_CFG_2 0x131c
-#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f)
-#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0)
-#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00)
-#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000)
-#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000)
-#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000)
-#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000)
-#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_3:
- */
-#define TX_PWR_CFG_3 0x1320
-#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f)
-#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0)
-#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00)
-#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000)
-#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000)
-#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000)
-#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000)
-#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000)
-
-/*
- * TX_PWR_CFG_4:
- */
-#define TX_PWR_CFG_4 0x1324
-#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f)
-#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0)
-#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00)
-#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000)
-
-/*
- * TX_PIN_CFG:
- */
-#define TX_PIN_CFG 0x1328
-#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001)
-#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002)
-#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004)
-#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008)
-#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010)
-#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020)
-#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040)
-#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080)
-#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100)
-#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200)
-#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400)
-#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800)
-#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000)
-#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000)
-#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000)
-#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000)
-#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000)
-#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000)
-#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000)
-#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000)
-
-/*
- * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
- */
-#define TX_BAND_CFG 0x132c
-#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001)
-#define TX_BAND_CFG_A FIELD32(0x00000002)
-#define TX_BAND_CFG_BG FIELD32(0x00000004)
-
-/*
- * TX_SW_CFG0:
- */
-#define TX_SW_CFG0 0x1330
-
-/*
- * TX_SW_CFG1:
- */
-#define TX_SW_CFG1 0x1334
-
-/*
- * TX_SW_CFG2:
- */
-#define TX_SW_CFG2 0x1338
-
-/*
- * TXOP_THRES_CFG:
- */
-#define TXOP_THRES_CFG 0x133c
-
-/*
- * TXOP_CTRL_CFG:
- */
-#define TXOP_CTRL_CFG 0x1340
-
-/*
- * TX_RTS_CFG:
- * RTS_THRES: unit:byte
- * RTS_FBK_EN: enable rts rate fallback
- */
-#define TX_RTS_CFG 0x1344
-#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff)
-#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00)
-#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000)
-
-/*
- * TX_TIMEOUT_CFG:
- * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us
- * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure
- * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation.
- * it is recommended that:
- * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT)
- */
-#define TX_TIMEOUT_CFG 0x1348
-#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0)
-#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00)
-#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000)
-
-/*
- * TX_RTY_CFG:
- * SHORT_RTY_LIMIT: short retry limit
- * LONG_RTY_LIMIT: long retry limit
- * LONG_RTY_THRE: Long retry threshoold
- * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode
- * 0:expired by retry limit, 1: expired by mpdu life timer
- * AGG_RTY_MODE: Aggregate MPDU retry mode
- * 0:expired by retry limit, 1: expired by mpdu life timer
- * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable
- */
-#define TX_RTY_CFG 0x134c
-#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff)
-#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00)
-#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000)
-#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000)
-#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000)
-#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000)
-
-/*
- * TX_LINK_CFG:
- * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us
- * MFB_ENABLE: TX apply remote MFB 1:enable
- * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable
- * 0: not apply remote remote unsolicit (MFS=7)
- * TX_MRQ_EN: MCS request TX enable
- * TX_RDG_EN: RDG TX enable
- * TX_CF_ACK_EN: Piggyback CF-ACK enable
- * REMOTE_MFB: remote MCS feedback
- * REMOTE_MFS: remote MCS feedback sequence number
- */
-#define TX_LINK_CFG 0x1350
-#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff)
-#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100)
-#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200)
-#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400)
-#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800)
-#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000)
-#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000)
-#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000)
-
-/*
- * HT_FBK_CFG0:
- */
-#define HT_FBK_CFG0 0x1354
-#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f)
-#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0)
-#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00)
-#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000)
-#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000)
-#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000)
-#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000)
-#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000)
-
-/*
- * HT_FBK_CFG1:
- */
-#define HT_FBK_CFG1 0x1358
-#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f)
-#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0)
-#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00)
-#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000)
-#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000)
-#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000)
-#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000)
-#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG0:
- */
-#define LG_FBK_CFG0 0x135c
-#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f)
-#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0)
-#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00)
-#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000)
-#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000)
-#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000)
-#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000)
-#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000)
-
-/*
- * LG_FBK_CFG1:
- */
-#define LG_FBK_CFG1 0x1360
-#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f)
-#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0)
-#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00)
-#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000)
-
-/*
- * CCK_PROT_CFG: CCK Protection
- * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd)
- * PROTECT_CTRL: Protection control frame type for CCK TX
- * 0:none, 1:RTS/CTS, 2:CTS-to-self
- * PROTECT_NAV: TXOP protection type for CCK TX
- * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect
- * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow
- * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow
- * RTS_TH_EN: RTS threshold enable on CCK TX
- */
-#define CCK_PROT_CFG 0x1364
-#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * OFDM_PROT_CFG: OFDM Protection
- */
-#define OFDM_PROT_CFG 0x1368
-#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * MM20_PROT_CFG: MM20 Protection
- */
-#define MM20_PROT_CFG 0x136c
-#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * MM40_PROT_CFG: MM40 Protection
- */
-#define MM40_PROT_CFG 0x1370
-#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * GF20_PROT_CFG: GF20 Protection
- */
-#define GF20_PROT_CFG 0x1374
-#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * GF40_PROT_CFG: GF40 Protection
- */
-#define GF40_PROT_CFG 0x1378
-#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff)
-#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000)
-#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000)
-#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000)
-#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000)
-
-/*
- * EXP_CTS_TIME:
- */
-#define EXP_CTS_TIME 0x137c
-
-/*
- * EXP_ACK_TIME:
- */
-#define EXP_ACK_TIME 0x1380
-
-/*
- * RX_FILTER_CFG: RX configuration register.
- */
-#define RX_FILTER_CFG 0x1400
-#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001)
-#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002)
-#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004)
-#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008)
-#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010)
-#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020)
-#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040)
-#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080)
-#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100)
-#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200)
-#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400)
-#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800)
-#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000)
-#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000)
-#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000)
-#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000)
-#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000)
-
-/*
- * AUTO_RSP_CFG:
- * AUTORESPONDER: 0: disable, 1: enable
- * BAC_ACK_POLICY: 0:long, 1:short preamble
- * CTS_40_MMODE: Response CTS 40MHz duplicate mode
- * CTS_40_MREF: Response CTS 40MHz duplicate mode
- * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble
- * DUAL_CTS_EN: Power bit value in control frame
- * ACK_CTS_PSM_BIT:Power bit value in control frame
- */
-#define AUTO_RSP_CFG 0x1404
-#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001)
-#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002)
-#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004)
-#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008)
-#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010)
-#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040)
-#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080)
-
-/*
- * LEGACY_BASIC_RATE:
- */
-#define LEGACY_BASIC_RATE 0x1408
-
-/*
- * HT_BASIC_RATE:
- */
-#define HT_BASIC_RATE 0x140c
-
-/*
- * HT_CTRL_CFG:
- */
-#define HT_CTRL_CFG 0x1410
-
-/*
- * SIFS_COST_CFG:
- */
-#define SIFS_COST_CFG 0x1414
-
-/*
- * RX_PARSER_CFG:
- * Set NAV for all received frames
- */
-#define RX_PARSER_CFG 0x1418
-
-/*
- * TX_SEC_CNT0:
- */
-#define TX_SEC_CNT0 0x1500
-
-/*
- * RX_SEC_CNT0:
- */
-#define RX_SEC_CNT0 0x1504
-
-/*
- * CCMP_FC_MUTE:
- */
-#define CCMP_FC_MUTE 0x1508
-
-/*
- * TXOP_HLDR_ADDR0:
- */
-#define TXOP_HLDR_ADDR0 0x1600
-
-/*
- * TXOP_HLDR_ADDR1:
- */
-#define TXOP_HLDR_ADDR1 0x1604
-
-/*
- * TXOP_HLDR_ET:
- */
-#define TXOP_HLDR_ET 0x1608
-
-/*
- * QOS_CFPOLL_RA_DW0:
- */
-#define QOS_CFPOLL_RA_DW0 0x160c
-
-/*
- * QOS_CFPOLL_RA_DW1:
- */
-#define QOS_CFPOLL_RA_DW1 0x1610
-
-/*
- * QOS_CFPOLL_QC:
- */
-#define QOS_CFPOLL_QC 0x1614
-
-/*
- * RX_STA_CNT0: RX PLCP error count & RX CRC error count
- */
-#define RX_STA_CNT0 0x1700
-#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff)
-#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT1: RX False CCA count & RX LONG frame count
- */
-#define RX_STA_CNT1 0x1704
-#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff)
-#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000)
-
-/*
- * RX_STA_CNT2:
- */
-#define RX_STA_CNT2 0x1708
-#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff)
-#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT0: TX Beacon count
- */
-#define TX_STA_CNT0 0x170c
-#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff)
-#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT1: TX tx count
- */
-#define TX_STA_CNT1 0x1710
-#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff)
-#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000)
-
-/*
- * TX_STA_CNT2: TX tx count
- */
-#define TX_STA_CNT2 0x1714
-#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff)
-#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_STA_FIFO: TX Result for specific PID status fifo register
- */
-#define TX_STA_FIFO 0x1718
-#define TX_STA_FIFO_VALID FIELD32(0x00000001)
-#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e)
-#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020)
-#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040)
-#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080)
-#define TX_STA_FIFO_WCID FIELD32(0x0000ff00)
-#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT: Debug counter
- */
-#define TX_AGG_CNT 0x171c
-#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT0:
- */
-#define TX_AGG_CNT0 0x1720
-#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT1:
- */
-#define TX_AGG_CNT1 0x1724
-#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT2:
- */
-#define TX_AGG_CNT2 0x1728
-#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT3:
- */
-#define TX_AGG_CNT3 0x172c
-#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT4:
- */
-#define TX_AGG_CNT4 0x1730
-#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT5:
- */
-#define TX_AGG_CNT5 0x1734
-#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT6:
- */
-#define TX_AGG_CNT6 0x1738
-#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000)
-
-/*
- * TX_AGG_CNT7:
- */
-#define TX_AGG_CNT7 0x173c
-#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff)
-#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000)
-
-/*
- * MPDU_DENSITY_CNT:
- * TX_ZERO_DEL: TX zero length delimiter count
- * RX_ZERO_DEL: RX zero length delimiter count
- */
-#define MPDU_DENSITY_CNT 0x1740
-#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff)
-#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000)
-
-/*
- * Security key table memory.
- * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry
- * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry
- * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry
- * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry
- * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry
- * SHARED_KEY_MODE_BASE: 4 bits * 32-entry
- */
-#define MAC_WCID_BASE 0x1800
-#define PAIRWISE_KEY_TABLE_BASE 0x4000
-#define MAC_IVEIV_TABLE_BASE 0x6000
-#define MAC_WCID_ATTRIBUTE_BASE 0x6800
-#define SHARED_KEY_TABLE_BASE 0x6c00
-#define SHARED_KEY_MODE_BASE 0x7000
-
-#define MAC_WCID_ENTRY(__idx) \
- ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
-#define PAIRWISE_KEY_ENTRY(__idx) \
- ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
-#define MAC_IVEIV_ENTRY(__idx) \
- ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) )
-#define MAC_WCID_ATTR_ENTRY(__idx) \
- ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
-#define SHARED_KEY_ENTRY(__idx) \
- ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
-#define SHARED_KEY_MODE_ENTRY(__idx) \
- ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
-
-struct mac_wcid_entry {
- u8 mac[6];
- u8 reserved[2];
-} __attribute__ ((packed));
-
-struct hw_key_entry {
- u8 key[16];
- u8 tx_mic[8];
- u8 rx_mic[8];
-} __attribute__ ((packed));
-
-struct mac_iveiv_entry {
- u8 iv[8];
-} __attribute__ ((packed));
-
-/*
- * MAC_WCID_ATTRIBUTE:
- */
-#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001)
-#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e)
-#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070)
-#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380)
-
-/*
- * SHARED_KEY_MODE:
- */
-#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007)
-#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070)
-#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700)
-#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000)
-#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000)
-#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000)
-#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000)
-#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000)
-
-/*
- * HOST-MCU communication
- */
-
-/*
- * H2M_MAILBOX_CSR: Host-to-MCU Mailbox.
- */
-#define H2M_MAILBOX_CSR 0x7010
-#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff)
-#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_CID:
- */
-#define H2M_MAILBOX_CID 0x7014
-#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff)
-#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00)
-#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000)
-#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000)
-
-/*
- * H2M_MAILBOX_STATUS:
- */
-#define H2M_MAILBOX_STATUS 0x701c
-
-/*
- * H2M_INT_SRC:
- */
-#define H2M_INT_SRC 0x7024
-
-/*
- * H2M_BBP_AGENT:
- */
-#define H2M_BBP_AGENT 0x7028
-
-/*
- * MCU_LEDCS: LED control for MCU Mailbox.
- */
-#define MCU_LEDCS_LED_MODE FIELD8(0x1f)
-#define MCU_LEDCS_POLARITY FIELD8(0x01)
-
-/*
- * HW_CS_CTS_BASE:
- * Carrier-sense CTS frame base address.
- * It's where mac stores carrier-sense frame for carrier-sense function.
- */
-#define HW_CS_CTS_BASE 0x7700
-
-/*
- * HW_DFS_CTS_BASE:
- * FS CTS frame base address. It's where mac stores CTS frame for DFS.
- */
-#define HW_DFS_CTS_BASE 0x7780
-
-/*
- * TXRX control registers - base address 0x3000
- */
-
-/*
- * TXRX_CSR1:
- * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first..
- */
-#define TXRX_CSR1 0x77d0
-
-/*
- * HW_DEBUG_SETTING_BASE:
- * since NULL frame won't be that long (256 byte)
- * We steal 16 tail bytes to save debugging settings
- */
-#define HW_DEBUG_SETTING_BASE 0x77f0
-#define HW_DEBUG_SETTING_BASE2 0x7770
-
-/*
- * HW_BEACON_BASE
- * In order to support maximum 8 MBSS and its maximum length
- * is 512 bytes for each beacon
- * Three section discontinue memory segments will be used.
- * 1. The original region for BCN 0~3
- * 2. Extract memory from FCE table for BCN 4~5
- * 3. Extract memory from Pair-wise key table for BCN 6~7
- * It occupied those memory of wcid 238~253 for BCN 6
- * and wcid 222~237 for BCN 7
- *
- * IMPORTANT NOTE: Not sure why legacy driver does this,
- * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6.
- */
-#define HW_BEACON_BASE0 0x7800
-#define HW_BEACON_BASE1 0x7a00
-#define HW_BEACON_BASE2 0x7c00
-#define HW_BEACON_BASE3 0x7e00
-#define HW_BEACON_BASE4 0x7200
-#define HW_BEACON_BASE5 0x7400
-#define HW_BEACON_BASE6 0x5dc0
-#define HW_BEACON_BASE7 0x5bc0
-
-#define HW_BEACON_OFFSET(__index) \
- ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
- (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
- (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
-
-/*
* 8051 firmware image.
*/
#define FIRMWARE_RT2870 "rt2870.bin"
#define FIRMWARE_IMAGE_BASE 0x3000
/*
- * BBP registers.
- * The wordsize of the BBP is 8 bits.
- */
-
-/*
- * BBP 1: TX Antenna
- */
-#define BBP1_TX_POWER FIELD8(0x07)
-#define BBP1_TX_ANTENNA FIELD8(0x18)
-
-/*
- * BBP 3: RX Antenna
- */
-#define BBP3_RX_ANTENNA FIELD8(0x18)
-#define BBP3_HT40_PLUS FIELD8(0x20)
-
-/*
- * BBP 4: Bandwidth
- */
-#define BBP4_TX_BF FIELD8(0x01)
-#define BBP4_BANDWIDTH FIELD8(0x18)
-
-/*
- * RFCSR registers
- * The wordsize of the RFCSR is 8 bits.
- */
-
-/*
- * RFCSR 6:
- */
-#define RFCSR6_R FIELD8(0x03)
-
-/*
- * RFCSR 7:
- */
-#define RFCSR7_RF_TUNING FIELD8(0x01)
-
-/*
- * RFCSR 12:
- */
-#define RFCSR12_TX_POWER FIELD8(0x1f)
-
-/*
- * RFCSR 22:
- */
-#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01)
-
-/*
- * RFCSR 23:
- */
-#define RFCSR23_FREQ_OFFSET FIELD8(0x7f)
-
-/*
- * RFCSR 30:
- */
-#define RFCSR30_RF_CALIBRATION FIELD8(0x80)
-
-/*
- * RF registers
- */
-
-/*
- * RF 2
- */
-#define RF2_ANTENNA_RX2 FIELD32(0x00000040)
-#define RF2_ANTENNA_TX1 FIELD32(0x00004000)
-#define RF2_ANTENNA_RX1 FIELD32(0x00020000)
-
-/*
- * RF 3
- */
-#define RF3_TXPOWER_G FIELD32(0x00003e00)
-#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200)
-#define RF3_TXPOWER_A FIELD32(0x00003c00)
-
-/*
- * RF 4
- */
-#define RF4_TXPOWER_G FIELD32(0x000007c0)
-#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040)
-#define RF4_TXPOWER_A FIELD32(0x00000780)
-#define RF4_FREQ_OFFSET FIELD32(0x001f8000)
-#define RF4_HT40 FIELD32(0x00200000)
-
-/*
- * EEPROM content.
- * The wordsize of the EEPROM is 16 bits.
- */
-
-/*
- * EEPROM Version
- */
-#define EEPROM_VERSION 0x0001
-#define EEPROM_VERSION_FAE FIELD16(0x00ff)
-#define EEPROM_VERSION_VERSION FIELD16(0xff00)
-
-/*
- * HW MAC address.
- */
-#define EEPROM_MAC_ADDR_0 0x0002
-#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_1 0x0003
-#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00)
-#define EEPROM_MAC_ADDR_2 0x0004
-#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff)
-#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00)
-
-/*
- * EEPROM ANTENNA config
- * RXPATH: 1: 1R, 2: 2R, 3: 3R
- * TXPATH: 1: 1T, 2: 2T
- */
-#define EEPROM_ANTENNA 0x001a
-#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f)
-#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0)
-#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00)
-
-/*
- * EEPROM NIC config
- * CARDBUS_ACCEL: 0 - enable, 1 - disable
- */
-#define EEPROM_NIC 0x001b
-#define EEPROM_NIC_HW_RADIO FIELD16(0x0001)
-#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002)
-#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004)
-#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008)
-#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010)
-#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020)
-#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040)
-#define EEPROM_NIC_WPS_PBC FIELD16(0x0080)
-#define EEPROM_NIC_BW40M_BG FIELD16(0x0100)
-#define EEPROM_NIC_BW40M_A FIELD16(0x0200)
-
-/*
- * EEPROM frequency
- */
-#define EEPROM_FREQ 0x001d
-#define EEPROM_FREQ_OFFSET FIELD16(0x00ff)
-#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00)
-#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000)
-
-/*
- * EEPROM LED
- * POLARITY_RDY_G: Polarity RDY_G setting.
- * POLARITY_RDY_A: Polarity RDY_A setting.
- * POLARITY_ACT: Polarity ACT setting.
- * POLARITY_GPIO_0: Polarity GPIO0 setting.
- * POLARITY_GPIO_1: Polarity GPIO1 setting.
- * POLARITY_GPIO_2: Polarity GPIO2 setting.
- * POLARITY_GPIO_3: Polarity GPIO3 setting.
- * POLARITY_GPIO_4: Polarity GPIO4 setting.
- * LED_MODE: Led mode.
- */
-#define EEPROM_LED1 0x001e
-#define EEPROM_LED2 0x001f
-#define EEPROM_LED3 0x0020
-#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001)
-#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002)
-#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004)
-#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008)
-#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010)
-#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020)
-#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040)
-#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080)
-#define EEPROM_LED_LED_MODE FIELD16(0x1f00)
-
-/*
- * EEPROM LNA
- */
-#define EEPROM_LNA 0x0022
-#define EEPROM_LNA_BG FIELD16(0x00ff)
-#define EEPROM_LNA_A0 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG offset
- */
-#define EEPROM_RSSI_BG 0x0023
-#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff)
-#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI BG2 offset
- */
-#define EEPROM_RSSI_BG2 0x0024
-#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff)
-#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI A offset
- */
-#define EEPROM_RSSI_A 0x0025
-#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff)
-#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00)
-
-/*
- * EEPROM RSSI A2 offset
- */
-#define EEPROM_RSSI_A2 0x0026
-#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff)
-#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00)
-
-/*
- * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
- * This is delta in 40MHZ.
- * VALUE: Tx Power dalta value (MAX=4)
- * TYPE: 1: Plus the delta value, 0: minus the delta value
- * TXPOWER: Enable:
- */
-#define EEPROM_TXPOWER_DELTA 0x0028
-#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f)
-#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040)
-#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080)
-
-/*
- * EEPROM TXPOWER 802.11BG
- */
-#define EEPROM_TXPOWER_BG1 0x0029
-#define EEPROM_TXPOWER_BG2 0x0030
-#define EEPROM_TXPOWER_BG_SIZE 7
-#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff)
-#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00)
-
-/*
- * EEPROM TXPOWER 802.11A
- */
-#define EEPROM_TXPOWER_A1 0x003c
-#define EEPROM_TXPOWER_A2 0x0053
-#define EEPROM_TXPOWER_A_SIZE 6
-#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff)
-#define EEPROM_TXPOWER_A_2 FIELD16(0xff00)
-
-/*
- * EEPROM TXpower byrate: 20MHZ power
- */
-#define EEPROM_TXPOWER_BYRATE 0x006f
-
-/*
- * EEPROM BBP.
- */
-#define EEPROM_BBP_START 0x0078
-#define EEPROM_BBP_SIZE 16
-#define EEPROM_BBP_VALUE FIELD16(0x00ff)
-#define EEPROM_BBP_REG_ID FIELD16(0xff00)
-
-/*
- * MCU mailbox commands.
- */
-#define MCU_SLEEP 0x30
-#define MCU_WAKEUP 0x31
-#define MCU_RADIO_OFF 0x35
-#define MCU_CURRENT 0x36
-#define MCU_LED 0x50
-#define MCU_LED_STRENGTH 0x51
-#define MCU_LED_1 0x52
-#define MCU_LED_2 0x53
-#define MCU_LED_3 0x54
-#define MCU_RADAR 0x60
-#define MCU_BOOT_SIGNAL 0x72
-#define MCU_BBP_SIGNAL 0x80
-#define MCU_POWER_SAVE 0x83
-
-/*
- * MCU mailbox tokens
- */
-#define TOKEN_WAKUP 3
-
-/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 4 * sizeof(__le32) )
#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
-#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) )
-#define RXD_DESC_SIZE ( 1 * sizeof(__le32) )
-#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) )
-
-/*
- * TX descriptor format for TX, PRIO and Beacon Ring.
- */
-
-/*
- * Word0
- */
-#define TXD_W0_SD_PTR0 FIELD32(0xffffffff)
-
-/*
- * Word1
- */
-#define TXD_W1_SD_LEN1 FIELD32(0x00003fff)
-#define TXD_W1_LAST_SEC1 FIELD32(0x00004000)
-#define TXD_W1_BURST FIELD32(0x00008000)
-#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000)
-#define TXD_W1_LAST_SEC0 FIELD32(0x40000000)
-#define TXD_W1_DMA_DONE FIELD32(0x80000000)
-
-/*
- * Word2
- */
-#define TXD_W2_SD_PTR1 FIELD32(0xffffffff)
-
-/*
- * Word3
- * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI
- * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler.
- * 0:MGMT, 1:HCCA 2:EDCA
- */
-#define TXD_W3_WIV FIELD32(0x01000000)
-#define TXD_W3_QSEL FIELD32(0x06000000)
-#define TXD_W3_TCO FIELD32(0x20000000)
-#define TXD_W3_UCO FIELD32(0x40000000)
-#define TXD_W3_ICO FIELD32(0x80000000)
+#define RXINFO_DESC_SIZE ( 1 * sizeof(__le32) )
/*
* TX Info structure
@@ -1807,52 +97,6 @@ struct mac_iveiv_entry {
#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000)
/*
- * TX WI structure
- */
-
-/*
- * Word0
- * FRAG: 1 To inform TKIP engine this is a fragment.
- * MIMO_PS: The remote peer is in dynamic MIMO-PS mode
- * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs
- * BW: Channel bandwidth 20MHz or 40 MHz
- * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED
- */
-#define TXWI_W0_FRAG FIELD32(0x00000001)
-#define TXWI_W0_MIMO_PS FIELD32(0x00000002)
-#define TXWI_W0_CF_ACK FIELD32(0x00000004)
-#define TXWI_W0_TS FIELD32(0x00000008)
-#define TXWI_W0_AMPDU FIELD32(0x00000010)
-#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0)
-#define TXWI_W0_TX_OP FIELD32(0x00000300)
-#define TXWI_W0_MCS FIELD32(0x007f0000)
-#define TXWI_W0_BW FIELD32(0x00800000)
-#define TXWI_W0_SHORT_GI FIELD32(0x01000000)
-#define TXWI_W0_STBC FIELD32(0x06000000)
-#define TXWI_W0_IFS FIELD32(0x08000000)
-#define TXWI_W0_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word1
- */
-#define TXWI_W1_ACK FIELD32(0x00000001)
-#define TXWI_W1_NSEQ FIELD32(0x00000002)
-#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc)
-#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00)
-#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define TXWI_W1_PACKETID FIELD32(0xf0000000)
-
-/*
- * Word2
- */
-#define TXWI_W2_IV FIELD32(0xffffffff)
-
-/*
- * Word3
- */
-#define TXWI_W3_EIV FIELD32(0xffffffff)
-
-/*
* RX descriptor format for RX Ring.
*/
@@ -1888,64 +132,4 @@ struct mac_iveiv_entry {
#define RXD_W0_LAST_AMSDU FIELD32(0x00080000)
#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000)
-/*
- * RX WI structure
- */
-
-/*
- * Word0
- */
-#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff)
-#define RXWI_W0_KEY_INDEX FIELD32(0x00000300)
-#define RXWI_W0_BSSID FIELD32(0x00001c00)
-#define RXWI_W0_UDF FIELD32(0x0000e000)
-#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000)
-#define RXWI_W0_TID FIELD32(0xf0000000)
-
-/*
- * Word1
- */
-#define RXWI_W1_FRAG FIELD32(0x0000000f)
-#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0)
-#define RXWI_W1_MCS FIELD32(0x007f0000)
-#define RXWI_W1_BW FIELD32(0x00800000)
-#define RXWI_W1_SHORT_GI FIELD32(0x01000000)
-#define RXWI_W1_STBC FIELD32(0x06000000)
-#define RXWI_W1_PHYMODE FIELD32(0xc0000000)
-
-/*
- * Word2
- */
-#define RXWI_W2_RSSI0 FIELD32(0x000000ff)
-#define RXWI_W2_RSSI1 FIELD32(0x0000ff00)
-#define RXWI_W2_RSSI2 FIELD32(0x00ff0000)
-
-/*
- * Word3
- */
-#define RXWI_W3_SNR0 FIELD32(0x000000ff)
-#define RXWI_W3_SNR1 FIELD32(0x0000ff00)
-
-/*
- * Macros for converting txpower from EEPROM to mac80211 value
- * and from mac80211 value to register value.
- */
-#define MIN_G_TXPOWER 0
-#define MIN_A_TXPOWER -7
-#define MAX_G_TXPOWER 31
-#define MAX_A_TXPOWER 15
-#define DEFAULT_TXPOWER 5
-
-#define TXPOWER_G_FROM_DEV(__txpower) \
- ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_G_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER)
-
-#define TXPOWER_A_FROM_DEV(__txpower) \
- ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower)
-
-#define TXPOWER_A_TO_DEV(__txpower) \
- clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
-
#endif /* RT2800USB_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 196de8ab8153..c83dbaefd57a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -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,9 +849,23 @@ 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.
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h
index 1046977e6a12..8e03c045e037 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.h
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.h
@@ -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 */
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 15a12487e04b..ae33eebe9a6f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -35,15 +35,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.
*/
static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
@@ -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);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index f02b48a90593..c9cbdaa1073f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -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;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index bd2d59c85f1b..9943e428bc21 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -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);
/*
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index bf9175a8c1f4..abb4907cf296 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -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];
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 2017ccc00145..76973b8c7099 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 88060e117541..785e0244e305 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -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---
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index 48b0bfd6c55a..da3bf1cebc08 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 566f1521ec22..94359b1a861f 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index bf5a8680a462..5cc89bbdac7a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -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) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index ba4a2b4f0f56..b7c96454cca3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -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) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 0666328ce9ab..990eb01b4c71 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 174b8209dbf3..9d7061b3c8a0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -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);
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 061d47520a32..565373ede265 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -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
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 31d396ba9188..e135d894b42a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h
index 3ab53d331f15..4e3f55ebb1a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.h
+++ b/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 417b4152feb1..7c2017f480ea 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -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 */
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 86132bb00787..d2149fcd3cf1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -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;
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
index 37d81ab6acc0..ca645f38109b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -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;
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
index 74b31eafe72d..5f809695f71a 100644
--- a/drivers/net/wireless/zd1211rw/Kconfig
+++ b/drivers/net/wireless/zd1211rw/Kconfig
@@ -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
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 9a4dd5992f65..4e3873bfd010 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -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
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 104f2f8897ec..fb1d7851b563 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -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/
diff --git a/drivers/staging/arlan/Kconfig b/drivers/staging/arlan/Kconfig
new file mode 100644
index 000000000000..0585ed8b4d3e
--- /dev/null
+++ b/drivers/staging/arlan/Kconfig
@@ -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.
diff --git a/drivers/staging/arlan/Makefile b/drivers/staging/arlan/Makefile
new file mode 100644
index 000000000000..9e58e5fae7b9
--- /dev/null
+++ b/drivers/staging/arlan/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_ARLAN) += arlan.o
+
+arlan-objs := arlan-main.o arlan-proc.o
diff --git a/drivers/staging/arlan/TODO b/drivers/staging/arlan/TODO
new file mode 100644
index 000000000000..9bd15a2f6d9e
--- /dev/null
+++ b/drivers/staging/arlan/TODO
@@ -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>.
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/staging/arlan/arlan-main.c
index 921a082487a1..921a082487a1 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/staging/arlan/arlan-main.c
diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/staging/arlan/arlan-proc.c
index a8b689635a3b..a8b689635a3b 100644
--- a/drivers/net/wireless/arlan-proc.c
+++ b/drivers/staging/arlan/arlan-proc.c
diff --git a/drivers/net/wireless/arlan.h b/drivers/staging/arlan/arlan.h
index fb3ad51a1caf..fb3ad51a1caf 100644
--- a/drivers/net/wireless/arlan.h
+++ b/drivers/staging/arlan/arlan.h
diff --git a/drivers/staging/netwave/Kconfig b/drivers/staging/netwave/Kconfig
new file mode 100644
index 000000000000..c0c996c0550a
--- /dev/null
+++ b/drivers/staging/netwave/Kconfig
@@ -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.
diff --git a/drivers/staging/netwave/Makefile b/drivers/staging/netwave/Makefile
new file mode 100644
index 000000000000..2ab89de59b9b
--- /dev/null
+++ b/drivers/staging/netwave/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
diff --git a/drivers/staging/netwave/TODO b/drivers/staging/netwave/TODO
new file mode 100644
index 000000000000..9bd15a2f6d9e
--- /dev/null
+++ b/drivers/staging/netwave/TODO
@@ -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>.
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/staging/netwave/netwave_cs.c
index 9498b46c99a4..9498b46c99a4 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/staging/netwave/netwave_cs.c
diff --git a/drivers/staging/strip/Kconfig b/drivers/staging/strip/Kconfig
new file mode 100644
index 000000000000..36257b5cd6e1
--- /dev/null
+++ b/drivers/staging/strip/Kconfig
@@ -0,0 +1,22 @@
+config STRIP
+ tristate "STRIP (Metricom starmode radio IP)"
+ depends on INET
+ 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.
diff --git a/drivers/staging/strip/Makefile b/drivers/staging/strip/Makefile
new file mode 100644
index 000000000000..6417bdcac2fb
--- /dev/null
+++ b/drivers/staging/strip/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_STRIP) += strip.o
diff --git a/drivers/staging/strip/TODO b/drivers/staging/strip/TODO
new file mode 100644
index 000000000000..9bd15a2f6d9e
--- /dev/null
+++ b/drivers/staging/strip/TODO
@@ -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>.
diff --git a/drivers/net/wireless/strip.c b/drivers/staging/strip/strip.c
index 698aade79d40..698aade79d40 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/staging/strip/strip.c
diff --git a/drivers/staging/wavelan/Kconfig b/drivers/staging/wavelan/Kconfig
new file mode 100644
index 000000000000..786060e025c0
--- /dev/null
+++ b/drivers/staging/wavelan/Kconfig
@@ -0,0 +1,38 @@
+config WAVELAN
+ tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
+ depends on ISA
+ 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
+ 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.
diff --git a/drivers/staging/wavelan/Makefile b/drivers/staging/wavelan/Makefile
new file mode 100644
index 000000000000..1cde17c69a43
--- /dev/null
+++ b/drivers/staging/wavelan/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_WAVELAN) += wavelan.o
+obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
diff --git a/drivers/staging/wavelan/TODO b/drivers/staging/wavelan/TODO
new file mode 100644
index 000000000000..9bd15a2f6d9e
--- /dev/null
+++ b/drivers/staging/wavelan/TODO
@@ -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>.
diff --git a/drivers/net/wireless/i82586.h b/drivers/staging/wavelan/i82586.h
index 5f65b250646f..5f65b250646f 100644
--- a/drivers/net/wireless/i82586.h
+++ b/drivers/staging/wavelan/i82586.h
diff --git a/drivers/net/wireless/i82593.h b/drivers/staging/wavelan/i82593.h
index afac5c7a323d..afac5c7a323d 100644
--- a/drivers/net/wireless/i82593.h
+++ b/drivers/staging/wavelan/i82593.h
diff --git a/drivers/net/wireless/wavelan.c b/drivers/staging/wavelan/wavelan.c
index d634b2da3b84..d634b2da3b84 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/staging/wavelan/wavelan.c
diff --git a/drivers/net/wireless/wavelan.h b/drivers/staging/wavelan/wavelan.h
index 9ab360558ffd..9ab360558ffd 100644
--- a/drivers/net/wireless/wavelan.h
+++ b/drivers/staging/wavelan/wavelan.h
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/staging/wavelan/wavelan.p.h
index dbe8de6e5f52..dbe8de6e5f52 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/staging/wavelan/wavelan.p.h
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/staging/wavelan/wavelan_cs.c
index 431a20ec6db6..431a20ec6db6 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/staging/wavelan/wavelan_cs.c
diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/staging/wavelan/wavelan_cs.h
index 2e4bfe4147c6..2e4bfe4147c6 100644
--- a/drivers/net/wireless/wavelan_cs.h
+++ b/drivers/staging/wavelan/wavelan_cs.h
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/staging/wavelan/wavelan_cs.p.h
index 81d91531c4f9..81d91531c4f9 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/staging/wavelan/wavelan_cs.p.h
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 52e15e079c61..0aa831467493 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -472,7 +472,7 @@ static inline int ieee80211_is_cfendack(__le16 fc)
}
/**
- * ieee80211_is_nullfunc - check if FTYPE=IEEE80211_FTYPE_DATA and STYPE=IEEE80211_STYPE_NULLFUNC
+ * ieee80211_is_nullfunc - check if frame is a regular (non-QoS) nullfunc frame
* @fc: frame control bytes in little-endian byteorder
*/
static inline int ieee80211_is_nullfunc(__le16 fc)
@@ -481,6 +481,16 @@ static inline int ieee80211_is_nullfunc(__le16 fc)
cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC);
}
+/**
+ * ieee80211_is_qos_nullfunc - check if frame is a QoS nullfunc frame
+ * @fc: frame control bytes in little-endian byteorder
+ */
+static inline int ieee80211_is_qos_nullfunc(__le16 fc)
+{
+ return (fc & cpu_to_le16(IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) ==
+ cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC);
+}
+
struct ieee80211s_hdr {
u8 flags;
u8 ttl;
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 23c3f3d97779..9d3d86aaccbb 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -80,7 +80,7 @@ struct ieee80211_radiotap_header {
* Additional extensions are made
* by setting bit 31.
*/
-};
+} __packed;
/* Name Data type Units
* ---- --------- -----
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c42c4a820b89..2c10eac637d8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -494,7 +494,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* @RX_FLAG_MMIC_ERROR: Michael MIC error was reported on this frame.
* Use together with %RX_FLAG_MMIC_STRIPPED.
* @RX_FLAG_DECRYPTED: This frame was decrypted in hardware.
- * @RX_FLAG_RADIOTAP: This frame starts with a radiotap header.
* @RX_FLAG_MMIC_STRIPPED: the Michael MIC is stripped off this frame,
* verification has been done by the hardware.
* @RX_FLAG_IV_STRIPPED: The IV/ICV are stripped from this frame.
@@ -515,7 +514,6 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = 1<<0,
RX_FLAG_DECRYPTED = 1<<1,
- RX_FLAG_RADIOTAP = 1<<2,
RX_FLAG_MMIC_STRIPPED = 1<<3,
RX_FLAG_IV_STRIPPED = 1<<4,
RX_FLAG_FAILED_FCS_CRC = 1<<5,
@@ -554,7 +552,7 @@ struct ieee80211_rx_status {
int freq;
int signal;
int noise;
- int qual;
+ int __deprecated qual;
int antenna;
int rate_idx;
int flag;
@@ -565,7 +563,9 @@ struct ieee80211_rx_status {
*
* Flags to define PHY configuration options
*
- * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported)
+ * @IEEE80211_CONF_MONITOR: there's a monitor interface present -- use this
+ * to determine for example whether to calculate timestamps for packets
+ * or not, do not use instead of filter flags!
* @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only)
* @IEEE80211_CONF_IDLE: The device is running, but idle; if the flag is set
* the driver should be prepared to handle configuration requests but
@@ -574,7 +574,7 @@ struct ieee80211_rx_status {
* it can also be unset in that case when monitor interfaces are active.
*/
enum ieee80211_conf_flags {
- IEEE80211_CONF_RADIOTAP = (1<<0),
+ IEEE80211_CONF_MONITOR = (1<<0),
IEEE80211_CONF_PS = (1<<1),
IEEE80211_CONF_IDLE = (1<<2),
};
@@ -584,7 +584,7 @@ enum ieee80211_conf_flags {
* enum ieee80211_conf_changed - denotes which configuration changed
*
* @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed
- * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed
+ * @IEEE80211_CONF_CHANGE_MONITOR: the monitor flag changed
* @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed
* @IEEE80211_CONF_CHANGE_POWER: the TX power changed
* @IEEE80211_CONF_CHANGE_CHANNEL: the channel/channel_type changed
@@ -593,7 +593,7 @@ enum ieee80211_conf_flags {
*/
enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2),
- IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3),
+ IEEE80211_CONF_CHANGE_MONITOR = BIT(3),
IEEE80211_CONF_CHANGE_PS = BIT(4),
IEEE80211_CONF_CHANGE_POWER = BIT(5),
IEEE80211_CONF_CHANGE_CHANNEL = BIT(6),
@@ -1661,8 +1661,7 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw);
* ieee80211_rx - receive frame
*
* Use this function to hand received frames to mac80211. The receive
- * buffer in @skb must start with an IEEE 802.11 header or a radiotap
- * header if %RX_FLAG_RADIOTAP is set in the @status flags.
+ * buffer in @skb must start with an IEEE 802.11 header.
*
* This function may not be called in IRQ context. Calls to this function
* for a single hardware must be synchronized against each other. Calls to
@@ -1744,19 +1743,45 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw,
struct sk_buff *skb);
/**
- * ieee80211_beacon_get - beacon generation function
+ * ieee80211_beacon_get_tim - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
+ * @tim_offset: pointer to variable that will receive the TIM IE offset.
+ * Set to 0 if invalid (in non-AP modes).
+ * @tim_length: pointer to variable that will receive the TIM IE length,
+ * (including the ID and length bytes!).
+ * Set to 0 if invalid (in non-AP modes).
+ *
+ * If the driver implements beaconing modes, it must use this function to
+ * obtain the beacon frame/template.
*
* If the beacon frames are generated by the host system (i.e., not in
- * hardware/firmware), the low-level driver uses this function to receive
- * the next beacon frame from the 802.11 code. The low-level is responsible
- * for calling this function before beacon data is needed (e.g., based on
- * hardware interrupt). Returned skb is used only once and low-level driver
- * is responsible for freeing it.
+ * hardware/firmware), the driver uses this function to get each beacon
+ * frame from mac80211 -- it is responsible for calling this function
+ * before the beacon is needed (e.g. based on hardware interrupt).
+ *
+ * If the beacon frames are generated by the device, then the driver
+ * must use the returned beacon as the template and change the TIM IE
+ * according to the current DTIM parameters/TIM bitmap.
+ *
+ * The driver is responsible for freeing the returned skb.
+ */
+struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 *tim_offset, u16 *tim_length);
+
+/**
+ * ieee80211_beacon_get - beacon generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
+ *
+ * See ieee80211_beacon_get_tim().
*/
-struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ return ieee80211_beacon_get_tim(hw, vif, NULL, NULL);
+}
/**
* ieee80211_rts_get - RTS frame generation function
@@ -2081,16 +2106,69 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra,
/**
* ieee80211_find_sta - find a station
*
- * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @vif: virtual interface to look for station on
* @addr: station's address
*
* This function must be called under RCU lock and the
* resulting pointer is only valid under RCU lock as well.
*/
-struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
+struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
const u8 *addr);
/**
+ * ieee80211_find_sta_by_hw - find a station on hardware
+ *
+ * @hw: pointer as obtained from ieee80211_alloc_hw()
+ * @addr: station's address
+ *
+ * This function must be called under RCU lock and the
+ * resulting pointer is only valid under RCU lock as well.
+ *
+ * NOTE: This function should not be used! When mac80211 is converted
+ * internally to properly keep track of stations on multiple
+ * virtual interfaces, it will not always know which station to
+ * return here since a single address might be used by multiple
+ * logical stations (e.g. consider a station connecting to another
+ * BSSID on the same AP hardware without disconnecting first).
+ *
+ * DO NOT USE THIS FUNCTION.
+ */
+struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
+ const u8 *addr);
+
+/**
+ * ieee80211_sta_block_awake - block station from waking up
+ * @hw: the hardware
+ * @pubsta: the station
+ * @block: whether to block or unblock
+ *
+ * Some devices require that all frames that are on the queues
+ * for a specific station that went to sleep are flushed before
+ * a poll response or frames after the station woke up can be
+ * delivered to that it. Note that such frames must be rejected
+ * by the driver as filtered, with the appropriate status flag.
+ *
+ * This function allows implementing this mode in a race-free
+ * manner.
+ *
+ * To do this, a driver must keep track of the number of frames
+ * still enqueued for a specific station. If this number is not
+ * zero when the station goes to sleep, the driver must call
+ * this function to force mac80211 to consider the station to
+ * be asleep regardless of the station's actual state. Once the
+ * number of outstanding frames reaches zero, the driver must
+ * call this function again to unblock the station. That will
+ * cause mac80211 to be able to send ps-poll responses, and if
+ * the station queried in the meantime then frames will also
+ * be sent out as a result of this. Additionally, the driver
+ * will be notified that the station woke up some time after
+ * it is unblocked, regardless of whether the station actually
+ * woke up while blocked or not.
+ */
+void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta, bool block);
+
+/**
* ieee80211_beacon_loss - inform hardware does not receive beacons
*
* @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b5131bd6fa1..56319b51d170 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -738,13 +738,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
err = sta_info_insert(sta);
if (err) {
- /* STA has been freed */
- if (err == -EEXIST && layer2_update) {
- /* Need to update layer 2 devices on reassociation */
- sta = sta_info_get(local, mac);
- if (sta)
- ieee80211_send_layer2_update(sta);
- }
rcu_read_unlock();
return err;
}
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 96991b68f048..82c807723b6f 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -1,3 +1,4 @@
+
/*
* mac80211 debugfs for wireless PHYs
*
@@ -38,16 +39,10 @@ static const struct file_operations name## _ops = { \
};
#define DEBUGFS_ADD(name) \
- local->debugfs.name = debugfs_create_file(#name, 0400, phyd, \
- local, &name## _ops);
+ debugfs_create_file(#name, 0400, phyd, local, &name## _ops);
#define DEBUGFS_ADD_MODE(name, mode) \
- local->debugfs.name = debugfs_create_file(#name, mode, phyd, \
- local, &name## _ops);
-
-#define DEBUGFS_DEL(name) \
- debugfs_remove(local->debugfs.name); \
- local->debugfs.name = NULL;
+ debugfs_create_file(#name, mode, phyd, local, &name## _ops);
DEBUGFS_READONLY_FILE(frequency, 20, "%d",
@@ -233,12 +228,7 @@ static const struct file_operations stats_ ##name## _ops = { \
};
#define DEBUGFS_STATS_ADD(name) \
- local->debugfs.stats.name = debugfs_create_file(#name, 0400, statsd,\
- local, &stats_ ##name## _ops);
-
-#define DEBUGFS_STATS_DEL(name) \
- debugfs_remove(local->debugfs.stats.name); \
- local->debugfs.stats.name = NULL;
+ debugfs_create_file(#name, 0400, statsd, local, &stats_ ##name## _ops);
DEBUGFS_STATS_FILE(transmitted_fragment_count, 20, "%u",
local->dot11TransmittedFragmentCount);
@@ -326,7 +316,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_ADD(noack);
statsd = debugfs_create_dir("statistics", phyd);
- local->debugfs.statistics = statsd;
/* if the dir failed, don't put all the other things into the root! */
if (!statsd)
@@ -367,57 +356,3 @@ void debugfs_hw_add(struct ieee80211_local *local)
DEBUGFS_STATS_ADD(dot11FCSErrorCount);
DEBUGFS_STATS_ADD(dot11RTSSuccessCount);
}
-
-void debugfs_hw_del(struct ieee80211_local *local)
-{
- DEBUGFS_DEL(frequency);
- DEBUGFS_DEL(total_ps_buffered);
- DEBUGFS_DEL(wep_iv);
- DEBUGFS_DEL(tsf);
- DEBUGFS_DEL(queues);
- DEBUGFS_DEL(reset);
- DEBUGFS_DEL(noack);
-
- DEBUGFS_STATS_DEL(transmitted_fragment_count);
- DEBUGFS_STATS_DEL(multicast_transmitted_frame_count);
- DEBUGFS_STATS_DEL(failed_count);
- DEBUGFS_STATS_DEL(retry_count);
- DEBUGFS_STATS_DEL(multiple_retry_count);
- DEBUGFS_STATS_DEL(frame_duplicate_count);
- DEBUGFS_STATS_DEL(received_fragment_count);
- DEBUGFS_STATS_DEL(multicast_received_frame_count);
- DEBUGFS_STATS_DEL(transmitted_frame_count);
- DEBUGFS_STATS_DEL(num_scans);
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- DEBUGFS_STATS_DEL(tx_handlers_drop);
- DEBUGFS_STATS_DEL(tx_handlers_queued);
- DEBUGFS_STATS_DEL(tx_handlers_drop_unencrypted);
- DEBUGFS_STATS_DEL(tx_handlers_drop_fragment);
- DEBUGFS_STATS_DEL(tx_handlers_drop_wep);
- DEBUGFS_STATS_DEL(tx_handlers_drop_not_assoc);
- DEBUGFS_STATS_DEL(tx_handlers_drop_unauth_port);
- DEBUGFS_STATS_DEL(rx_handlers_drop);
- DEBUGFS_STATS_DEL(rx_handlers_queued);
- DEBUGFS_STATS_DEL(rx_handlers_drop_nullfunc);
- DEBUGFS_STATS_DEL(rx_handlers_drop_defrag);
- DEBUGFS_STATS_DEL(rx_handlers_drop_short);
- DEBUGFS_STATS_DEL(rx_handlers_drop_passive_scan);
- DEBUGFS_STATS_DEL(tx_expand_skb_head);
- DEBUGFS_STATS_DEL(tx_expand_skb_head_cloned);
- DEBUGFS_STATS_DEL(rx_expand_skb_head);
- DEBUGFS_STATS_DEL(rx_expand_skb_head2);
- DEBUGFS_STATS_DEL(rx_handlers_fragments);
- DEBUGFS_STATS_DEL(tx_status_drop);
-#endif
- DEBUGFS_STATS_DEL(dot11ACKFailureCount);
- DEBUGFS_STATS_DEL(dot11RTSFailureCount);
- DEBUGFS_STATS_DEL(dot11FCSErrorCount);
- DEBUGFS_STATS_DEL(dot11RTSSuccessCount);
-
- debugfs_remove(local->debugfs.statistics);
- local->debugfs.statistics = NULL;
- debugfs_remove(local->debugfs.stations);
- local->debugfs.stations = NULL;
- debugfs_remove(local->debugfs.keys);
- local->debugfs.keys = NULL;
-}
diff --git a/net/mac80211/debugfs.h b/net/mac80211/debugfs.h
index dd2541935c27..68e6a2050f9a 100644
--- a/net/mac80211/debugfs.h
+++ b/net/mac80211/debugfs.h
@@ -3,14 +3,12 @@
#ifdef CONFIG_MAC80211_DEBUGFS
extern void debugfs_hw_add(struct ieee80211_local *local);
-extern void debugfs_hw_del(struct ieee80211_local *local);
extern int mac80211_open_file_generic(struct inode *inode, struct file *file);
#else
static inline void debugfs_hw_add(struct ieee80211_local *local)
{
return;
}
-static inline void debugfs_hw_del(struct ieee80211_local *local) {}
#endif
#endif /* __MAC80211_DEBUGFS_H */
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 99c752588b30..e0f5224630da 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -225,8 +225,8 @@ static ssize_t key_key_read(struct file *file, char __user *userbuf,
KEY_OPS(key);
#define DEBUGFS_ADD(name) \
- key->debugfs.name = debugfs_create_file(#name, 0400,\
- key->debugfs.dir, key, &key_##name##_ops);
+ debugfs_create_file(#name, 0400, key->debugfs.dir, \
+ key, &key_##name##_ops);
void ieee80211_debugfs_key_add(struct ieee80211_key *key)
{
@@ -271,30 +271,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
DEBUGFS_ADD(ifindex);
};
-#define DEBUGFS_DEL(name) \
- debugfs_remove(key->debugfs.name); key->debugfs.name = NULL;
-
void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
{
if (!key)
return;
- DEBUGFS_DEL(keylen);
- DEBUGFS_DEL(flags);
- DEBUGFS_DEL(keyidx);
- DEBUGFS_DEL(hw_key_idx);
- DEBUGFS_DEL(tx_rx_count);
- DEBUGFS_DEL(algorithm);
- DEBUGFS_DEL(tx_spec);
- DEBUGFS_DEL(rx_spec);
- DEBUGFS_DEL(replays);
- DEBUGFS_DEL(icverrors);
- DEBUGFS_DEL(key);
- DEBUGFS_DEL(ifindex);
-
- debugfs_remove(key->debugfs.stalink);
- key->debugfs.stalink = NULL;
- debugfs_remove(key->debugfs.dir);
+ debugfs_remove_recursive(key->debugfs.dir);
key->debugfs.dir = NULL;
}
void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
@@ -302,7 +284,7 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
char buf[50];
struct ieee80211_key *key;
- if (!sdata->debugfsdir)
+ if (!sdata->debugfs.dir)
return;
/* this is running under the key lock */
@@ -310,9 +292,9 @@ void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata)
key = sdata->default_key;
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
- sdata->common_debugfs.default_key =
+ sdata->debugfs.default_key =
debugfs_create_symlink("default_key",
- sdata->debugfsdir, buf);
+ sdata->debugfs.dir, buf);
} else
ieee80211_debugfs_key_remove_default(sdata);
}
@@ -322,8 +304,8 @@ void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata)
if (!sdata)
return;
- debugfs_remove(sdata->common_debugfs.default_key);
- sdata->common_debugfs.default_key = NULL;
+ debugfs_remove(sdata->debugfs.default_key);
+ sdata->debugfs.default_key = NULL;
}
void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
@@ -331,7 +313,7 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
char buf[50];
struct ieee80211_key *key;
- if (!sdata->debugfsdir)
+ if (!sdata->debugfs.dir)
return;
/* this is running under the key lock */
@@ -339,9 +321,9 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
key = sdata->default_mgmt_key;
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
- sdata->common_debugfs.default_mgmt_key =
+ sdata->debugfs.default_mgmt_key =
debugfs_create_symlink("default_mgmt_key",
- sdata->debugfsdir, buf);
+ sdata->debugfs.dir, buf);
} else
ieee80211_debugfs_key_remove_mgmt_default(sdata);
}
@@ -351,8 +333,8 @@ void ieee80211_debugfs_key_remove_mgmt_default(struct ieee80211_sub_if_data *sda
if (!sdata)
return;
- debugfs_remove(sdata->common_debugfs.default_mgmt_key);
- sdata->common_debugfs.default_mgmt_key = NULL;
+ debugfs_remove(sdata->debugfs.default_mgmt_key);
+ sdata->debugfs.default_mgmt_key = NULL;
}
void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 61234e79022b..8782264f49e7 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -152,9 +152,9 @@ IEEE80211_IF_FILE(min_discovery_timeout,
#endif
-#define DEBUGFS_ADD(name, type)\
- sdata->debugfs.type.name = debugfs_create_file(#name, 0400,\
- sdata->debugfsdir, sdata, &name##_ops);
+#define DEBUGFS_ADD(name, type) \
+ debugfs_create_file(#name, 0400, sdata->debugfs.dir, \
+ sdata, &name##_ops);
static void add_sta_files(struct ieee80211_sub_if_data *sdata)
{
@@ -199,30 +199,32 @@ static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
}
#ifdef CONFIG_MAC80211_MESH
-#define MESHSTATS_ADD(name)\
- sdata->mesh_stats.name = debugfs_create_file(#name, 0400,\
- sdata->mesh_stats_dir, sdata, &name##_ops);
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
{
- sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats",
- sdata->debugfsdir);
+ struct dentry *dir = debugfs_create_dir("mesh_stats",
+ sdata->debugfs.dir);
+
+#define MESHSTATS_ADD(name)\
+ debugfs_create_file(#name, 0400, dir, sdata, &name##_ops);
+
MESHSTATS_ADD(fwded_mcast);
MESHSTATS_ADD(fwded_unicast);
MESHSTATS_ADD(fwded_frames);
MESHSTATS_ADD(dropped_frames_ttl);
MESHSTATS_ADD(dropped_frames_no_route);
MESHSTATS_ADD(estab_plinks);
+#undef MESHSTATS_ADD
}
-#define MESHPARAMS_ADD(name)\
- sdata->mesh_config.name = debugfs_create_file(#name, 0600,\
- sdata->mesh_config_dir, sdata, &name##_ops);
-
static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
{
- sdata->mesh_config_dir = debugfs_create_dir("mesh_config",
- sdata->debugfsdir);
+ struct dentry *dir = debugfs_create_dir("mesh_config",
+ sdata->debugfs.dir);
+
+#define MESHPARAMS_ADD(name) \
+ debugfs_create_file(#name, 0600, dir, sdata, &name##_ops);
+
MESHPARAMS_ADD(dot11MeshMaxRetries);
MESHPARAMS_ADD(dot11MeshRetryTimeout);
MESHPARAMS_ADD(dot11MeshConfirmTimeout);
@@ -236,12 +238,14 @@ static void add_mesh_config(struct ieee80211_sub_if_data *sdata)
MESHPARAMS_ADD(dot11MeshHWMPmaxPREQretries);
MESHPARAMS_ADD(path_refresh_time);
MESHPARAMS_ADD(min_discovery_timeout);
+
+#undef MESHPARAMS_ADD
}
#endif
static void add_files(struct ieee80211_sub_if_data *sdata)
{
- if (!sdata->debugfsdir)
+ if (!sdata->debugfs.dir)
return;
switch (sdata->vif.type) {
@@ -274,134 +278,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
}
}
-#define DEBUGFS_DEL(name, type) \
- do { \
- debugfs_remove(sdata->debugfs.type.name); \
- sdata->debugfs.type.name = NULL; \
- } while (0)
-
-static void del_sta_files(struct ieee80211_sub_if_data *sdata)
-{
- DEBUGFS_DEL(drop_unencrypted, sta);
- DEBUGFS_DEL(force_unicast_rateidx, sta);
- DEBUGFS_DEL(max_ratectrl_rateidx, sta);
-
- DEBUGFS_DEL(bssid, sta);
- DEBUGFS_DEL(aid, sta);
- DEBUGFS_DEL(capab, sta);
-}
-
-static void del_ap_files(struct ieee80211_sub_if_data *sdata)
-{
- DEBUGFS_DEL(drop_unencrypted, ap);
- DEBUGFS_DEL(force_unicast_rateidx, ap);
- DEBUGFS_DEL(max_ratectrl_rateidx, ap);
-
- DEBUGFS_DEL(num_sta_ps, ap);
- DEBUGFS_DEL(dtim_count, ap);
- DEBUGFS_DEL(num_buffered_multicast, ap);
-}
-
-static void del_wds_files(struct ieee80211_sub_if_data *sdata)
-{
- DEBUGFS_DEL(drop_unencrypted, wds);
- DEBUGFS_DEL(force_unicast_rateidx, wds);
- DEBUGFS_DEL(max_ratectrl_rateidx, wds);
-
- DEBUGFS_DEL(peer, wds);
-}
-
-static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
-{
- DEBUGFS_DEL(drop_unencrypted, vlan);
- DEBUGFS_DEL(force_unicast_rateidx, vlan);
- DEBUGFS_DEL(max_ratectrl_rateidx, vlan);
-}
-
-static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
-{
-}
-
-#ifdef CONFIG_MAC80211_MESH
-#define MESHSTATS_DEL(name) \
- do { \
- debugfs_remove(sdata->mesh_stats.name); \
- sdata->mesh_stats.name = NULL; \
- } while (0)
-
-static void del_mesh_stats(struct ieee80211_sub_if_data *sdata)
-{
- MESHSTATS_DEL(fwded_mcast);
- MESHSTATS_DEL(fwded_unicast);
- MESHSTATS_DEL(fwded_frames);
- MESHSTATS_DEL(dropped_frames_ttl);
- MESHSTATS_DEL(dropped_frames_no_route);
- MESHSTATS_DEL(estab_plinks);
- debugfs_remove(sdata->mesh_stats_dir);
- sdata->mesh_stats_dir = NULL;
-}
-
-#define MESHPARAMS_DEL(name) \
- do { \
- debugfs_remove(sdata->mesh_config.name); \
- sdata->mesh_config.name = NULL; \
- } while (0)
-
-static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
-{
- MESHPARAMS_DEL(dot11MeshMaxRetries);
- MESHPARAMS_DEL(dot11MeshRetryTimeout);
- MESHPARAMS_DEL(dot11MeshConfirmTimeout);
- MESHPARAMS_DEL(dot11MeshHoldingTimeout);
- MESHPARAMS_DEL(dot11MeshTTL);
- MESHPARAMS_DEL(auto_open_plinks);
- MESHPARAMS_DEL(dot11MeshMaxPeerLinks);
- MESHPARAMS_DEL(dot11MeshHWMPactivePathTimeout);
- MESHPARAMS_DEL(dot11MeshHWMPpreqMinInterval);
- MESHPARAMS_DEL(dot11MeshHWMPnetDiameterTraversalTime);
- MESHPARAMS_DEL(dot11MeshHWMPmaxPREQretries);
- MESHPARAMS_DEL(path_refresh_time);
- MESHPARAMS_DEL(min_discovery_timeout);
- debugfs_remove(sdata->mesh_config_dir);
- sdata->mesh_config_dir = NULL;
-}
-#endif
-
-static void del_files(struct ieee80211_sub_if_data *sdata)
-{
- if (!sdata->debugfsdir)
- return;
-
- switch (sdata->vif.type) {
- case NL80211_IFTYPE_MESH_POINT:
-#ifdef CONFIG_MAC80211_MESH
- del_mesh_stats(sdata);
- del_mesh_config(sdata);
-#endif
- break;
- case NL80211_IFTYPE_STATION:
- del_sta_files(sdata);
- break;
- case NL80211_IFTYPE_ADHOC:
- /* XXX */
- break;
- case NL80211_IFTYPE_AP:
- del_ap_files(sdata);
- break;
- case NL80211_IFTYPE_WDS:
- del_wds_files(sdata);
- break;
- case NL80211_IFTYPE_MONITOR:
- del_monitor_files(sdata);
- break;
- case NL80211_IFTYPE_AP_VLAN:
- del_vlan_files(sdata);
- break;
- default:
- break;
- }
-}
-
static int notif_registered;
void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
@@ -412,16 +288,18 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
return;
sprintf(buf, "netdev:%s", sdata->dev->name);
- sdata->debugfsdir = debugfs_create_dir(buf,
+ sdata->debugfs.dir = debugfs_create_dir(buf,
sdata->local->hw.wiphy->debugfsdir);
add_files(sdata);
}
void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
{
- del_files(sdata);
- debugfs_remove(sdata->debugfsdir);
- sdata->debugfsdir = NULL;
+ if (!sdata->debugfs.dir)
+ return;
+
+ debugfs_remove_recursive(sdata->debugfs.dir);
+ sdata->debugfs.dir = NULL;
}
static int netdev_notify(struct notifier_block *nb,
@@ -444,7 +322,7 @@ static int netdev_notify(struct notifier_block *nb,
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- dir = sdata->debugfsdir;
+ dir = sdata->debugfs.dir;
if (!dir)
return 0;
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 33a2e892115b..f043c29070d7 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -57,7 +57,6 @@ STA_FILE(tx_filtered, tx_filtered_count, LU);
STA_FILE(tx_retry_failed, tx_retry_failed, LU);
STA_FILE(tx_retry_count, tx_retry_count, LU);
STA_FILE(last_signal, last_signal, D);
-STA_FILE(last_qual, last_qual, D);
STA_FILE(last_noise, last_noise, D);
STA_FILE(wep_weak_iv_count, wep_weak_iv_count, LU);
@@ -67,10 +66,11 @@ static ssize_t sta_flags_read(struct file *file, char __user *userbuf,
char buf[100];
struct sta_info *sta = file->private_data;
u32 staflags = get_sta_flags(sta);
- int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s",
+ int res = scnprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s",
staflags & WLAN_STA_AUTH ? "AUTH\n" : "",
staflags & WLAN_STA_ASSOC ? "ASSOC\n" : "",
- staflags & WLAN_STA_PS ? "PS\n" : "",
+ staflags & WLAN_STA_PS_STA ? "PS (sta)\n" : "",
+ staflags & WLAN_STA_PS_DRIVER ? "PS (driver)\n" : "",
staflags & WLAN_STA_AUTHORIZED ? "AUTHORIZED\n" : "",
staflags & WLAN_STA_SHORT_PREAMBLE ? "SHORT PREAMBLE\n" : "",
staflags & WLAN_STA_WME ? "WME\n" : "",
@@ -158,13 +158,9 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
STA_OPS(agg_status);
#define DEBUGFS_ADD(name) \
- sta->debugfs.name = debugfs_create_file(#name, 0400, \
+ debugfs_create_file(#name, 0400, \
sta->debugfs.dir, sta, &sta_ ##name## _ops);
-#define DEBUGFS_DEL(name) \
- debugfs_remove(sta->debugfs.name);\
- sta->debugfs.name = NULL;
-
void ieee80211_sta_debugfs_add(struct sta_info *sta)
{
@@ -209,36 +205,12 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
DEBUGFS_ADD(tx_retry_failed);
DEBUGFS_ADD(tx_retry_count);
DEBUGFS_ADD(last_signal);
- DEBUGFS_ADD(last_qual);
DEBUGFS_ADD(last_noise);
DEBUGFS_ADD(wep_weak_iv_count);
}
void ieee80211_sta_debugfs_remove(struct sta_info *sta)
{
- DEBUGFS_DEL(flags);
- DEBUGFS_DEL(num_ps_buf_frames);
- DEBUGFS_DEL(inactive_ms);
- DEBUGFS_DEL(last_seq_ctrl);
- DEBUGFS_DEL(agg_status);
- DEBUGFS_DEL(aid);
- DEBUGFS_DEL(dev);
- DEBUGFS_DEL(rx_packets);
- DEBUGFS_DEL(tx_packets);
- DEBUGFS_DEL(rx_bytes);
- DEBUGFS_DEL(tx_bytes);
- DEBUGFS_DEL(rx_duplicates);
- DEBUGFS_DEL(rx_fragments);
- DEBUGFS_DEL(rx_dropped);
- DEBUGFS_DEL(tx_fragments);
- DEBUGFS_DEL(tx_filtered);
- DEBUGFS_DEL(tx_retry_failed);
- DEBUGFS_DEL(tx_retry_count);
- DEBUGFS_DEL(last_signal);
- DEBUGFS_DEL(last_qual);
- DEBUGFS_DEL(last_noise);
- DEBUGFS_DEL(wep_weak_iv_count);
-
- debugfs_remove(sta->debugfs.dir);
+ debugfs_remove_recursive(sta->debugfs.dir);
sta->debugfs.dir = NULL;
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index f1362f32c17d..fbffce90edbc 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -455,6 +455,10 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
ieee80211_sta_expire(sdata, IEEE80211_IBSS_INACTIVITY_LIMIT);
+ if (time_before(jiffies, ifibss->last_scan_completed +
+ IEEE80211_IBSS_MERGE_INTERVAL))
+ return;
+
if (ieee80211_sta_active_ibss(sdata))
return;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 588005c84a6d..1ef767366b77 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -176,7 +176,6 @@ struct ieee80211_rx_data {
struct ieee80211_rate *rate;
unsigned int flags;
- int sent_ps_buffered;
int queue;
u32 tkip_iv32;
u16 tkip_iv16;
@@ -471,74 +470,11 @@ struct ieee80211_sub_if_data {
} u;
#ifdef CONFIG_MAC80211_DEBUGFS
- struct dentry *debugfsdir;
- union {
- struct {
- struct dentry *drop_unencrypted;
- struct dentry *bssid;
- struct dentry *aid;
- struct dentry *capab;
- struct dentry *force_unicast_rateidx;
- struct dentry *max_ratectrl_rateidx;
- } sta;
- struct {
- struct dentry *drop_unencrypted;
- struct dentry *num_sta_ps;
- struct dentry *dtim_count;
- struct dentry *force_unicast_rateidx;
- struct dentry *max_ratectrl_rateidx;
- struct dentry *num_buffered_multicast;
- } ap;
- struct {
- struct dentry *drop_unencrypted;
- struct dentry *peer;
- struct dentry *force_unicast_rateidx;
- struct dentry *max_ratectrl_rateidx;
- } wds;
- struct {
- struct dentry *drop_unencrypted;
- struct dentry *force_unicast_rateidx;
- struct dentry *max_ratectrl_rateidx;
- } vlan;
- struct {
- struct dentry *mode;
- } monitor;
- } debugfs;
struct {
+ struct dentry *dir;
struct dentry *default_key;
struct dentry *default_mgmt_key;
- } common_debugfs;
-
-#ifdef CONFIG_MAC80211_MESH
- struct dentry *mesh_stats_dir;
- struct {
- struct dentry *fwded_mcast;
- struct dentry *fwded_unicast;
- struct dentry *fwded_frames;
- struct dentry *dropped_frames_ttl;
- struct dentry *dropped_frames_no_route;
- struct dentry *estab_plinks;
- struct timer_list mesh_path_timer;
- } mesh_stats;
-
- struct dentry *mesh_config_dir;
- struct {
- struct dentry *dot11MeshRetryTimeout;
- struct dentry *dot11MeshConfirmTimeout;
- struct dentry *dot11MeshHoldingTimeout;
- struct dentry *dot11MeshMaxRetries;
- struct dentry *dot11MeshTTL;
- struct dentry *auto_open_plinks;
- struct dentry *dot11MeshMaxPeerLinks;
- struct dentry *dot11MeshHWMPactivePathTimeout;
- struct dentry *dot11MeshHWMPpreqMinInterval;
- struct dentry *dot11MeshHWMPnetDiameterTraversalTime;
- struct dentry *dot11MeshHWMPmaxPREQretries;
- struct dentry *path_refresh_time;
- struct dentry *min_discovery_timeout;
- } mesh_config;
-#endif
-
+ } debugfs;
#endif
/* must be last, dynamically sized area in this! */
struct ieee80211_vif vif;
@@ -730,10 +666,9 @@ struct ieee80211_local {
unsigned long scanning;
struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request *int_scan_req;
- struct cfg80211_scan_request *scan_req;
+ struct cfg80211_scan_request *scan_req, *hw_scan_req;
struct ieee80211_channel *scan_channel;
- const u8 *orig_ies;
- int orig_ies_len;
+ enum ieee80211_band hw_scan_band;
int scan_channel_idx;
int scan_ies_len;
@@ -818,53 +753,6 @@ struct ieee80211_local {
#ifdef CONFIG_MAC80211_DEBUGFS
struct local_debugfsdentries {
struct dentry *rcdir;
- struct dentry *rcname;
- struct dentry *frequency;
- struct dentry *total_ps_buffered;
- struct dentry *wep_iv;
- struct dentry *tsf;
- struct dentry *queues;
- struct dentry *reset;
- struct dentry *noack;
- struct dentry *statistics;
- struct local_debugfsdentries_statsdentries {
- struct dentry *transmitted_fragment_count;
- struct dentry *multicast_transmitted_frame_count;
- struct dentry *failed_count;
- struct dentry *retry_count;
- struct dentry *multiple_retry_count;
- struct dentry *frame_duplicate_count;
- struct dentry *received_fragment_count;
- struct dentry *multicast_received_frame_count;
- struct dentry *transmitted_frame_count;
- struct dentry *wep_undecryptable_count;
- struct dentry *num_scans;
-#ifdef CONFIG_MAC80211_DEBUG_COUNTERS
- struct dentry *tx_handlers_drop;
- struct dentry *tx_handlers_queued;
- struct dentry *tx_handlers_drop_unencrypted;
- struct dentry *tx_handlers_drop_fragment;
- struct dentry *tx_handlers_drop_wep;
- struct dentry *tx_handlers_drop_not_assoc;
- struct dentry *tx_handlers_drop_unauth_port;
- struct dentry *rx_handlers_drop;
- struct dentry *rx_handlers_queued;
- struct dentry *rx_handlers_drop_nullfunc;
- struct dentry *rx_handlers_drop_defrag;
- struct dentry *rx_handlers_drop_short;
- struct dentry *rx_handlers_drop_passive_scan;
- struct dentry *tx_expand_skb_head;
- struct dentry *tx_expand_skb_head_cloned;
- struct dentry *rx_expand_skb_head;
- struct dentry *rx_expand_skb_head2;
- struct dentry *rx_handlers_fragments;
- struct dentry *tx_status_drop;
-#endif
- struct dentry *dot11ACKFailureCount;
- struct dentry *dot11RTSFailureCount;
- struct dentry *dot11FCSErrorCount;
- struct dentry *dot11RTSSuccessCount;
- } stats;
struct dentry *stations;
struct dentry *keys;
} debugfs;
@@ -1160,7 +1048,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u8 *extra, size_t extra_len, const u8 *bssid,
const u8 *key, u8 key_len, u8 key_idx);
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
- const u8 *ie, size_t ie_len);
+ const u8 *ie, size_t ie_len,
+ enum ieee80211_band band);
void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 14f10eb91c5c..8495161b99b8 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -214,8 +214,8 @@ static int ieee80211_open(struct net_device *dev)
/* must be before the call to ieee80211_configure_filter */
local->monitors++;
if (local->monitors == 1) {
- local->hw.conf.flags |= IEEE80211_CONF_RADIOTAP;
- hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+ local->hw.conf.flags |= IEEE80211_CONF_MONITOR;
+ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
}
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
@@ -435,8 +435,8 @@ static int ieee80211_stop(struct net_device *dev)
local->monitors--;
if (local->monitors == 0) {
- local->hw.conf.flags &= ~IEEE80211_CONF_RADIOTAP;
- hw_reconf_flags |= IEEE80211_CONF_CHANGE_RADIOTAP;
+ local->hw.conf.flags &= ~IEEE80211_CONF_MONITOR;
+ hw_reconf_flags |= IEEE80211_CONF_CHANGE_MONITOR;
}
if (sdata->u.mntr_flags & MONITOR_FLAG_FCSFAIL)
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index 9572e00f532c..a49f93b79e92 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -118,18 +118,6 @@ struct ieee80211_key {
struct {
struct dentry *stalink;
struct dentry *dir;
- struct dentry *keylen;
- struct dentry *flags;
- struct dentry *keyidx;
- struct dentry *hw_key_idx;
- struct dentry *tx_rx_count;
- struct dentry *algorithm;
- struct dentry *tx_spec;
- struct dentry *rx_spec;
- struct dentry *replays;
- struct dentry *icverrors;
- struct dentry *key;
- struct dentry *ifindex;
int cnt;
} debugfs;
#endif
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 797f53942e5f..beb8718d905e 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -385,13 +385,13 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
* can be unknown, for example with different interrupt status
* bits.
*/
- if (test_sta_flags(sta, WLAN_STA_PS) &&
+ if (test_sta_flags(sta, WLAN_STA_PS_STA) &&
skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) {
skb_queue_tail(&sta->tx_filtered, skb);
return;
}
- if (!test_sta_flags(sta, WLAN_STA_PS) &&
+ if (!test_sta_flags(sta, WLAN_STA_PS_STA) &&
!(info->flags & IEEE80211_TX_INTFL_RETRIED)) {
/* Software retry the packet once */
info->flags |= IEEE80211_TX_INTFL_RETRIED;
@@ -406,7 +406,7 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local,
"queue_len=%d PS=%d @%lu\n",
wiphy_name(local->hw.wiphy),
skb_queue_len(&sta->tx_filtered),
- !!test_sta_flags(sta, WLAN_STA_PS), jiffies);
+ !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies);
#endif
dev_kfree_skb(skb);
}
@@ -446,7 +446,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
if (sta) {
if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
- test_sta_flags(sta, WLAN_STA_PS)) {
+ test_sta_flags(sta, WLAN_STA_PS_STA)) {
/*
* The STA is in power save mode, so assume
* that this TX packet failed because of that.
@@ -901,6 +901,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
i++;
}
}
+ local->int_scan_req->n_channels = i;
local->network_latency_notifier.notifier_call =
ieee80211_max_network_latency;
@@ -923,7 +924,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
fail_wep:
sta_info_stop(local);
fail_sta_info:
- debugfs_hw_del(local);
destroy_workqueue(local->workqueue);
fail_workqueue:
wiphy_unregister(local->hw.wiphy);
@@ -959,7 +959,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
ieee80211_clear_tx_pending(local);
sta_info_stop(local);
rate_control_deinitialize(local);
- debugfs_hw_del(local);
if (skb_queue_len(&local->skb_queue)
|| skb_queue_len(&local->skb_queue_unreliable))
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index b33efc4fc267..ccda7454fb17 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -163,8 +163,7 @@ struct rate_control_ref *rate_control_alloc(const char *name,
#ifdef CONFIG_MAC80211_DEBUGFS
debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir);
local->debugfs.rcdir = debugfsdir;
- local->debugfs.rcname = debugfs_create_file("name", 0400, debugfsdir,
- ref, &rcname_ops);
+ debugfs_create_file("name", 0400, debugfsdir, ref, &rcname_ops);
#endif
ref->priv = ref->ops->alloc(&local->hw, debugfsdir);
@@ -188,9 +187,7 @@ static void rate_control_release(struct kref *kref)
ctrl_ref->ops->free(ctrl_ref->priv);
#ifdef CONFIG_MAC80211_DEBUGFS
- debugfs_remove(ctrl_ref->local->debugfs.rcname);
- ctrl_ref->local->debugfs.rcname = NULL;
- debugfs_remove(ctrl_ref->local->debugfs.rcdir);
+ debugfs_remove_recursive(ctrl_ref->local->debugfs.rcdir);
ctrl_ref->local->debugfs.rcdir = NULL;
#endif
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5c385e3c1d1f..28316b2a585f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -39,11 +39,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
* only useful for monitoring.
*/
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
- struct sk_buff *skb,
- int rtap_len)
+ struct sk_buff *skb)
{
- skb_pull(skb, rtap_len);
-
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
if (likely(skb->len > FCS_LEN))
skb_trim(skb, skb->len - FCS_LEN);
@@ -59,15 +56,14 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
}
static inline int should_drop_frame(struct sk_buff *skb,
- int present_fcs_len,
- int radiotap_len)
+ int present_fcs_len)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
return 1;
- if (unlikely(skb->len < 16 + present_fcs_len + radiotap_len))
+ if (unlikely(skb->len < 16 + present_fcs_len))
return 1;
if (ieee80211_is_ctl(hdr->frame_control) &&
!ieee80211_is_pspoll(hdr->frame_control) &&
@@ -95,10 +91,6 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
if (len & 1) /* padding for RX_FLAGS if necessary */
len++;
- /* make sure radiotap starts at a naturally aligned address */
- if (len % 8)
- len = roundup(len, 8);
-
return len;
}
@@ -116,6 +108,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_radiotap_header *rthdr;
unsigned char *pos;
+ u16 rx_flags = 0;
rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
memset(rthdr, 0, rtap_len);
@@ -134,7 +127,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_TSFT */
if (status->flag & RX_FLAG_TSFT) {
- *(__le64 *)pos = cpu_to_le64(status->mactime);
+ put_unaligned_le64(status->mactime, pos);
rthdr->it_present |=
cpu_to_le32(1 << IEEE80211_RADIOTAP_TSFT);
pos += 8;
@@ -166,17 +159,17 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos++;
/* IEEE80211_RADIOTAP_CHANNEL */
- *(__le16 *)pos = cpu_to_le16(status->freq);
+ put_unaligned_le16(status->freq, pos);
pos += 2;
if (status->band == IEEE80211_BAND_5GHZ)
- *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_5GHZ);
+ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
+ pos);
else if (rate->flags & IEEE80211_RATE_ERP_G)
- *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
- IEEE80211_CHAN_2GHZ);
+ put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
+ pos);
else
- *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK |
- IEEE80211_CHAN_2GHZ);
+ put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
+ pos);
pos += 2;
/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
@@ -205,10 +198,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
/* IEEE80211_RADIOTAP_RX_FLAGS */
/* ensure 2 byte alignment for the 2 byte field as required */
- if ((pos - (unsigned char *)rthdr) & 1)
+ if ((pos - (u8 *)rthdr) & 1)
pos++;
if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
- *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP);
+ rx_flags |= IEEE80211_RADIOTAP_F_RX_BADPLCP;
+ put_unaligned_le16(rx_flags, pos);
pos += 2;
}
@@ -227,7 +221,6 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
struct sk_buff *skb, *skb2;
struct net_device *prev_dev = NULL;
int present_fcs_len = 0;
- int rtap_len = 0;
/*
* First, we may need to make a copy of the skb because
@@ -237,25 +230,23 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
* We don't need to, of course, if we aren't going to return
* the SKB because it has a bad FCS/PLCP checksum.
*/
- if (status->flag & RX_FLAG_RADIOTAP)
- rtap_len = ieee80211_get_radiotap_len(origskb->data);
- else
- /* room for the radiotap header based on driver features */
- needed_headroom = ieee80211_rx_radiotap_len(local, status);
+
+ /* room for the radiotap header based on driver features */
+ needed_headroom = ieee80211_rx_radiotap_len(local, status);
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN;
if (!local->monitors) {
- if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
+ if (should_drop_frame(origskb, present_fcs_len)) {
dev_kfree_skb(origskb);
return NULL;
}
- return remove_monitor_info(local, origskb, rtap_len);
+ return remove_monitor_info(local, origskb);
}
- if (should_drop_frame(origskb, present_fcs_len, rtap_len)) {
+ if (should_drop_frame(origskb, present_fcs_len)) {
/* only need to expand headroom if necessary */
skb = origskb;
origskb = NULL;
@@ -279,16 +270,14 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
*/
skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
- origskb = remove_monitor_info(local, origskb, rtap_len);
+ origskb = remove_monitor_info(local, origskb);
if (!skb)
return origskb;
}
- /* if necessary, prepend radiotap information */
- if (!(status->flag & RX_FLAG_RADIOTAP))
- ieee80211_add_rx_radiotap_header(local, skb, rate,
- needed_headroom);
+ /* prepend radiotap information */
+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom);
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -792,7 +781,7 @@ static void ap_sta_ps_start(struct sta_info *sta)
struct ieee80211_local *local = sdata->local;
atomic_inc(&sdata->bss->num_sta_ps);
- set_sta_flags(sta, WLAN_STA_PS);
+ set_sta_flags(sta, WLAN_STA_PS_STA);
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_SLEEP, &sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
@@ -800,38 +789,28 @@ static void ap_sta_ps_start(struct sta_info *sta)
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
}
-static int ap_sta_ps_end(struct sta_info *sta)
+static void ap_sta_ps_end(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct ieee80211_local *local = sdata->local;
- int sent, buffered;
atomic_dec(&sdata->bss->num_sta_ps);
- clear_sta_flags(sta, WLAN_STA_PS);
- drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
-
- if (!skb_queue_empty(&sta->ps_tx_buf))
- sta_info_clear_tim_bit(sta);
+ clear_sta_flags(sta, WLAN_STA_PS_STA);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d exits power save mode\n",
sdata->dev->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
- /* Send all buffered frames to the station */
- sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
- buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
- sent += buffered;
- local->total_ps_buffered -= buffered;
-
+ if (test_sta_flags(sta, WLAN_STA_PS_DRIVER)) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
- "since STA not sleeping anymore\n", sdata->dev->name,
- sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
+ printk(KERN_DEBUG "%s: STA %pM aid %d driver-ps-blocked\n",
+ sdata->dev->name, sta->sta.addr, sta->sta.aid);
#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ return;
+ }
- return sent;
+ ieee80211_sta_ps_deliver_wakeup(sta);
}
static ieee80211_rx_result debug_noinline
@@ -870,7 +849,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
sta->rx_fragments++;
sta->rx_bytes += rx->skb->len;
sta->last_signal = rx->status->signal;
- sta->last_qual = rx->status->qual;
sta->last_noise = rx->status->noise;
/*
@@ -880,7 +858,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
if (!ieee80211_has_morefrags(hdr->frame_control) &&
(rx->sdata->vif.type == NL80211_IFTYPE_AP ||
rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
- if (test_sta_flags(sta, WLAN_STA_PS)) {
+ if (test_sta_flags(sta, WLAN_STA_PS_STA)) {
/*
* Ignore doze->wake transitions that are
* indicated by non-data frames, the standard
@@ -891,19 +869,24 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
*/
if (ieee80211_is_data(hdr->frame_control) &&
!ieee80211_has_pm(hdr->frame_control))
- rx->sent_ps_buffered += ap_sta_ps_end(sta);
+ ap_sta_ps_end(sta);
} else {
if (ieee80211_has_pm(hdr->frame_control))
ap_sta_ps_start(sta);
}
}
- /* Drop data::nullfunc frames silently, since they are used only to
- * control station power saving mode. */
- if (ieee80211_is_nullfunc(hdr->frame_control)) {
+ /*
+ * Drop (qos-)data::nullfunc frames silently, since they
+ * are used only to control station power saving mode.
+ */
+ if (ieee80211_is_nullfunc(hdr->frame_control) ||
+ ieee80211_is_qos_nullfunc(hdr->frame_control)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_nullfunc);
- /* Update counter and free packet here to avoid counting this
- * as a dropped packed. */
+ /*
+ * Update counter and free packet here to avoid
+ * counting this as a dropped packed.
+ */
sta->rx_packets++;
dev_kfree_skb(rx->skb);
return RX_QUEUED;
@@ -1103,9 +1086,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
static ieee80211_rx_result debug_noinline
ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
- struct sk_buff *skb;
- int no_pending_pkts;
+ struct ieee80211_sub_if_data *sdata = rx->sdata;
__le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
@@ -1116,56 +1097,10 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
(sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
return RX_DROP_UNUSABLE;
- skb = skb_dequeue(&rx->sta->tx_filtered);
- if (!skb) {
- skb = skb_dequeue(&rx->sta->ps_tx_buf);
- if (skb)
- rx->local->total_ps_buffered--;
- }
- no_pending_pkts = skb_queue_empty(&rx->sta->tx_filtered) &&
- skb_queue_empty(&rx->sta->ps_tx_buf);
-
- if (skb) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *) skb->data;
-
- /*
- * Tell TX path to send this frame even though the STA may
- * still remain is PS mode after this frame exchange.
- */
- info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
-
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
- rx->sta->sta.addr, rx->sta->sta.aid,
- skb_queue_len(&rx->sta->ps_tx_buf));
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
-
- /* Use MoreData flag to indicate whether there are more
- * buffered frames for this STA */
- if (no_pending_pkts)
- hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
- else
- hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
-
- ieee80211_add_pending_skb(rx->local, skb);
-
- if (no_pending_pkts)
- sta_info_clear_tim_bit(rx->sta);
-#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- } else if (!rx->sent_ps_buffered) {
- /*
- * FIXME: This can be the result of a race condition between
- * us expiring a frame and the station polling for it.
- * Should we send it a null-func frame indicating we
- * have nothing buffered for it?
- */
- printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
- "though there are no buffered frames for it\n",
- rx->dev->name, rx->sta->sta.addr);
-#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
- }
+ if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
+ ieee80211_sta_ps_deliver_poll_response(rx->sta);
+ else
+ set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
/* Free PS Poll skb here instead of returning RX_DROP that would
* count as an dropped frame. */
@@ -1337,10 +1272,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
skb = NULL;
} else {
u8 *data = skb->data;
- size_t len = skb->len;
- u8 *new = __skb_push(skb, align);
- memmove(new, data, len);
- __skb_trim(skb, len);
+ size_t len = skb_headlen(skb);
+ skb->data -= align;
+ memmove(skb->data, data, len);
+ skb_set_tail_pointer(skb, len);
}
}
#endif
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 7a350d2690a0..4cf387c944bf 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -12,8 +12,6 @@
* published by the Free Software Foundation.
*/
-/* TODO: figure out how to avoid that the "current BSS" expires */
-
#include <linux/wireless.h>
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
@@ -189,6 +187,39 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
return RX_QUEUED;
}
+/* return false if no more work */
+static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
+{
+ struct cfg80211_scan_request *req = local->scan_req;
+ enum ieee80211_band band;
+ int i, ielen, n_chans;
+
+ do {
+ if (local->hw_scan_band == IEEE80211_NUM_BANDS)
+ return false;
+
+ band = local->hw_scan_band;
+ n_chans = 0;
+ for (i = 0; i < req->n_channels; i++) {
+ if (req->channels[i]->band == band) {
+ local->hw_scan_req->channels[n_chans] =
+ req->channels[i];
+ n_chans++;
+ }
+ }
+
+ local->hw_scan_band++;
+ } while (!n_chans);
+
+ local->hw_scan_req->n_channels = n_chans;
+
+ ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie,
+ req->ie, req->ie_len, band);
+ local->hw_scan_req->ie_len = ielen;
+
+ return true;
+}
+
/*
* inform AP that we will go to sleep so that it will buffer the frames
* while we scan
@@ -249,13 +280,6 @@ static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata)
}
}
-static void ieee80211_restore_scan_ies(struct ieee80211_local *local)
-{
- kfree(local->scan_req->ie);
- local->scan_req->ie = local->orig_ies;
- local->scan_req->ie_len = local->orig_ies_len;
-}
-
void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
{
struct ieee80211_local *local = hw_to_local(hw);
@@ -264,25 +288,36 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
mutex_lock(&local->scan_mtx);
- if (WARN_ON(!local->scanning)) {
+ /*
+ * It's ok to abort a not-yet-running scan (that
+ * we have one at all will be verified by checking
+ * local->scan_req next), but not to complete it
+ * successfully.
+ */
+ if (WARN_ON(!local->scanning && !aborted))
+ aborted = true;
+
+ if (WARN_ON(!local->scan_req)) {
mutex_unlock(&local->scan_mtx);
return;
}
- if (WARN_ON(!local->scan_req)) {
+ was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
+ if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
+ ieee80211_queue_delayed_work(&local->hw,
+ &local->scan_work, 0);
mutex_unlock(&local->scan_mtx);
return;
}
- if (test_bit(SCAN_HW_SCANNING, &local->scanning))
- ieee80211_restore_scan_ies(local);
+ kfree(local->hw_scan_req);
+ local->hw_scan_req = NULL;
if (local->scan_req != local->int_scan_req)
cfg80211_scan_done(local->scan_req, aborted);
local->scan_req = NULL;
local->scan_sdata = NULL;
- was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
local->scanning = 0;
local->scan_channel = NULL;
@@ -394,19 +429,23 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
if (local->ops->hw_scan) {
u8 *ies;
- int ielen;
- ies = kmalloc(2 + IEEE80211_MAX_SSID_LEN +
- local->scan_ies_len + req->ie_len, GFP_KERNEL);
- if (!ies)
+ local->hw_scan_req = kmalloc(
+ sizeof(*local->hw_scan_req) +
+ req->n_channels * sizeof(req->channels[0]) +
+ 2 + IEEE80211_MAX_SSID_LEN + local->scan_ies_len +
+ req->ie_len, GFP_KERNEL);
+ if (!local->hw_scan_req)
return -ENOMEM;
- ielen = ieee80211_build_preq_ies(local, ies,
- req->ie, req->ie_len);
- local->orig_ies = req->ie;
- local->orig_ies_len = req->ie_len;
- req->ie = ies;
- req->ie_len = ielen;
+ local->hw_scan_req->ssids = req->ssids;
+ local->hw_scan_req->n_ssids = req->n_ssids;
+ ies = (u8 *)local->hw_scan_req +
+ sizeof(*local->hw_scan_req) +
+ req->n_channels * sizeof(req->channels[0]);
+ local->hw_scan_req->ie = ies;
+
+ local->hw_scan_band = 0;
}
local->scan_req = req;
@@ -438,16 +477,17 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(local);
mutex_unlock(&local->scan_mtx);
- if (local->ops->hw_scan)
- rc = drv_hw_scan(local, local->scan_req);
- else
+ if (local->ops->hw_scan) {
+ WARN_ON(!ieee80211_prep_hw_scan(local));
+ rc = drv_hw_scan(local, local->hw_scan_req);
+ } else
rc = ieee80211_start_sw_scan(local);
mutex_lock(&local->scan_mtx);
if (rc) {
- if (local->ops->hw_scan)
- ieee80211_restore_scan_ies(local);
+ kfree(local->hw_scan_req);
+ local->hw_scan_req = NULL;
local->scanning = 0;
ieee80211_recalc_idle(local);
@@ -574,23 +614,14 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
{
int skip;
struct ieee80211_channel *chan;
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
skip = 0;
chan = local->scan_req->channels[local->scan_channel_idx];
- if (chan->flags & IEEE80211_CHAN_DISABLED ||
- (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- chan->flags & IEEE80211_CHAN_NO_IBSS))
+ local->scan_channel = chan;
+ if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
skip = 1;
- if (!skip) {
- local->scan_channel = chan;
- if (ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_CHANNEL))
- skip = 1;
- }
-
/* advance state machine to next channel/band */
local->scan_channel_idx++;
@@ -656,6 +687,14 @@ void ieee80211_scan_work(struct work_struct *work)
return;
}
+ if (local->hw_scan_req) {
+ int rc = drv_hw_scan(local, local->hw_scan_req);
+ mutex_unlock(&local->scan_mtx);
+ if (rc)
+ ieee80211_scan_completed(&local->hw, true);
+ return;
+ }
+
if (local->scan_req && !local->scanning) {
struct cfg80211_scan_request *req = local->scan_req;
int rc;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 594f2318c3d8..be59456e8a42 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -171,6 +171,8 @@ void sta_info_destroy(struct sta_info *sta)
local = sta->local;
+ cancel_work_sync(&sta->drv_unblock_wk);
+
rate_control_remove_sta_debugfs(sta);
ieee80211_sta_debugfs_remove(sta);
@@ -259,6 +261,21 @@ static void sta_info_hash_add(struct ieee80211_local *local,
rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta);
}
+static void sta_unblock(struct work_struct *wk)
+{
+ struct sta_info *sta;
+
+ sta = container_of(wk, struct sta_info, drv_unblock_wk);
+
+ if (sta->dead)
+ return;
+
+ if (!test_sta_flags(sta, WLAN_STA_PS_STA))
+ ieee80211_sta_ps_deliver_wakeup(sta);
+ else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL))
+ ieee80211_sta_ps_deliver_poll_response(sta);
+}
+
struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
u8 *addr, gfp_t gfp)
{
@@ -272,6 +289,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
spin_lock_init(&sta->lock);
spin_lock_init(&sta->flaglock);
+ INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
memcpy(sta->sta.addr, addr, ETH_ALEN);
sta->local = local;
@@ -478,8 +496,10 @@ static void __sta_info_unlink(struct sta_info **sta)
}
list_del(&(*sta)->list);
+ (*sta)->dead = true;
- if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) {
+ if (test_and_clear_sta_flags(*sta,
+ WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) {
BUG_ON(!sdata->bss);
atomic_dec(&sdata->bss->num_sta_ps);
@@ -801,8 +821,8 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
sta_info_destroy(sta);
}
-struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
- const u8 *addr)
+struct ieee80211_sta *ieee80211_find_sta_by_hw(struct ieee80211_hw *hw,
+ const u8 *addr)
{
struct sta_info *sta = sta_info_get(hw_to_local(hw), addr);
@@ -810,4 +830,114 @@ struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_hw *hw,
return NULL;
return &sta->sta;
}
+EXPORT_SYMBOL_GPL(ieee80211_find_sta_by_hw);
+
+struct ieee80211_sta *ieee80211_find_sta(struct ieee80211_vif *vif,
+ const u8 *addr)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ if (!vif)
+ return NULL;
+
+ sdata = vif_to_sdata(vif);
+
+ return ieee80211_find_sta_by_hw(&sdata->local->hw, addr);
+}
EXPORT_SYMBOL(ieee80211_find_sta);
+
+/* powersave support code */
+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
+{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ieee80211_local *local = sdata->local;
+ int sent, buffered;
+
+ drv_sta_notify(local, &sdata->vif, STA_NOTIFY_AWAKE, &sta->sta);
+
+ if (!skb_queue_empty(&sta->ps_tx_buf))
+ sta_info_clear_tim_bit(sta);
+
+ /* Send all buffered frames to the station */
+ sent = ieee80211_add_pending_skbs(local, &sta->tx_filtered);
+ buffered = ieee80211_add_pending_skbs(local, &sta->ps_tx_buf);
+ sent += buffered;
+ local->total_ps_buffered -= buffered;
+
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "%s: STA %pM aid %d sending %d filtered/%d PS frames "
+ "since STA not sleeping anymore\n", sdata->dev->name,
+ sta->sta.addr, sta->sta.aid, sent - buffered, buffered);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+}
+
+void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta)
+{
+ struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ieee80211_local *local = sdata->local;
+ struct sk_buff *skb;
+ int no_pending_pkts;
+
+ skb = skb_dequeue(&sta->tx_filtered);
+ if (!skb) {
+ skb = skb_dequeue(&sta->ps_tx_buf);
+ if (skb)
+ local->total_ps_buffered--;
+ }
+ no_pending_pkts = skb_queue_empty(&sta->tx_filtered) &&
+ skb_queue_empty(&sta->ps_tx_buf);
+
+ if (skb) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr =
+ (struct ieee80211_hdr *) skb->data;
+
+ /*
+ * Tell TX path to send this frame even though the STA may
+ * still remain is PS mode after this frame exchange.
+ */
+ info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE;
+
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ printk(KERN_DEBUG "STA %pM aid %d: PS Poll (entries after %d)\n",
+ sta->sta.addr, sta->sta.aid,
+ skb_queue_len(&sta->ps_tx_buf));
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+
+ /* Use MoreData flag to indicate whether there are more
+ * buffered frames for this STA */
+ if (no_pending_pkts)
+ hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
+ else
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+
+ ieee80211_add_pending_skb(local, skb);
+
+ if (no_pending_pkts)
+ sta_info_clear_tim_bit(sta);
+#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
+ } else {
+ /*
+ * FIXME: This can be the result of a race condition between
+ * us expiring a frame and the station polling for it.
+ * Should we send it a null-func frame indicating we
+ * have nothing buffered for it?
+ */
+ printk(KERN_DEBUG "%s: STA %pM sent PS Poll even "
+ "though there are no buffered frames for it\n",
+ sdata->dev->name, sta->sta.addr);
+#endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
+ }
+}
+
+void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
+ struct ieee80211_sta *pubsta, bool block)
+{
+ struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+
+ if (block)
+ set_sta_flags(sta, WLAN_STA_PS_DRIVER);
+ else
+ ieee80211_queue_work(hw, &sta->drv_unblock_wk);
+}
+EXPORT_SYMBOL(ieee80211_sta_block_awake);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index ccc3adf962c7..4673454176ed 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -12,6 +12,7 @@
#include <linux/list.h>
#include <linux/types.h>
#include <linux/if_ether.h>
+#include <linux/workqueue.h>
#include "key.h"
/**
@@ -21,7 +22,7 @@
*
* @WLAN_STA_AUTH: Station is authenticated.
* @WLAN_STA_ASSOC: Station is associated.
- * @WLAN_STA_PS: Station is in power-save mode
+ * @WLAN_STA_PS_STA: Station is in power-save mode
* @WLAN_STA_AUTHORIZED: Station is authorized to send/receive traffic.
* This bit is always checked so needs to be enabled for all stations
* when virtual port control is not in use.
@@ -36,11 +37,16 @@
* @WLAN_STA_MFP: Management frame protection is used with this STA.
* @WLAN_STA_SUSPEND: Set/cleared during a suspend/resume cycle.
* Used to deny ADDBA requests (both TX and RX).
+ * @WLAN_STA_PS_DRIVER: driver requires keeping this station in
+ * power-save mode logically to flush frames that might still
+ * be in the queues
+ * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping
+ * station in power-save mode, reply when the driver unblocks.
*/
enum ieee80211_sta_info_flags {
WLAN_STA_AUTH = 1<<0,
WLAN_STA_ASSOC = 1<<1,
- WLAN_STA_PS = 1<<2,
+ WLAN_STA_PS_STA = 1<<2,
WLAN_STA_AUTHORIZED = 1<<3,
WLAN_STA_SHORT_PREAMBLE = 1<<4,
WLAN_STA_ASSOC_AP = 1<<5,
@@ -48,7 +54,9 @@ enum ieee80211_sta_info_flags {
WLAN_STA_WDS = 1<<7,
WLAN_STA_CLEAR_PS_FILT = 1<<9,
WLAN_STA_MFP = 1<<10,
- WLAN_STA_SUSPEND = 1<<11
+ WLAN_STA_SUSPEND = 1<<11,
+ WLAN_STA_PS_DRIVER = 1<<12,
+ WLAN_STA_PSPOLL = 1<<13,
};
#define STA_TID_NUM 16
@@ -193,7 +201,6 @@ struct sta_ampdu_mlme {
* @rx_fragments: number of received MPDUs
* @rx_dropped: number of dropped MPDUs from this STA
* @last_signal: signal of last received frame from this STA
- * @last_qual: qual of last received frame from this STA
* @last_noise: noise of last received frame from this STA
* @last_seq_ctrl: last received seq/frag number from this STA (per RX queue)
* @tx_filtered_count: number of frames the hardware filtered for this STA
@@ -217,6 +224,8 @@ struct sta_ampdu_mlme {
* @plink_timer_was_running: used by suspend/resume to restore timers
* @debugfs: debug filesystem info
* @sta: station information we share with the driver
+ * @dead: set to true when sta is unlinked
+ * @drv_unblock_wk used for driver PS unblocking
*/
struct sta_info {
/* General information, mostly static */
@@ -230,8 +239,12 @@ struct sta_info {
spinlock_t lock;
spinlock_t flaglock;
+ struct work_struct drv_unblock_wk;
+
u16 listen_interval;
+ bool dead;
+
/*
* for use by the internal lifetime management,
* see __sta_info_unlink
@@ -259,7 +272,6 @@ struct sta_info {
unsigned long rx_fragments;
unsigned long rx_dropped;
int last_signal;
- int last_qual;
int last_noise;
__le16 last_seq_ctrl[NUM_RX_DATA_QUEUES];
@@ -301,28 +313,6 @@ struct sta_info {
#ifdef CONFIG_MAC80211_DEBUGFS
struct sta_info_debugfsdentries {
struct dentry *dir;
- struct dentry *flags;
- struct dentry *num_ps_buf_frames;
- struct dentry *inactive_ms;
- struct dentry *last_seq_ctrl;
- struct dentry *agg_status;
- struct dentry *aid;
- struct dentry *dev;
- struct dentry *rx_packets;
- struct dentry *tx_packets;
- struct dentry *rx_bytes;
- struct dentry *tx_bytes;
- struct dentry *rx_duplicates;
- struct dentry *rx_fragments;
- struct dentry *rx_dropped;
- struct dentry *tx_fragments;
- struct dentry *tx_filtered;
- struct dentry *tx_retry_failed;
- struct dentry *tx_retry_count;
- struct dentry *last_signal;
- struct dentry *last_qual;
- struct dentry *last_noise;
- struct dentry *wep_weak_iv_count;
bool add_has_run;
} debugfs;
#endif
@@ -454,4 +444,7 @@ int sta_info_flush(struct ieee80211_local *local,
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
unsigned long exp_time);
+void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta);
+void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
+
#endif /* STA_INFO_H */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index eaa4118de988..bfaa43e096d2 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -317,12 +317,11 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
if (!atomic_read(&tx->sdata->bss->num_sta_ps))
return TX_CONTINUE;
- /* buffered in hardware */
- if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) {
- info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
+ info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
+ /* device releases frame after DTIM beacon */
+ if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING))
return TX_CONTINUE;
- }
/* buffered in mac80211 */
if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
@@ -375,7 +374,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
staflags = get_sta_flags(sta);
- if (unlikely((staflags & WLAN_STA_PS) &&
+ if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) &&
!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) {
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "STA %pM aid %d: PS buffer (entries "
@@ -398,8 +397,13 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
} else
tx->local->total_ps_buffered++;
- /* Queue frame to be sent after STA sends an PS Poll frame */
- if (skb_queue_empty(&sta->ps_tx_buf))
+ /*
+ * Queue frame to be sent after STA wakes up/polls,
+ * but don't set the TIM bit if the driver is blocking
+ * wakeup or poll response transmissions anyway.
+ */
+ if (skb_queue_empty(&sta->ps_tx_buf) &&
+ !(staflags & WLAN_STA_PS_DRIVER))
sta_info_set_tim_bit(sta);
info->control.jiffies = jiffies;
@@ -409,7 +413,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx)
return TX_QUEUED;
}
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
- else if (unlikely(test_sta_flags(sta, WLAN_STA_PS))) {
+ else if (unlikely(staflags & WLAN_STA_PS_STA)) {
printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll "
"set -> send frame\n", tx->dev->name,
sta->sta.addr);
@@ -1201,23 +1205,25 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
struct sk_buff *skb = tx->skb;
ieee80211_tx_result res = TX_DROP;
-#define CALL_TXH(txh) \
- res = txh(tx); \
- if (res != TX_CONTINUE) \
- goto txh_done;
-
- CALL_TXH(ieee80211_tx_h_check_assoc)
- CALL_TXH(ieee80211_tx_h_ps_buf)
- CALL_TXH(ieee80211_tx_h_select_key)
- CALL_TXH(ieee80211_tx_h_michael_mic_add)
- CALL_TXH(ieee80211_tx_h_rate_ctrl)
- CALL_TXH(ieee80211_tx_h_misc)
- CALL_TXH(ieee80211_tx_h_sequence)
- CALL_TXH(ieee80211_tx_h_fragment)
+#define CALL_TXH(txh) \
+ do { \
+ res = txh(tx); \
+ if (res != TX_CONTINUE) \
+ goto txh_done; \
+ } while (0)
+
+ CALL_TXH(ieee80211_tx_h_check_assoc);
+ CALL_TXH(ieee80211_tx_h_ps_buf);
+ CALL_TXH(ieee80211_tx_h_select_key);
+ CALL_TXH(ieee80211_tx_h_michael_mic_add);
+ CALL_TXH(ieee80211_tx_h_rate_ctrl);
+ CALL_TXH(ieee80211_tx_h_misc);
+ CALL_TXH(ieee80211_tx_h_sequence);
+ CALL_TXH(ieee80211_tx_h_fragment);
/* handlers after fragment must be aware of tx info fragmentation! */
- CALL_TXH(ieee80211_tx_h_stats)
- CALL_TXH(ieee80211_tx_h_encrypt)
- CALL_TXH(ieee80211_tx_h_calculate_duration)
+ CALL_TXH(ieee80211_tx_h_stats);
+ CALL_TXH(ieee80211_tx_h_encrypt);
+ CALL_TXH(ieee80211_tx_h_calculate_duration);
#undef CALL_TXH
txh_done:
@@ -1387,6 +1393,30 @@ static int ieee80211_skb_resize(struct ieee80211_local *local,
return 0;
}
+static bool need_dynamic_ps(struct ieee80211_local *local)
+{
+ /* driver doesn't support power save */
+ if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
+ return false;
+
+ /* hardware does dynamic power save */
+ if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
+ return false;
+
+ /* dynamic power save disabled */
+ if (local->hw.conf.dynamic_ps_timeout <= 0)
+ return false;
+
+ /* we are scanning, don't enable power save */
+ if (local->scanning)
+ return false;
+
+ if (!local->ps_sdata)
+ return false;
+
+ return true;
+}
+
static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
@@ -1399,9 +1429,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
dev_hold(sdata->dev);
- if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
- local->hw.conf.dynamic_ps_timeout > 0 &&
- !(local->scanning) && local->ps_sdata) {
+ if (need_dynamic_ps(local)) {
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_QUEUE_STOP_REASON_PS);
@@ -1990,8 +2018,9 @@ static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss,
}
}
-struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 *tim_offset, u16 *tim_length)
{
struct ieee80211_local *local = hw_to_local(hw);
struct sk_buff *skb = NULL;
@@ -2008,6 +2037,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
sdata = vif_to_sdata(vif);
+ if (tim_offset)
+ *tim_offset = 0;
+ if (tim_length)
+ *tim_length = 0;
+
if (sdata->vif.type == NL80211_IFTYPE_AP) {
ap = &sdata->u.ap;
beacon = rcu_dereference(ap->beacon);
@@ -2043,6 +2077,11 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&local->sta_lock, flags);
}
+ if (tim_offset)
+ *tim_offset = beacon->head_len;
+ if (tim_length)
+ *tim_length = skb->len - beacon->head_len;
+
if (beacon->tail)
memcpy(skb_put(skb, beacon->tail_len),
beacon->tail, beacon->tail_len);
@@ -2119,7 +2158,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
rcu_read_unlock();
return skb;
}
-EXPORT_SYMBOL(ieee80211_beacon_get);
+EXPORT_SYMBOL(ieee80211_beacon_get_tim);
void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
const void *frame, size_t frame_len,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index aeb65b3d2295..aedbaaa067e6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -872,13 +872,14 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
}
int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
- const u8 *ie, size_t ie_len)
+ const u8 *ie, size_t ie_len,
+ enum ieee80211_band band)
{
struct ieee80211_supported_band *sband;
u8 *pos, *supp_rates_len, *esupp_rates_len = NULL;
int i;
- sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+ sband = local->hw.wiphy->bands[band];
pos = buffer;
@@ -966,7 +967,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
memcpy(pos, ssid, ssid_len);
pos += ssid_len;
- skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len));
+ skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len,
+ local->hw.conf.channel->band));
ieee80211_tx_skb(sdata, skb, 0);
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 07252967be9c..02835172b227 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -546,7 +546,7 @@ void wiphy_unregister(struct wiphy *wiphy)
* First remove the hardware from everywhere, this makes
* it impossible to find from userspace.
*/
- cfg80211_debugfs_rdev_del(rdev);
+ debugfs_remove_recursive(rdev->wiphy.debugfsdir);
list_del(&rdev->list);
/*
@@ -569,7 +569,6 @@ void wiphy_unregister(struct wiphy *wiphy)
cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev);
- debugfs_remove(rdev->wiphy.debugfsdir);
mutex_unlock(&cfg80211_mutex);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 68b321997d4c..5aeebb9085f8 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -72,17 +72,6 @@ struct cfg80211_registered_device {
/* current channel */
struct ieee80211_channel *channel;
-#ifdef CONFIG_CFG80211_DEBUGFS
- /* Debugfs entries */
- struct wiphy_debugfsdentries {
- struct dentry *rts_threshold;
- struct dentry *fragmentation_threshold;
- struct dentry *short_retry_limit;
- struct dentry *long_retry_limit;
- struct dentry *ht40allow_map;
- } debugfs;
-#endif
-
/* must be last because of the way we do wiphy_priv(),
* and it should at least be aligned to NETDEV_ALIGN */
struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 13d93d84f902..2e4895615037 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -104,11 +104,7 @@ static const struct file_operations ht40allow_map_ops = {
};
#define DEBUGFS_ADD(name) \
- rdev->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \
- &rdev->wiphy, &name## _ops);
-#define DEBUGFS_DEL(name) \
- debugfs_remove(rdev->debugfs.name); \
- rdev->debugfs.name = NULL;
+ debugfs_create_file(#name, S_IRUGO, phyd, &rdev->wiphy, &name## _ops);
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
{
@@ -120,12 +116,3 @@ void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev)
DEBUGFS_ADD(long_retry_limit);
DEBUGFS_ADD(ht40allow_map);
}
-
-void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev)
-{
- DEBUGFS_DEL(rts_threshold);
- DEBUGFS_DEL(fragmentation_threshold);
- DEBUGFS_DEL(short_retry_limit);
- DEBUGFS_DEL(long_retry_limit);
- DEBUGFS_DEL(ht40allow_map);
-}
diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h
index 6419b6d6ce3e..74fdd3811427 100644
--- a/net/wireless/debugfs.h
+++ b/net/wireless/debugfs.h
@@ -3,12 +3,9 @@
#ifdef CONFIG_CFG80211_DEBUGFS
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev);
-void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev);
#else
static inline
void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) {}
-static inline
-void cfg80211_debugfs_rdev_del(struct cfg80211_registered_device *rdev) {}
#endif
#endif /* __CFG80211_DEBUGFS_H */
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 83c2a288dc63..2610b746effa 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -62,7 +62,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
u8 *ie = mgmt->u.assoc_resp.variable;
int i, ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
struct cfg80211_internal_bss *bss = NULL;
- bool need_connect_result = true;
wdev_lock(wdev);
@@ -97,7 +96,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
WARN_ON(!bss);
} else if (wdev->conn) {
cfg80211_sme_failed_assoc(wdev);
- need_connect_result = false;
/*
* do not call connect_result() now because the
* sme will schedule work that does it later.
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f48394126bf9..8ed62b6c172b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2988,7 +2988,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- request->n_channels = n_channels;
if (n_ssids)
request->ssids = (void *)&request->channels[n_channels];
request->n_ssids = n_ssids;
@@ -2999,32 +2998,53 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
request->ie = (void *)(request->channels + n_channels);
}
+ i = 0;
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
/* user specified, bail out if channel not found */
- request->n_channels = n_channels;
- i = 0;
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
- request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr));
- if (!request->channels[i]) {
+ struct ieee80211_channel *chan;
+
+ chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
+
+ if (!chan) {
err = -EINVAL;
goto out_free;
}
+
+ /* ignore disabled channels */
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ request->channels[i] = chan;
i++;
}
} else {
/* all channels */
- i = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j;
if (!wiphy->bands[band])
continue;
for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
- request->channels[i] = &wiphy->bands[band]->channels[j];
+ struct ieee80211_channel *chan;
+
+ chan = &wiphy->bands[band]->channels[j];
+
+ if (chan->flags & IEEE80211_CHAN_DISABLED)
+ continue;
+
+ request->channels[i] = chan;
i++;
}
}
}
+ if (!i) {
+ err = -EINVAL;
+ goto out_free;
+ }
+
+ request->n_channels = i;
+
i = 0;
if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2e8c515f3c5c..e2d344ff6745 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -650,9 +650,15 @@ int cfg80211_wext_siwscan(struct net_device *dev,
i = 0;
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
int j;
+
if (!wiphy->bands[band])
continue;
+
for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
+ /* ignore disabled channels */
+ if (wiphy->bands[band]->channels[j].flags &
+ IEEE80211_CHAN_DISABLED)
+ continue;
/* If we have a wireless request structure and the
* wireless request specifies frequencies, then search
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 561a45cf2a6a..41abcbdc5fb9 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -904,8 +904,6 @@ static int cfg80211_set_auth_alg(struct wireless_dev *wdev,
static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
{
- wdev->wext.connect.crypto.wpa_versions = 0;
-
if (wpa_versions & ~(IW_AUTH_WPA_VERSION_WPA |
IW_AUTH_WPA_VERSION_WPA2|
IW_AUTH_WPA_VERSION_DISABLED))
@@ -933,8 +931,6 @@ static int cfg80211_set_wpa_version(struct wireless_dev *wdev, u32 wpa_versions)
static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
{
- wdev->wext.connect.crypto.cipher_group = 0;
-
if (cipher & IW_AUTH_CIPHER_WEP40)
wdev->wext.connect.crypto.cipher_group =
WLAN_CIPHER_SUITE_WEP40;
@@ -950,6 +946,8 @@ static int cfg80211_set_cipher_group(struct wireless_dev *wdev, u32 cipher)
else if (cipher & IW_AUTH_CIPHER_AES_CMAC)
wdev->wext.connect.crypto.cipher_group =
WLAN_CIPHER_SUITE_AES_CMAC;
+ else if (cipher & IW_AUTH_CIPHER_NONE)
+ wdev->wext.connect.crypto.cipher_group = 0;
else
return -EINVAL;