aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/Kconfig73
-rw-r--r--drivers/net/wireless/Makefile8
-rw-r--r--drivers/net/wireless/adm8211.c11
-rw-r--r--drivers/net/wireless/airo.c1243
-rw-r--r--drivers/net/wireless/ath5k/Makefile2
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h1173
-rw-r--r--drivers/net/wireless/ath5k/base.c2974
-rw-r--r--drivers/net/wireless/ath5k/base.h179
-rw-r--r--drivers/net/wireless/ath5k/debug.c469
-rw-r--r--drivers/net/wireless/ath5k/debug.h216
-rw-r--r--drivers/net/wireless/ath5k/hw.c4351
-rw-r--r--drivers/net/wireless/ath5k/hw.h588
-rw-r--r--drivers/net/wireless/ath5k/initvals.c1347
-rw-r--r--drivers/net/wireless/ath5k/phy.c2071
-rw-r--r--drivers/net/wireless/ath5k/reg.h1987
-rw-r--r--drivers/net/wireless/ath5k/regdom.c121
-rw-r--r--drivers/net/wireless/ath5k/regdom.h500
-rw-r--r--drivers/net/wireless/atmel.c33
-rw-r--r--drivers/net/wireless/b43/Kconfig58
-rw-r--r--drivers/net/wireless/b43/Makefile12
-rw-r--r--drivers/net/wireless/b43/b43.h151
-rw-r--r--drivers/net/wireless/b43/debugfs.c9
-rw-r--r--drivers/net/wireless/b43/dma.c155
-rw-r--r--drivers/net/wireless/b43/dma.h50
-rw-r--r--drivers/net/wireless/b43/leds.c10
-rw-r--r--drivers/net/wireless/b43/lo.c72
-rw-r--r--drivers/net/wireless/b43/main.c1167
-rw-r--r--drivers/net/wireless/b43/main.h5
-rw-r--r--drivers/net/wireless/b43/nphy.c489
-rw-r--r--drivers/net/wireless/b43/nphy.h932
-rw-r--r--drivers/net/wireless/b43/phy.c1010
-rw-r--r--drivers/net/wireless/b43/phy.h103
-rw-r--r--drivers/net/wireless/b43/pio.c652
-rw-r--r--drivers/net/wireless/b43/pio.h153
-rw-r--r--drivers/net/wireless/b43/tables.c112
-rw-r--r--drivers/net/wireless/b43/tables.h12
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c2476
-rw-r--r--drivers/net/wireless/b43/tables_nphy.h159
-rw-r--r--drivers/net/wireless/b43/wa.c674
-rw-r--r--drivers/net/wireless/b43/wa.h7
-rw-r--r--drivers/net/wireless/b43/xmit.c201
-rw-r--r--drivers/net/wireless/b43/xmit.h200
-rw-r--r--drivers/net/wireless/b43legacy/Kconfig16
-rw-r--r--drivers/net/wireless/b43legacy/Makefile29
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h39
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/ilt.c2
-rw-r--r--drivers/net/wireless/b43legacy/leds.c417
-rw-r--r--drivers/net/wireless/b43legacy/leds.h61
-rw-r--r--drivers/net/wireless/b43legacy/main.c394
-rw-r--r--drivers/net/wireless/b43legacy/main.h2
-rw-r--r--drivers/net/wireless/b43legacy/phy.c75
-rw-r--r--drivers/net/wireless/b43legacy/phy.h16
-rw-r--r--drivers/net/wireless/b43legacy/radio.c36
-rw-r--r--drivers/net/wireless/b43legacy/radio.h4
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c205
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.h59
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c32
-rw-r--r--drivers/net/wireless/bcm43xx/Kconfig9
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx.h6
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_main.c40
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_pio.c6
-rw-r--r--drivers/net/wireless/bcm43xx/bcm43xx_xmit.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h34
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c72
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h34
-rw-r--r--drivers/net/wireless/hostap/hostap_cs.c15
-rw-r--r--drivers/net/wireless/hostap/hostap_download.c22
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c30
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c9
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c69
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c6
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c16
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h202
-rw-r--r--drivers/net/wireless/ipw2100.c13
-rw-r--r--drivers/net/wireless/ipw2200.c177
-rw-r--r--drivers/net/wireless/ipw2200.h190
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig180
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-commands.h (renamed from drivers/net/wireless/iwlwifi/iwl-commands.h)1014
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-debug.h (renamed from drivers/net/wireless/iwlwifi/iwl-debug.h)76
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h616
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-io.h431
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c348
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c727
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h950
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-commands.h2651
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-debug.h152
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h2062
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-io.h431
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.c1534
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-rs.h121
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c1551
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.h1199
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-channel.h161
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h336
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hw.h537
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h470
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-priv.h308
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c3328
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c3914
-rw-r--r--drivers/net/wireless/iwlwifi/iwlwifi.h708
-rw-r--r--drivers/net/wireless/libertas/11d.c154
-rw-r--r--drivers/net/wireless/libertas/11d.h26
-rw-r--r--drivers/net/wireless/libertas/README40
-rw-r--r--drivers/net/wireless/libertas/assoc.c458
-rw-r--r--drivers/net/wireless/libertas/assoc.h32
-rw-r--r--drivers/net/wireless/libertas/cmd.c1407
-rw-r--r--drivers/net/wireless/libertas/cmd.h61
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c662
-rw-r--r--drivers/net/wireless/libertas/debugfs.c1495
-rw-r--r--drivers/net/wireless/libertas/debugfs.h12
-rw-r--r--drivers/net/wireless/libertas/decl.h102
-rw-r--r--drivers/net/wireless/libertas/defs.h67
-rw-r--r--drivers/net/wireless/libertas/dev.h179
-rw-r--r--drivers/net/wireless/libertas/ethtool.c114
-rw-r--r--drivers/net/wireless/libertas/host.h392
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h147
-rw-r--r--drivers/net/wireless/libertas/if_cs.c88
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c88
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h4
-rw-r--r--drivers/net/wireless/libertas/if_usb.c729
-rw-r--r--drivers/net/wireless/libertas/if_usb.h109
-rw-r--r--drivers/net/wireless/libertas/join.c313
-rw-r--r--drivers/net/wireless/libertas/join.h38
-rw-r--r--drivers/net/wireless/libertas/main.c1438
-rw-r--r--drivers/net/wireless/libertas/rx.c226
-rw-r--r--drivers/net/wireless/libertas/scan.c1192
-rw-r--r--drivers/net/wireless/libertas/scan.h94
-rw-r--r--drivers/net/wireless/libertas/tx.c253
-rw-r--r--drivers/net/wireless/libertas/types.h25
-rw-r--r--drivers/net/wireless/libertas/wext.c867
-rw-r--r--drivers/net/wireless/libertas/wext.h14
-rw-r--r--drivers/net/wireless/orinoco.c544
-rw-r--r--drivers/net/wireless/orinoco.h12
-rw-r--r--drivers/net/wireless/p54common.c14
-rw-r--r--drivers/net/wireless/p54pci.c93
-rw-r--r--drivers/net/wireless/p54pci.h4
-rw-r--r--drivers/net/wireless/prism54/isl_38xx.h10
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c16
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_dev.h3
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.c2
-rw-r--r--drivers/net/wireless/prism54/islpci_eth.h38
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.c4
-rw-r--r--drivers/net/wireless/prism54/islpci_mgt.h2
-rw-r--r--drivers/net/wireless/ray_cs.c69
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c271
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.h24
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c225
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c239
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.h17
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h241
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c100
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c231
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.h4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c435
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dump.h121
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00firmware.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h12
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c87
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c104
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h12
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00rfkill.c39
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00ring.h50
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c156
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h24
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c495
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h14
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c270
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.h14
-rw-r--r--drivers/net/wireless/rtl8180.h151
-rw-r--r--drivers/net/wireless/rtl8180_dev.c1051
-rw-r--r--drivers/net/wireless/rtl8180_grf5101.c179
-rw-r--r--drivers/net/wireless/rtl8180_grf5101.h28
-rw-r--r--drivers/net/wireless/rtl8180_max2820.c150
-rw-r--r--drivers/net/wireless/rtl8180_max2820.h28
-rw-r--r--drivers/net/wireless/rtl8180_rtl8225.c779
-rw-r--r--drivers/net/wireless/rtl8180_rtl8225.h23
-rw-r--r--drivers/net/wireless/rtl8180_sa2400.c201
-rw-r--r--drivers/net/wireless/rtl8180_sa2400.h36
-rw-r--r--drivers/net/wireless/rtl8187.h4
-rw-r--r--drivers/net/wireless/rtl8187_dev.c69
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.c52
-rw-r--r--drivers/net/wireless/rtl8187_rtl8225.h9
-rw-r--r--drivers/net/wireless/rtl818x.h29
-rw-r--r--drivers/net/wireless/wavelan.c36
-rw-r--r--drivers/net/wireless/wavelan.p.h1
-rw-r--r--drivers/net/wireless/wavelan_cs.c43
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h3
-rw-r--r--drivers/net/wireless/zd1211rw/Kconfig7
-rw-r--r--drivers/net/wireless/zd1211rw/Makefile3
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c126
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h60
-rw-r--r--drivers/net/wireless/zd1211rw/zd_def.h5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.c196
-rw-r--r--drivers/net/wireless/zd1211rw/zd_ieee80211.h49
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c1559
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h117
-rw-r--r--drivers/net/wireless/zd1211rw/zd_netdev.c264
-rw-r--r--drivers/net/wireless/zd1211rw/zd_netdev.h45
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf.h5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al2230.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_al7230b.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_rf2959.c5
-rw-r--r--drivers/net/wireless/zd1211rw/zd_rf_uw2453.c7
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c289
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.h36
213 files changed, 50550 insertions, 22463 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 2c08c0a5a0df..f372960904b2 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -545,6 +545,62 @@ config USB_ZD1201
To compile this driver as a module, choose M here: the
module will be called zd1201.
+config RTL8180
+ tristate "Realtek 8180/8185 PCI support"
+ depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
+ select EEPROM_93CX6
+ ---help---
+ This is a driver for RTL8180 and RTL8185 based cards.
+ These are PCI based chips found in cards such as:
+
+ (RTL8185 802.11g)
+ A-Link WL54PC
+
+ (RTL8180 802.11b)
+ Belkin F5D6020 v3
+ Belkin F5D6020 v3
+ Dlink DWL-610
+ Dlink DWL-510
+ Netgear MA521
+ Level-One WPC-0101
+ Acer Aspire 1357 LMi
+ VCTnet PC-11B1
+ Ovislink AirLive WL-1120PCM
+ Mentor WL-PCI
+ Linksys WPC11 v4
+ TrendNET TEW-288PI
+ D-Link DWL-520 Rev D
+ Repotec RP-WP7126
+ TP-Link TL-WN250/251
+ Zonet ZEW1000
+ Longshine LCS-8031-R
+ HomeLine HLW-PCC200
+ GigaFast WF721-AEX
+ Planet WL-3553
+ Encore ENLWI-PCI1-NT
+ TrendNET TEW-266PC
+ Gigabyte GN-WLMR101
+ Siemens-fujitsu Amilo D1840W
+ Edimax EW-7126
+ PheeNet WL-11PCIR
+ Tonze PC-2100T
+ Planet WL-8303
+ Dlink DWL-650 v M1
+ Edimax EW-7106
+ Q-Tec 770WC
+ Topcom Skyr@cer 4011b
+ Roper FreeLan 802.11b (edition 2004)
+ Wistron Neweb Corp CB-200B
+ Pentagram HorNET
+ QTec 775WC
+ TwinMOS Booming B Series
+ Micronet SP906BB
+ Sweex LC700010
+ Surecom EP-9428
+ Safecom SWLCR-1100
+
+ Thanks to Realtek for their support!
+
config RTL8187
tristate "Realtek 8187 USB support"
depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
@@ -648,6 +704,23 @@ config P54_PCI
If you choose to build a module, it'll be called p54pci.
+config ATH5K
+ tristate "Atheros 5xxx wireless cards support"
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ ---help---
+ This module adds support for wireless adapters based on
+ Atheros 5xxx chipset.
+
+ Currently the following chip versions are supported:
+
+ MAC: AR5211 AR5212
+ PHY: RF5111/2111 RF5112/2112 RF5413/2413
+
+ This driver uses the kernel's mac80211 subsystem.
+
+ If you choose to build a module, it'll be called ath5k. Say M if
+ unsure.
+
source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/bcm43xx/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 6f32b53ee128..6af7b158624e 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -47,14 +47,20 @@ obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o
obj-$(CONFIG_USB_ZD1201) += zd1201.o
obj-$(CONFIG_LIBERTAS) += libertas/
+rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
+
+obj-$(CONFIG_RTL8180) += rtl8180.o
obj-$(CONFIG_RTL8187) += rtl8187.o
obj-$(CONFIG_ADM8211) += adm8211.o
-obj-$(CONFIG_IWLWIFI) += iwlwifi/
+obj-$(CONFIG_IWL3945) += iwlwifi/
+obj-$(CONFIG_IWL4965) += iwlwifi/
obj-$(CONFIG_RT2X00) += rt2x00/
obj-$(CONFIG_P54_COMMON) += p54common.o
obj-$(CONFIG_P54_USB) += p54usb.o
obj-$(CONFIG_P54_PCI) += p54pci.o
+
+obj-$(CONFIG_ATH5K) += ath5k/
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index 5bf7913aadda..79796186713e 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -104,7 +104,7 @@ static int adm8211_read_eeprom(struct ieee80211_hw *dev)
if (!priv->eeprom)
return -ENOMEM;
- eeprom_93cx6_multiread(&eeprom, 0, (__le16 __force *)priv->eeprom, words);
+ eeprom_93cx6_multiread(&eeprom, 0, (__le16 *)priv->eeprom, words);
cr49 = le16_to_cpu(priv->eeprom->cr49);
priv->rf_type = (cr49 >> 3) & 0x7;
@@ -1312,7 +1312,8 @@ static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
return 0;
}
-static int adm8211_config_interface(struct ieee80211_hw *dev, int if_id,
+static int adm8211_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct adm8211_priv *priv = dev->priv;
@@ -1867,9 +1868,9 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
goto err_iounmap;
}
- *(u32 *)perm_addr = le32_to_cpu((__force __le32)ADM8211_CSR_READ(PAR0));
- *(u16 *)&perm_addr[4] =
- le16_to_cpu((__force __le16)ADM8211_CSR_READ(PAR1) & 0xFFFF);
+ *(__le32 *)perm_addr = cpu_to_le32(ADM8211_CSR_READ(PAR0));
+ *(__le16 *)&perm_addr[4] =
+ cpu_to_le16(ADM8211_CSR_READ(PAR1) & 0xFFFF);
if (!is_valid_ether_addr(perm_addr)) {
printk(KERN_WARNING "%s (adm8211): Invalid hwaddr in EEPROM!\n",
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 074055e18c5c..932d6b1c9d0b 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -38,6 +38,7 @@
#include <linux/crypto.h>
#include <asm/io.h>
#include <asm/system.h>
+#include <asm/unaligned.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -500,140 +501,143 @@ typedef struct {
/* This structure came from an email sent to me from an engineer at
aironet for inclusion into this driver */
typedef struct {
- u16 len;
- u16 kindex;
+ __le16 len;
+ __le16 kindex;
u8 mac[ETH_ALEN];
- u16 klen;
+ __le16 klen;
u8 key[16];
} WepKeyRid;
/* These structures are from the Aironet's PC4500 Developers Manual */
typedef struct {
- u16 len;
+ __le16 len;
u8 ssid[32];
} Ssid;
typedef struct {
- u16 len;
+ __le16 len;
Ssid ssids[3];
} SsidRid;
typedef struct {
- u16 len;
- u16 modulation;
-#define MOD_DEFAULT 0
-#define MOD_CCK 1
-#define MOD_MOK 2
+ __le16 len;
+ __le16 modulation;
+#define MOD_DEFAULT cpu_to_le16(0)
+#define MOD_CCK cpu_to_le16(1)
+#define MOD_MOK cpu_to_le16(2)
} ModulationRid;
typedef struct {
- u16 len; /* sizeof(ConfigRid) */
- u16 opmode; /* operating mode */
-#define MODE_STA_IBSS 0
-#define MODE_STA_ESS 1
-#define MODE_AP 2
-#define MODE_AP_RPTR 3
-#define MODE_ETHERNET_HOST (0<<8) /* rx payloads converted */
-#define MODE_LLC_HOST (1<<8) /* rx payloads left as is */
-#define MODE_AIRONET_EXTEND (1<<9) /* enable Aironet extenstions */
-#define MODE_AP_INTERFACE (1<<10) /* enable ap interface extensions */
-#define MODE_ANTENNA_ALIGN (1<<11) /* enable antenna alignment */
-#define MODE_ETHER_LLC (1<<12) /* enable ethernet LLC */
-#define MODE_LEAF_NODE (1<<13) /* enable leaf node bridge */
-#define MODE_CF_POLLABLE (1<<14) /* enable CF pollable */
-#define MODE_MIC (1<<15) /* enable MIC */
- u16 rmode; /* receive mode */
-#define RXMODE_BC_MC_ADDR 0
-#define RXMODE_BC_ADDR 1 /* ignore multicasts */
-#define RXMODE_ADDR 2 /* ignore multicast and broadcast */
-#define RXMODE_RFMON 3 /* wireless monitor mode */
-#define RXMODE_RFMON_ANYBSS 4
-#define RXMODE_LANMON 5 /* lan style monitor -- data packets only */
-#define RXMODE_DISABLE_802_3_HEADER (1<<8) /* disables 802.3 header on rx */
-#define RXMODE_NORMALIZED_RSSI (1<<9) /* return normalized RSSI */
- u16 fragThresh;
- u16 rtsThres;
+ __le16 len; /* sizeof(ConfigRid) */
+ __le16 opmode; /* operating mode */
+#define MODE_STA_IBSS cpu_to_le16(0)
+#define MODE_STA_ESS cpu_to_le16(1)
+#define MODE_AP cpu_to_le16(2)
+#define MODE_AP_RPTR cpu_to_le16(3)
+#define MODE_CFG_MASK cpu_to_le16(0xff)
+#define MODE_ETHERNET_HOST cpu_to_le16(0<<8) /* rx payloads converted */
+#define MODE_LLC_HOST cpu_to_le16(1<<8) /* rx payloads left as is */
+#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extenstions */
+#define MODE_AP_INTERFACE cpu_to_le16(1<<10) /* enable ap interface extensions */
+#define MODE_ANTENNA_ALIGN cpu_to_le16(1<<11) /* enable antenna alignment */
+#define MODE_ETHER_LLC cpu_to_le16(1<<12) /* enable ethernet LLC */
+#define MODE_LEAF_NODE cpu_to_le16(1<<13) /* enable leaf node bridge */
+#define MODE_CF_POLLABLE cpu_to_le16(1<<14) /* enable CF pollable */
+#define MODE_MIC cpu_to_le16(1<<15) /* enable MIC */
+ __le16 rmode; /* receive mode */
+#define RXMODE_BC_MC_ADDR cpu_to_le16(0)
+#define RXMODE_BC_ADDR cpu_to_le16(1) /* ignore multicasts */
+#define RXMODE_ADDR cpu_to_le16(2) /* ignore multicast and broadcast */
+#define RXMODE_RFMON cpu_to_le16(3) /* wireless monitor mode */
+#define RXMODE_RFMON_ANYBSS cpu_to_le16(4)
+#define RXMODE_LANMON cpu_to_le16(5) /* lan style monitor -- data packets only */
+#define RXMODE_MASK cpu_to_le16(255)
+#define RXMODE_DISABLE_802_3_HEADER cpu_to_le16(1<<8) /* disables 802.3 header on rx */
+#define RXMODE_FULL_MASK (RXMODE_MASK | RXMODE_DISABLE_802_3_HEADER)
+#define RXMODE_NORMALIZED_RSSI cpu_to_le16(1<<9) /* return normalized RSSI */
+ __le16 fragThresh;
+ __le16 rtsThres;
u8 macAddr[ETH_ALEN];
u8 rates[8];
- u16 shortRetryLimit;
- u16 longRetryLimit;
- u16 txLifetime; /* in kusec */
- u16 rxLifetime; /* in kusec */
- u16 stationary;
- u16 ordering;
- u16 u16deviceType; /* for overriding device type */
- u16 cfpRate;
- u16 cfpDuration;
- u16 _reserved1[3];
+ __le16 shortRetryLimit;
+ __le16 longRetryLimit;
+ __le16 txLifetime; /* in kusec */
+ __le16 rxLifetime; /* in kusec */
+ __le16 stationary;
+ __le16 ordering;
+ __le16 u16deviceType; /* for overriding device type */
+ __le16 cfpRate;
+ __le16 cfpDuration;
+ __le16 _reserved1[3];
/*---------- Scanning/Associating ----------*/
- u16 scanMode;
-#define SCANMODE_ACTIVE 0
-#define SCANMODE_PASSIVE 1
-#define SCANMODE_AIROSCAN 2
- u16 probeDelay; /* in kusec */
- u16 probeEnergyTimeout; /* in kusec */
- u16 probeResponseTimeout;
- u16 beaconListenTimeout;
- u16 joinNetTimeout;
- u16 authTimeout;
- u16 authType;
-#define AUTH_OPEN 0x1
-#define AUTH_ENCRYPT 0x101
-#define AUTH_SHAREDKEY 0x102
-#define AUTH_ALLOW_UNENCRYPTED 0x200
- u16 associationTimeout;
- u16 specifiedApTimeout;
- u16 offlineScanInterval;
- u16 offlineScanDuration;
- u16 linkLossDelay;
- u16 maxBeaconLostTime;
- u16 refreshInterval;
-#define DISABLE_REFRESH 0xFFFF
- u16 _reserved1a[1];
+ __le16 scanMode;
+#define SCANMODE_ACTIVE cpu_to_le16(0)
+#define SCANMODE_PASSIVE cpu_to_le16(1)
+#define SCANMODE_AIROSCAN cpu_to_le16(2)
+ __le16 probeDelay; /* in kusec */
+ __le16 probeEnergyTimeout; /* in kusec */
+ __le16 probeResponseTimeout;
+ __le16 beaconListenTimeout;
+ __le16 joinNetTimeout;
+ __le16 authTimeout;
+ __le16 authType;
+#define AUTH_OPEN cpu_to_le16(0x1)
+#define AUTH_ENCRYPT cpu_to_le16(0x101)
+#define AUTH_SHAREDKEY cpu_to_le16(0x102)
+#define AUTH_ALLOW_UNENCRYPTED cpu_to_le16(0x200)
+ __le16 associationTimeout;
+ __le16 specifiedApTimeout;
+ __le16 offlineScanInterval;
+ __le16 offlineScanDuration;
+ __le16 linkLossDelay;
+ __le16 maxBeaconLostTime;
+ __le16 refreshInterval;
+#define DISABLE_REFRESH cpu_to_le16(0xFFFF)
+ __le16 _reserved1a[1];
/*---------- Power save operation ----------*/
- u16 powerSaveMode;
-#define POWERSAVE_CAM 0
-#define POWERSAVE_PSP 1
-#define POWERSAVE_PSPCAM 2
- u16 sleepForDtims;
- u16 listenInterval;
- u16 fastListenInterval;
- u16 listenDecay;
- u16 fastListenDelay;
- u16 _reserved2[2];
+ __le16 powerSaveMode;
+#define POWERSAVE_CAM cpu_to_le16(0)
+#define POWERSAVE_PSP cpu_to_le16(1)
+#define POWERSAVE_PSPCAM cpu_to_le16(2)
+ __le16 sleepForDtims;
+ __le16 listenInterval;
+ __le16 fastListenInterval;
+ __le16 listenDecay;
+ __le16 fastListenDelay;
+ __le16 _reserved2[2];
/*---------- Ap/Ibss config items ----------*/
- u16 beaconPeriod;
- u16 atimDuration;
- u16 hopPeriod;
- u16 channelSet;
- u16 channel;
- u16 dtimPeriod;
- u16 bridgeDistance;
- u16 radioID;
+ __le16 beaconPeriod;
+ __le16 atimDuration;
+ __le16 hopPeriod;
+ __le16 channelSet;
+ __le16 channel;
+ __le16 dtimPeriod;
+ __le16 bridgeDistance;
+ __le16 radioID;
/*---------- Radio configuration ----------*/
- u16 radioType;
-#define RADIOTYPE_DEFAULT 0
-#define RADIOTYPE_802_11 1
-#define RADIOTYPE_LEGACY 2
+ __le16 radioType;
+#define RADIOTYPE_DEFAULT cpu_to_le16(0)
+#define RADIOTYPE_802_11 cpu_to_le16(1)
+#define RADIOTYPE_LEGACY cpu_to_le16(2)
u8 rxDiversity;
u8 txDiversity;
- u16 txPower;
+ __le16 txPower;
#define TXPOWER_DEFAULT 0
- u16 rssiThreshold;
+ __le16 rssiThreshold;
#define RSSI_DEFAULT 0
- u16 modulation;
-#define PREAMBLE_AUTO 0
-#define PREAMBLE_LONG 1
-#define PREAMBLE_SHORT 2
- u16 preamble;
- u16 homeProduct;
- u16 radioSpecific;
+ __le16 modulation;
+#define PREAMBLE_AUTO cpu_to_le16(0)
+#define PREAMBLE_LONG cpu_to_le16(1)
+#define PREAMBLE_SHORT cpu_to_le16(2)
+ __le16 preamble;
+ __le16 homeProduct;
+ __le16 radioSpecific;
/*---------- Aironet Extensions ----------*/
u8 nodeName[16];
- u16 arlThreshold;
- u16 arlDecay;
- u16 arlDelay;
- u16 _reserved4[1];
+ __le16 arlThreshold;
+ __le16 arlDecay;
+ __le16 arlDelay;
+ __le16 _reserved4[1];
/*---------- Aironet Extensions ----------*/
u8 magicAction;
#define MAGIC_ACTION_STSCHG 1
@@ -643,34 +647,34 @@ typedef struct {
#define MAGIC_SWITCH_TO_PSP (0<<10)
#define MAGIC_STAY_IN_CAM (1<<10)
u8 magicControl;
- u16 autoWake;
+ __le16 autoWake;
} ConfigRid;
typedef struct {
- u16 len;
+ __le16 len;
u8 mac[ETH_ALEN];
- u16 mode;
- u16 errorCode;
- u16 sigQuality;
- u16 SSIDlen;
+ __le16 mode;
+ __le16 errorCode;
+ __le16 sigQuality;
+ __le16 SSIDlen;
char SSID[32];
char apName[16];
u8 bssid[4][ETH_ALEN];
- u16 beaconPeriod;
- u16 dimPeriod;
- u16 atimDuration;
- u16 hopPeriod;
- u16 channelSet;
- u16 channel;
- u16 hopsToBackbone;
- u16 apTotalLoad;
- u16 generatedLoad;
- u16 accumulatedArl;
- u16 signalQuality;
- u16 currentXmitRate;
- u16 apDevExtensions;
- u16 normalizedSignalStrength;
- u16 shortPreamble;
+ __le16 beaconPeriod;
+ __le16 dimPeriod;
+ __le16 atimDuration;
+ __le16 hopPeriod;
+ __le16 channelSet;
+ __le16 channel;
+ __le16 hopsToBackbone;
+ __le16 apTotalLoad;
+ __le16 generatedLoad;
+ __le16 accumulatedArl;
+ __le16 signalQuality;
+ __le16 currentXmitRate;
+ __le16 apDevExtensions;
+ __le16 normalizedSignalStrength;
+ __le16 shortPreamble;
u8 apIP[4];
u8 noisePercent; /* Noise percent in last second */
u8 noisedBm; /* Noise dBm in last second */
@@ -678,9 +682,9 @@ typedef struct {
u8 noiseAvedBm; /* Noise dBm in last minute */
u8 noiseMaxPercent; /* Highest noise percent in last minute */
u8 noiseMaxdBm; /* Highest noise dbm in last minute */
- u16 load;
+ __le16 load;
u8 carrier[4];
- u16 assocStatus;
+ __le16 assocStatus;
#define STAT_NOPACKETS 0
#define STAT_NOCARRIERSET 10
#define STAT_GOTCARRIERSET 11
@@ -705,82 +709,82 @@ typedef struct {
} StatusRid;
typedef struct {
- u16 len;
- u16 spacer;
- u32 vals[100];
+ __le16 len;
+ __le16 spacer;
+ __le32 vals[100];
} StatsRid;
typedef struct {
- u16 len;
+ __le16 len;
u8 ap[4][ETH_ALEN];
} APListRid;
typedef struct {
- u16 len;
+ __le16 len;
char oui[3];
char zero;
- u16 prodNum;
+ __le16 prodNum;
char manName[32];
char prodName[16];
char prodVer[8];
char factoryAddr[ETH_ALEN];
char aironetAddr[ETH_ALEN];
- u16 radioType;
- u16 country;
+ __le16 radioType;
+ __le16 country;
char callid[ETH_ALEN];
char supportedRates[8];
char rxDiversity;
char txDiversity;
- u16 txPowerLevels[8];
- u16 hardVer;
- u16 hardCap;
- u16 tempRange;
- u16 softVer;
- u16 softSubVer;
- u16 interfaceVer;
- u16 softCap;
- u16 bootBlockVer;
- u16 requiredHard;
- u16 extSoftCap;
+ __le16 txPowerLevels[8];
+ __le16 hardVer;
+ __le16 hardCap;
+ __le16 tempRange;
+ __le16 softVer;
+ __le16 softSubVer;
+ __le16 interfaceVer;
+ __le16 softCap;
+ __le16 bootBlockVer;
+ __le16 requiredHard;
+ __le16 extSoftCap;
} CapabilityRid;
/* Only present on firmware >= 5.30.17 */
typedef struct {
- u16 unknown[4];
+ __le16 unknown[4];
u8 fixed[12]; /* WLAN management frame */
u8 iep[624];
} BSSListRidExtra;
typedef struct {
- u16 len;
- u16 index; /* First is 0 and 0xffff means end of list */
+ __le16 len;
+ __le16 index; /* First is 0 and 0xffff means end of list */
#define RADIO_FH 1 /* Frequency hopping radio type */
#define RADIO_DS 2 /* Direct sequence radio type */
#define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */
- u16 radioType;
+ __le16 radioType;
u8 bssid[ETH_ALEN]; /* Mac address of the BSS */
u8 zero;
u8 ssidLen;
u8 ssid[32];
- u16 dBm;
-#define CAP_ESS (1<<0)
-#define CAP_IBSS (1<<1)
-#define CAP_PRIVACY (1<<4)
-#define CAP_SHORTHDR (1<<5)
- u16 cap;
- u16 beaconInterval;
+ __le16 dBm;
+#define CAP_ESS cpu_to_le16(1<<0)
+#define CAP_IBSS cpu_to_le16(1<<1)
+#define CAP_PRIVACY cpu_to_le16(1<<4)
+#define CAP_SHORTHDR cpu_to_le16(1<<5)
+ __le16 cap;
+ __le16 beaconInterval;
u8 rates[8]; /* Same as rates for config rid */
struct { /* For frequency hopping only */
- u16 dwell;
+ __le16 dwell;
u8 hopSet;
u8 hopPattern;
u8 hopIndex;
u8 fill;
} fh;
- u16 dsChannel;
- u16 atimWindow;
+ __le16 dsChannel;
+ __le16 atimWindow;
/* Only present on firmware >= 5.30.17 */
BSSListRidExtra extra;
@@ -811,7 +815,7 @@ typedef struct {
} MICRid;
typedef struct {
- u16 typelen;
+ __be16 typelen;
union {
u8 snap[8];
@@ -823,8 +827,8 @@ typedef struct {
u8 fieldtype[2];
} llc;
} u;
- u32 mic;
- u32 seq;
+ __be32 mic;
+ __be32 seq;
} MICBuffer;
typedef struct {
@@ -943,7 +947,7 @@ typedef struct {
int position; // current position (byte offset) in message
union {
u8 d8[4];
- u32 d32;
+ __be32 d32;
} part; // saves partial message word across update() calls
} emmh32_context;
@@ -1100,11 +1104,11 @@ static void enable_interrupts(struct airo_info*);
static void disable_interrupts(struct airo_info*);
static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);
static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);
-static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
+static int aux_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen,
int whichbap);
-static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,
+static int fast_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen,
int whichbap);
-static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen,
+static int bap_write(struct airo_info*, const __le16 *pu16Src, int bytelen,
int whichbap);
static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);
static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);
@@ -1187,7 +1191,7 @@ struct airo_info {
#define JOB_WSTATS 8
#define JOB_SCAN_RESULTS 9
unsigned long jobs;
- int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
+ int (*bap_read)(struct airo_info*, __le16 *pu16Dst, int bytelen,
int whichbap);
unsigned short *flash;
tdsRssiEntry *rssi;
@@ -1235,8 +1239,9 @@ struct airo_info {
BSSListElement *networks;
};
-static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
- int whichbap) {
+static inline int bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen,
+ int whichbap)
+{
return ai->bap_read(ai, pu16Dst, bytelen, whichbap);
}
@@ -1635,7 +1640,7 @@ static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen,
crypto_cipher_encrypt_one(tfm, plain, plain);
cipher = plain;
for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) {
- context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
+ context->coeff[i++] = ntohl(*(__be32 *)&cipher[j]);
j += 4;
}
}
@@ -1668,12 +1673,12 @@ static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
context->position++;
len--;
} while (byte_position < 4);
- MIC_ACCUM(htonl(context->part.d32));
+ MIC_ACCUM(ntohl(context->part.d32));
}
/* deal with full 32-bit words */
while (len >= 4) {
- MIC_ACCUM(htonl(*(u32 *)pOctets));
+ MIC_ACCUM(ntohl(*(__be32 *)pOctets));
context->position += 4;
pOctets += 4;
len -= 4;
@@ -1706,7 +1711,7 @@ static void emmh32_final(emmh32_context *context, u8 digest[4])
byte_position = context->position & 3;
if (byte_position) {
/* have a partial word in part to deal with */
- val = htonl(context->part.d32);
+ val = ntohl(context->part.d32);
MIC_ACCUM(val & mask32[byte_position]); /* zero empty bytes */
}
@@ -1726,8 +1731,8 @@ static void emmh32_final(emmh32_context *context, u8 digest[4])
}
static int readBSSListRid(struct airo_info *ai, int first,
- BSSListRid *list) {
- int rc;
+ BSSListRid *list)
+{
Cmd cmd;
Resp rsp;
@@ -1744,75 +1749,43 @@ static int readBSSListRid(struct airo_info *ai, int first,
schedule_timeout_uninterruptible(3 * HZ);
ai->list_bss_task = NULL;
}
- rc = PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
+ return PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext,
list, ai->bssListRidLen, 1);
-
- list->len = le16_to_cpu(list->len);
- list->index = le16_to_cpu(list->index);
- list->radioType = le16_to_cpu(list->radioType);
- list->cap = le16_to_cpu(list->cap);
- list->beaconInterval = le16_to_cpu(list->beaconInterval);
- list->fh.dwell = le16_to_cpu(list->fh.dwell);
- list->dsChannel = le16_to_cpu(list->dsChannel);
- list->atimWindow = le16_to_cpu(list->atimWindow);
- list->dBm = le16_to_cpu(list->dBm);
- return rc;
}
-static int readWepKeyRid(struct airo_info*ai, WepKeyRid *wkr, int temp, int lock) {
- int rc = PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,
+static int readWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int temp, int lock)
+{
+ return PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM,
wkr, sizeof(*wkr), lock);
-
- wkr->len = le16_to_cpu(wkr->len);
- wkr->kindex = le16_to_cpu(wkr->kindex);
- wkr->klen = le16_to_cpu(wkr->klen);
- return rc;
}
-/* In the writeXXXRid routines we copy the rids so that we don't screwup
- * the originals when we endian them... */
-static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lock) {
- int rc;
- WepKeyRid wkr = *pwkr;
- wkr.len = cpu_to_le16(wkr.len);
- wkr.kindex = cpu_to_le16(wkr.kindex);
- wkr.klen = cpu_to_le16(wkr.klen);
- rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
- if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
+static int writeWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int perm, int lock)
+{
+ int rc;
+ rc = PC4500_writerid(ai, RID_WEP_TEMP, wkr, sizeof(*wkr), lock);
+ if (rc!=SUCCESS)
+ airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
if (perm) {
- rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
- if (rc!=SUCCESS) {
+ rc = PC4500_writerid(ai, RID_WEP_PERM, wkr, sizeof(*wkr), lock);
+ if (rc!=SUCCESS)
airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
- }
}
return rc;
}
-static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) {
- int i;
- int rc = PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
-
- ssidr->len = le16_to_cpu(ssidr->len);
- for(i = 0; i < 3; i++) {
- ssidr->ssids[i].len = le16_to_cpu(ssidr->ssids[i].len);
- }
- return rc;
+static int readSsidRid(struct airo_info*ai, SsidRid *ssidr)
+{
+ return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1);
}
-static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) {
- int rc;
- int i;
- SsidRid ssidr = *pssidr;
- ssidr.len = cpu_to_le16(ssidr.len);
- for(i = 0; i < 3; i++) {
- ssidr.ssids[i].len = cpu_to_le16(ssidr.ssids[i].len);
- }
- rc = PC4500_writerid(ai, RID_SSID, &ssidr, sizeof(ssidr), lock);
- return rc;
+static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock)
+{
+ return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock);
}
-static int readConfigRid(struct airo_info*ai, int lock) {
+
+static int readConfigRid(struct airo_info *ai, int lock)
+{
int rc;
- u16 *s;
ConfigRid cfg;
if (ai->config.len)
@@ -1822,24 +1795,12 @@ static int readConfigRid(struct airo_info*ai, int lock) {
if (rc != SUCCESS)
return rc;
- for(s = &cfg.len; s <= &cfg.rtsThres; s++) *s = le16_to_cpu(*s);
-
- for(s = &cfg.shortRetryLimit; s <= &cfg.radioType; s++)
- *s = le16_to_cpu(*s);
-
- for(s = &cfg.txPower; s <= &cfg.radioSpecific; s++)
- *s = le16_to_cpu(*s);
-
- for(s = &cfg.arlThreshold; s <= &cfg._reserved4[0]; s++)
- *s = cpu_to_le16(*s);
-
- for(s = &cfg.autoWake; s <= &cfg.autoWake; s++)
- *s = cpu_to_le16(*s);
-
ai->config = cfg;
return SUCCESS;
}
-static inline void checkThrottle(struct airo_info *ai) {
+
+static inline void checkThrottle(struct airo_info *ai)
+{
int i;
/* Old hardware had a limit on encryption speed */
if (ai->config.authType != AUTH_OPEN && maxencrypt) {
@@ -1850,8 +1811,9 @@ static inline void checkThrottle(struct airo_info *ai) {
}
}
}
-static int writeConfigRid(struct airo_info*ai, int lock) {
- u16 *s;
+
+static int writeConfigRid(struct airo_info *ai, int lock)
+{
ConfigRid cfgr;
if (!test_bit (FLAG_COMMIT, &ai->flags))
@@ -1862,70 +1824,37 @@ static int writeConfigRid(struct airo_info*ai, int lock) {
checkThrottle(ai);
cfgr = ai->config;
- if ((cfgr.opmode & 0xFF) == MODE_STA_IBSS)
+ if ((cfgr.opmode & MODE_CFG_MASK) == MODE_STA_IBSS)
set_bit(FLAG_ADHOC, &ai->flags);
else
clear_bit(FLAG_ADHOC, &ai->flags);
- for(s = &cfgr.len; s <= &cfgr.rtsThres; s++) *s = cpu_to_le16(*s);
-
- for(s = &cfgr.shortRetryLimit; s <= &cfgr.radioType; s++)
- *s = cpu_to_le16(*s);
-
- for(s = &cfgr.txPower; s <= &cfgr.radioSpecific; s++)
- *s = cpu_to_le16(*s);
-
- for(s = &cfgr.arlThreshold; s <= &cfgr._reserved4[0]; s++)
- *s = cpu_to_le16(*s);
-
- for(s = &cfgr.autoWake; s <= &cfgr.autoWake; s++)
- *s = cpu_to_le16(*s);
-
return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock);
}
-static int readStatusRid(struct airo_info*ai, StatusRid *statr, int lock) {
- int rc = PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
- u16 *s;
- statr->len = le16_to_cpu(statr->len);
- for(s = &statr->mode; s <= &statr->SSIDlen; s++) *s = le16_to_cpu(*s);
-
- for(s = &statr->beaconPeriod; s <= &statr->shortPreamble; s++)
- *s = le16_to_cpu(*s);
- statr->load = le16_to_cpu(statr->load);
- statr->assocStatus = le16_to_cpu(statr->assocStatus);
- return rc;
+static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock)
+{
+ return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock);
}
-static int readAPListRid(struct airo_info*ai, APListRid *aplr) {
- int rc = PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
- aplr->len = le16_to_cpu(aplr->len);
- return rc;
+
+static int readAPListRid(struct airo_info *ai, APListRid *aplr)
+{
+ return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1);
}
-static int writeAPListRid(struct airo_info*ai, APListRid *aplr, int lock) {
- int rc;
- aplr->len = cpu_to_le16(aplr->len);
- rc = PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
- return rc;
+
+static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock)
+{
+ return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock);
}
-static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) {
- int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
- u16 *s;
- capr->len = le16_to_cpu(capr->len);
- capr->prodNum = le16_to_cpu(capr->prodNum);
- capr->radioType = le16_to_cpu(capr->radioType);
- capr->country = le16_to_cpu(capr->country);
- for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)
- *s = le16_to_cpu(*s);
- return rc;
+static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock)
+{
+ return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);
}
-static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {
- int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);
- u32 *i;
- sr->len = le16_to_cpu(sr->len);
- for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i);
- return rc;
+static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock)
+{
+ return PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);
}
static void try_auto_wep(struct airo_info *ai)
@@ -2026,13 +1955,14 @@ static int mpi_send_packet (struct net_device *dev)
{
struct sk_buff *skb;
unsigned char *buffer;
- s16 len, *payloadLen;
+ s16 len;
+ __le16 *payloadLen;
struct airo_info *ai = dev->priv;
u8 *sendbuf;
/* get a packet to send */
- if ((skb = skb_dequeue(&ai->txq)) == 0) {
+ if ((skb = skb_dequeue(&ai->txq)) == NULL) {
airo_print_err(dev->name,
"%s: Dequeue'd zero in send_packet()",
__FUNCTION__);
@@ -2059,7 +1989,7 @@ static int mpi_send_packet (struct net_device *dev)
memcpy((char *)ai->txfids[0].virtual_host_addr,
(char *)&wifictlhdr8023, sizeof(wifictlhdr8023));
- payloadLen = (s16 *)(ai->txfids[0].virtual_host_addr +
+ payloadLen = (__le16 *)(ai->txfids[0].virtual_host_addr +
sizeof(wifictlhdr8023));
sendbuf = ai->txfids[0].virtual_host_addr +
sizeof(wifictlhdr8023) + 2 ;
@@ -2069,7 +1999,7 @@ static int mpi_send_packet (struct net_device *dev)
* we don't need to account for it in the length
*/
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
- (ntohs(((u16 *)buffer)[6]) != 0x888E)) {
+ (ntohs(((__be16 *)buffer)[6]) != 0x888E)) {
MICBuffer pMic;
if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS)
@@ -2104,7 +2034,7 @@ static int mpi_send_packet (struct net_device *dev)
static void get_tx_error(struct airo_info *ai, s32 fid)
{
- u16 status;
+ __le16 status;
if (fid < 0)
status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status;
@@ -2135,7 +2065,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
/* Faster to skip over useless data than to do
* another bap_setup(). We are at offset 0x6 and
* need to go to 0x18 and read 6 bytes - Jean II */
- bap_read(ai, (u16 *) junk, 0x18, BAP0);
+ bap_read(ai, (__le16 *) junk, 0x18, BAP0);
/* Copy 802.11 dest address.
* We use the 802.11 header because the frame may
@@ -2289,9 +2219,10 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
return 0;
}
-static void airo_read_stats(struct airo_info *ai) {
+static void airo_read_stats(struct airo_info *ai)
+{
StatsRid stats_rid;
- u32 *vals = stats_rid.vals;
+ __le32 *vals = stats_rid.vals;
clear_bit(JOB_STATS, &ai->jobs);
if (ai->power.event) {
@@ -2301,20 +2232,23 @@ static void airo_read_stats(struct airo_info *ai) {
readStatsRid(ai, &stats_rid, RID_STATS, 0);
up(&ai->sem);
- ai->stats.rx_packets = vals[43] + vals[44] + vals[45];
- ai->stats.tx_packets = vals[39] + vals[40] + vals[41];
- ai->stats.rx_bytes = vals[92];
- ai->stats.tx_bytes = vals[91];
- ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];
- ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors;
- ai->stats.multicast = vals[43];
- ai->stats.collisions = vals[89];
+ ai->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) +
+ le32_to_cpu(vals[45]);
+ ai->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) +
+ le32_to_cpu(vals[41]);
+ ai->stats.rx_bytes = le32_to_cpu(vals[92]);
+ ai->stats.tx_bytes = le32_to_cpu(vals[91]);
+ ai->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) +
+ le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]);
+ ai->stats.tx_errors = le32_to_cpu(vals[42]) + ai->stats.tx_fifo_errors;
+ ai->stats.multicast = le32_to_cpu(vals[43]);
+ ai->stats.collisions = le32_to_cpu(vals[89]);
/* detailed rx_errors: */
- ai->stats.rx_length_errors = vals[3];
- ai->stats.rx_crc_errors = vals[4];
- ai->stats.rx_frame_errors = vals[2];
- ai->stats.rx_fifo_errors = vals[0];
+ ai->stats.rx_length_errors = le32_to_cpu(vals[3]);
+ ai->stats.rx_crc_errors = le32_to_cpu(vals[4]);
+ ai->stats.rx_frame_errors = le32_to_cpu(vals[2]);
+ ai->stats.rx_fifo_errors = le32_to_cpu(vals[0]);
}
static struct net_device_stats *airo_get_stats(struct net_device *dev)
@@ -2801,8 +2735,9 @@ static int airo_test_wpa_capable(struct airo_info *ai)
if (status != SUCCESS) return 0;
/* Only firmware versions 5.30.17 or better can do WPA */
- if ((cap_rid.softVer > 0x530)
- || ((cap_rid.softVer == 0x530) && (cap_rid.softSubVer >= 17))) {
+ if (le16_to_cpu(cap_rid.softVer) > 0x530
+ || (le16_to_cpu(cap_rid.softVer) == 0x530
+ && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
airo_print_info("", "WPA is supported.");
return 1;
}
@@ -3037,14 +2972,14 @@ static void airo_process_scan_results (struct airo_info *ai) {
/* Try to read the first entry of the scan result */
rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0);
- if((rc) || (bss.index == 0xffff)) {
+ if((rc) || (bss.index == cpu_to_le16(0xffff))) {
/* No scan results */
goto out;
}
/* Read and parse all entries */
tmp_net = NULL;
- while((!rc) && (bss.index != 0xffff)) {
+ while((!rc) && (bss.index != cpu_to_le16(0xffff))) {
/* Grab a network off the free list */
if (!list_empty(&ai->network_free_list)) {
tmp_net = list_entry(ai->network_free_list.next,
@@ -3177,8 +3112,24 @@ static int airo_thread(void *data) {
return 0;
}
-static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
- struct net_device *dev = (struct net_device *)dev_id;
+static int header_len(__le16 ctl)
+{
+ u16 fc = le16_to_cpu(ctl);
+ switch (fc & 0xc) {
+ case 4:
+ if ((fc & 0xe0) == 0xc0)
+ return 10; /* one-address control packet */
+ return 16; /* two-address control packet */
+ case 8:
+ if ((fc & 0x300) == 0x300)
+ return 30; /* WDS packet */
+ }
+ return 24;
+}
+
+static irqreturn_t airo_interrupt(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
u16 status;
u16 fid;
struct airo_info *apriv = dev->priv;
@@ -3281,19 +3232,20 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
/* Check to see if there is something to receive */
if ( status & EV_RX ) {
struct sk_buff *skb = NULL;
- u16 fc, len, hdrlen = 0;
+ __le16 fc, v;
+ u16 len, hdrlen = 0;
#pragma pack(1)
struct {
- u16 status, len;
+ __le16 status, len;
u8 rssi[2];
u8 rate;
u8 freq;
- u16 tmp[4];
+ __le16 tmp[4];
} hdr;
#pragma pack()
u16 gap;
- u16 tmpbuf[4];
- u16 *buffer;
+ __le16 tmpbuf[4];
+ __le16 *buffer;
if (test_bit(FLAG_MPI,&apriv->flags)) {
if (test_bit(FLAG_802_11, &apriv->flags))
@@ -3309,7 +3261,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
/* Get the packet length */
if (test_bit(FLAG_802_11, &apriv->flags)) {
bap_setup (apriv, fid, 4, BAP0);
- bap_read (apriv, (u16*)&hdr, sizeof(hdr), BAP0);
+ bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0);
/* Bad CRC. Ignore packet */
if (le16_to_cpu(hdr.status) & 2)
hdr.len = 0;
@@ -3317,7 +3269,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
hdr.len = 0;
} else {
bap_setup (apriv, fid, 0x36, BAP0);
- bap_read (apriv, (u16*)&hdr.len, 2, BAP0);
+ bap_read (apriv, &hdr.len, 2, BAP0);
}
len = le16_to_cpu(hdr.len);
@@ -3329,23 +3281,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
goto badrx;
if (test_bit(FLAG_802_11, &apriv->flags)) {
- bap_read (apriv, (u16*)&fc, sizeof(fc), BAP0);
- fc = le16_to_cpu(fc);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ bap_read (apriv, &fc, sizeof(fc), BAP0);
+ hdrlen = header_len(fc);
} else
hdrlen = ETH_ALEN * 2;
@@ -3355,15 +3292,15 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
goto badrx;
}
skb_reserve(skb, 2); /* This way the IP header is aligned */
- buffer = (u16*)skb_put (skb, len + hdrlen);
+ buffer = (__le16*)skb_put (skb, len + hdrlen);
if (test_bit(FLAG_802_11, &apriv->flags)) {
buffer[0] = fc;
bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
if (hdrlen == 24)
bap_read (apriv, tmpbuf, 6, BAP0);
- bap_read (apriv, &gap, sizeof(gap), BAP0);
- gap = le16_to_cpu(gap);
+ bap_read (apriv, &v, sizeof(v), BAP0);
+ gap = le16_to_cpu(v);
if (gap) {
if (gap <= 8) {
bap_read (apriv, tmpbuf, gap, BAP0);
@@ -3377,7 +3314,7 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id) {
MICBuffer micbuf;
bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
if (apriv->micstats.enabled) {
- bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
+ bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0);
if (ntohs(micbuf.typelen) > 0x05DC)
bap_setup (apriv, fid, 0x44, BAP0);
else {
@@ -3405,7 +3342,7 @@ badrx:
if (!test_bit(FLAG_802_11, &apriv->flags)) {
sa = (char*)buffer + 6;
bap_setup (apriv, fid, 8, BAP0);
- bap_read (apriv, (u16*)hdr.rssi, 2, BAP0);
+ bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0);
} else
sa = (char*)buffer + 10;
wstats.qual = hdr.rssi[0];
@@ -3676,14 +3613,15 @@ void mpi_receive_802_11 (struct airo_info *ai)
{
RxFid rxd;
struct sk_buff *skb = NULL;
- u16 fc, len, hdrlen = 0;
+ u16 len, hdrlen = 0;
+ __le16 fc;
#pragma pack(1)
struct {
- u16 status, len;
+ __le16 status, len;
u8 rssi[2];
u8 rate;
u8 freq;
- u16 tmp[4];
+ __le16 tmp[4];
} hdr;
#pragma pack()
u16 gap;
@@ -3706,23 +3644,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
if (len == 0)
goto badrx;
- memcpy ((char *)&fc, ptr, sizeof(fc));
- fc = le16_to_cpu(fc);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ fc = get_unaligned((__le16 *)ptr);
+ hdrlen = header_len(fc);
skb = dev_alloc_skb( len + hdrlen + 2 );
if ( !skb ) {
@@ -3734,9 +3657,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
ptr += hdrlen;
if (hdrlen == 24)
ptr += 6;
- memcpy ((char *)&gap, ptr, sizeof(gap));
- ptr += sizeof(gap);
- gap = le16_to_cpu(gap);
+ gap = le16_to_cpu(get_unaligned((__le16 *)ptr));
+ ptr += sizeof(__le16);
if (gap) {
if (gap <= 8)
ptr += gap;
@@ -3788,7 +3710,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
int status;
int i;
SsidRid mySsid;
- u16 lastindex;
+ __le16 lastindex;
WepKeyRid wkr;
int rc;
@@ -3850,7 +3772,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
else {
kfree(ai->rssi);
ai->rssi = NULL;
- if (cap_rid.softCap & 8)
+ if (cap_rid.softCap & cpu_to_le16(8))
ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
else
airo_print_warn(ai->dev->name, "unknown received signal "
@@ -3860,8 +3782,9 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
ai->config.authType = AUTH_OPEN;
ai->config.modulation = MOD_CCK;
- if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
- (micsetup(ai) == SUCCESS)) {
+ if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) &&
+ (cap_rid.extSoftCap & cpu_to_le16(1)) &&
+ micsetup(ai) == SUCCESS) {
ai->config.opmode |= MODE_MIC;
set_bit(FLAG_MIC_CAPABLE, &ai->flags);
}
@@ -3897,13 +3820,13 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
if ( ssids[0] ) {
int i;
for( i = 0; i < 3 && ssids[i]; i++ ) {
- mySsid.ssids[i].len = strlen(ssids[i]);
- if ( mySsid.ssids[i].len > 32 )
- mySsid.ssids[i].len = 32;
- memcpy(mySsid.ssids[i].ssid, ssids[i],
- mySsid.ssids[i].len);
+ size_t len = strlen(ssids[i]);
+ if (len > 32)
+ len = 32;
+ mySsid.ssids[i].len = cpu_to_le16(len);
+ memcpy(mySsid.ssids[i].ssid, ssids[i], len);
}
- mySsid.len = sizeof(mySsid);
+ mySsid.len = cpu_to_le16(sizeof(mySsid));
}
status = writeConfigRid(ai, lock);
@@ -3923,7 +3846,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
rc = readWepKeyRid(ai, &wkr, 1, lock);
if (rc == SUCCESS) do {
lastindex = wkr.kindex;
- if (wkr.kindex == 0xffff) {
+ if (wkr.kindex == cpu_to_le16(0xffff)) {
ai->defindex = wkr.mac[0];
}
rc = readWepKeyRid(ai, &wkr, 0, lock);
@@ -4038,7 +3961,7 @@ static u16 aux_setup(struct airo_info *ai, u16 page,
}
/* requires call to bap_setup() first */
-static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst,
+static int aux_bap_read(struct airo_info *ai, __le16 *pu16Dst,
int bytelen, int whichbap)
{
u16 len;
@@ -4075,7 +3998,7 @@ static int aux_bap_read(struct airo_info *ai, u16 *pu16Dst,
/* requires call to bap_setup() first */
-static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst,
+static int fast_bap_read(struct airo_info *ai, __le16 *pu16Dst,
int bytelen, int whichbap)
{
bytelen = (bytelen + 1) & (~1); // round up to even value
@@ -4087,7 +4010,7 @@ static int fast_bap_read(struct airo_info *ai, u16 *pu16Dst,
}
/* requires call to bap_setup() first */
-static int bap_write(struct airo_info *ai, const u16 *pu16Src,
+static int bap_write(struct airo_info *ai, const __le16 *pu16Src,
int bytelen, int whichbap)
{
bytelen = (bytelen + 1) & (~1); // round up to even value
@@ -4163,7 +4086,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
// read the rid length field
bap_read(ai, pBuf, 2, BAP1);
// length for remaining part of rid
- len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;
+ len = min(len, (int)le16_to_cpu(*(__le16*)pBuf)) - 2;
if ( len <= 2 ) {
airo_print_err(ai->dev->name,
@@ -4173,7 +4096,7 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
goto done;
}
// read remainder of the rid
- rc = bap_read(ai, ((u16*)pBuf)+1, len, BAP1);
+ rc = bap_read(ai, ((__le16*)pBuf)+1, len, BAP1);
}
done:
if (lock)
@@ -4189,7 +4112,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
u16 status;
int rc = SUCCESS;
- *(u16*)pBuf = cpu_to_le16((u16)len);
+ *(__le16*)pBuf = cpu_to_le16((u16)len);
if (lock) {
if (down_interruptible(&ai->sem))
@@ -4263,7 +4186,7 @@ static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw)
Cmd cmd;
Resp rsp;
u16 txFid;
- u16 txControl;
+ __le16 txControl;
cmd.cmd = CMD_ALLOCATETX;
cmd.parm0 = lenPayload;
@@ -4317,7 +4240,7 @@ done:
Make sure the BAP1 spinlock is held when this is called. */
static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
{
- u16 payloadLen;
+ __le16 payloadLen;
Cmd cmd;
Resp rsp;
int miclen = 0;
@@ -4333,7 +4256,7 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
len -= ETH_ALEN * 2;
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
- (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
+ (ntohs(((__be16 *)pPacket)[6]) != 0x888E)) {
if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
return ERROR;
miclen = sizeof(pMic);
@@ -4345,10 +4268,10 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
* we have to subtract the 12 bytes for the addresses off */
payloadLen = cpu_to_le16(len + miclen);
bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
- bap_write(ai, (const u16*)pPacket, sizeof(etherHead), BAP1);
+ bap_write(ai, (__le16*)pPacket, sizeof(etherHead), BAP1);
if (miclen)
- bap_write(ai, (const u16*)&pMic, miclen, BAP1);
- bap_write(ai, (const u16*)(pPacket + sizeof(etherHead)), len, BAP1);
+ bap_write(ai, (__le16*)&pMic, miclen, BAP1);
+ bap_write(ai, (__le16*)(pPacket + sizeof(etherHead)), len, BAP1);
// issue the transmit command
memset( &cmd, 0, sizeof( cmd ) );
cmd.cmd = CMD_TRANSMIT;
@@ -4360,35 +4283,17 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
{
- u16 fc, payloadLen;
+ __le16 fc, payloadLen;
Cmd cmd;
Resp rsp;
int hdrlen;
- struct {
- u8 addr4[ETH_ALEN];
- u16 gaplen;
- u8 gap[6];
- } gap;
+ static u8 tail[(30-10) + 2 + 6] = {[30-10] = 6};
+ /* padding of header to full size + le16 gaplen (6) + gaplen bytes */
u16 txFid = len;
len >>= 16;
- gap.gaplen = 6;
- fc = le16_to_cpu(*(const u16*)pPacket);
- switch (fc & 0xc) {
- case 4:
- if ((fc & 0xe0) == 0xc0)
- hdrlen = 10;
- else
- hdrlen = 16;
- break;
- case 8:
- if ((fc&0x300)==0x300){
- hdrlen = 30;
- break;
- }
- default:
- hdrlen = 24;
- }
+ fc = *(__le16*)pPacket;
+ hdrlen = header_len(fc);
if (len < hdrlen) {
airo_print_warn(ai->dev->name, "Short packet %d", len);
@@ -4403,11 +4308,10 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
payloadLen = cpu_to_le16(len-hdrlen);
bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1);
if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR;
- bap_write(ai, (const u16*)pPacket, hdrlen, BAP1);
- bap_write(ai, hdrlen == 30 ?
- (const u16*)&gap.gaplen : (const u16*)&gap, 38 - hdrlen, BAP1);
+ bap_write(ai, (__le16 *)pPacket, hdrlen, BAP1);
+ bap_write(ai, (__le16 *)(tail + (hdrlen - 10)), 38 - hdrlen, BAP1);
- bap_write(ai, (const u16*)(pPacket + hdrlen), len - hdrlen, BAP1);
+ bap_write(ai, (__le16 *)(pPacket + hdrlen), len - hdrlen, BAP1);
// issue the transmit command
memset( &cmd, 0, sizeof( cmd ) );
cmd.cmd = CMD_TRANSMIT;
@@ -4722,13 +4626,15 @@ static ssize_t proc_write( struct file *file,
return len;
}
-static int proc_status_open( struct inode *inode, struct file *file ) {
+static int proc_status_open(struct inode *inode, struct file *file)
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *apriv = dev->priv;
CapabilityRid cap_rid;
StatusRid status_rid;
+ u16 mode;
int i;
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
@@ -4742,16 +4648,18 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
readStatusRid(apriv, &status_rid, 1);
readCapabilityRid(apriv, &cap_rid, 1);
+ mode = le16_to_cpu(status_rid.mode);
+
i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n",
- status_rid.mode & 1 ? "CFG ": "",
- status_rid.mode & 2 ? "ACT ": "",
- status_rid.mode & 0x10 ? "SYN ": "",
- status_rid.mode & 0x20 ? "LNK ": "",
- status_rid.mode & 0x40 ? "LEAP ": "",
- status_rid.mode & 0x80 ? "PRIV ": "",
- status_rid.mode & 0x100 ? "KEY ": "",
- status_rid.mode & 0x200 ? "WEP ": "",
- status_rid.mode & 0x8000 ? "ERR ": "");
+ mode & 1 ? "CFG ": "",
+ mode & 2 ? "ACT ": "",
+ mode & 0x10 ? "SYN ": "",
+ mode & 0x20 ? "LNK ": "",
+ mode & 0x40 ? "LEAP ": "",
+ mode & 0x80 ? "PRIV ": "",
+ mode & 0x100 ? "KEY ": "",
+ mode & 0x200 ? "WEP ": "",
+ mode & 0x8000 ? "ERR ": "");
sprintf( data->rbuffer+i, "Mode: %x\n"
"Signal Strength: %d\n"
"Signal Quality: %d\n"
@@ -4764,24 +4672,24 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
"Radio type: %x\nCountry: %x\nHardware Version: %x\n"
"Software Version: %x\nSoftware Subversion: %x\n"
"Boot block version: %x\n",
- (int)status_rid.mode,
- (int)status_rid.normalizedSignalStrength,
- (int)status_rid.signalQuality,
- (int)status_rid.SSIDlen,
+ le16_to_cpu(status_rid.mode),
+ le16_to_cpu(status_rid.normalizedSignalStrength),
+ le16_to_cpu(status_rid.signalQuality),
+ le16_to_cpu(status_rid.SSIDlen),
status_rid.SSID,
status_rid.apName,
- (int)status_rid.channel,
- (int)status_rid.currentXmitRate/2,
+ le16_to_cpu(status_rid.channel),
+ le16_to_cpu(status_rid.currentXmitRate) / 2,
version,
cap_rid.prodName,
cap_rid.manName,
cap_rid.prodVer,
- cap_rid.radioType,
- cap_rid.country,
- cap_rid.hardVer,
- (int)cap_rid.softVer,
- (int)cap_rid.softSubVer,
- (int)cap_rid.bootBlockVer );
+ le16_to_cpu(cap_rid.radioType),
+ le16_to_cpu(cap_rid.country),
+ le16_to_cpu(cap_rid.hardVer),
+ le16_to_cpu(cap_rid.softVer),
+ le16_to_cpu(cap_rid.softSubVer),
+ le16_to_cpu(cap_rid.bootBlockVer));
data->readlen = strlen( data->rbuffer );
return 0;
}
@@ -4801,14 +4709,16 @@ static int proc_stats_open( struct inode *inode, struct file *file ) {
static int proc_stats_rid_open( struct inode *inode,
struct file *file,
- u16 rid ) {
+ u16 rid )
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *apriv = dev->priv;
StatsRid stats;
int i, j;
- u32 *vals = stats.vals;
+ __le32 *vals = stats.vals;
+ int len = le16_to_cpu(stats.len);
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -4821,17 +4731,17 @@ static int proc_stats_rid_open( struct inode *inode,
readStatsRid(apriv, &stats, rid, 1);
j = 0;
- for(i=0; statsLabels[i]!=(char *)-1 &&
- i*4<stats.len; i++){
+ for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) {
if (!statsLabels[i]) continue;
if (j+strlen(statsLabels[i])+16>4096) {
airo_print_warn(apriv->dev->name,
"Potentially disasterous buffer overflow averted!");
break;
}
- j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]);
+ j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i],
+ le32_to_cpu(vals[i]));
}
- if (i*4>=stats.len){
+ if (i*4 >= len) {
airo_print_warn(apriv->dev->name, "Got a short rid");
}
data->readlen = j;
@@ -4856,7 +4766,14 @@ static int airo_config_commit(struct net_device *dev,
struct iw_request_info *info, void *zwrq,
char *extra);
-static void proc_config_on_close( struct inode *inode, struct file *file ) {
+static inline int sniffing_mode(struct airo_info *ai)
+{
+ return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >=
+ le16_to_cpu(RXMODE_RFMON);
+}
+
+static void proc_config_on_close(struct inode *inode, struct file *file)
+{
struct proc_data *data = file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
@@ -4873,16 +4790,16 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
/*** Mode processing */
if ( !strncmp( line, "Mode: ", 6 ) ) {
line += 6;
- if ((ai->config.rmode & 0xff) >= RXMODE_RFMON)
- set_bit (FLAG_RESET, &ai->flags);
- ai->config.rmode &= 0xfe00;
+ if (sniffing_mode(ai))
+ set_bit (FLAG_RESET, &ai->flags);
+ ai->config.rmode &= ~RXMODE_FULL_MASK;
clear_bit (FLAG_802_11, &ai->flags);
- ai->config.opmode &= 0xFF00;
+ ai->config.opmode &= ~MODE_CFG_MASK;
ai->config.scanMode = SCANMODE_ACTIVE;
if ( line[0] == 'a' ) {
- ai->config.opmode |= 0;
+ ai->config.opmode |= MODE_STA_IBSS;
} else {
- ai->config.opmode |= 1;
+ ai->config.opmode |= MODE_STA_ESS;
if ( line[0] == 'r' ) {
ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
ai->config.scanMode = SCANMODE_PASSIVE;
@@ -4948,7 +4865,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 9;
v = get_dec_u16(line, &i, i+3);
if ( v != -1 ) {
- ai->config.channelSet = (u16)v;
+ ai->config.channelSet = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
}
} else if ( !strncmp( line, "XmitPower: ", 11 ) ) {
@@ -4956,20 +4873,20 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 11;
v = get_dec_u16(line, &i, i+3);
if ( v != -1 ) {
- ai->config.txPower = (u16)v;
+ ai->config.txPower = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
}
} else if ( !strncmp( line, "WEP: ", 5 ) ) {
line += 5;
switch( line[0] ) {
case 's':
- ai->config.authType = (u16)AUTH_SHAREDKEY;
+ ai->config.authType = AUTH_SHAREDKEY;
break;
case 'e':
- ai->config.authType = (u16)AUTH_ENCRYPT;
+ ai->config.authType = AUTH_ENCRYPT;
break;
default:
- ai->config.authType = (u16)AUTH_OPEN;
+ ai->config.authType = AUTH_OPEN;
break;
}
set_bit (FLAG_COMMIT, &ai->flags);
@@ -4979,7 +4896,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 16;
v = get_dec_u16(line, &i, 3);
v = (v<0) ? 0 : ((v>255) ? 255 : v);
- ai->config.longRetryLimit = (u16)v;
+ ai->config.longRetryLimit = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) {
int v, i = 0;
@@ -4987,7 +4904,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 17;
v = get_dec_u16(line, &i, 3);
v = (v<0) ? 0 : ((v>255) ? 255 : v);
- ai->config.shortRetryLimit = (u16)v;
+ ai->config.shortRetryLimit = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) {
int v, i = 0;
@@ -4995,7 +4912,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 14;
v = get_dec_u16(line, &i, 4);
v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
- ai->config.rtsThres = (u16)v;
+ ai->config.rtsThres = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
int v, i = 0;
@@ -5003,7 +4920,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 16;
v = get_dec_u16(line, &i, 5);
v = (v<0) ? 0 : v;
- ai->config.txLifetime = (u16)v;
+ ai->config.txLifetime = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) {
int v, i = 0;
@@ -5011,7 +4928,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
line += 16;
v = get_dec_u16(line, &i, 5);
v = (v<0) ? 0 : v;
- ai->config.rxLifetime = (u16)v;
+ ai->config.rxLifetime = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if ( !strncmp( line, "TXDiversity: ", 13 ) ) {
ai->config.txDiversity =
@@ -5030,7 +4947,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
v = get_dec_u16(line, &i, 4);
v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
v = v & 0xfffe; /* Make sure its even */
- ai->config.fragThresh = (u16)v;
+ ai->config.fragThresh = cpu_to_le16(v);
set_bit (FLAG_COMMIT, &ai->flags);
} else if (!strncmp(line, "Modulation: ", 12)) {
line += 12;
@@ -5057,8 +4974,9 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
airo_config_commit(dev, NULL, NULL, NULL);
}
-static char *get_rmode(u16 mode) {
- switch(mode&0xff) {
+static char *get_rmode(__le16 mode)
+{
+ switch(mode & RXMODE_MASK) {
case RXMODE_RFMON: return "rfmon";
case RXMODE_RFMON_ANYBSS: return "yna (any) bss rfmon";
case RXMODE_LANMON: return "lanmon";
@@ -5066,12 +4984,14 @@ static char *get_rmode(u16 mode) {
return "ESS";
}
-static int proc_config_open( struct inode *inode, struct file *file ) {
+static int proc_config_open(struct inode *inode, struct file *file)
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
int i;
+ __le16 mode;
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -5090,6 +5010,7 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
readConfigRid(ai, 1);
+ mode = ai->config.opmode & MODE_CFG_MASK;
i = sprintf( data->rbuffer,
"Mode: %s\n"
"Radio: %s\n"
@@ -5098,15 +5019,16 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
"DataRates: %d %d %d %d %d %d %d %d\n"
"Channel: %d\n"
"XmitPower: %d\n",
- (ai->config.opmode & 0xFF) == 0 ? "adhoc" :
- (ai->config.opmode & 0xFF) == 1 ? get_rmode(ai->config.rmode):
- (ai->config.opmode & 0xFF) == 2 ? "AP" :
- (ai->config.opmode & 0xFF) == 3 ? "AP RPTR" : "Error",
+ mode == MODE_STA_IBSS ? "adhoc" :
+ mode == MODE_STA_ESS ? get_rmode(ai->config.rmode):
+ mode == MODE_AP ? "AP" :
+ mode == MODE_AP_RPTR ? "AP RPTR" : "Error",
test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on",
ai->config.nodeName,
- ai->config.powerSaveMode == 0 ? "CAM" :
- ai->config.powerSaveMode == 1 ? "PSP" :
- ai->config.powerSaveMode == 2 ? "PSPCAM" : "Error",
+ ai->config.powerSaveMode == POWERSAVE_CAM ? "CAM" :
+ ai->config.powerSaveMode == POWERSAVE_PSP ? "PSP" :
+ ai->config.powerSaveMode == POWERSAVE_PSPCAM ? "PSPCAM" :
+ "Error",
(int)ai->config.rates[0],
(int)ai->config.rates[1],
(int)ai->config.rates[2],
@@ -5115,8 +5037,8 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
(int)ai->config.rates[5],
(int)ai->config.rates[6],
(int)ai->config.rates[7],
- (int)ai->config.channelSet,
- (int)ai->config.txPower
+ le16_to_cpu(ai->config.channelSet),
+ le16_to_cpu(ai->config.txPower)
);
sprintf( data->rbuffer + i,
"LongRetryLimit: %d\n"
@@ -5130,19 +5052,19 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
"WEP: %s\n"
"Modulation: %s\n"
"Preamble: %s\n",
- (int)ai->config.longRetryLimit,
- (int)ai->config.shortRetryLimit,
- (int)ai->config.rtsThres,
- (int)ai->config.txLifetime,
- (int)ai->config.rxLifetime,
+ le16_to_cpu(ai->config.longRetryLimit),
+ le16_to_cpu(ai->config.shortRetryLimit),
+ le16_to_cpu(ai->config.rtsThres),
+ le16_to_cpu(ai->config.txLifetime),
+ le16_to_cpu(ai->config.rxLifetime),
ai->config.txDiversity == 1 ? "left" :
ai->config.txDiversity == 2 ? "right" : "both",
ai->config.rxDiversity == 1 ? "left" :
ai->config.rxDiversity == 2 ? "right" : "both",
- (int)ai->config.fragThresh,
+ le16_to_cpu(ai->config.fragThresh),
ai->config.authType == AUTH_ENCRYPT ? "encrypt" :
ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open",
- ai->config.modulation == 0 ? "default" :
+ ai->config.modulation == MOD_DEFAULT ? "default" :
ai->config.modulation == MOD_CCK ? "cck" :
ai->config.modulation == MOD_MOK ? "mok" : "error",
ai->config.preamble == PREAMBLE_AUTO ? "auto" :
@@ -5153,34 +5075,38 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
return 0;
}
-static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
+static void proc_SSID_on_close(struct inode *inode, struct file *file)
+{
struct proc_data *data = (struct proc_data *)file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
SsidRid SSID_rid;
int i;
- int offset = 0;
+ char *p = data->wbuffer;
+ char *end = p + data->writelen;
- if ( !data->writelen ) return;
+ if (!data->writelen)
+ return;
- memset( &SSID_rid, 0, sizeof( SSID_rid ) );
+ *end = '\n'; /* sentinel; we have space for it */
- for( i = 0; i < 3; i++ ) {
- int j;
- for( j = 0; j+offset < data->writelen && j < 32 &&
- data->wbuffer[offset+j] != '\n'; j++ ) {
- SSID_rid.ssids[i].ssid[j] = data->wbuffer[offset+j];
- }
- if ( j == 0 ) break;
- SSID_rid.ssids[i].len = j;
- offset += j;
- while( data->wbuffer[offset] != '\n' &&
- offset < data->writelen ) offset++;
- offset++;
+ memset(&SSID_rid, 0, sizeof(SSID_rid));
+
+ for (i = 0; i < 3 && p < end; i++) {
+ int j = 0;
+ /* copy up to 32 characters from this line */
+ while (*p != '\n' && j < 32)
+ SSID_rid.ssids[i].ssid[j++] = *p++;
+ if (j == 0)
+ break;
+ SSID_rid.ssids[i].len = cpu_to_le16(j);
+ /* skip to the beginning of the next line */
+ while (*p++ != '\n')
+ ;
}
if (i)
- SSID_rid.len = sizeof(SSID_rid);
+ SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
disable_MAC(ai, 1);
writeSsidRid(ai, &SSID_rid, 1);
enable_MAC(ai, 1);
@@ -5204,7 +5130,7 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
if ( !data->writelen ) return;
memset( &APList_rid, 0, sizeof(APList_rid) );
- APList_rid.len = sizeof(APList_rid);
+ APList_rid.len = cpu_to_le16(sizeof(APList_rid));
for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
int j;
@@ -5244,39 +5170,40 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
static int get_wep_key(struct airo_info *ai, u16 index) {
WepKeyRid wkr;
int rc;
- u16 lastindex;
+ __le16 lastindex;
rc = readWepKeyRid(ai, &wkr, 1, 1);
if (rc == SUCCESS) do {
lastindex = wkr.kindex;
- if (wkr.kindex == index) {
+ if (wkr.kindex == cpu_to_le16(index)) {
if (index == 0xffff) {
return wkr.mac[0];
}
- return wkr.klen;
+ return le16_to_cpu(wkr.klen);
}
readWepKeyRid(ai, &wkr, 0, 1);
- } while(lastindex != wkr.kindex);
+ } while (lastindex != wkr.kindex);
return -1;
}
static int set_wep_key(struct airo_info *ai, u16 index,
- const char *key, u16 keylen, int perm, int lock ) {
+ const char *key, u16 keylen, int perm, int lock )
+{
static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
WepKeyRid wkr;
memset(&wkr, 0, sizeof(wkr));
if (keylen == 0) {
// We are selecting which key to use
- wkr.len = sizeof(wkr);
- wkr.kindex = 0xffff;
+ wkr.len = cpu_to_le16(sizeof(wkr));
+ wkr.kindex = cpu_to_le16(0xffff);
wkr.mac[0] = (char)index;
if (perm) ai->defindex = (char)index;
} else {
// We are actually setting the key
- wkr.len = sizeof(wkr);
- wkr.kindex = index;
- wkr.klen = keylen;
+ wkr.len = cpu_to_le16(sizeof(wkr));
+ wkr.kindex = cpu_to_le16(index);
+ wkr.klen = cpu_to_le16(keylen);
memcpy( wkr.key, key, keylen );
memcpy( wkr.mac, macaddr, ETH_ALEN );
}
@@ -5328,14 +5255,15 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
set_wep_key(ai, index, key, i/3, 1, 1);
}
-static int proc_wepkey_open( struct inode *inode, struct file *file ) {
+static int proc_wepkey_open( struct inode *inode, struct file *file )
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
struct airo_info *ai = dev->priv;
char *ptr;
WepKeyRid wkr;
- u16 lastindex;
+ __le16 lastindex;
int j=0;
int rc;
@@ -5361,12 +5289,13 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) {
rc = readWepKeyRid(ai, &wkr, 1, 1);
if (rc == SUCCESS) do {
lastindex = wkr.kindex;
- if (wkr.kindex == 0xffff) {
+ if (wkr.kindex == cpu_to_le16(0xffff)) {
j += sprintf(ptr+j, "Tx key = %d\n",
(int)wkr.mac[0]);
} else {
j += sprintf(ptr+j, "Key %d set with length = %d\n",
- (int)wkr.kindex, (int)wkr.klen);
+ le16_to_cpu(wkr.kindex),
+ le16_to_cpu(wkr.klen));
}
readWepKeyRid(ai, &wkr, 0, 1);
} while((lastindex != wkr.kindex) && (j < 180-30));
@@ -5375,7 +5304,8 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) {
return 0;
}
-static int proc_SSID_open( struct inode *inode, struct file *file ) {
+static int proc_SSID_open(struct inode *inode, struct file *file)
+{
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
@@ -5393,7 +5323,8 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) {
}
data->writelen = 0;
data->maxwritelen = 33*3;
- if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) {
+ /* allocate maxwritelen + 1; we'll want a sentinel */
+ if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) {
kfree (data->rbuffer);
kfree (file->private_data);
return -ENOMEM;
@@ -5402,14 +5333,15 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) {
readSsidRid(ai, &SSID_rid);
ptr = data->rbuffer;
- for( i = 0; i < 3; i++ ) {
+ for (i = 0; i < 3; i++) {
int j;
- if ( !SSID_rid.ssids[i].len ) break;
- for( j = 0; j < 32 &&
- j < SSID_rid.ssids[i].len &&
- SSID_rid.ssids[i].ssid[j]; j++ ) {
+ size_t len = le16_to_cpu(SSID_rid.ssids[i].len);
+ if (!len)
+ break;
+ if (len > 32)
+ len = 32;
+ for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++)
*ptr++ = SSID_rid.ssids[i].ssid[j];
- }
*ptr++ = '\n';
}
*ptr = '\0';
@@ -5505,14 +5437,14 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
Since it is a rare condition, we'll just live with it, otherwise
we have to add a spin lock... */
rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
- while(rc == 0 && BSSList_rid.index != 0xffff) {
+ while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
ptr += sprintf(ptr, "%s %*s rssi = %d",
print_mac(mac, BSSList_rid.bssid),
(int)BSSList_rid.ssidLen,
BSSList_rid.ssid,
- (int)BSSList_rid.dBm);
+ le16_to_cpu(BSSList_rid.dBm));
ptr += sprintf(ptr, " channel = %d %s %s %s %s\n",
- (int)BSSList_rid.dsChannel,
+ le16_to_cpu(BSSList_rid.dsChannel),
BSSList_rid.cap & CAP_ESS ? "ESS" : "",
BSSList_rid.cap & CAP_IBSS ? "adhoc" : "",
BSSList_rid.cap & CAP_PRIVACY ? "wep" : "",
@@ -5780,21 +5712,27 @@ static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm)
static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid)
{
int quality = 0;
+ u16 sq;
- if ((status_rid->mode & 0x3f) == 0x3f && (cap_rid->hardCap & 8)) {
- if (memcmp(cap_rid->prodName, "350", 3))
- if (status_rid->signalQuality > 0x20)
- quality = 0;
- else
- quality = 0x20 - status_rid->signalQuality;
+ if ((status_rid->mode & cpu_to_le16(0x3f)) != cpu_to_le16(0x3f))
+ return 0;
+
+ if (!(cap_rid->hardCap & cpu_to_le16(8)))
+ return 0;
+
+ sq = le16_to_cpu(status_rid->signalQuality);
+ if (memcmp(cap_rid->prodName, "350", 3))
+ if (sq > 0x20)
+ quality = 0;
else
- if (status_rid->signalQuality > 0xb0)
- quality = 0;
- else if (status_rid->signalQuality < 0x10)
- quality = 0xa0;
- else
- quality = 0xb0 - status_rid->signalQuality;
- }
+ quality = 0x20 - sq;
+ else
+ if (sq > 0xb0)
+ quality = 0;
+ else if (sq < 0x10)
+ quality = 0xa0;
+ else
+ quality = 0xb0 - sq;
return quality;
}
@@ -5852,7 +5790,7 @@ static int airo_set_freq(struct net_device *dev,
} else {
readConfigRid(local, 1);
/* Yes ! We can set it !!! */
- local->config.channelSet = (u16) channel;
+ local->config.channelSet = cpu_to_le16(channel);
set_bit (FLAG_COMMIT, &local->flags);
}
}
@@ -5873,12 +5811,12 @@ static int airo_get_freq(struct net_device *dev,
int ch;
readConfigRid(local, 1);
- if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
+ if ((local->config.opmode & MODE_CFG_MASK) == MODE_STA_ESS)
status_rid.channel = local->config.channelSet;
else
readStatusRid(local, &status_rid, 1);
- ch = (int)status_rid.channel;
+ ch = le16_to_cpu(status_rid.channel);
if((ch > 0) && (ch < 15)) {
fwrq->m = frequency_list[ch - 1] * 100000;
fwrq->e = 1;
@@ -5925,9 +5863,9 @@ static int airo_set_essid(struct net_device *dev,
memset(SSID_rid.ssids[index].ssid, 0,
sizeof(SSID_rid.ssids[index].ssid));
memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length);
- SSID_rid.ssids[index].len = dwrq->length;
+ SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length);
}
- SSID_rid.len = sizeof(SSID_rid);
+ SSID_rid.len = cpu_to_le16(sizeof(SSID_rid));
/* Write it to the card */
disable_MAC(local, 1);
writeSsidRid(local, &SSID_rid, 1);
@@ -5954,11 +5892,11 @@ static int airo_get_essid(struct net_device *dev,
* get the relevant SSID from the SSID list... */
/* Get the current SSID */
- memcpy(extra, status_rid.SSID, status_rid.SSIDlen);
+ memcpy(extra, status_rid.SSID, le16_to_cpu(status_rid.SSIDlen));
/* If none, we may want to get the one that was set */
/* Push it out ! */
- dwrq->length = status_rid.SSIDlen;
+ dwrq->length = le16_to_cpu(status_rid.SSIDlen);
dwrq->flags = 1; /* active */
return 0;
@@ -5992,7 +5930,7 @@ static int airo_set_wap(struct net_device *dev,
up(&local->sem);
} else {
memset(&APList_rid, 0, sizeof(APList_rid));
- APList_rid.len = sizeof(APList_rid);
+ APList_rid.len = cpu_to_le16(sizeof(APList_rid));
memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN);
disable_MAC(local, 1);
writeAPListRid(local, &APList_rid, 1);
@@ -6148,7 +6086,7 @@ static int airo_get_rate(struct net_device *dev,
readStatusRid(local, &status_rid, 1);
- vwrq->value = status_rid.currentXmitRate * 500000;
+ vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
/* If more than one rate, set auto */
readConfigRid(local, 1);
vwrq->fixed = (local->config.rates[1] == 0);
@@ -6174,7 +6112,7 @@ static int airo_set_rts(struct net_device *dev,
return -EINVAL;
}
readConfigRid(local, 1);
- local->config.rtsThres = rthr;
+ local->config.rtsThres = cpu_to_le16(rthr);
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
@@ -6192,7 +6130,7 @@ static int airo_get_rts(struct net_device *dev,
struct airo_info *local = dev->priv;
readConfigRid(local, 1);
- vwrq->value = local->config.rtsThres;
+ vwrq->value = le16_to_cpu(local->config.rtsThres);
vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
@@ -6218,7 +6156,7 @@ static int airo_set_frag(struct net_device *dev,
}
fthr &= ~0x1; /* Get an even value - is it really needed ??? */
readConfigRid(local, 1);
- local->config.fragThresh = (u16)fthr;
+ local->config.fragThresh = cpu_to_le16(fthr);
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
@@ -6236,7 +6174,7 @@ static int airo_get_frag(struct net_device *dev,
struct airo_info *local = dev->priv;
readConfigRid(local, 1);
- vwrq->value = local->config.fragThresh;
+ vwrq->value = le16_to_cpu(local->config.fragThresh);
vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
vwrq->fixed = 1;
@@ -6256,42 +6194,42 @@ static int airo_set_mode(struct net_device *dev,
int reset = 0;
readConfigRid(local, 1);
- if ((local->config.rmode & 0xff) >= RXMODE_RFMON)
+ if (sniffing_mode(local))
reset = 1;
switch(*uwrq) {
case IW_MODE_ADHOC:
- local->config.opmode &= 0xFF00;
+ local->config.opmode &= ~MODE_CFG_MASK;
local->config.opmode |= MODE_STA_IBSS;
- local->config.rmode &= 0xfe00;
+ local->config.rmode &= ~RXMODE_FULL_MASK;
local->config.scanMode = SCANMODE_ACTIVE;
clear_bit (FLAG_802_11, &local->flags);
break;
case IW_MODE_INFRA:
- local->config.opmode &= 0xFF00;
+ local->config.opmode &= ~MODE_CFG_MASK;
local->config.opmode |= MODE_STA_ESS;
- local->config.rmode &= 0xfe00;
+ local->config.rmode &= ~RXMODE_FULL_MASK;
local->config.scanMode = SCANMODE_ACTIVE;
clear_bit (FLAG_802_11, &local->flags);
break;
case IW_MODE_MASTER:
- local->config.opmode &= 0xFF00;
+ local->config.opmode &= ~MODE_CFG_MASK;
local->config.opmode |= MODE_AP;
- local->config.rmode &= 0xfe00;
+ local->config.rmode &= ~RXMODE_FULL_MASK;
local->config.scanMode = SCANMODE_ACTIVE;
clear_bit (FLAG_802_11, &local->flags);
break;
case IW_MODE_REPEAT:
- local->config.opmode &= 0xFF00;
+ local->config.opmode &= ~MODE_CFG_MASK;
local->config.opmode |= MODE_AP_RPTR;
- local->config.rmode &= 0xfe00;
+ local->config.rmode &= ~RXMODE_FULL_MASK;
local->config.scanMode = SCANMODE_ACTIVE;
clear_bit (FLAG_802_11, &local->flags);
break;
case IW_MODE_MONITOR:
- local->config.opmode &= 0xFF00;
+ local->config.opmode &= ~MODE_CFG_MASK;
local->config.opmode |= MODE_STA_ESS;
- local->config.rmode &= 0xfe00;
+ local->config.rmode &= ~RXMODE_FULL_MASK;
local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER;
local->config.scanMode = SCANMODE_PASSIVE;
set_bit (FLAG_802_11, &local->flags);
@@ -6319,7 +6257,7 @@ static int airo_get_mode(struct net_device *dev,
readConfigRid(local, 1);
/* If not managed, assume it's ad-hoc */
- switch (local->config.opmode & 0xFF) {
+ switch (local->config.opmode & MODE_CFG_MASK) {
case MODE_STA_ESS:
*uwrq = IW_MODE_INFRA;
break;
@@ -6336,6 +6274,13 @@ static int airo_get_mode(struct net_device *dev,
return 0;
}
+static inline int valid_index(CapabilityRid *p, int index)
+{
+ if (index < 0)
+ return 0;
+ return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
+}
+
/*------------------------------------------------------------------*/
/*
* Wireless Handler : set Encryption Key
@@ -6348,12 +6293,12 @@ static int airo_set_encode(struct net_device *dev,
struct airo_info *local = dev->priv;
CapabilityRid cap_rid; /* Card capability info */
int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
- u16 currentAuthType = local->config.authType;
+ __le16 currentAuthType = local->config.authType;
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this...
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
} */
readConfigRid(local, 1);
@@ -6373,7 +6318,7 @@ static int airo_set_encode(struct net_device *dev,
return -EINVAL;
}
/* Check the index (none -> use current) */
- if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4:1)))
+ if (!valid_index(&cap_rid, index))
index = current_index;
/* Set the length */
if (dwrq->length > MIN_KEY_SIZE)
@@ -6403,13 +6348,12 @@ static int airo_set_encode(struct net_device *dev,
} else {
/* Do we want to just set the transmit key index ? */
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
- if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
+ if (valid_index(&cap_rid, index)) {
set_wep_key(local, index, NULL, 0, perm, 1);
} else
/* Don't complain if only change the mode */
- if(!dwrq->flags & IW_ENCODE_MODE) {
+ if (!(dwrq->flags & IW_ENCODE_MODE))
return -EINVAL;
- }
}
/* Read the flags */
if(dwrq->flags & IW_ENCODE_DISABLED)
@@ -6439,7 +6383,7 @@ static int airo_get_encode(struct net_device *dev,
/* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1);
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
}
readConfigRid(local, 1);
@@ -6461,7 +6405,7 @@ static int airo_get_encode(struct net_device *dev,
memset(extra, 0, 16);
/* Which key do we want ? -1 -> tx index */
- if ((index < 0) || (index >= ((cap_rid.softCap & 0x80) ? 4 : 1)))
+ if (!valid_index(&cap_rid, index))
index = get_wep_key(local, 0xffff);
dwrq->flags |= index + 1;
/* Copy the key to the user buffer */
@@ -6486,14 +6430,14 @@ static int airo_set_encodeext(struct net_device *dev,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
CapabilityRid cap_rid; /* Card capability info */
int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
- u16 currentAuthType = local->config.authType;
+ __le16 currentAuthType = local->config.authType;
int idx, key_len, alg = ext->alg, set_key = 1;
wep_key_t key;
/* Is WEP supported ? */
readCapabilityRid(local, &cap_rid, 1);
/* Older firmware doesn't support this...
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
} */
readConfigRid(local, 1);
@@ -6501,7 +6445,7 @@ static int airo_set_encodeext(struct net_device *dev,
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ if (!valid_index(&cap_rid, idx - 1))
return -EINVAL;
idx--;
} else
@@ -6575,7 +6519,7 @@ static int airo_get_encodeext(struct net_device *dev,
/* Is it supported ? */
readCapabilityRid(local, &cap_rid, 1);
- if(!(cap_rid.softCap & 2)) {
+ if(!(cap_rid.softCap & cpu_to_le16(2))) {
return -EOPNOTSUPP;
}
readConfigRid(local, 1);
@@ -6586,7 +6530,7 @@ static int airo_get_encodeext(struct net_device *dev,
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+ if (!valid_index(&cap_rid, idx - 1))
return -EINVAL;
idx--;
} else
@@ -6632,7 +6576,7 @@ static int airo_set_auth(struct net_device *dev,
{
struct airo_info *local = dev->priv;
struct iw_param *param = &wrqu->param;
- u16 currentAuthType = local->config.authType;
+ __le16 currentAuthType = local->config.authType;
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
@@ -6700,7 +6644,7 @@ static int airo_get_auth(struct net_device *dev,
{
struct airo_info *local = dev->priv;
struct iw_param *param = &wrqu->param;
- u16 currentAuthType = local->config.authType;
+ __le16 currentAuthType = local->config.authType;
switch (param->flags & IW_AUTH_INDEX) {
case IW_AUTH_DROP_UNENCRYPTED:
@@ -6751,6 +6695,7 @@ static int airo_set_txpow(struct net_device *dev,
CapabilityRid cap_rid; /* Card capability info */
int i;
int rc = -EINVAL;
+ __le16 v = cpu_to_le16(vwrq->value);
readCapabilityRid(local, &cap_rid, 1);
@@ -6764,9 +6709,9 @@ static int airo_set_txpow(struct net_device *dev,
}
clear_bit (FLAG_RADIO_OFF, &local->flags);
for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
- if ((vwrq->value==cap_rid.txPowerLevels[i])) {
+ if (v == cap_rid.txPowerLevels[i]) {
readConfigRid(local, 1);
- local->config.txPower = vwrq->value;
+ local->config.txPower = v;
set_bit (FLAG_COMMIT, &local->flags);
rc = -EINPROGRESS; /* Call commit handler */
break;
@@ -6786,7 +6731,7 @@ static int airo_get_txpow(struct net_device *dev,
struct airo_info *local = dev->priv;
readConfigRid(local, 1);
- vwrq->value = local->config.txPower;
+ vwrq->value = le16_to_cpu(local->config.txPower);
vwrq->fixed = 1; /* No power control */
vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags);
vwrq->flags = IW_TXPOW_MWATT;
@@ -6811,20 +6756,21 @@ static int airo_set_retry(struct net_device *dev,
}
readConfigRid(local, 1);
if(vwrq->flags & IW_RETRY_LIMIT) {
+ __le16 v = cpu_to_le16(vwrq->value);
if(vwrq->flags & IW_RETRY_LONG)
- local->config.longRetryLimit = vwrq->value;
+ local->config.longRetryLimit = v;
else if (vwrq->flags & IW_RETRY_SHORT)
- local->config.shortRetryLimit = vwrq->value;
+ local->config.shortRetryLimit = v;
else {
/* No modifier : set both */
- local->config.longRetryLimit = vwrq->value;
- local->config.shortRetryLimit = vwrq->value;
+ local->config.longRetryLimit = v;
+ local->config.shortRetryLimit = v;
}
set_bit (FLAG_COMMIT, &local->flags);
rc = -EINPROGRESS; /* Call commit handler */
}
if(vwrq->flags & IW_RETRY_LIFETIME) {
- local->config.txLifetime = vwrq->value / 1024;
+ local->config.txLifetime = cpu_to_le16(vwrq->value / 1024);
set_bit (FLAG_COMMIT, &local->flags);
rc = -EINPROGRESS; /* Call commit handler */
}
@@ -6848,14 +6794,14 @@ static int airo_get_retry(struct net_device *dev,
/* Note : by default, display the min retry number */
if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
vwrq->flags = IW_RETRY_LIFETIME;
- vwrq->value = (int)local->config.txLifetime * 1024;
+ vwrq->value = le16_to_cpu(local->config.txLifetime) * 1024;
} else if((vwrq->flags & IW_RETRY_LONG)) {
vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
- vwrq->value = (int)local->config.longRetryLimit;
+ vwrq->value = le16_to_cpu(local->config.longRetryLimit);
} else {
vwrq->flags = IW_RETRY_LIMIT;
- vwrq->value = (int)local->config.shortRetryLimit;
- if((int)local->config.shortRetryLimit != (int)local->config.longRetryLimit)
+ vwrq->value = le16_to_cpu(local->config.shortRetryLimit);
+ if(local->config.shortRetryLimit != local->config.longRetryLimit)
vwrq->flags |= IW_RETRY_SHORT;
}
@@ -6936,16 +6882,17 @@ static int airo_get_range(struct net_device *dev,
range->min_frag = 256;
range->max_frag = AIRO_DEF_MTU;
- if(cap_rid.softCap & 2) {
+ if(cap_rid.softCap & cpu_to_le16(2)) {
// WEP: RC4 40 bits
range->encoding_size[0] = 5;
// RC4 ~128 bits
- if (cap_rid.softCap & 0x100) {
+ if (cap_rid.softCap & cpu_to_le16(0x100)) {
range->encoding_size[1] = 13;
range->num_encoding_sizes = 2;
} else
range->num_encoding_sizes = 1;
- range->max_encoding_tokens = (cap_rid.softCap & 0x80) ? 4 : 1;
+ range->max_encoding_tokens =
+ cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1;
} else {
range->num_encoding_sizes = 0;
range->max_encoding_tokens = 0;
@@ -6960,7 +6907,7 @@ static int airo_get_range(struct net_device *dev,
/* Transmit Power - values are in mW */
for(i = 0 ; i < 8 ; i++) {
- range->txpower[i] = cap_rid.txPowerLevels[i];
+ range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]);
if(range->txpower[i] == 0)
break;
}
@@ -6999,38 +6946,37 @@ static int airo_set_power(struct net_device *dev,
readConfigRid(local, 1);
if (vwrq->disabled) {
- if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
+ if (sniffing_mode(local))
return -EINVAL;
- }
local->config.powerSaveMode = POWERSAVE_CAM;
- local->config.rmode &= 0xFF00;
+ local->config.rmode &= ~RXMODE_MASK;
local->config.rmode |= RXMODE_BC_MC_ADDR;
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
}
if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- local->config.fastListenDelay = (vwrq->value + 500) / 1024;
+ local->config.fastListenDelay = cpu_to_le16((vwrq->value + 500) / 1024);
local->config.powerSaveMode = POWERSAVE_PSPCAM;
set_bit (FLAG_COMMIT, &local->flags);
} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
- local->config.fastListenInterval = local->config.listenInterval = (vwrq->value + 500) / 1024;
+ local->config.fastListenInterval =
+ local->config.listenInterval =
+ cpu_to_le16((vwrq->value + 500) / 1024);
local->config.powerSaveMode = POWERSAVE_PSPCAM;
set_bit (FLAG_COMMIT, &local->flags);
}
switch (vwrq->flags & IW_POWER_MODE) {
case IW_POWER_UNICAST_R:
- if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
+ if (sniffing_mode(local))
return -EINVAL;
- }
- local->config.rmode &= 0xFF00;
+ local->config.rmode &= ~RXMODE_MASK;
local->config.rmode |= RXMODE_ADDR;
set_bit (FLAG_COMMIT, &local->flags);
break;
case IW_POWER_ALL_R:
- if ((local->config.rmode & 0xFF) >= RXMODE_RFMON) {
+ if (sniffing_mode(local))
return -EINVAL;
- }
- local->config.rmode &= 0xFF00;
+ local->config.rmode &= ~RXMODE_MASK;
local->config.rmode |= RXMODE_BC_MC_ADDR;
set_bit (FLAG_COMMIT, &local->flags);
case IW_POWER_ON:
@@ -7054,20 +7000,20 @@ static int airo_get_power(struct net_device *dev,
char *extra)
{
struct airo_info *local = dev->priv;
- int mode;
+ __le16 mode;
readConfigRid(local, 1);
mode = local->config.powerSaveMode;
if ((vwrq->disabled = (mode == POWERSAVE_CAM)))
return 0;
if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- vwrq->value = (int)local->config.fastListenDelay * 1024;
+ vwrq->value = le16_to_cpu(local->config.fastListenDelay) * 1024;
vwrq->flags = IW_POWER_TIMEOUT;
} else {
- vwrq->value = (int)local->config.fastListenInterval * 1024;
+ vwrq->value = le16_to_cpu(local->config.fastListenInterval) * 1024;
vwrq->flags = IW_POWER_PERIOD;
}
- if ((local->config.rmode & 0xFF) == RXMODE_ADDR)
+ if ((local->config.rmode & RXMODE_MASK) == RXMODE_ADDR)
vwrq->flags |= IW_POWER_UNICAST_R;
else
vwrq->flags |= IW_POWER_ALL_R;
@@ -7087,7 +7033,8 @@ static int airo_set_sens(struct net_device *dev,
struct airo_info *local = dev->priv;
readConfigRid(local, 1);
- local->config.rssiThreshold = vwrq->disabled ? RSSI_DEFAULT : vwrq->value;
+ local->config.rssiThreshold =
+ cpu_to_le16(vwrq->disabled ? RSSI_DEFAULT : vwrq->value);
set_bit (FLAG_COMMIT, &local->flags);
return -EINPROGRESS; /* Call commit handler */
@@ -7105,7 +7052,7 @@ static int airo_get_sens(struct net_device *dev,
struct airo_info *local = dev->priv;
readConfigRid(local, 1);
- vwrq->value = local->config.rssiThreshold;
+ vwrq->value = le16_to_cpu(local->config.rssiThreshold);
vwrq->disabled = (vwrq->value == 0);
vwrq->fixed = 1;
@@ -7130,26 +7077,28 @@ static int airo_get_aplist(struct net_device *dev,
int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
for (i = 0; i < IW_MAX_AP; i++) {
+ u16 dBm;
if (readBSSListRid(local, loseSync, &BSSList))
break;
loseSync = 0;
memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN);
address[i].sa_family = ARPHRD_ETHER;
+ dBm = le16_to_cpu(BSSList.dBm);
if (local->rssi) {
- qual[i].level = 0x100 - BSSList.dBm;
- qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
+ qual[i].level = 0x100 - dBm;
+ qual[i].qual = airo_dbm_to_pct(local->rssi, dBm);
qual[i].updated = IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
| IW_QUAL_DBM;
} else {
- qual[i].level = (BSSList.dBm + 321) / 2;
+ qual[i].level = (dBm + 321) / 2;
qual[i].qual = 0;
qual[i].updated = IW_QUAL_QUAL_INVALID
| IW_QUAL_LEVEL_UPDATED
| IW_QUAL_DBM;
}
qual[i].noise = local->wstats.qual.noise;
- if (BSSList.index == 0xffff)
+ if (BSSList.index == cpu_to_le16(0xffff))
break;
}
if (!i) {
@@ -7240,10 +7189,11 @@ static inline char *airo_translate_scan(struct net_device *dev,
{
struct airo_info *ai = dev->priv;
struct iw_event iwe; /* Temporary buffer */
- u16 capabilities;
+ __le16 capabilities;
char * current_val; /* For rates */
int i;
char * buf;
+ u16 dBm;
/* First entry *MUST* be the AP MAC address */
iwe.cmd = SIOCGIWAP;
@@ -7263,7 +7213,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
/* Add mode */
iwe.cmd = SIOCGIWMODE;
- capabilities = le16_to_cpu(bss->cap);
+ capabilities = bss->cap;
if(capabilities & (CAP_ESS | CAP_IBSS)) {
if(capabilities & CAP_ESS)
iwe.u.mode = IW_MODE_MASTER;
@@ -7282,16 +7232,18 @@ static inline char *airo_translate_scan(struct net_device *dev,
iwe.u.freq.e = 1;
current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+ dBm = le16_to_cpu(bss->dBm);
+
/* Add quality statistics */
iwe.cmd = IWEVQUAL;
if (ai->rssi) {
- iwe.u.qual.level = 0x100 - bss->dBm;
- iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
+ iwe.u.qual.level = 0x100 - dBm;
+ iwe.u.qual.qual = airo_dbm_to_pct(ai->rssi, dBm);
iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
| IW_QUAL_LEVEL_UPDATED
| IW_QUAL_DBM;
} else {
- iwe.u.qual.level = (bss->dBm + 321) / 2;
+ iwe.u.qual.level = (dBm + 321) / 2;
iwe.u.qual.qual = 0;
iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
| IW_QUAL_LEVEL_UPDATED
@@ -7670,7 +7622,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
StatusRid status_rid;
StatsRid stats_rid;
CapabilityRid cap_rid;
- u32 *vals = stats_rid.vals;
+ __le32 *vals = stats_rid.vals;
/* Get stats out of the card */
clear_bit(JOB_WSTATS, &local->jobs);
@@ -7684,18 +7636,22 @@ static void airo_read_wireless_stats(struct airo_info *local)
up(&local->sem);
/* The status */
- local->wstats.status = status_rid.mode;
+ local->wstats.status = le16_to_cpu(status_rid.mode);
/* Signal quality and co */
if (local->rssi) {
- local->wstats.qual.level = airo_rssi_to_dbm( local->rssi, status_rid.sigQuality );
+ local->wstats.qual.level =
+ airo_rssi_to_dbm(local->rssi,
+ le16_to_cpu(status_rid.sigQuality));
/* normalizedSignalStrength appears to be a percentage */
- local->wstats.qual.qual = status_rid.normalizedSignalStrength;
+ local->wstats.qual.qual =
+ le16_to_cpu(status_rid.normalizedSignalStrength);
} else {
- local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
+ local->wstats.qual.level =
+ (le16_to_cpu(status_rid.normalizedSignalStrength) + 321) / 2;
local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
}
- if (status_rid.len >= 124) {
+ if (le16_to_cpu(status_rid.len) >= 124) {
local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
} else {
@@ -7705,12 +7661,15 @@ static void airo_read_wireless_stats(struct airo_info *local)
/* Packets discarded in the wireless adapter due to wireless
* specific problems */
- local->wstats.discard.nwid = vals[56] + vals[57] + vals[58];/* SSID Mismatch */
- local->wstats.discard.code = vals[6];/* RxWepErr */
- local->wstats.discard.fragment = vals[30];
- local->wstats.discard.retries = vals[10];
- local->wstats.discard.misc = vals[1] + vals[32];
- local->wstats.miss.beacon = vals[34];
+ local->wstats.discard.nwid = le32_to_cpu(vals[56]) +
+ le32_to_cpu(vals[57]) +
+ le32_to_cpu(vals[58]); /* SSID Mismatch */
+ local->wstats.discard.code = le32_to_cpu(vals[6]);/* RxWepErr */
+ local->wstats.discard.fragment = le32_to_cpu(vals[30]);
+ local->wstats.discard.retries = le32_to_cpu(vals[10]);
+ local->wstats.discard.misc = le32_to_cpu(vals[1]) +
+ le32_to_cpu(vals[32]);
+ local->wstats.miss.beacon = le32_to_cpu(vals[34]);
}
static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
@@ -7896,7 +7855,7 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
if (test_bit(FLAG_MIC_CAPABLE, &ai->flags))
cfg->opmode |= MODE_MIC;
- if ((cfg->opmode & 0xFF) == MODE_STA_IBSS)
+ if ((cfg->opmode & MODE_CFG_MASK) == MODE_STA_IBSS)
set_bit (FLAG_ADHOC, &ai->flags);
else
clear_bit (FLAG_ADHOC, &ai->flags);
diff --git a/drivers/net/wireless/ath5k/Makefile b/drivers/net/wireless/ath5k/Makefile
new file mode 100644
index 000000000000..321641f99e13
--- /dev/null
+++ b/drivers/net/wireless/ath5k/Makefile
@@ -0,0 +1,2 @@
+ath5k-objs = base.o hw.o regdom.o initvals.o phy.o debug.o
+obj-$(CONFIG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
new file mode 100644
index 000000000000..c79066b38d3b
--- /dev/null
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -0,0 +1,1173 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _ATH5K_H
+#define _ATH5K_H
+
+/* Set this to 1 to disable regulatory domain restrictions for channel tests.
+ * WARNING: This is for debuging only and has side effects (eg. scan takes too
+ * long and results timeouts). It's also illegal to tune to some of the
+ * supported frequencies in some countries, so use this at your own risk,
+ * you've been warned. */
+#define CHAN_DEBUG 0
+
+#include <linux/io.h>
+#include <linux/types.h>
+#include <net/mac80211.h>
+
+#include "hw.h"
+#include "regdom.h"
+
+/* PCI IDs */
+#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */
+#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */
+#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */
+#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */
+#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */
+#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */
+#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */
+#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */
+#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */
+#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */
+#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */
+#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */
+#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */
+
+/****************************\
+ GENERIC DRIVER DEFINITIONS
+\****************************/
+
+#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__)
+
+#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \
+ printk(_level "ath5k %s: " _fmt, \
+ ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \
+ ##__VA_ARGS__)
+
+#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \
+ if (net_ratelimit()) \
+ ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \
+ } while (0)
+
+#define ATH5K_INFO(_sc, _fmt, ...) \
+ ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__)
+
+#define ATH5K_WARN(_sc, _fmt, ...) \
+ ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__)
+
+#define ATH5K_ERR(_sc, _fmt, ...) \
+ ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__)
+
+/*
+ * Some tuneable values (these should be changeable by the user)
+ */
+#define AR5K_TUNE_DMA_BEACON_RESP 2
+#define AR5K_TUNE_SW_BEACON_RESP 10
+#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
+#define AR5K_TUNE_RADAR_ALERT false
+#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
+#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1)
+#define AR5K_TUNE_REGISTER_TIMEOUT 20000
+/* Register for RSSI threshold has a mask of 0xff, so 255 seems to
+ * be the max value. */
+#define AR5K_TUNE_RSSI_THRES 129
+/* This must be set when setting the RSSI threshold otherwise it can
+ * prevent a reset. If AR5K_RSSI_THR is read after writing to it
+ * the BMISS_THRES will be seen as 0, seems harware doesn't keep
+ * track of it. Max value depends on harware. For AR5210 this is just 7.
+ * For AR5211+ this seems to be up to 255. */
+#define AR5K_TUNE_BMISS_THRES 7
+#define AR5K_TUNE_REGISTER_DWELL_TIME 20000
+#define AR5K_TUNE_BEACON_INTERVAL 100
+#define AR5K_TUNE_AIFS 2
+#define AR5K_TUNE_AIFS_11B 2
+#define AR5K_TUNE_AIFS_XR 0
+#define AR5K_TUNE_CWMIN 15
+#define AR5K_TUNE_CWMIN_11B 31
+#define AR5K_TUNE_CWMIN_XR 3
+#define AR5K_TUNE_CWMAX 1023
+#define AR5K_TUNE_CWMAX_11B 1023
+#define AR5K_TUNE_CWMAX_XR 7
+#define AR5K_TUNE_NOISE_FLOOR -72
+#define AR5K_TUNE_MAX_TXPOWER 60
+#define AR5K_TUNE_DEFAULT_TXPOWER 30
+#define AR5K_TUNE_TPC_TXPOWER true
+#define AR5K_TUNE_ANT_DIVERSITY true
+#define AR5K_TUNE_HWTXTRIES 4
+
+/* token to use for aifs, cwmin, cwmax in MadWiFi */
+#define AR5K_TXQ_USEDEFAULT ((u32) -1)
+
+/* GENERIC CHIPSET DEFINITIONS */
+
+/* MAC Chips */
+enum ath5k_version {
+ AR5K_AR5210 = 0,
+ AR5K_AR5211 = 1,
+ AR5K_AR5212 = 2,
+};
+
+/* PHY Chips */
+enum ath5k_radio {
+ AR5K_RF5110 = 0,
+ AR5K_RF5111 = 1,
+ AR5K_RF5112 = 2,
+ AR5K_RF5413 = 3,
+};
+
+/*
+ * Common silicon revision/version values
+ */
+
+enum ath5k_srev_type {
+ AR5K_VERSION_VER,
+ AR5K_VERSION_RAD,
+};
+
+struct ath5k_srev_name {
+ const char *sr_name;
+ enum ath5k_srev_type sr_type;
+ u_int sr_val;
+};
+
+#define AR5K_SREV_UNKNOWN 0xffff
+
+#define AR5K_SREV_VER_AR5210 0x00
+#define AR5K_SREV_VER_AR5311 0x10
+#define AR5K_SREV_VER_AR5311A 0x20
+#define AR5K_SREV_VER_AR5311B 0x30
+#define AR5K_SREV_VER_AR5211 0x40
+#define AR5K_SREV_VER_AR5212 0x50
+#define AR5K_SREV_VER_AR5213 0x55
+#define AR5K_SREV_VER_AR5213A 0x59
+#define AR5K_SREV_VER_AR2424 0xa0
+#define AR5K_SREV_VER_AR5424 0xa3
+#define AR5K_SREV_VER_AR5413 0xa4
+#define AR5K_SREV_VER_AR5414 0xa5
+#define AR5K_SREV_VER_AR5416 0xc0 /* ? */
+#define AR5K_SREV_VER_AR5418 0xca
+
+#define AR5K_SREV_RAD_5110 0x00
+#define AR5K_SREV_RAD_5111 0x10
+#define AR5K_SREV_RAD_5111A 0x15
+#define AR5K_SREV_RAD_2111 0x20
+#define AR5K_SREV_RAD_5112 0x30
+#define AR5K_SREV_RAD_5112A 0x35
+#define AR5K_SREV_RAD_2112 0x40
+#define AR5K_SREV_RAD_2112A 0x45
+#define AR5K_SREV_RAD_SC1 0x63 /* Found on 5413/5414 */
+#define AR5K_SREV_RAD_SC2 0xa2 /* Found on 2424/5424 */
+#define AR5K_SREV_RAD_5133 0xc0 /* MIMO found on 5418 */
+
+/* IEEE defs */
+
+#define IEEE80211_MAX_LEN 2500
+
+/* TODO add support to mac80211 for vendor-specific rates and modes */
+
+/*
+ * Some of this information is based on Documentation from:
+ *
+ * http://madwifi.org/wiki/ChipsetFeatures/SuperAG
+ *
+ * Modulation for Atheros' eXtended Range - range enhancing extension that is
+ * supposed to double the distance an Atheros client device can keep a
+ * connection with an Atheros access point. This is achieved by increasing
+ * the receiver sensitivity up to, -105dBm, which is about 20dB above what
+ * the 802.11 specifications demand. In addition, new (proprietary) data rates
+ * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s.
+ *
+ * Please note that can you either use XR or TURBO but you cannot use both,
+ * they are exclusive.
+ *
+ */
+#define MODULATION_XR 0x00000200
+/*
+ * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a
+ * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s
+ * signaling rate achieved through the bonding of two 54Mbit/s 802.11g
+ * channels. To use this feature your Access Point must also suport it.
+ * There is also a distinction between "static" and "dynamic" turbo modes:
+ *
+ * - Static: is the dumb version: devices set to this mode stick to it until
+ * the mode is turned off.
+ * - Dynamic: is the intelligent version, the network decides itself if it
+ * is ok to use turbo. As soon as traffic is detected on adjacent channels
+ * (which would get used in turbo mode), or when a non-turbo station joins
+ * the network, turbo mode won't be used until the situation changes again.
+ * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which
+ * monitors the used radio band in order to decide whether turbo mode may
+ * be used or not.
+ *
+ * This article claims Super G sticks to bonding of channels 5 and 6 for
+ * USA:
+ *
+ * http://www.pcworld.com/article/id,113428-page,1/article.html
+ *
+ * The channel bonding seems to be driver specific though. In addition to
+ * deciding what channels will be used, these "Turbo" modes are accomplished
+ * by also enabling the following features:
+ *
+ * - Bursting: allows multiple frames to be sent at once, rather than pausing
+ * after each frame. Bursting is a standards-compliant feature that can be
+ * used with any Access Point.
+ * - Fast frames: increases the amount of information that can be sent per
+ * frame, also resulting in a reduction of transmission overhead. It is a
+ * proprietary feature that needs to be supported by the Access Point.
+ * - Compression: data frames are compressed in real time using a Lempel Ziv
+ * algorithm. This is done transparently. Once this feature is enabled,
+ * compression and decompression takes place inside the chipset, without
+ * putting additional load on the host CPU.
+ *
+ */
+#define MODULATION_TURBO 0x00000080
+
+enum ath5k_vendor_mode {
+ MODE_ATHEROS_TURBO = NUM_IEEE80211_MODES+1,
+ MODE_ATHEROS_TURBOG
+};
+
+/* Number of supported mac80211 enum ieee80211_phymode modes by this driver */
+#define NUM_DRIVER_MODES 3
+
+/* adding this flag to rate_code enables short preamble, see ar5212_reg.h */
+#define AR5K_SET_SHORT_PREAMBLE 0x04
+
+#define HAS_SHPREAMBLE(_ix) (rt->rates[_ix].modulation == IEEE80211_RATE_CCK_2)
+#define SHPREAMBLE_FLAG(_ix) (HAS_SHPREAMBLE(_ix) ? AR5K_SET_SHORT_PREAMBLE : 0)
+
+/****************\
+ TX DEFINITIONS
+\****************/
+
+/*
+ * Tx Descriptor
+ */
+struct ath5k_tx_status {
+ u16 ts_seqnum;
+ u16 ts_tstamp;
+ u8 ts_status;
+ u8 ts_rate;
+ s8 ts_rssi;
+ u8 ts_shortretry;
+ u8 ts_longretry;
+ u8 ts_virtcol;
+ u8 ts_antenna;
+};
+
+#define AR5K_TXSTAT_ALTRATE 0x80
+#define AR5K_TXERR_XRETRY 0x01
+#define AR5K_TXERR_FILT 0x02
+#define AR5K_TXERR_FIFO 0x04
+
+/**
+ * enum ath5k_tx_queue - Queue types used to classify tx queues.
+ * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue
+ * @AR5K_TX_QUEUE_DATA: A normal data queue
+ * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue
+ * @AR5K_TX_QUEUE_BEACON: The beacon queue
+ * @AR5K_TX_QUEUE_CAB: The after-beacon queue
+ * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue
+ */
+enum ath5k_tx_queue {
+ AR5K_TX_QUEUE_INACTIVE = 0,
+ AR5K_TX_QUEUE_DATA,
+ AR5K_TX_QUEUE_XR_DATA,
+ AR5K_TX_QUEUE_BEACON,
+ AR5K_TX_QUEUE_CAB,
+ AR5K_TX_QUEUE_UAPSD,
+};
+
+#define AR5K_NUM_TX_QUEUES 10
+#define AR5K_NUM_TX_QUEUES_NOQCU 2
+
+/*
+ * Queue syb-types to classify normal data queues.
+ * These are the 4 Access Categories as defined in
+ * WME spec. 0 is the lowest priority and 4 is the
+ * highest. Normal data that hasn't been classified
+ * goes to the Best Effort AC.
+ */
+enum ath5k_tx_queue_subtype {
+ AR5K_WME_AC_BK = 0, /*Background traffic*/
+ AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/
+ AR5K_WME_AC_VI, /*Video traffic*/
+ AR5K_WME_AC_VO, /*Voice traffic*/
+};
+
+/*
+ * Queue ID numbers as returned by the hw functions, each number
+ * represents a hw queue. If hw does not support hw queues
+ * (eg 5210) all data goes in one queue. These match
+ * d80211 definitions (net80211/MadWiFi don't use them).
+ */
+enum ath5k_tx_queue_id {
+ AR5K_TX_QUEUE_ID_NOQCU_DATA = 0,
+ AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1,
+ AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/
+ AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/
+ AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/
+ AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/
+ AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/
+ AR5K_TX_QUEUE_ID_UAPSD = 8,
+ AR5K_TX_QUEUE_ID_XR_DATA = 9,
+};
+
+
+/*
+ * Flags to set hw queue's parameters...
+ */
+#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */
+#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */
+#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
+#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0020 /* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0040 /* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0080 /* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0100 /* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0200 /* Enable hw compression -not implemented-*/
+
+/*
+ * A struct to hold tx queue's parameters
+ */
+struct ath5k_txq_info {
+ enum ath5k_tx_queue tqi_type;
+ enum ath5k_tx_queue_subtype tqi_subtype;
+ u16 tqi_flags; /* Tx queue flags (see above) */
+ u32 tqi_aifs; /* Arbitrated Interframe Space */
+ s32 tqi_cw_min; /* Minimum Contention Window */
+ s32 tqi_cw_max; /* Maximum Contention Window */
+ u32 tqi_cbr_period; /* Constant bit rate period */
+ u32 tqi_cbr_overflow_limit;
+ u32 tqi_burst_time;
+ u32 tqi_ready_time; /* Not used */
+};
+
+/*
+ * Transmit packet types.
+ * These are not fully used inside OpenHAL yet
+ */
+enum ath5k_pkt_type {
+ AR5K_PKT_TYPE_NORMAL = 0,
+ AR5K_PKT_TYPE_ATIM = 1,
+ AR5K_PKT_TYPE_PSPOLL = 2,
+ AR5K_PKT_TYPE_BEACON = 3,
+ AR5K_PKT_TYPE_PROBE_RESP = 4,
+ AR5K_PKT_TYPE_PIFS = 5,
+};
+
+/*
+ * TX power and TPC settings
+ */
+#define AR5K_TXPOWER_OFDM(_r, _v) ( \
+ ((0 & 1) << ((_v) + 6)) | \
+ (((ah->ah_txpower.txp_rates[(_r)]) & 0x3f) << (_v)) \
+)
+
+#define AR5K_TXPOWER_CCK(_r, _v) ( \
+ (ah->ah_txpower.txp_rates[(_r)] & 0x3f) << (_v) \
+)
+
+/*
+ * DMA size definitions (2^n+2)
+ */
+enum ath5k_dmasize {
+ AR5K_DMASIZE_4B = 0,
+ AR5K_DMASIZE_8B,
+ AR5K_DMASIZE_16B,
+ AR5K_DMASIZE_32B,
+ AR5K_DMASIZE_64B,
+ AR5K_DMASIZE_128B,
+ AR5K_DMASIZE_256B,
+ AR5K_DMASIZE_512B
+};
+
+
+/****************\
+ RX DEFINITIONS
+\****************/
+
+/*
+ * Rx Descriptor
+ */
+struct ath5k_rx_status {
+ u16 rs_datalen;
+ u16 rs_tstamp;
+ u8 rs_status;
+ u8 rs_phyerr;
+ s8 rs_rssi;
+ u8 rs_keyix;
+ u8 rs_rate;
+ u8 rs_antenna;
+ u8 rs_more;
+};
+
+#define AR5K_RXERR_CRC 0x01
+#define AR5K_RXERR_PHY 0x02
+#define AR5K_RXERR_FIFO 0x04
+#define AR5K_RXERR_DECRYPT 0x08
+#define AR5K_RXERR_MIC 0x10
+#define AR5K_RXKEYIX_INVALID ((u8) - 1)
+#define AR5K_TXKEYIX_INVALID ((u32) - 1)
+
+struct ath5k_mib_stats {
+ u32 ackrcv_bad;
+ u32 rts_bad;
+ u32 rts_good;
+ u32 fcs_bad;
+ u32 beacons;
+};
+
+
+
+
+/**************************\
+ BEACON TIMERS DEFINITIONS
+\**************************/
+
+#define AR5K_BEACON_PERIOD 0x0000ffff
+#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/
+#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/
+
+#if 0
+/**
+ * struct ath5k_beacon_state - Per-station beacon timer state.
+ * @bs_interval: in TU's, can also include the above flags
+ * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a
+ * Point Coordination Function capable AP
+ */
+struct ath5k_beacon_state {
+ u32 bs_next_beacon;
+ u32 bs_next_dtim;
+ u32 bs_interval;
+ u8 bs_dtim_period;
+ u8 bs_cfp_period;
+ u16 bs_cfp_max_duration;
+ u16 bs_cfp_du_remain;
+ u16 bs_tim_offset;
+ u16 bs_sleep_duration;
+ u16 bs_bmiss_threshold;
+ u32 bs_cfp_next;
+};
+#endif
+
+
+/*
+ * TSF to TU conversion:
+ *
+ * TSF is a 64bit value in usec (microseconds).
+ * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of
+ * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024).
+ */
+#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10)
+
+
+
+/********************\
+ COMMON DEFINITIONS
+\********************/
+
+/*
+ * Atheros descriptor
+ */
+struct ath5k_desc {
+ u32 ds_link;
+ u32 ds_data;
+ u32 ds_ctl0;
+ u32 ds_ctl1;
+ u32 ds_hw[4];
+
+ union {
+ struct ath5k_rx_status rx;
+ struct ath5k_tx_status tx;
+ } ds_us;
+
+#define ds_rxstat ds_us.rx
+#define ds_txstat ds_us.tx
+
+} __packed;
+
+#define AR5K_RXDESC_INTREQ 0x0020
+
+#define AR5K_TXDESC_CLRDMASK 0x0001
+#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/
+#define AR5K_TXDESC_RTSENA 0x0004
+#define AR5K_TXDESC_CTSENA 0x0008
+#define AR5K_TXDESC_INTREQ 0x0010
+#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/
+
+#define AR5K_SLOT_TIME_9 396
+#define AR5K_SLOT_TIME_20 880
+#define AR5K_SLOT_TIME_MAX 0xffff
+
+/* channel_flags */
+#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
+#define CHANNEL_TURBO 0x0010 /* Turbo Channel */
+#define CHANNEL_CCK 0x0020 /* CCK channel */
+#define CHANNEL_OFDM 0x0040 /* OFDM channel */
+#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
+#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
+#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
+#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
+#define CHANNEL_XR 0x0800 /* XR channel */
+
+#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM)
+#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK)
+#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM)
+#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO)
+#define CHANNEL_108A CHANNEL_T
+#define CHANNEL_108G CHANNEL_TG
+#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR)
+
+#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \
+ CHANNEL_TURBO)
+
+#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO)
+#define CHANNEL_MODES CHANNEL_ALL
+
+/*
+ * Used internaly in OpenHAL (ar5211.c/ar5212.c
+ * for reset_tx_queue). Also see struct struct ieee80211_channel.
+ */
+#define IS_CHAN_XR(_c) ((_c.val & CHANNEL_XR) != 0)
+#define IS_CHAN_B(_c) ((_c.val & CHANNEL_B) != 0)
+
+/*
+ * The following structure will be used to map 2GHz channels to
+ * 5GHz Atheros channels.
+ */
+struct ath5k_athchan_2ghz {
+ u32 a2_flags;
+ u16 a2_athchan;
+};
+
+/*
+ * Rate definitions
+ * TODO: Clean them up or move them on mac80211 -most of these infos are
+ * used by the rate control algorytm on MadWiFi.
+ */
+
+/* Max number of rates on the rate table and what it seems
+ * Atheros hardware supports */
+#define AR5K_MAX_RATES 32
+
+/**
+ * struct ath5k_rate - rate structure
+ * @valid: is this a valid rate for the current mode
+ * @modulation: respective mac80211 modulation
+ * @rate_kbps: rate in kbit/s
+ * @rate_code: hardware rate value, used in &struct ath5k_desc, on RX on
+ * &struct ath5k_rx_status.rs_rate and on TX on
+ * &struct ath5k_tx_status.ts_rate. Seems the ar5xxx harware supports
+ * up to 32 rates, indexed by 1-32. This means we really only need
+ * 6 bits for the rate_code.
+ * @dot11_rate: respective IEEE-802.11 rate value
+ * @control_rate: index of rate assumed to be used to send control frames.
+ * This can be used to set override the value on the rate duration
+ * registers. This is only useful if we can override in the harware at
+ * what rate we want to send control frames at. Note that IEEE-802.11
+ * Ch. 9.6 (after IEEE 802.11g changes) defines the rate at which we
+ * should send ACK/CTS, if we change this value we can be breaking
+ * the spec.
+ *
+ * This structure is used to get the RX rate or set the TX rate on the
+ * hardware descriptors. It is also used for internal modulation control
+ * and settings.
+ *
+ * On RX after the &struct ath5k_desc is parsed by the appropriate
+ * ah_proc_rx_desc() the respective hardware rate value is set in
+ * &struct ath5k_rx_status.rs_rate. On TX the desired rate is set in
+ * &struct ath5k_tx_status.ts_rate which is later used to setup the
+ * &struct ath5k_desc correctly. This is the hardware rate map we are
+ * aware of:
+ *
+ * rate_code 1 2 3 4 5 6 7 8
+ * rate_kbps 3000 1000 ? ? ? 2000 500 48000
+ *
+ * rate_code 9 10 11 12 13 14 15 16
+ * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ?
+ *
+ * rate_code 17 18 19 20 21 22 23 24
+ * rate_kbps ? ? ? ? ? ? ? 11000
+ *
+ * rate_code 25 26 27 28 29 30 31 32
+ * rate_kbps 5500 2000 1000 ? ? ? ? ?
+ *
+ */
+struct ath5k_rate {
+ u8 valid;
+ u32 modulation;
+ u16 rate_kbps;
+ u8 rate_code;
+ u8 dot11_rate;
+ u8 control_rate;
+};
+
+/* XXX: GRR all this stuff to get leds blinking ??? (check out setcurmode) */
+struct ath5k_rate_table {
+ u16 rate_count;
+ u8 rate_code_to_index[AR5K_MAX_RATES]; /* Back-mapping */
+ struct ath5k_rate rates[AR5K_MAX_RATES];
+};
+
+/*
+ * Rate tables...
+ */
+#define AR5K_RATES_11A { 8, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
+ { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 0 }, \
+ { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 0 }, \
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 2 }, \
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 2 }, \
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 4 } } \
+}
+
+#define AR5K_RATES_11B { 4, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
+ { 1, IEEE80211_RATE_CCK, 1000, 27, 130, 0 }, \
+ { 1, IEEE80211_RATE_CCK_2, 2000, 26, 132, 1 }, \
+ { 1, IEEE80211_RATE_CCK_2, 5500, 25, 139, 1 }, \
+ { 1, IEEE80211_RATE_CCK_2, 11000, 24, 150, 1 } } \
+}
+
+#define AR5K_RATES_11G { 12, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 10, 8, 6, 4, \
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 3, 2, 1, 0, 255, 255, 255, 255 }, { \
+ { 1, IEEE80211_RATE_CCK, 1000, 27, 2, 0 }, \
+ { 1, IEEE80211_RATE_CCK_2, 2000, 26, 4, 1 }, \
+ { 1, IEEE80211_RATE_CCK_2, 5500, 25, 11, 1 }, \
+ { 1, IEEE80211_RATE_CCK_2, 11000, 24, 22, 1 }, \
+ { 0, IEEE80211_RATE_OFDM, 6000, 11, 12, 4 }, \
+ { 0, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 24, 6 }, \
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 48, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
+}
+
+#define AR5K_RATES_TURBO { 8, { \
+ 255, 255, 255, 255, 255, 255, 255, 255, 6, 4, 2, 0, \
+ 7, 5, 3, 1, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
+ { 1, MODULATION_TURBO, 6000, 11, 140, 0 }, \
+ { 1, MODULATION_TURBO, 9000, 15, 18, 0 }, \
+ { 1, MODULATION_TURBO, 12000, 10, 152, 2 }, \
+ { 1, MODULATION_TURBO, 18000, 14, 36, 2 }, \
+ { 1, MODULATION_TURBO, 24000, 9, 176, 4 }, \
+ { 1, MODULATION_TURBO, 36000, 13, 72, 4 }, \
+ { 1, MODULATION_TURBO, 48000, 8, 96, 4 }, \
+ { 1, MODULATION_TURBO, 54000, 12, 108, 4 } } \
+}
+
+#define AR5K_RATES_XR { 12, { \
+ 255, 3, 1, 255, 255, 255, 2, 0, 10, 8, 6, 4, \
+ 11, 9, 7, 5, 255, 255, 255, 255, 255, 255, 255, 255, \
+ 255, 255, 255, 255, 255, 255, 255, 255 }, { \
+ { 1, MODULATION_XR, 500, 7, 129, 0 }, \
+ { 1, MODULATION_XR, 1000, 2, 139, 1 }, \
+ { 1, MODULATION_XR, 2000, 6, 150, 2 }, \
+ { 1, MODULATION_XR, 3000, 1, 150, 3 }, \
+ { 1, IEEE80211_RATE_OFDM, 6000, 11, 140, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 9000, 15, 18, 4 }, \
+ { 1, IEEE80211_RATE_OFDM, 12000, 10, 152, 6 }, \
+ { 1, IEEE80211_RATE_OFDM, 18000, 14, 36, 6 }, \
+ { 1, IEEE80211_RATE_OFDM, 24000, 9, 176, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 36000, 13, 72, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 48000, 8, 96, 8 }, \
+ { 1, IEEE80211_RATE_OFDM, 54000, 12, 108, 8 } } \
+}
+
+/*
+ * Crypto definitions
+ */
+
+#define AR5K_KEYCACHE_SIZE 8
+
+/***********************\
+ HW RELATED DEFINITIONS
+\***********************/
+
+/*
+ * Misc definitions
+ */
+#define AR5K_RSSI_EP_MULTIPLIER (1<<7)
+
+#define AR5K_ASSERT_ENTRY(_e, _s) do { \
+ if (_e >= _s) \
+ return (false); \
+} while (0)
+
+
+enum ath5k_ant_setting {
+ AR5K_ANT_VARIABLE = 0, /* variable by programming */
+ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
+ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
+ AR5K_ANT_MAX = 3,
+};
+
+/*
+ * Hardware interrupt abstraction
+ */
+
+/**
+ * enum ath5k_int - Hardware interrupt masks helpers
+ *
+ * @AR5K_INT_RX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_RXOK or AR5K_ISR_RXERR
+ * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?)
+ * @AR5K_INT_RXNOFRM: No frame received (?)
+ * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The
+ * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's
+ * LinkPtr is NULL. For more details, refer to:
+ * http://www.freepatentsonline.com/20030225739.html
+ * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors).
+ * Note that Rx overrun is not always fatal, on some chips we can continue
+ * operation without reseting the card, that's why int_fatal is not
+ * common for all chips.
+ * @AR5K_INT_TX: mask to identify received frame interrupts, of type
+ * AR5K_ISR_TXOK or AR5K_ISR_TXERR
+ * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?)
+ * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold
+ * We currently do increments on interrupt by
+ * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2
+ * @AR5K_INT_MIB: Indicates the Management Information Base counters should be
+ * checked. We should do this with ath5k_hw_update_mib_counters() but
+ * it seems we should also then do some noise immunity work.
+ * @AR5K_INT_RXPHY: RX PHY Error
+ * @AR5K_INT_RXKCM: ??
+ * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
+ * beacon that must be handled in software. The alternative is if you
+ * have VEOL support, in that case you let the hardware deal with things.
+ * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing
+ * beacons from the AP have associated with, we should probably try to
+ * reassociate. When in IBSS mode this might mean we have not received
+ * any beacons from any local stations. Note that every station in an
+ * IBSS schedules to send beacons at the Target Beacon Transmission Time
+ * (TBTT) with a random backoff.
+ * @AR5K_INT_BNR: Beacon Not Ready interrupt - ??
+ * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now
+ * until properly handled
+ * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
+ * errors. These types of errors we can enable seem to be of type
+ * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
+ * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER
+ * @AR5K_INT_NOCARD: signals the card has been removed
+ * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
+ * bit value
+ *
+ * These are mapped to take advantage of some common bits
+ * between the MACs, to be able to set intr properties
+ * easier. Some of them are not used yet inside hw.c. Most map
+ * to the respective hw interrupt value as they are common amogst different
+ * MACs.
+ */
+enum ath5k_int {
+ AR5K_INT_RX = 0x00000001, /* Not common */
+ AR5K_INT_RXDESC = 0x00000002,
+ AR5K_INT_RXNOFRM = 0x00000008,
+ AR5K_INT_RXEOL = 0x00000010,
+ AR5K_INT_RXORN = 0x00000020,
+ AR5K_INT_TX = 0x00000040, /* Not common */
+ AR5K_INT_TXDESC = 0x00000080,
+ AR5K_INT_TXURN = 0x00000800,
+ AR5K_INT_MIB = 0x00001000,
+ AR5K_INT_RXPHY = 0x00004000,
+ AR5K_INT_RXKCM = 0x00008000,
+ AR5K_INT_SWBA = 0x00010000,
+ AR5K_INT_BMISS = 0x00040000,
+ AR5K_INT_BNR = 0x00100000, /* Not common */
+ AR5K_INT_GPIO = 0x01000000,
+ AR5K_INT_FATAL = 0x40000000, /* Not common */
+ AR5K_INT_GLOBAL = 0x80000000,
+
+ AR5K_INT_COMMON = AR5K_INT_RXNOFRM
+ | AR5K_INT_RXDESC
+ | AR5K_INT_RXEOL
+ | AR5K_INT_RXORN
+ | AR5K_INT_TXURN
+ | AR5K_INT_TXDESC
+ | AR5K_INT_MIB
+ | AR5K_INT_RXPHY
+ | AR5K_INT_RXKCM
+ | AR5K_INT_SWBA
+ | AR5K_INT_BMISS
+ | AR5K_INT_GPIO,
+ AR5K_INT_NOCARD = 0xffffffff
+};
+
+/*
+ * Power management
+ */
+enum ath5k_power_mode {
+ AR5K_PM_UNDEFINED = 0,
+ AR5K_PM_AUTO,
+ AR5K_PM_AWAKE,
+ AR5K_PM_FULL_SLEEP,
+ AR5K_PM_NETWORK_SLEEP,
+};
+
+/*
+ * These match net80211 definitions (not used in
+ * d80211).
+ */
+#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/
+#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/
+#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/
+#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/
+#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/
+
+/* GPIO-controlled software LED */
+#define AR5K_SOFTLED_PIN 0
+#define AR5K_SOFTLED_ON 0
+#define AR5K_SOFTLED_OFF 1
+
+/*
+ * Chipset capabilities -see ath5k_hw_get_capability-
+ * get_capability function is not yet fully implemented
+ * in OpenHAL so most of these don't work yet...
+ */
+enum ath5k_capability_type {
+ AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */
+ AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */
+ AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */
+ AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */
+ AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */
+ AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */
+ AR5K_CAP_VEOL = 7, /* Supports virtual EOL */
+ AR5K_CAP_COMPRESSION = 8, /* Supports compression */
+ AR5K_CAP_BURST = 9, /* Supports packet bursting */
+ AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */
+ AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */
+ AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */
+ AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */
+ AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */
+ AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */
+ AR5K_CAP_XR = 16, /* Supports XR mode */
+ AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */
+ AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */
+ AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */
+ AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */
+};
+
+struct ath5k_capabilities {
+ /*
+ * Supported PHY modes
+ * (ie. CHANNEL_A, CHANNEL_B, ...)
+ */
+ DECLARE_BITMAP(cap_mode, NUM_DRIVER_MODES);
+
+ /*
+ * Frequency range (without regulation restrictions)
+ */
+ struct {
+ u16 range_2ghz_min;
+ u16 range_2ghz_max;
+ u16 range_5ghz_min;
+ u16 range_5ghz_max;
+ } cap_range;
+
+ /*
+ * Active regulation domain settings
+ */
+ struct {
+ enum ath5k_regdom reg_current;
+ enum ath5k_regdom reg_hw;
+ } cap_regdomain;
+
+ /*
+ * Values stored in the EEPROM (some of them...)
+ */
+ struct ath5k_eeprom_info cap_eeprom;
+
+ /*
+ * Queue information
+ */
+ struct {
+ u8 q_tx_num;
+ } cap_queues;
+};
+
+
+/***************************************\
+ HARDWARE ABSTRACTION LAYER STRUCTURE
+\***************************************/
+
+/*
+ * Misc defines
+ */
+
+#define AR5K_MAX_GPIO 10
+#define AR5K_MAX_RF_BANKS 8
+
+struct ath5k_hw {
+ u32 ah_magic;
+
+ struct ath5k_softc *ah_sc;
+ void __iomem *ah_iobase;
+
+ enum ath5k_int ah_imr;
+
+ enum ieee80211_if_types ah_op_mode;
+ enum ath5k_power_mode ah_power_mode;
+ struct ieee80211_channel ah_current_channel;
+ bool ah_turbo;
+ bool ah_calibration;
+ bool ah_running;
+ bool ah_single_chip;
+ enum ath5k_rfgain ah_rf_gain;
+
+ u32 ah_mac_srev;
+ u16 ah_mac_version;
+ u16 ah_mac_revision;
+ u16 ah_phy_revision;
+ u16 ah_radio_5ghz_revision;
+ u16 ah_radio_2ghz_revision;
+
+ enum ath5k_version ah_version;
+ enum ath5k_radio ah_radio;
+ u32 ah_phy;
+
+ bool ah_5ghz;
+ bool ah_2ghz;
+
+#define ah_regdomain ah_capabilities.cap_regdomain.reg_current
+#define ah_regdomain_hw ah_capabilities.cap_regdomain.reg_hw
+#define ah_modes ah_capabilities.cap_mode
+#define ah_ee_version ah_capabilities.cap_eeprom.ee_version
+
+ u32 ah_atim_window;
+ u32 ah_aifs;
+ u32 ah_cw_min;
+ u32 ah_cw_max;
+ bool ah_software_retry;
+ u32 ah_limit_tx_retries;
+
+ u32 ah_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
+ bool ah_ant_diversity;
+
+ u8 ah_sta_id[ETH_ALEN];
+
+ /* Current BSSID we are trying to assoc to / creating.
+ * This is passed by mac80211 on config_interface() and cached here for
+ * use in resets */
+ u8 ah_bssid[ETH_ALEN];
+
+ u32 ah_gpio[AR5K_MAX_GPIO];
+ int ah_gpio_npins;
+
+ struct ath5k_capabilities ah_capabilities;
+
+ struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES];
+ u32 ah_txq_status;
+ u32 ah_txq_imr_txok;
+ u32 ah_txq_imr_txerr;
+ u32 ah_txq_imr_txurn;
+ u32 ah_txq_imr_txdesc;
+ u32 ah_txq_imr_txeol;
+ u32 *ah_rf_banks;
+ size_t ah_rf_banks_size;
+ struct ath5k_gain ah_gain;
+ u32 ah_offset[AR5K_MAX_RF_BANKS];
+
+ struct {
+ u16 txp_pcdac[AR5K_EEPROM_POWER_TABLE_SIZE];
+ u16 txp_rates[AR5K_MAX_RATES];
+ s16 txp_min;
+ s16 txp_max;
+ bool txp_tpc;
+ s16 txp_ofdm;
+ } ah_txpower;
+
+ struct {
+ bool r_enabled;
+ int r_last_alert;
+ struct ieee80211_channel r_last_channel;
+ } ah_radar;
+
+ /* noise floor from last periodic calibration */
+ s32 ah_noise_floor;
+
+ /*
+ * Function pointers
+ */
+ int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int, unsigned int);
+ bool (*ah_setup_xtx_desc)(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+ int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *);
+ int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *);
+};
+
+/*
+ * Prototypes
+ */
+
+/* General Functions */
+extern int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, bool is_set);
+/* Attach/Detach Functions */
+extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version);
+extern const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah, unsigned int mode);
+extern void ath5k_hw_detach(struct ath5k_hw *ah);
+/* Reset Functions */
+extern int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode, struct ieee80211_channel *channel, bool change_channel);
+/* Power management functions */
+extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
+/* DMA Related Functions */
+extern void ath5k_hw_start_rx(struct ath5k_hw *ah);
+extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah);
+extern u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah);
+extern void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr);
+extern int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr);
+extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase);
+/* Interrupt handling */
+extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah);
+extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask);
+extern enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask);
+/* EEPROM access functions */
+extern int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain);
+/* Protocol Control Unit Functions */
+extern int ath5k_hw_set_opmode(struct ath5k_hw *ah);
+/* BSSID Functions */
+extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac);
+extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac);
+extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id);
+extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask);
+/* Receive start/stop functions */
+extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah);
+extern void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah);
+/* RX Filter functions */
+extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1);
+extern int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index);
+extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index);
+extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah);
+extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter);
+/* Beacon related functions */
+extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah);
+extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah);
+extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah);
+extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval);
+#if 0
+extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state);
+extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah);
+extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr);
+#endif
+extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ath5k_mib_stats *statistics);
+/* ACK bit rate */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high);
+/* ACK/CTS Timeouts */
+extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah);
+extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout);
+extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah);
+/* Key table (WEP) functions */
+extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry);
+extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry);
+extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac);
+extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac);
+/* Queue Control Unit, DFS Control Unit Functions */
+extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue, const struct ath5k_txq_info *queue_info);
+extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info);
+extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
+extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
+extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time);
+extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah);
+/* Hardware Descriptor Functions */
+extern int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, u32 size, unsigned int flags);
+/* GPIO Functions */
+extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state);
+extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio);
+extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio);
+extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val);
+extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level);
+/* Regulatory Domain/Channels Setup */
+extern u16 ath5k_get_regdomain(struct ath5k_hw *ah);
+/* Misc functions */
+extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result);
+
+
+/* Initial register settings functions */
+extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
+/* Initialize RF */
+extern int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int mode);
+extern int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq);
+extern enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah);
+extern int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah);
+
+
+/* PHY/RF channel functions */
+extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags);
+extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel);
+/* PHY calibration */
+extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
+extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
+/* Misc PHY functions */
+extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
+extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
+extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
+/* TX power setup */
+extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, unsigned int txpower);
+extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
+
+
+static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
+{
+ return ioread32(ah->ah_iobase + reg);
+}
+
+static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
+{
+ iowrite32(val, ah->ah_iobase + reg);
+}
+
+#endif
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
new file mode 100644
index 000000000000..72bcf321d1ce
--- /dev/null
+++ b/drivers/net/wireless/ath5k/base.c
@@ -0,0 +1,2974 @@
+/*-
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/cache.h>
+#include <linux/pci.h>
+#include <linux/ethtool.h>
+#include <linux/uaccess.h>
+
+#include <net/ieee80211_radiotap.h>
+
+#include <asm/unaligned.h>
+
+#include "base.h"
+#include "reg.h"
+#include "debug.h"
+
+/* unaligned little endian access */
+#define LE_READ_2(_p) (le16_to_cpu(get_unaligned((__le16 *)(_p))))
+#define LE_READ_4(_p) (le32_to_cpu(get_unaligned((__le32 *)(_p))))
+
+enum {
+ ATH_LED_TX,
+ ATH_LED_RX,
+};
+
+static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
+
+
+/******************\
+* Internal defines *
+\******************/
+
+/* Module info */
+MODULE_AUTHOR("Jiri Slaby");
+MODULE_AUTHOR("Nick Kossifidis");
+MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards.");
+MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION("0.1.1 (EXPERIMENTAL)");
+
+
+/* Known PCI ids */
+static struct pci_device_id ath5k_pci_id_table[] __devinitdata = {
+ { PCI_VDEVICE(ATHEROS, 0x0207), .driver_data = AR5K_AR5210 }, /* 5210 early */
+ { PCI_VDEVICE(ATHEROS, 0x0007), .driver_data = AR5K_AR5210 }, /* 5210 */
+ { PCI_VDEVICE(ATHEROS, 0x0011), .driver_data = AR5K_AR5211 }, /* 5311 - this is on AHB bus !*/
+ { PCI_VDEVICE(ATHEROS, 0x0012), .driver_data = AR5K_AR5211 }, /* 5211 */
+ { PCI_VDEVICE(ATHEROS, 0x0013), .driver_data = AR5K_AR5212 }, /* 5212 */
+ { PCI_VDEVICE(3COM_2, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 5212 */
+ { PCI_VDEVICE(3COM, 0x0013), .driver_data = AR5K_AR5212 }, /* 3com 3CRDAG675 5212 */
+ { PCI_VDEVICE(ATHEROS, 0x1014), .driver_data = AR5K_AR5212 }, /* IBM minipci 5212 */
+ { PCI_VDEVICE(ATHEROS, 0x0014), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0015), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0016), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0017), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0018), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x0019), .driver_data = AR5K_AR5212 }, /* 5212 combatible */
+ { PCI_VDEVICE(ATHEROS, 0x001a), .driver_data = AR5K_AR5212 }, /* 2413 Griffin-lite */
+ { PCI_VDEVICE(ATHEROS, 0x001b), .driver_data = AR5K_AR5212 }, /* 5413 Eagle */
+ { PCI_VDEVICE(ATHEROS, 0x001c), .driver_data = AR5K_AR5212 }, /* 5424 Condor (PCI-E)*/
+ { PCI_VDEVICE(ATHEROS, 0x0023), .driver_data = AR5K_AR5212 }, /* 5416 */
+ { PCI_VDEVICE(ATHEROS, 0x0024), .driver_data = AR5K_AR5212 }, /* 5418 */
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table);
+
+/* Known SREVs */
+static struct ath5k_srev_name srev_names[] = {
+ { "5210", AR5K_VERSION_VER, AR5K_SREV_VER_AR5210 },
+ { "5311", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311 },
+ { "5311A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311A },
+ { "5311B", AR5K_VERSION_VER, AR5K_SREV_VER_AR5311B },
+ { "5211", AR5K_VERSION_VER, AR5K_SREV_VER_AR5211 },
+ { "5212", AR5K_VERSION_VER, AR5K_SREV_VER_AR5212 },
+ { "5213", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213 },
+ { "5213A", AR5K_VERSION_VER, AR5K_SREV_VER_AR5213A },
+ { "2424", AR5K_VERSION_VER, AR5K_SREV_VER_AR2424 },
+ { "5424", AR5K_VERSION_VER, AR5K_SREV_VER_AR5424 },
+ { "5413", AR5K_VERSION_VER, AR5K_SREV_VER_AR5413 },
+ { "5414", AR5K_VERSION_VER, AR5K_SREV_VER_AR5414 },
+ { "5416", AR5K_VERSION_VER, AR5K_SREV_VER_AR5416 },
+ { "5418", AR5K_VERSION_VER, AR5K_SREV_VER_AR5418 },
+ { "xxxxx", AR5K_VERSION_VER, AR5K_SREV_UNKNOWN },
+ { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
+ { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
+ { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 },
+ { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 },
+ { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A },
+ { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 },
+ { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A },
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC1 },
+ { "SChip", AR5K_VERSION_RAD, AR5K_SREV_RAD_SC2 },
+ { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
+ { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
+};
+
+/*
+ * Prototypes - PCI stack related functions
+ */
+static int __devinit ath5k_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id);
+static void __devexit ath5k_pci_remove(struct pci_dev *pdev);
+#ifdef CONFIG_PM
+static int ath5k_pci_suspend(struct pci_dev *pdev,
+ pm_message_t state);
+static int ath5k_pci_resume(struct pci_dev *pdev);
+#else
+#define ath5k_pci_suspend NULL
+#define ath5k_pci_resume NULL
+#endif /* CONFIG_PM */
+
+static struct pci_driver ath5k_pci_drv_id = {
+ .name = "ath5k_pci",
+ .id_table = ath5k_pci_id_table,
+ .probe = ath5k_pci_probe,
+ .remove = __devexit_p(ath5k_pci_remove),
+ .suspend = ath5k_pci_suspend,
+ .resume = ath5k_pci_resume,
+};
+
+
+
+/*
+ * Prototypes - MAC 802.11 stack related functions
+ */
+static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl);
+static int ath5k_reset(struct ieee80211_hw *hw);
+static int ath5k_start(struct ieee80211_hw *hw);
+static void ath5k_stop(struct ieee80211_hw *hw);
+static int ath5k_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf);
+static void ath5k_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf);
+static int ath5k_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf);
+static int ath5k_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf);
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+ int mc_count, struct dev_mc_list *mclist);
+static int ath5k_set_key(struct ieee80211_hw *hw,
+ enum set_key_cmd cmd,
+ const u8 *local_addr, const u8 *addr,
+ struct ieee80211_key_conf *key);
+static int ath5k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats);
+static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats);
+static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
+static void ath5k_reset_tsf(struct ieee80211_hw *hw);
+static int ath5k_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl);
+
+static struct ieee80211_ops ath5k_hw_ops = {
+ .tx = ath5k_tx,
+ .start = ath5k_start,
+ .stop = ath5k_stop,
+ .add_interface = ath5k_add_interface,
+ .remove_interface = ath5k_remove_interface,
+ .config = ath5k_config,
+ .config_interface = ath5k_config_interface,
+ .configure_filter = ath5k_configure_filter,
+ .set_key = ath5k_set_key,
+ .get_stats = ath5k_get_stats,
+ .conf_tx = NULL,
+ .get_tx_stats = ath5k_get_tx_stats,
+ .get_tsf = ath5k_get_tsf,
+ .reset_tsf = ath5k_reset_tsf,
+ .beacon_update = ath5k_beacon_update,
+};
+
+/*
+ * Prototypes - Internal functions
+ */
+/* Attach detach */
+static int ath5k_attach(struct pci_dev *pdev,
+ struct ieee80211_hw *hw);
+static void ath5k_detach(struct pci_dev *pdev,
+ struct ieee80211_hw *hw);
+/* Channel/mode setup */
+static inline short ath5k_ieee2mhz(short chan);
+static unsigned int ath5k_copy_rates(struct ieee80211_rate *rates,
+ const struct ath5k_rate_table *rt,
+ unsigned int max);
+static unsigned int ath5k_copy_channels(struct ath5k_hw *ah,
+ struct ieee80211_channel *channels,
+ unsigned int mode,
+ unsigned int max);
+static int ath5k_getchannels(struct ieee80211_hw *hw);
+static int ath5k_chan_set(struct ath5k_softc *sc,
+ struct ieee80211_channel *chan);
+static void ath5k_setcurmode(struct ath5k_softc *sc,
+ unsigned int mode);
+static void ath5k_mode_setup(struct ath5k_softc *sc);
+/* Descriptor setup */
+static int ath5k_desc_alloc(struct ath5k_softc *sc,
+ struct pci_dev *pdev);
+static void ath5k_desc_free(struct ath5k_softc *sc,
+ struct pci_dev *pdev);
+/* Buffers setup */
+static int ath5k_rxbuf_setup(struct ath5k_softc *sc,
+ struct ath5k_buf *bf);
+static int ath5k_txbuf_setup(struct ath5k_softc *sc,
+ struct ath5k_buf *bf,
+ struct ieee80211_tx_control *ctl);
+
+static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
+ struct ath5k_buf *bf)
+{
+ BUG_ON(!bf);
+ if (!bf->skb)
+ return;
+ pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len,
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb(bf->skb);
+ bf->skb = NULL;
+}
+
+/* Queues setup */
+static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc,
+ int qtype, int subtype);
+static int ath5k_beaconq_setup(struct ath5k_hw *ah);
+static int ath5k_beaconq_config(struct ath5k_softc *sc);
+static void ath5k_txq_drainq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+static void ath5k_txq_cleanup(struct ath5k_softc *sc);
+static void ath5k_txq_release(struct ath5k_softc *sc);
+/* Rx handling */
+static int ath5k_rx_start(struct ath5k_softc *sc);
+static void ath5k_rx_stop(struct ath5k_softc *sc);
+static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc,
+ struct ath5k_desc *ds,
+ struct sk_buff *skb);
+static void ath5k_tasklet_rx(unsigned long data);
+/* Tx handling */
+static void ath5k_tx_processq(struct ath5k_softc *sc,
+ struct ath5k_txq *txq);
+static void ath5k_tasklet_tx(unsigned long data);
+/* Beacon handling */
+static int ath5k_beacon_setup(struct ath5k_softc *sc,
+ struct ath5k_buf *bf,
+ struct ieee80211_tx_control *ctl);
+static void ath5k_beacon_send(struct ath5k_softc *sc);
+static void ath5k_beacon_config(struct ath5k_softc *sc);
+static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+
+static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
+{
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+
+ if ((tsf & 0x7fff) < rstamp)
+ tsf -= 0x8000;
+
+ return (tsf & ~0x7fff) | rstamp;
+}
+
+/* Interrupt handling */
+static int ath5k_init(struct ath5k_softc *sc);
+static int ath5k_stop_locked(struct ath5k_softc *sc);
+static int ath5k_stop_hw(struct ath5k_softc *sc);
+static irqreturn_t ath5k_intr(int irq, void *dev_id);
+static void ath5k_tasklet_reset(unsigned long data);
+
+static void ath5k_calibrate(unsigned long data);
+/* LED functions */
+static void ath5k_led_off(unsigned long data);
+static void ath5k_led_blink(struct ath5k_softc *sc,
+ unsigned int on,
+ unsigned int off);
+static void ath5k_led_event(struct ath5k_softc *sc,
+ int event);
+
+
+/*
+ * Module init/exit functions
+ */
+static int __init
+init_ath5k_pci(void)
+{
+ int ret;
+
+ ath5k_debug_init();
+
+ ret = pci_register_driver(&ath5k_pci_drv_id);
+ if (ret) {
+ printk(KERN_ERR "ath5k_pci: can't register pci driver\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void __exit
+exit_ath5k_pci(void)
+{
+ pci_unregister_driver(&ath5k_pci_drv_id);
+
+ ath5k_debug_finish();
+}
+
+module_init(init_ath5k_pci);
+module_exit(exit_ath5k_pci);
+
+
+/********************\
+* PCI Initialization *
+\********************/
+
+static const char *
+ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
+{
+ const char *name = "xxxxx";
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(srev_names); i++) {
+ if (srev_names[i].sr_type != type)
+ continue;
+ if ((val & 0xff) < srev_names[i + 1].sr_val) {
+ name = srev_names[i].sr_name;
+ break;
+ }
+ }
+
+ return name;
+}
+
+static int __devinit
+ath5k_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ void __iomem *mem;
+ struct ath5k_softc *sc;
+ struct ieee80211_hw *hw;
+ int ret;
+ u8 csz;
+
+ ret = pci_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "can't enable device\n");
+ goto err;
+ }
+
+ /* XXX 32-bit addressing only */
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ if (ret) {
+ dev_err(&pdev->dev, "32-bit DMA not available\n");
+ goto err_dis;
+ }
+
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
+ if (csz == 0) {
+ /*
+ * Linux 2.4.18 (at least) writes the cache line size
+ * register as a 16-bit wide register which is wrong.
+ * We must have this setup properly for rx buffer
+ * DMA to work so force a reasonable value here if it
+ * comes up zero.
+ */
+ csz = L1_CACHE_BYTES / sizeof(u32);
+ pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
+ }
+ /*
+ * The default setting of latency timer yields poor results,
+ * set it to the value used by other systems. It may be worth
+ * tweaking this setting more.
+ */
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
+
+ /* Enable bus mastering */
+ pci_set_master(pdev);
+
+ /*
+ * Disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state.
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ret = pci_request_region(pdev, 0, "ath5k");
+ if (ret) {
+ dev_err(&pdev->dev, "cannot reserve PCI memory region\n");
+ goto err_dis;
+ }
+
+ mem = pci_iomap(pdev, 0, 0);
+ if (!mem) {
+ dev_err(&pdev->dev, "cannot remap PCI memory region\n") ;
+ ret = -EIO;
+ goto err_reg;
+ }
+
+ /*
+ * Allocate hw (mac80211 main struct)
+ * and hw->priv (driver private data)
+ */
+ hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops);
+ if (hw == NULL) {
+ dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n");
+ ret = -ENOMEM;
+ goto err_map;
+ }
+
+ dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy));
+
+ /* Initialize driver private data */
+ SET_IEEE80211_DEV(hw, &pdev->dev);
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS;
+ hw->extra_tx_headroom = 2;
+ hw->channel_change_time = 5000;
+ /* these names are misleading */
+ hw->max_rssi = -110; /* signal in dBm */
+ hw->max_noise = -110; /* noise in dBm */
+ hw->max_signal = 100; /* we will provide a percentage based on rssi */
+ sc = hw->priv;
+ sc->hw = hw;
+ sc->pdev = pdev;
+
+ ath5k_debug_init_device(sc);
+
+ /*
+ * Mark the device as detached to avoid processing
+ * interrupts until setup is complete.
+ */
+ __set_bit(ATH_STAT_INVALID, sc->status);
+
+ sc->iobase = mem; /* So we can unmap it on detach */
+ sc->cachelsz = csz * sizeof(u32); /* convert to bytes */
+ sc->opmode = IEEE80211_IF_TYPE_STA;
+ mutex_init(&sc->lock);
+ spin_lock_init(&sc->rxbuflock);
+ spin_lock_init(&sc->txbuflock);
+
+ /* Set private data */
+ pci_set_drvdata(pdev, hw);
+
+ /* Enable msi for devices that support it */
+ pci_enable_msi(pdev);
+
+ /* Setup interrupt handler */
+ ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc);
+ if (ret) {
+ ATH5K_ERR(sc, "request_irq failed\n");
+ goto err_free;
+ }
+
+ /* Initialize device */
+ sc->ah = ath5k_hw_attach(sc, id->driver_data);
+ if (IS_ERR(sc->ah)) {
+ ret = PTR_ERR(sc->ah);
+ goto err_irq;
+ }
+
+ /* Finish private driver data initialization */
+ ret = ath5k_attach(pdev, hw);
+ if (ret)
+ goto err_ah;
+
+ ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_VER,sc->ah->ah_mac_srev),
+ sc->ah->ah_mac_srev,
+ sc->ah->ah_phy_revision);
+
+ if(!sc->ah->ah_single_chip){
+ /* Single chip radio (!RF5111) */
+ if(sc->ah->ah_radio_5ghz_revision && !sc->ah->ah_radio_2ghz_revision) {
+ /* No 5GHz support -> report 2GHz radio */
+ if(!test_bit(MODE_IEEE80211A, sc->ah->ah_capabilities.cap_mode)){
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* No 2GHz support (5110 and some 5Ghz only cards) -> report 5Ghz radio */
+ } else if(!test_bit(MODE_IEEE80211B, sc->ah->ah_capabilities.cap_mode)){
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ /* Multiband radio */
+ } else {
+ ATH5K_INFO(sc, "RF%s multiband radio found"
+ " (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ }
+ }
+ /* Multi chip radio (RF5111 - RF2111) -> report both 2GHz/5GHz radios */
+ else if(sc->ah->ah_radio_5ghz_revision && sc->ah->ah_radio_2ghz_revision){
+ ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_5ghz_revision),
+ sc->ah->ah_radio_5ghz_revision);
+ ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n",
+ ath5k_chip_name(AR5K_VERSION_RAD,sc->ah->ah_radio_2ghz_revision),
+ sc->ah->ah_radio_2ghz_revision);
+ }
+ }
+
+
+ /* ready to process interrupts */
+ __clear_bit(ATH_STAT_INVALID, sc->status);
+
+ return 0;
+err_ah:
+ ath5k_hw_detach(sc->ah);
+err_irq:
+ free_irq(pdev->irq, sc);
+err_free:
+ pci_disable_msi(pdev);
+ ieee80211_free_hw(hw);
+err_map:
+ pci_iounmap(pdev, mem);
+err_reg:
+ pci_release_region(pdev, 0);
+err_dis:
+ pci_disable_device(pdev);
+err:
+ return ret;
+}
+
+static void __devexit
+ath5k_pci_remove(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = hw->priv;
+
+ ath5k_debug_finish_device(sc);
+ ath5k_detach(pdev, hw);
+ ath5k_hw_detach(sc->ah);
+ free_irq(pdev->irq, sc);
+ pci_disable_msi(pdev);
+ pci_iounmap(pdev, sc->iobase);
+ pci_release_region(pdev, 0);
+ pci_disable_device(pdev);
+ ieee80211_free_hw(hw);
+}
+
+#ifdef CONFIG_PM
+static int
+ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = hw->priv;
+
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status))
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, 1);
+
+ ath5k_stop_hw(sc);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, PCI_D3hot);
+
+ return 0;
+}
+
+static int
+ath5k_pci_resume(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int i, err;
+
+ err = pci_set_power_state(pdev, PCI_D0);
+ if (err)
+ return err;
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_restore_state(pdev);
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+ * re-disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state
+ */
+ pci_write_config_byte(pdev, 0x41, 0);
+
+ ath5k_init(sc);
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
+ ath5k_hw_set_gpio_output(ah, sc->led_pin);
+ ath5k_hw_set_gpio(ah, sc->led_pin, 0);
+ }
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up or resume.
+ *
+ * FIXME: This may need to be revisited when mac80211 becomes
+ * aware of suspend/resume.
+ */
+ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+ ath5k_hw_reset_key(ah, i);
+
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+
+/***********************\
+* Driver Initialization *
+\***********************/
+
+static int
+ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ u8 mac[ETH_ALEN];
+ unsigned int i;
+ int ret;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
+
+ /*
+ * Check if the MAC has multi-rate retry support.
+ * We do this by trying to setup a fake extended
+ * descriptor. MAC's that don't have support will
+ * return false w/o doing anything. MAC's that do
+ * support it will return true w/o doing anything.
+ */
+ if (ah->ah_setup_xtx_desc(ah, NULL, 0, 0, 0, 0, 0, 0))
+ __set_bit(ATH_STAT_MRRETRY, sc->status);
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+ ath5k_hw_reset_key(ah, i);
+
+ /*
+ * Collect the channel list. The 802.11 layer
+ * is resposible for filtering this list based
+ * on settings like the phy mode and regulatory
+ * domain restrictions.
+ */
+ ret = ath5k_getchannels(hw);
+ if (ret) {
+ ATH5K_ERR(sc, "can't get channels\n");
+ goto err;
+ }
+
+ /* NB: setup here so ath5k_rate_update is happy */
+ if (test_bit(MODE_IEEE80211A, ah->ah_modes))
+ ath5k_setcurmode(sc, MODE_IEEE80211A);
+ else
+ ath5k_setcurmode(sc, MODE_IEEE80211B);
+
+ /*
+ * Allocate tx+rx descriptors and populate the lists.
+ */
+ ret = ath5k_desc_alloc(sc, pdev);
+ if (ret) {
+ ATH5K_ERR(sc, "can't allocate descriptors\n");
+ goto err;
+ }
+
+ /*
+ * Allocate hardware transmit queues: one queue for
+ * beacon frames and one data queue for each QoS
+ * priority. Note that hw functions handle reseting
+ * these queues at the needed time.
+ */
+ ret = ath5k_beaconq_setup(ah);
+ if (ret < 0) {
+ ATH5K_ERR(sc, "can't setup a beacon xmit queue\n");
+ goto err_desc;
+ }
+ sc->bhalq = ret;
+
+ sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK);
+ if (IS_ERR(sc->txq)) {
+ ATH5K_ERR(sc, "can't setup xmit queue\n");
+ ret = PTR_ERR(sc->txq);
+ goto err_bhal;
+ }
+
+ tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
+ tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
+ tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
+ setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
+ setup_timer(&sc->led_tim, ath5k_led_off, (unsigned long)sc);
+
+ sc->led_on = 0; /* low true */
+ /*
+ * Auto-enable soft led processing for IBM cards and for
+ * 5211 minipci cards.
+ */
+ if (pdev->device == PCI_DEVICE_ID_ATHEROS_AR5212_IBM ||
+ pdev->device == PCI_DEVICE_ID_ATHEROS_AR5211) {
+ __set_bit(ATH_STAT_LEDSOFT, sc->status);
+ sc->led_pin = 0;
+ }
+ /* Enable softled on PIN1 on HP Compaq nc6xx, nc4000 & nx5000 laptops */
+ if (pdev->subsystem_vendor == PCI_VENDOR_ID_COMPAQ) {
+ __set_bit(ATH_STAT_LEDSOFT, sc->status);
+ sc->led_pin = 0;
+ }
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
+ ath5k_hw_set_gpio_output(ah, sc->led_pin);
+ ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
+ }
+
+ ath5k_hw_get_lladdr(ah, mac);
+ SET_IEEE80211_PERM_ADDR(hw, mac);
+ /* All MAC address bits matter for ACKs */
+ memset(sc->bssidmask, 0xff, ETH_ALEN);
+ ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
+
+ ret = ieee80211_register_hw(hw);
+ if (ret) {
+ ATH5K_ERR(sc, "can't register ieee80211 hw\n");
+ goto err_queues;
+ }
+
+ return 0;
+err_queues:
+ ath5k_txq_release(sc);
+err_bhal:
+ ath5k_hw_release_tx_queue(ah, sc->bhalq);
+err_desc:
+ ath5k_desc_free(sc, pdev);
+err:
+ return ret;
+}
+
+static void
+ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ /*
+ * NB: the order of these is important:
+ * o call the 802.11 layer before detaching ath5k_hw to
+ * insure callbacks into the driver to delete global
+ * key cache entries can be handled
+ * o reclaim the tx queue data structures after calling
+ * the 802.11 layer as we'll get called back to reclaim
+ * node state and potentially want to use them
+ * o to cleanup the tx queues the hal is called, so detach
+ * it last
+ * XXX: ??? detach ath5k_hw ???
+ * Other than that, it's straightforward...
+ */
+ ieee80211_unregister_hw(hw);
+ ath5k_desc_free(sc, pdev);
+ ath5k_txq_release(sc);
+ ath5k_hw_release_tx_queue(sc->ah, sc->bhalq);
+
+ /*
+ * NB: can't reclaim these until after ieee80211_ifdetach
+ * returns because we'll get called back to reclaim node
+ * state and potentially want to use them.
+ */
+}
+
+
+
+
+/********************\
+* Channel/mode setup *
+\********************/
+
+/*
+ * Convert IEEE channel number to MHz frequency.
+ */
+static inline short
+ath5k_ieee2mhz(short chan)
+{
+ if (chan <= 14 || chan >= 27)
+ return ieee80211chan2mhz(chan);
+ else
+ return 2212 + chan * 20;
+}
+
+static unsigned int
+ath5k_copy_rates(struct ieee80211_rate *rates,
+ const struct ath5k_rate_table *rt,
+ unsigned int max)
+{
+ unsigned int i, count;
+
+ if (rt == NULL)
+ return 0;
+
+ for (i = 0, count = 0; i < rt->rate_count && max > 0; i++) {
+ if (!rt->rates[i].valid)
+ continue;
+ rates->rate = rt->rates[i].rate_kbps / 100;
+ rates->val = rt->rates[i].rate_code;
+ rates->flags = rt->rates[i].modulation;
+ rates++;
+ count++;
+ max--;
+ }
+
+ return count;
+}
+
+static unsigned int
+ath5k_copy_channels(struct ath5k_hw *ah,
+ struct ieee80211_channel *channels,
+ unsigned int mode,
+ unsigned int max)
+{
+ static const struct { unsigned int mode, mask, chan; } map[] = {
+ [MODE_IEEE80211A] = { CHANNEL_OFDM, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_A },
+ [MODE_ATHEROS_TURBO] = { CHANNEL_OFDM|CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_T },
+ [MODE_IEEE80211B] = { CHANNEL_CCK, CHANNEL_CCK, CHANNEL_B },
+ [MODE_IEEE80211G] = { CHANNEL_OFDM, CHANNEL_OFDM, CHANNEL_G },
+ [MODE_ATHEROS_TURBOG] = { CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_OFDM | CHANNEL_TURBO, CHANNEL_TG },
+ };
+ static const struct ath5k_regchannel chans_2ghz[] =
+ IEEE80211_CHANNELS_2GHZ;
+ static const struct ath5k_regchannel chans_5ghz[] =
+ IEEE80211_CHANNELS_5GHZ;
+ const struct ath5k_regchannel *chans;
+ enum ath5k_regdom dmn;
+ unsigned int i, count, size, chfreq, all, f, ch;
+
+ if (!test_bit(mode, ah->ah_modes))
+ return 0;
+
+ all = ah->ah_regdomain == DMN_DEFAULT || CHAN_DEBUG == 1;
+
+ switch (mode) {
+ case MODE_IEEE80211A:
+ case MODE_ATHEROS_TURBO:
+ /* 1..220, but 2GHz frequencies are filtered by check_channel */
+ size = all ? 220 : ARRAY_SIZE(chans_5ghz);
+ chans = chans_5ghz;
+ dmn = ath5k_regdom2flag(ah->ah_regdomain,
+ IEEE80211_CHANNELS_5GHZ_MIN);
+ chfreq = CHANNEL_5GHZ;
+ break;
+ case MODE_IEEE80211B:
+ case MODE_IEEE80211G:
+ case MODE_ATHEROS_TURBOG:
+ size = all ? 26 : ARRAY_SIZE(chans_2ghz);
+ chans = chans_2ghz;
+ dmn = ath5k_regdom2flag(ah->ah_regdomain,
+ IEEE80211_CHANNELS_2GHZ_MIN);
+ chfreq = CHANNEL_2GHZ;
+ break;
+ default:
+ ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n");
+ return 0;
+ }
+
+ for (i = 0, count = 0; i < size && max > 0; i++) {
+ ch = all ? i + 1 : chans[i].chan;
+ f = ath5k_ieee2mhz(ch);
+ /* Check if channel is supported by the chipset */
+ if (!ath5k_channel_ok(ah, f, chfreq))
+ continue;
+
+ /* Match regulation domain */
+ if (!all && !(IEEE80211_DMN(chans[i].domain) &
+ IEEE80211_DMN(dmn)))
+ continue;
+
+ if (!all && (chans[i].mode & map[mode].mask) != map[mode].mode)
+ continue;
+
+ /* Write channel and increment counter */
+ channels->chan = ch;
+ channels->freq = f;
+ channels->val = map[mode].chan;
+ channels++;
+ count++;
+ max--;
+ }
+
+ return count;
+}
+
+/* Only tries to register modes our EEPROM says it can support */
+#define REGISTER_MODE(m) do { \
+ ret = ath5k_register_mode(hw, m); \
+ if (ret) \
+ return ret; \
+} while (0) \
+
+static inline int
+ath5k_register_mode(struct ieee80211_hw *hw, u8 m)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ieee80211_hw_mode *modes = sc->modes;
+ unsigned int i;
+ int ret;
+
+ if (!test_bit(m, sc->ah->ah_capabilities.cap_mode))
+ return 0;
+
+ for (i = 0; i < NUM_DRIVER_MODES; i++) {
+ if (modes[i].mode != m || !modes[i].num_channels)
+ continue;
+ ret = ieee80211_register_hwmode(hw, &modes[i]);
+ if (ret) {
+ ATH5K_ERR(sc, "can't register hwmode %u\n", m);
+ return ret;
+ }
+ return 0;
+ }
+ BUG();
+}
+
+static int
+ath5k_getchannels(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ struct ieee80211_hw_mode *modes = sc->modes;
+ unsigned int i, max_r, max_c;
+ int ret;
+
+ BUILD_BUG_ON(ARRAY_SIZE(sc->modes) < 3);
+
+ /* The order here does not matter */
+ modes[0].mode = MODE_IEEE80211G;
+ modes[1].mode = MODE_IEEE80211B;
+ modes[2].mode = MODE_IEEE80211A;
+
+ max_r = ARRAY_SIZE(sc->rates);
+ max_c = ARRAY_SIZE(sc->channels);
+
+ for (i = 0; i < NUM_DRIVER_MODES; i++) {
+ struct ieee80211_hw_mode *mode = &modes[i];
+ const struct ath5k_rate_table *hw_rates;
+
+ if (i == 0) {
+ modes[0].rates = sc->rates;
+ modes->channels = sc->channels;
+ } else {
+ struct ieee80211_hw_mode *prev_mode = &modes[i-1];
+ int prev_num_r = prev_mode->num_rates;
+ int prev_num_c = prev_mode->num_channels;
+ mode->rates = &prev_mode->rates[prev_num_r];
+ mode->channels = &prev_mode->channels[prev_num_c];
+ }
+
+ hw_rates = ath5k_hw_get_rate_table(ah, mode->mode);
+ mode->num_rates = ath5k_copy_rates(mode->rates, hw_rates,
+ max_r);
+ mode->num_channels = ath5k_copy_channels(ah, mode->channels,
+ mode->mode, max_c);
+ max_r -= mode->num_rates;
+ max_c -= mode->num_channels;
+ }
+
+ /* We try to register all modes this driver supports. We don't bother
+ * with MODE_IEEE80211B for AR5212 as MODE_IEEE80211G already accounts
+ * for that as per mac80211. Then, REGISTER_MODE() will will actually
+ * check the eeprom reading for more reliable capability information.
+ * Order matters here as per mac80211's latest preference. This will
+ * all hopefullly soon go away. */
+
+ REGISTER_MODE(MODE_IEEE80211G);
+ if (ah->ah_version != AR5K_AR5212)
+ REGISTER_MODE(MODE_IEEE80211B);
+ REGISTER_MODE(MODE_IEEE80211A);
+
+ ath5k_debug_dump_modes(sc, modes);
+
+ return ret;
+}
+
+/*
+ * Set/change channels. If the channel is really being changed,
+ * it's done by reseting the chip. To accomplish this we must
+ * first cleanup any pending DMA, then restart stuff after a la
+ * ath5k_init.
+ */
+static int
+ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
+{
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "%u (%u MHz) -> %u (%u MHz)\n",
+ sc->curchan->chan, sc->curchan->freq,
+ chan->chan, chan->freq);
+
+ if (chan->freq != sc->curchan->freq || chan->val != sc->curchan->val) {
+ /*
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ ath5k_hw_set_intr(ah, 0); /* disable interrupts */
+ ath5k_txq_cleanup(sc); /* clear pending tx frames */
+ ath5k_rx_stop(sc); /* turn off frame recv */
+ ret = ath5k_hw_reset(ah, sc->opmode, chan, true);
+ if (ret) {
+ ATH5K_ERR(sc, "%s: unable to reset channel %u "
+ "(%u Mhz)\n", __func__, chan->chan, chan->freq);
+ return ret;
+ }
+ sc->curchan = chan;
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
+
+ /*
+ * Re-enable rx framework.
+ */
+ ret = ath5k_rx_start(sc);
+ if (ret) {
+ ATH5K_ERR(sc, "%s: unable to restart recv logic\n",
+ __func__);
+ return ret;
+ }
+
+ /*
+ * Change channels and update the h/w rate map
+ * if we're switching; e.g. 11a to 11b/g.
+ *
+ * XXX needed?
+ */
+/* ath5k_chan_change(sc, chan); */
+
+ ath5k_beacon_config(sc);
+ /*
+ * Re-enable interrupts.
+ */
+ ath5k_hw_set_intr(ah, sc->imask);
+ }
+
+ return 0;
+}
+
+static void
+ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode)
+{
+ if (unlikely(test_bit(ATH_STAT_LEDSOFT, sc->status))) {
+ /* from Atheros NDIS driver, w/ permission */
+ static const struct {
+ u16 rate; /* tx/rx 802.11 rate */
+ u16 timeOn; /* LED on time (ms) */
+ u16 timeOff; /* LED off time (ms) */
+ } blinkrates[] = {
+ { 108, 40, 10 },
+ { 96, 44, 11 },
+ { 72, 50, 13 },
+ { 48, 57, 14 },
+ { 36, 67, 16 },
+ { 24, 80, 20 },
+ { 22, 100, 25 },
+ { 18, 133, 34 },
+ { 12, 160, 40 },
+ { 10, 200, 50 },
+ { 6, 240, 58 },
+ { 4, 267, 66 },
+ { 2, 400, 100 },
+ { 0, 500, 130 }
+ };
+ const struct ath5k_rate_table *rt =
+ ath5k_hw_get_rate_table(sc->ah, mode);
+ unsigned int i, j;
+
+ BUG_ON(rt == NULL);
+
+ memset(sc->hwmap, 0, sizeof(sc->hwmap));
+ for (i = 0; i < 32; i++) {
+ u8 ix = rt->rate_code_to_index[i];
+ if (ix == 0xff) {
+ sc->hwmap[i].ledon = msecs_to_jiffies(500);
+ sc->hwmap[i].ledoff = msecs_to_jiffies(130);
+ continue;
+ }
+ sc->hwmap[i].txflags = IEEE80211_RADIOTAP_F_DATAPAD;
+ if (SHPREAMBLE_FLAG(ix) || rt->rates[ix].modulation ==
+ IEEE80211_RATE_OFDM)
+ sc->hwmap[i].txflags |=
+ IEEE80211_RADIOTAP_F_SHORTPRE;
+ /* receive frames include FCS */
+ sc->hwmap[i].rxflags = sc->hwmap[i].txflags |
+ IEEE80211_RADIOTAP_F_FCS;
+ /* setup blink rate table to avoid per-packet lookup */
+ for (j = 0; j < ARRAY_SIZE(blinkrates) - 1; j++)
+ if (blinkrates[j].rate == /* XXX why 7f? */
+ (rt->rates[ix].dot11_rate&0x7f))
+ break;
+
+ sc->hwmap[i].ledon = msecs_to_jiffies(blinkrates[j].
+ timeOn);
+ sc->hwmap[i].ledoff = msecs_to_jiffies(blinkrates[j].
+ timeOff);
+ }
+ }
+
+ sc->curmode = mode;
+}
+
+static void
+ath5k_mode_setup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 rfilt;
+
+ /* configure rx filter */
+ rfilt = sc->filter_flags;
+ ath5k_hw_set_rx_filter(ah, rfilt);
+
+ if (ath5k_hw_hasbssidmask(ah))
+ ath5k_hw_set_bssid_mask(ah, sc->bssidmask);
+
+ /* configure operational mode */
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_set_mcast_filter(ah, 0, 0);
+ ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
+}
+
+
+
+
+/***************\
+* Buffers setup *
+\***************/
+
+static int
+ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct sk_buff *skb = bf->skb;
+ struct ath5k_desc *ds;
+
+ if (likely(skb == NULL)) {
+ unsigned int off;
+
+ /*
+ * Allocate buffer with headroom_needed space for the
+ * fake physical layer header at the start.
+ */
+ skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1);
+ if (unlikely(skb == NULL)) {
+ ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
+ sc->rxbufsize + sc->cachelsz - 1);
+ return -ENOMEM;
+ }
+ /*
+ * Cache-line-align. This is important (for the
+ * 5210 at least) as not doing so causes bogus data
+ * in rx'd frames.
+ */
+ off = ((unsigned long)skb->data) % sc->cachelsz;
+ if (off != 0)
+ skb_reserve(skb, sc->cachelsz - off);
+
+ bf->skb = skb;
+ bf->skbaddr = pci_map_single(sc->pdev,
+ skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(bf->skbaddr))) {
+ ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
+ dev_kfree_skb(skb);
+ bf->skb = NULL;
+ return -ENOMEM;
+ }
+ }
+
+ /*
+ * Setup descriptors. For receive we always terminate
+ * the descriptor list with a self-linked entry so we'll
+ * not get overrun under high load (as can happen with a
+ * 5212 when ANI processing enables PHY error frames).
+ *
+ * To insure the last descriptor is self-linked we create
+ * each descriptor as self-linked and add it to the end. As
+ * each additional descriptor is added the previous self-linked
+ * entry is ``fixed'' naturally. This should be safe even
+ * if DMA is happening. When processing RX interrupts we
+ * never remove/process the last, self-linked, entry on the
+ * descriptor list. This insures the hardware always has
+ * someplace to write a new frame.
+ */
+ ds = bf->desc;
+ ds->ds_link = bf->daddr; /* link to self */
+ ds->ds_data = bf->skbaddr;
+ ath5k_hw_setup_rx_desc(ah, ds,
+ skb_tailroom(skb), /* buffer size */
+ 0);
+
+ if (sc->rxlink != NULL)
+ *sc->rxlink = bf->daddr;
+ sc->rxlink = &ds->ds_link;
+ return 0;
+}
+
+static int
+ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ struct ieee80211_tx_control *ctl)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq = sc->txq;
+ struct ath5k_desc *ds = bf->desc;
+ struct sk_buff *skb = bf->skb;
+ unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID;
+ int ret;
+
+ flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK;
+ bf->ctl = *ctl;
+ /* XXX endianness */
+ bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+
+ if (ctl->flags & IEEE80211_TXCTL_NO_ACK)
+ flags |= AR5K_TXDESC_NOACK;
+
+ pktlen = skb->len + FCS_LEN;
+
+ if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) {
+ keyidx = ctl->key_idx;
+ pktlen += ctl->icv_len;
+ }
+
+ ret = ah->ah_setup_tx_desc(ah, ds, pktlen,
+ ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
+ (ctl->power_level * 2), ctl->tx_rate, ctl->retry_limit, keyidx, 0, flags, 0, 0);
+ if (ret)
+ goto err_unmap;
+
+ ds->ds_link = 0;
+ ds->ds_data = bf->skbaddr;
+
+ spin_lock_bh(&txq->lock);
+ list_add_tail(&bf->list, &txq->q);
+ sc->tx_stats.data[txq->qnum].len++;
+ if (txq->link == NULL) /* is this first packet? */
+ ath5k_hw_put_tx_buf(ah, txq->qnum, bf->daddr);
+ else /* no, so only link it */
+ *txq->link = bf->daddr;
+
+ txq->link = &ds->ds_link;
+ ath5k_hw_tx_start(ah, txq->qnum);
+ spin_unlock_bh(&txq->lock);
+
+ return 0;
+err_unmap:
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+ return ret;
+}
+
+/*******************\
+* Descriptors setup *
+\*******************/
+
+static int
+ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev)
+{
+ struct ath5k_desc *ds;
+ struct ath5k_buf *bf;
+ dma_addr_t da;
+ unsigned int i;
+ int ret;
+
+ /* allocate descriptors */
+ sc->desc_len = sizeof(struct ath5k_desc) *
+ (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1);
+ sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr);
+ if (sc->desc == NULL) {
+ ATH5K_ERR(sc, "can't allocate descriptors\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ ds = sc->desc;
+ da = sc->desc_daddr;
+ ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n",
+ ds, sc->desc_len, (unsigned long long)sc->desc_daddr);
+
+ bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF,
+ sizeof(struct ath5k_buf), GFP_KERNEL);
+ if (bf == NULL) {
+ ATH5K_ERR(sc, "can't allocate bufptr\n");
+ ret = -ENOMEM;
+ goto err_free;
+ }
+ sc->bufptr = bf;
+
+ INIT_LIST_HEAD(&sc->rxbuf);
+ for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->rxbuf);
+ }
+
+ INIT_LIST_HEAD(&sc->txbuf);
+ sc->txbuf_len = ATH_TXBUF;
+ for (i = 0; i < ATH_TXBUF; i++, bf++, ds++,
+ da += sizeof(*ds)) {
+ bf->desc = ds;
+ bf->daddr = da;
+ list_add_tail(&bf->list, &sc->txbuf);
+ }
+
+ /* beacon buffer */
+ bf->desc = ds;
+ bf->daddr = da;
+ sc->bbuf = bf;
+
+ return 0;
+err_free:
+ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+err:
+ sc->desc = NULL;
+ return ret;
+}
+
+static void
+ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev)
+{
+ struct ath5k_buf *bf;
+
+ ath5k_txbuf_free(sc, sc->bbuf);
+ list_for_each_entry(bf, &sc->txbuf, list)
+ ath5k_txbuf_free(sc, bf);
+ list_for_each_entry(bf, &sc->rxbuf, list)
+ ath5k_txbuf_free(sc, bf);
+
+ /* Free memory associated with all descriptors */
+ pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr);
+
+ kfree(sc->bufptr);
+ sc->bufptr = NULL;
+}
+
+
+
+
+
+/**************\
+* Queues setup *
+\**************/
+
+static struct ath5k_txq *
+ath5k_txq_setup(struct ath5k_softc *sc,
+ int qtype, int subtype)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq *txq;
+ struct ath5k_txq_info qi = {
+ .tqi_subtype = subtype,
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT
+ };
+ int qnum;
+
+ /*
+ * Enable interrupts only for EOL and DESC conditions.
+ * We mark tx descriptors to receive a DESC interrupt
+ * when a tx queue gets deep; otherwise waiting for the
+ * EOL to reap descriptors. Note that this is done to
+ * reduce interrupt load and this only defers reaping
+ * descriptors, never transmitting frames. Aside from
+ * reducing interrupts this also permits more concurrency.
+ * The only potential downside is if the tx queue backs
+ * up in which case the top half of the kernel may backup
+ * due to a lack of tx descriptors.
+ */
+ qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE |
+ AR5K_TXQ_FLAG_TXDESCINT_ENABLE;
+ qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi);
+ if (qnum < 0) {
+ /*
+ * NB: don't print a message, this happens
+ * normally on parts with too few tx queues
+ */
+ return ERR_PTR(qnum);
+ }
+ if (qnum >= ARRAY_SIZE(sc->txqs)) {
+ ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n",
+ qnum, ARRAY_SIZE(sc->txqs));
+ ath5k_hw_release_tx_queue(ah, qnum);
+ return ERR_PTR(-EINVAL);
+ }
+ txq = &sc->txqs[qnum];
+ if (!txq->setup) {
+ txq->qnum = qnum;
+ txq->link = NULL;
+ INIT_LIST_HEAD(&txq->q);
+ spin_lock_init(&txq->lock);
+ txq->setup = true;
+ }
+ return &sc->txqs[qnum];
+}
+
+static int
+ath5k_beaconq_setup(struct ath5k_hw *ah)
+{
+ struct ath5k_txq_info qi = {
+ .tqi_aifs = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_min = AR5K_TXQ_USEDEFAULT,
+ .tqi_cw_max = AR5K_TXQ_USEDEFAULT,
+ /* NB: for dynamic turbo, don't enable any other interrupts */
+ .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE
+ };
+
+ return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi);
+}
+
+static int
+ath5k_beaconq_config(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_txq_info qi;
+ int ret;
+
+ ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi);
+ if (ret)
+ return ret;
+ if (sc->opmode == IEEE80211_IF_TYPE_AP) {
+ /*
+ * Always burst out beacon and CAB traffic
+ * (aifs = cwmin = cwmax = 0)
+ */
+ qi.tqi_aifs = 0;
+ qi.tqi_cw_min = 0;
+ qi.tqi_cw_max = 0;
+ } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ /*
+ * Adhoc mode; backoff between 0 and (2 * cw_min).
+ */
+ qi.tqi_aifs = 0;
+ qi.tqi_cw_min = 0;
+ qi.tqi_cw_max = 2 * ah->ah_cw_min;
+ }
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n",
+ qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max);
+
+ ret = ath5k_hw_setup_tx_queueprops(ah, sc->bhalq, &qi);
+ if (ret) {
+ ATH5K_ERR(sc, "%s: unable to update parameters for beacon "
+ "hardware queue!\n", __func__);
+ return ret;
+ }
+
+ return ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */;
+}
+
+static void
+ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ath5k_buf *bf, *bf0;
+
+ /*
+ * NB: this assumes output has been stopped and
+ * we do not need to block ath5k_tx_tasklet
+ */
+ spin_lock_bh(&txq->lock);
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ath5k_debug_printtxbuf(sc, bf, !sc->ah->ah_proc_tx_desc(sc->ah,
+ bf->desc));
+
+ ath5k_txbuf_free(sc, bf);
+
+ spin_lock_bh(&sc->txbuflock);
+ sc->tx_stats.data[txq->qnum].len--;
+ list_move_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ spin_unlock_bh(&sc->txbuflock);
+ }
+ txq->link = NULL;
+ spin_unlock_bh(&txq->lock);
+}
+
+/*
+ * Drain the transmit queues and reclaim resources.
+ */
+static void
+ath5k_txq_cleanup(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ unsigned int i;
+
+ /* XXX return value */
+ if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) {
+ /* don't touch the hardware if marked invalid */
+ ath5k_hw_stop_tx_dma(ah, sc->bhalq);
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n",
+ ath5k_hw_get_tx_buf(ah, sc->bhalq));
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
+ if (sc->txqs[i].setup) {
+ ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum);
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, "
+ "link %p\n",
+ sc->txqs[i].qnum,
+ ath5k_hw_get_tx_buf(ah,
+ sc->txqs[i].qnum),
+ sc->txqs[i].link);
+ }
+ }
+ ieee80211_start_queues(sc->hw); /* XXX move to callers */
+
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++)
+ if (sc->txqs[i].setup)
+ ath5k_txq_drainq(sc, &sc->txqs[i]);
+}
+
+static void
+ath5k_txq_release(struct ath5k_softc *sc)
+{
+ struct ath5k_txq *txq = sc->txqs;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++)
+ if (txq->setup) {
+ ath5k_hw_release_tx_queue(sc->ah, txq->qnum);
+ txq->setup = false;
+ }
+}
+
+
+
+
+/*************\
+* RX Handling *
+\*************/
+
+/*
+ * Enable the receive h/w following a reset.
+ */
+static int
+ath5k_rx_start(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_buf *bf;
+ int ret;
+
+ sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
+ sc->cachelsz, sc->rxbufsize);
+
+ sc->rxlink = NULL;
+
+ spin_lock_bh(&sc->rxbuflock);
+ list_for_each_entry(bf, &sc->rxbuf, list) {
+ ret = ath5k_rxbuf_setup(sc, bf);
+ if (ret != 0) {
+ spin_unlock_bh(&sc->rxbuflock);
+ goto err;
+ }
+ }
+ bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ spin_unlock_bh(&sc->rxbuflock);
+
+ ath5k_hw_put_rx_buf(ah, bf->daddr);
+ ath5k_hw_start_rx(ah); /* enable recv descriptors */
+ ath5k_mode_setup(sc); /* set filters, etc. */
+ ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
+
+ return 0;
+err:
+ return ret;
+}
+
+/*
+ * Disable the receive h/w in preparation for a reset.
+ */
+static void
+ath5k_rx_stop(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ ath5k_hw_stop_pcu_recv(ah); /* disable PCU */
+ ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */
+ ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */
+ mdelay(3); /* 3ms is long enough for 1 frame */
+
+ ath5k_debug_printrxbuffs(sc, ah);
+
+ sc->rxlink = NULL; /* just in case */
+}
+
+static unsigned int
+ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
+ struct sk_buff *skb)
+{
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+ unsigned int keyix, hlen = ieee80211_get_hdrlen_from_skb(skb);
+
+ if (!(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+ ds->ds_rxstat.rs_keyix != AR5K_RXKEYIX_INVALID)
+ return RX_FLAG_DECRYPTED;
+
+ /* Apparently when a default key is used to decrypt the packet
+ the hw does not set the index used to decrypt. In such cases
+ get the index from the packet. */
+ if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) &&
+ !(ds->ds_rxstat.rs_status & AR5K_RXERR_DECRYPT) &&
+ skb->len >= hlen + 4) {
+ keyix = skb->data[hlen + 3] >> 6;
+
+ if (test_bit(keyix, sc->keymap))
+ return RX_FLAG_DECRYPTED;
+ }
+
+ return 0;
+}
+
+
+static void
+ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
+{
+ u32 hw_tu;
+ struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
+
+ if ((mgmt->frame_control & IEEE80211_FCTL_FTYPE) ==
+ IEEE80211_FTYPE_MGMT &&
+ (mgmt->frame_control & IEEE80211_FCTL_STYPE) ==
+ IEEE80211_STYPE_BEACON &&
+ mgmt->u.beacon.capab_info & WLAN_CAPABILITY_IBSS &&
+ memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
+ /*
+ * Received an IBSS beacon with the same BSSID. Hardware might
+ * have updated the TSF, check if we need to update timers.
+ */
+ hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
+ if (hw_tu >= sc->nexttbtt) {
+ ath5k_beacon_update_timers(sc,
+ mgmt->u.beacon.timestamp);
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "detected HW merge from received beacon\n");
+ }
+ }
+}
+
+
+static void
+ath5k_tasklet_rx(unsigned long data)
+{
+ struct ieee80211_rx_status rxs = {};
+ struct sk_buff *skb;
+ struct ath5k_softc *sc = (void *)data;
+ struct ath5k_buf *bf;
+ struct ath5k_desc *ds;
+ u16 len;
+ u8 stat;
+ int ret;
+ int hdrlen;
+ int pad;
+
+ spin_lock(&sc->rxbuflock);
+ do {
+ if (unlikely(list_empty(&sc->rxbuf))) {
+ ATH5K_WARN(sc, "empty rx buf pool\n");
+ break;
+ }
+ bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+ BUG_ON(bf->skb == NULL);
+ skb = bf->skb;
+ ds = bf->desc;
+
+ /* TODO only one segment */
+ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
+ sc->desc_len, PCI_DMA_FROMDEVICE);
+
+ if (unlikely(ds->ds_link == bf->daddr)) /* this is the end */
+ break;
+
+ ret = sc->ah->ah_proc_rx_desc(sc->ah, ds);
+ if (unlikely(ret == -EINPROGRESS))
+ break;
+ else if (unlikely(ret)) {
+ ATH5K_ERR(sc, "error in processing rx descriptor\n");
+ return;
+ }
+
+ if (unlikely(ds->ds_rxstat.rs_more)) {
+ ATH5K_WARN(sc, "unsupported jumbo\n");
+ goto next;
+ }
+
+ stat = ds->ds_rxstat.rs_status;
+ if (unlikely(stat)) {
+ if (stat & AR5K_RXERR_PHY)
+ goto next;
+ if (stat & AR5K_RXERR_DECRYPT) {
+ /*
+ * Decrypt error. If the error occurred
+ * because there was no hardware key, then
+ * let the frame through so the upper layers
+ * can process it. This is necessary for 5210
+ * parts which have no way to setup a ``clear''
+ * key cache entry.
+ *
+ * XXX do key cache faulting
+ */
+ if (ds->ds_rxstat.rs_keyix ==
+ AR5K_RXKEYIX_INVALID &&
+ !(stat & AR5K_RXERR_CRC))
+ goto accept;
+ }
+ if (stat & AR5K_RXERR_MIC) {
+ rxs.flag |= RX_FLAG_MMIC_ERROR;
+ goto accept;
+ }
+
+ /* let crypto-error packets fall through in MNTR */
+ if ((stat & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) ||
+ sc->opmode != IEEE80211_IF_TYPE_MNTR)
+ goto next;
+ }
+accept:
+ len = ds->ds_rxstat.rs_datalen;
+ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, len,
+ PCI_DMA_FROMDEVICE);
+ pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+ PCI_DMA_FROMDEVICE);
+ bf->skb = NULL;
+
+ skb_put(skb, len);
+
+ /*
+ * the hardware adds a padding to 4 byte boundaries between
+ * the header and the payload data if the header length is
+ * not multiples of 4 - remove it
+ */
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ if (hdrlen & 3) {
+ pad = hdrlen % 4;
+ memmove(skb->data + pad, skb->data, hdrlen);
+ skb_pull(skb, pad);
+ }
+
+ /*
+ * always extend the mac timestamp, since this information is
+ * also needed for proper IBSS merging.
+ *
+ * XXX: it might be too late to do it here, since rs_tstamp is
+ * 15bit only. that means TSF extension has to be done within
+ * 32768usec (about 32ms). it might be necessary to move this to
+ * the interrupt handler, like it is done in madwifi.
+ */
+ rxs.mactime = ath5k_extend_tsf(sc->ah, ds->ds_rxstat.rs_tstamp);
+ rxs.flag |= RX_FLAG_TSFT;
+
+ rxs.freq = sc->curchan->freq;
+ rxs.channel = sc->curchan->chan;
+ rxs.phymode = sc->curmode;
+
+ /*
+ * signal quality:
+ * the names here are misleading and the usage of these
+ * values by iwconfig makes it even worse
+ */
+ /* noise floor in dBm, from the last noise calibration */
+ rxs.noise = sc->ah->ah_noise_floor;
+ /* signal level in dBm */
+ rxs.ssi = rxs.noise + ds->ds_rxstat.rs_rssi;
+ /*
+ * "signal" is actually displayed as Link Quality by iwconfig
+ * we provide a percentage based on rssi (assuming max rssi 64)
+ */
+ rxs.signal = ds->ds_rxstat.rs_rssi * 100 / 64;
+
+ rxs.antenna = ds->ds_rxstat.rs_antenna;
+ rxs.rate = ds->ds_rxstat.rs_rate;
+ rxs.flag |= ath5k_rx_decrypted(sc, ds, skb);
+
+ ath5k_debug_dump_skb(sc, skb, "RX ", 0);
+
+ /* check beacons in IBSS mode */
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+ ath5k_check_ibss_hw_merge(sc, skb);
+
+ __ieee80211_rx(sc->hw, skb, &rxs);
+ sc->led_rxrate = ds->ds_rxstat.rs_rate;
+ ath5k_led_event(sc, ATH_LED_RX);
+next:
+ list_move_tail(&bf->list, &sc->rxbuf);
+ } while (ath5k_rxbuf_setup(sc, bf) == 0);
+ spin_unlock(&sc->rxbuflock);
+}
+
+
+
+
+/*************\
+* TX Handling *
+\*************/
+
+static void
+ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
+{
+ struct ieee80211_tx_status txs = {};
+ struct ath5k_buf *bf, *bf0;
+ struct ath5k_desc *ds;
+ struct sk_buff *skb;
+ int ret;
+
+ spin_lock(&txq->lock);
+ list_for_each_entry_safe(bf, bf0, &txq->q, list) {
+ ds = bf->desc;
+
+ /* TODO only one segment */
+ pci_dma_sync_single_for_cpu(sc->pdev, sc->desc_daddr,
+ sc->desc_len, PCI_DMA_FROMDEVICE);
+ ret = sc->ah->ah_proc_tx_desc(sc->ah, ds);
+ if (unlikely(ret == -EINPROGRESS))
+ break;
+ else if (unlikely(ret)) {
+ ATH5K_ERR(sc, "error %d while processing queue %u\n",
+ ret, txq->qnum);
+ break;
+ }
+
+ skb = bf->skb;
+ bf->skb = NULL;
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
+ PCI_DMA_TODEVICE);
+
+ txs.control = bf->ctl;
+ txs.retry_count = ds->ds_txstat.ts_shortretry +
+ ds->ds_txstat.ts_longretry / 6;
+ if (unlikely(ds->ds_txstat.ts_status)) {
+ sc->ll_stats.dot11ACKFailureCount++;
+ if (ds->ds_txstat.ts_status & AR5K_TXERR_XRETRY)
+ txs.excessive_retries = 1;
+ else if (ds->ds_txstat.ts_status & AR5K_TXERR_FILT)
+ txs.flags |= IEEE80211_TX_STATUS_TX_FILTERED;
+ } else {
+ txs.flags |= IEEE80211_TX_STATUS_ACK;
+ txs.ack_signal = ds->ds_txstat.ts_rssi;
+ }
+
+ ieee80211_tx_status(sc->hw, skb, &txs);
+ sc->tx_stats.data[txq->qnum].count++;
+
+ spin_lock(&sc->txbuflock);
+ sc->tx_stats.data[txq->qnum].len--;
+ list_move_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ spin_unlock(&sc->txbuflock);
+ }
+ if (likely(list_empty(&txq->q)))
+ txq->link = NULL;
+ spin_unlock(&txq->lock);
+ if (sc->txbuf_len > ATH_TXBUF / 5)
+ ieee80211_wake_queues(sc->hw);
+}
+
+static void
+ath5k_tasklet_tx(unsigned long data)
+{
+ struct ath5k_softc *sc = (void *)data;
+
+ ath5k_tx_processq(sc, sc->txq);
+
+ ath5k_led_event(sc, ATH_LED_TX);
+}
+
+
+
+
+/*****************\
+* Beacon handling *
+\*****************/
+
+/*
+ * Setup the beacon frame for transmit.
+ */
+static int
+ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
+ struct ieee80211_tx_control *ctl)
+{
+ struct sk_buff *skb = bf->skb;
+ struct ath5k_hw *ah = sc->ah;
+ struct ath5k_desc *ds;
+ int ret, antenna = 0;
+ u32 flags;
+
+ bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] "
+ "skbaddr %llx\n", skb, skb->data, skb->len,
+ (unsigned long long)bf->skbaddr);
+ if (pci_dma_mapping_error(bf->skbaddr)) {
+ ATH5K_ERR(sc, "beacon DMA mapping failed\n");
+ return -EIO;
+ }
+
+ ds = bf->desc;
+
+ flags = AR5K_TXDESC_NOACK;
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS && ath5k_hw_hasveol(ah)) {
+ ds->ds_link = bf->daddr; /* self-linked */
+ flags |= AR5K_TXDESC_VEOL;
+ /*
+ * Let hardware handle antenna switching if txantenna is not set
+ */
+ } else {
+ ds->ds_link = 0;
+ /*
+ * Switch antenna every 4 beacons if txantenna is not set
+ * XXX assumes two antennas
+ */
+ if (antenna == 0)
+ antenna = sc->bsent & 4 ? 2 : 1;
+ }
+
+ ds->ds_data = bf->skbaddr;
+ ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN,
+ ieee80211_get_hdrlen_from_skb(skb),
+ AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
+ AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
+ if (ret)
+ goto err_unmap;
+
+ return 0;
+err_unmap:
+ pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE);
+ return ret;
+}
+
+/*
+ * Transmit a beacon frame at SWBA. Dynamic updates to the
+ * frame contents are done as needed and the slot time is
+ * also adjusted based on current state.
+ *
+ * this is usually called from interrupt context (ath5k_intr())
+ * but also from ath5k_beacon_config() in IBSS mode which in turn
+ * can be called from a tasklet and user context
+ */
+static void
+ath5k_beacon_send(struct ath5k_softc *sc)
+{
+ struct ath5k_buf *bf = sc->bbuf;
+ struct ath5k_hw *ah = sc->ah;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "in beacon_send\n");
+
+ if (unlikely(bf->skb == NULL || sc->opmode == IEEE80211_IF_TYPE_STA ||
+ sc->opmode == IEEE80211_IF_TYPE_MNTR)) {
+ ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL);
+ return;
+ }
+ /*
+ * Check if the previous beacon has gone out. If
+ * not don't don't try to post another, skip this
+ * period and wait for the next. Missed beacons
+ * indicate a problem and should not occur. If we
+ * miss too many consecutive beacons reset the device.
+ */
+ if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) {
+ sc->bmisscount++;
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+ "missed %u consecutive beacons\n", sc->bmisscount);
+ if (sc->bmisscount > 3) { /* NB: 3 is a guess */
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+ "stuck beacon time (%u missed)\n",
+ sc->bmisscount);
+ tasklet_schedule(&sc->restq);
+ }
+ return;
+ }
+ if (unlikely(sc->bmisscount != 0)) {
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC,
+ "resume beacon xmit after %u misses\n",
+ sc->bmisscount);
+ sc->bmisscount = 0;
+ }
+
+ /*
+ * Stop any current dma and put the new frame on the queue.
+ * This should never fail since we check above that no frames
+ * are still pending on the queue.
+ */
+ if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) {
+ ATH5K_WARN(sc, "beacon queue %u didn't stop?\n", sc->bhalq);
+ /* NB: hw still stops DMA, so proceed */
+ }
+ pci_dma_sync_single_for_cpu(sc->pdev, bf->skbaddr, bf->skb->len,
+ PCI_DMA_TODEVICE);
+
+ ath5k_hw_put_tx_buf(ah, sc->bhalq, bf->daddr);
+ ath5k_hw_tx_start(ah, sc->bhalq);
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON_PROC, "TXDP[%u] = %llx (%p)\n",
+ sc->bhalq, (unsigned long long)bf->daddr, bf->desc);
+
+ sc->bsent++;
+}
+
+
+/**
+ * ath5k_beacon_update_timers - update beacon timers
+ *
+ * @sc: struct ath5k_softc pointer we are operating on
+ * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a
+ * beacon timer update based on the current HW TSF.
+ *
+ * Calculate the next target beacon transmit time (TBTT) based on the timestamp
+ * of a received beacon or the current local hardware TSF and write it to the
+ * beacon timer registers.
+ *
+ * This is called in a variety of situations, e.g. when a beacon is received,
+ * when a HW merge has been detected, but also when an new IBSS is created or
+ * when we otherwise know we have to update the timers, but we keep it in this
+ * function to have it all together in one place.
+ */
+static void
+ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
+{
+ struct ath5k_hw *ah = sc->ah;
+ u32 nexttbtt, intval, hw_tu, bc_tu;
+ u64 hw_tsf;
+
+ intval = sc->bintval & AR5K_BEACON_PERIOD;
+ if (WARN_ON(!intval))
+ return;
+
+ /* beacon TSF converted to TU */
+ bc_tu = TSF_TO_TU(bc_tsf);
+
+ /* current TSF converted to TU */
+ hw_tsf = ath5k_hw_get_tsf64(ah);
+ hw_tu = TSF_TO_TU(hw_tsf);
+
+#define FUDGE 3
+ /* we use FUDGE to make sure the next TBTT is ahead of the current TU */
+ if (bc_tsf == -1) {
+ /*
+ * no beacons received, called internally.
+ * just need to refresh timers based on HW TSF.
+ */
+ nexttbtt = roundup(hw_tu + FUDGE, intval);
+ } else if (bc_tsf == 0) {
+ /*
+ * no beacon received, probably called by ath5k_reset_tsf().
+ * reset TSF to start with 0.
+ */
+ nexttbtt = intval;
+ intval |= AR5K_BEACON_RESET_TSF;
+ } else if (bc_tsf > hw_tsf) {
+ /*
+ * beacon received, SW merge happend but HW TSF not yet updated.
+ * not possible to reconfigure timers yet, but next time we
+ * receive a beacon with the same BSSID, the hardware will
+ * automatically update the TSF and then we need to reconfigure
+ * the timers.
+ */
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "need to wait for HW TSF sync\n");
+ return;
+ } else {
+ /*
+ * most important case for beacon synchronization between STA.
+ *
+ * beacon received and HW TSF has been already updated by HW.
+ * update next TBTT based on the TSF of the beacon, but make
+ * sure it is ahead of our local TSF timer.
+ */
+ nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval);
+ }
+#undef FUDGE
+
+ sc->nexttbtt = nexttbtt;
+
+ intval |= AR5K_BEACON_ENA;
+ ath5k_hw_init_beacon(ah, nexttbtt, intval);
+
+ /*
+ * debugging output last in order to preserve the time critical aspect
+ * of this function
+ */
+ if (bc_tsf == -1)
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "reconfigured timers based on HW TSF\n");
+ else if (bc_tsf == 0)
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "reset HW TSF and timers\n");
+ else
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "updated timers based on beacon TSF\n");
+
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n",
+ bc_tsf, hw_tsf, bc_tu, hw_tu, nexttbtt);
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n",
+ intval & AR5K_BEACON_PERIOD,
+ intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "",
+ intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : "");
+}
+
+
+/**
+ * ath5k_beacon_config - Configure the beacon queues and interrupts
+ *
+ * @sc: struct ath5k_softc pointer we are operating on
+ *
+ * When operating in station mode we want to receive a BMISS interrupt when we
+ * stop seeing beacons from the AP we've associated with so we can look for
+ * another AP to associate with.
+ *
+ * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
+ * interrupts to detect HW merges only.
+ *
+ * AP mode is missing.
+ */
+static void
+ath5k_beacon_config(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ ath5k_hw_set_intr(ah, 0);
+ sc->bmisscount = 0;
+
+ if (sc->opmode == IEEE80211_IF_TYPE_STA) {
+ sc->imask |= AR5K_INT_BMISS;
+ } else if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ /*
+ * In IBSS mode we use a self-linked tx descriptor and let the
+ * hardware send the beacons automatically. We have to load it
+ * only once here.
+ * We use the SWBA interrupt only to keep track of the beacon
+ * timers in order to detect HW merges (automatic TSF updates).
+ */
+ ath5k_beaconq_config(sc);
+
+ sc->imask |= AR5K_INT_SWBA;
+
+ if (ath5k_hw_hasveol(ah))
+ ath5k_beacon_send(sc);
+ }
+ /* TODO else AP */
+
+ ath5k_hw_set_intr(ah, sc->imask);
+}
+
+
+/********************\
+* Interrupt handling *
+\********************/
+
+static int
+ath5k_init(struct ath5k_softc *sc)
+{
+ int ret;
+
+ mutex_lock(&sc->lock);
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
+
+ /*
+ * Stop anything previously setup. This is safe
+ * no matter this is the first time through or not.
+ */
+ ath5k_stop_locked(sc);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ sc->curchan = sc->hw->conf.chan;
+ ret = ath5k_hw_reset(sc->ah, sc->opmode, sc->curchan, false);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to reset hardware: %d\n", ret);
+ goto done;
+ }
+ /*
+ * This is needed only to setup initial state
+ * but it's best done after a reset.
+ */
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
+
+ /*
+ * Setup the hardware after reset: the key cache
+ * is filled as needed and the receive engine is
+ * set going. Frame transmit is handled entirely
+ * in the frame output path; there's nothing to do
+ * here except setup the interrupt mask.
+ */
+ ret = ath5k_rx_start(sc);
+ if (ret)
+ goto done;
+
+ /*
+ * Enable interrupts.
+ */
+ sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
+ AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL;
+
+ ath5k_hw_set_intr(sc->ah, sc->imask);
+ /* Set ack to be sent at low bit-rates */
+ ath5k_hw_set_ack_bitrate_high(sc->ah, false);
+
+ mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+ msecs_to_jiffies(ath5k_calinterval * 1000)));
+
+ ret = 0;
+done:
+ mutex_unlock(&sc->lock);
+ return ret;
+}
+
+static int
+ath5k_stop_locked(struct ath5k_softc *sc)
+{
+ struct ath5k_hw *ah = sc->ah;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n",
+ test_bit(ATH_STAT_INVALID, sc->status));
+
+ /*
+ * Shutdown the hardware and driver:
+ * stop output from above
+ * disable interrupts
+ * turn off timers
+ * turn off the radio
+ * clear transmit machinery
+ * clear receive machinery
+ * drain and release tx queues
+ * reclaim beacon resources
+ * power down hardware
+ *
+ * Note that some of this work is not possible if the
+ * hardware is gone (invalid).
+ */
+ ieee80211_stop_queues(sc->hw);
+
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+ if (test_bit(ATH_STAT_LEDSOFT, sc->status)) {
+ del_timer_sync(&sc->led_tim);
+ ath5k_hw_set_gpio(ah, sc->led_pin, !sc->led_on);
+ __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
+ }
+ ath5k_hw_set_intr(ah, 0);
+ }
+ ath5k_txq_cleanup(sc);
+ if (!test_bit(ATH_STAT_INVALID, sc->status)) {
+ ath5k_rx_stop(sc);
+ ath5k_hw_phy_disable(ah);
+ } else
+ sc->rxlink = NULL;
+
+ return 0;
+}
+
+/*
+ * Stop the device, grabbing the top-level lock to protect
+ * against concurrent entry through ath5k_init (which can happen
+ * if another thread does a system call and the thread doing the
+ * stop is preempted).
+ */
+static int
+ath5k_stop_hw(struct ath5k_softc *sc)
+{
+ int ret;
+
+ mutex_lock(&sc->lock);
+ ret = ath5k_stop_locked(sc);
+ if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
+ /*
+ * Set the chip in full sleep mode. Note that we are
+ * careful to do this only when bringing the interface
+ * completely to a stop. When the chip is in this state
+ * it must be carefully woken up or references to
+ * registers in the PCI clock domain may freeze the bus
+ * (and system). This varies by chip and is mostly an
+ * issue with newer parts that go to sleep more quickly.
+ */
+ if (sc->ah->ah_mac_srev >= 0x78) {
+ /*
+ * XXX
+ * don't put newer MAC revisions > 7.8 to sleep because
+ * of the above mentioned problems
+ */
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, "
+ "not putting device to sleep\n");
+ } else {
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
+ "putting device to full sleep\n");
+ ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0);
+ }
+ }
+ ath5k_txbuf_free(sc, sc->bbuf);
+ mutex_unlock(&sc->lock);
+
+ del_timer_sync(&sc->calib_tim);
+
+ return ret;
+}
+
+static irqreturn_t
+ath5k_intr(int irq, void *dev_id)
+{
+ struct ath5k_softc *sc = dev_id;
+ struct ath5k_hw *ah = sc->ah;
+ enum ath5k_int status;
+ unsigned int counter = 1000;
+
+ if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) ||
+ !ath5k_hw_is_intr_pending(ah)))
+ return IRQ_NONE;
+
+ do {
+ /*
+ * Figure out the reason(s) for the interrupt. Note
+ * that get_isr returns a pseudo-ISR that may include
+ * bits we haven't explicitly enabled so we mask the
+ * value to insure we only process bits we requested.
+ */
+ ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */
+ ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n",
+ status, sc->imask);
+ status &= sc->imask; /* discard unasked for bits */
+ if (unlikely(status & AR5K_INT_FATAL)) {
+ /*
+ * Fatal errors are unrecoverable.
+ * Typically these are caused by DMA errors.
+ */
+ tasklet_schedule(&sc->restq);
+ } else if (unlikely(status & AR5K_INT_RXORN)) {
+ tasklet_schedule(&sc->restq);
+ } else {
+ if (status & AR5K_INT_SWBA) {
+ /*
+ * Software beacon alert--time to send a beacon.
+ * Handle beacon transmission directly; deferring
+ * this is too slow to meet timing constraints
+ * under load.
+ *
+ * In IBSS mode we use this interrupt just to
+ * keep track of the next TBTT (target beacon
+ * transmission time) in order to detect hardware
+ * merges (TSF updates).
+ */
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ /* XXX: only if VEOL suppported */
+ u64 tsf = ath5k_hw_get_tsf64(ah);
+ sc->nexttbtt += sc->bintval;
+ ATH5K_DBG(sc, ATH5K_DEBUG_BEACON,
+ "SWBA nexttbtt: %x hw_tu: %x "
+ "TSF: %llx\n",
+ sc->nexttbtt,
+ TSF_TO_TU(tsf), tsf);
+ } else {
+ ath5k_beacon_send(sc);
+ }
+ }
+ if (status & AR5K_INT_RXEOL) {
+ /*
+ * NB: the hardware should re-read the link when
+ * RXE bit is written, but it doesn't work at
+ * least on older hardware revs.
+ */
+ sc->rxlink = NULL;
+ }
+ if (status & AR5K_INT_TXURN) {
+ /* bump tx trigger level */
+ ath5k_hw_update_tx_triglevel(ah, true);
+ }
+ if (status & AR5K_INT_RX)
+ tasklet_schedule(&sc->rxtq);
+ if (status & AR5K_INT_TX)
+ tasklet_schedule(&sc->txtq);
+ if (status & AR5K_INT_BMISS) {
+ }
+ if (status & AR5K_INT_MIB) {
+ /* TODO */
+ }
+ }
+ } while (ath5k_hw_is_intr_pending(ah) && counter-- > 0);
+
+ if (unlikely(!counter))
+ ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
+
+ return IRQ_HANDLED;
+}
+
+static void
+ath5k_tasklet_reset(unsigned long data)
+{
+ struct ath5k_softc *sc = (void *)data;
+
+ ath5k_reset(sc->hw);
+}
+
+/*
+ * Periodically recalibrate the PHY to account
+ * for temperature/environment changes.
+ */
+static void
+ath5k_calibrate(unsigned long data)
+{
+ struct ath5k_softc *sc = (void *)data;
+ struct ath5k_hw *ah = sc->ah;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
+ sc->curchan->chan, sc->curchan->val);
+
+ if (ath5k_hw_get_rf_gain(ah) == AR5K_RFGAIN_NEED_CHANGE) {
+ /*
+ * Rfgain is out of bounds, reset the chip
+ * to load new gain values.
+ */
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n");
+ ath5k_reset(sc->hw);
+ }
+ if (ath5k_hw_phy_calibrate(ah, sc->curchan))
+ ATH5K_ERR(sc, "calibration of channel %u failed\n",
+ sc->curchan->chan);
+
+ mod_timer(&sc->calib_tim, round_jiffies(jiffies +
+ msecs_to_jiffies(ath5k_calinterval * 1000)));
+}
+
+
+
+/***************\
+* LED functions *
+\***************/
+
+static void
+ath5k_led_off(unsigned long data)
+{
+ struct ath5k_softc *sc = (void *)data;
+
+ if (test_bit(ATH_STAT_LEDENDBLINK, sc->status))
+ __clear_bit(ATH_STAT_LEDBLINKING, sc->status);
+ else {
+ __set_bit(ATH_STAT_LEDENDBLINK, sc->status);
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on);
+ mod_timer(&sc->led_tim, jiffies + sc->led_off);
+ }
+}
+
+/*
+ * Blink the LED according to the specified on/off times.
+ */
+static void
+ath5k_led_blink(struct ath5k_softc *sc, unsigned int on,
+ unsigned int off)
+{
+ ATH5K_DBG(sc, ATH5K_DEBUG_LED, "on %u off %u\n", on, off);
+ ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on);
+ __set_bit(ATH_STAT_LEDBLINKING, sc->status);
+ __clear_bit(ATH_STAT_LEDENDBLINK, sc->status);
+ sc->led_off = off;
+ mod_timer(&sc->led_tim, jiffies + on);
+}
+
+static void
+ath5k_led_event(struct ath5k_softc *sc, int event)
+{
+ if (likely(!test_bit(ATH_STAT_LEDSOFT, sc->status)))
+ return;
+ if (unlikely(test_bit(ATH_STAT_LEDBLINKING, sc->status)))
+ return; /* don't interrupt active blink */
+ switch (event) {
+ case ATH_LED_TX:
+ ath5k_led_blink(sc, sc->hwmap[sc->led_txrate].ledon,
+ sc->hwmap[sc->led_txrate].ledoff);
+ break;
+ case ATH_LED_RX:
+ ath5k_led_blink(sc, sc->hwmap[sc->led_rxrate].ledon,
+ sc->hwmap[sc->led_rxrate].ledoff);
+ break;
+ }
+}
+
+
+
+
+/********************\
+* Mac80211 functions *
+\********************/
+
+static int
+ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_buf *bf;
+ unsigned long flags;
+ int hdrlen;
+ int pad;
+
+ ath5k_debug_dump_skb(sc, skb, "TX ", 1);
+
+ if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
+ ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n");
+
+ /*
+ * the hardware expects the header padded to 4 byte boundaries
+ * if this is not the case we add the padding after the header
+ */
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ if (hdrlen & 3) {
+ pad = hdrlen % 4;
+ if (skb_headroom(skb) < pad) {
+ ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
+ " headroom to pad %d\n", hdrlen, pad);
+ return -1;
+ }
+ skb_push(skb, pad);
+ memmove(skb->data, skb->data+pad, hdrlen);
+ }
+
+ sc->led_txrate = ctl->tx_rate;
+
+ spin_lock_irqsave(&sc->txbuflock, flags);
+ if (list_empty(&sc->txbuf)) {
+ ATH5K_ERR(sc, "no further txbuf available, dropping packet\n");
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+ ieee80211_stop_queue(hw, ctl->queue);
+ return -1;
+ }
+ bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list);
+ list_del(&bf->list);
+ sc->txbuf_len--;
+ if (list_empty(&sc->txbuf))
+ ieee80211_stop_queues(hw);
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+
+ bf->skb = skb;
+
+ if (ath5k_txbuf_setup(sc, bf, ctl)) {
+ bf->skb = NULL;
+ spin_lock_irqsave(&sc->txbuflock, flags);
+ list_add_tail(&bf->list, &sc->txbuf);
+ sc->txbuf_len++;
+ spin_unlock_irqrestore(&sc->txbuflock, flags);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
+ return 0;
+}
+
+static int
+ath5k_reset(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+ /*
+ * Convert to a hw channel description with the flags
+ * constrained to reflect the current operating mode.
+ */
+ sc->curchan = hw->conf.chan;
+
+ ath5k_hw_set_intr(ah, 0);
+ ath5k_txq_cleanup(sc);
+ ath5k_rx_stop(sc);
+
+ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, true);
+ if (unlikely(ret)) {
+ ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+ goto err;
+ }
+ ath5k_hw_set_txpower_limit(sc->ah, 0);
+
+ ret = ath5k_rx_start(sc);
+ if (unlikely(ret)) {
+ ATH5K_ERR(sc, "can't start recv logic\n");
+ goto err;
+ }
+ /*
+ * We may be doing a reset in response to an ioctl
+ * that changes the channel so update any state that
+ * might change as a result.
+ *
+ * XXX needed?
+ */
+/* ath5k_chan_change(sc, c); */
+ ath5k_beacon_config(sc);
+ /* intrs are started by ath5k_beacon_config */
+
+ ieee80211_wake_queues(hw);
+
+ return 0;
+err:
+ return ret;
+}
+
+static int ath5k_start(struct ieee80211_hw *hw)
+{
+ return ath5k_init(hw->priv);
+}
+
+static void ath5k_stop(struct ieee80211_hw *hw)
+{
+ ath5k_stop_hw(hw->priv);
+}
+
+static int ath5k_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct ath5k_softc *sc = hw->priv;
+ int ret;
+
+ mutex_lock(&sc->lock);
+ if (sc->vif) {
+ ret = 0;
+ goto end;
+ }
+
+ sc->vif = conf->vif;
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_STA:
+ case IEEE80211_IF_TYPE_IBSS:
+ case IEEE80211_IF_TYPE_MNTR:
+ sc->opmode = conf->type;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto end;
+ }
+ ret = 0;
+end:
+ mutex_unlock(&sc->lock);
+ return ret;
+}
+
+static void
+ath5k_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ mutex_lock(&sc->lock);
+ if (sc->vif != conf->vif)
+ goto end;
+
+ sc->vif = NULL;
+end:
+ mutex_unlock(&sc->lock);
+}
+
+static int
+ath5k_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ sc->bintval = conf->beacon_int;
+ ath5k_setcurmode(sc, conf->phymode);
+
+ return ath5k_chan_set(sc, conf->chan);
+}
+
+static int
+ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ int ret;
+
+ /* Set to a reasonable value. Note that this will
+ * be set to mac80211's value at ath5k_config(). */
+ sc->bintval = 1000;
+ mutex_lock(&sc->lock);
+ if (sc->vif != vif) {
+ ret = -EIO;
+ goto unlock;
+ }
+ if (conf->bssid) {
+ /* Cache for later use during resets */
+ memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
+ /* XXX: assoc id is set to 0 for now, mac80211 doesn't have
+ * a clean way of letting us retrieve this yet. */
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ }
+ mutex_unlock(&sc->lock);
+
+ return ath5k_reset(hw);
+unlock:
+ mutex_unlock(&sc->lock);
+ return ret;
+}
+
+#define SUPPORTED_FIF_FLAGS \
+ FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \
+ FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \
+ FIF_BCN_PRBRESP_PROMISC
+/*
+ * o always accept unicast, broadcast, and multicast traffic
+ * o multicast traffic for all BSSIDs will be enabled if mac80211
+ * says it should be
+ * o maintain current state of phy ofdm or phy cck error reception.
+ * If the hardware detects any of these type of errors then
+ * ath5k_hw_get_rx_filter() will pass to us the respective
+ * hardware filters to be able to receive these type of frames.
+ * o probe request frames are accepted only when operating in
+ * hostap, adhoc, or monitor modes
+ * o enable promiscuous mode according to the interface state
+ * o accept beacons:
+ * - when operating in adhoc mode so the 802.11 layer creates
+ * node table entries for peers,
+ * - when operating in station mode for collecting rssi data when
+ * the station is otherwise quiet, or
+ * - when scanning
+ */
+static void ath5k_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ struct ath5k_softc *sc = hw->priv;
+ struct ath5k_hw *ah = sc->ah;
+ u32 mfilt[2], val, rfilt;
+ u8 pos;
+ int i;
+
+ mfilt[0] = 0;
+ mfilt[1] = 0;
+
+ /* Only deal with supported flags */
+ changed_flags &= SUPPORTED_FIF_FLAGS;
+ *new_flags &= SUPPORTED_FIF_FLAGS;
+
+ /* If HW detects any phy or radar errors, leave those filters on.
+ * Also, always enable Unicast, Broadcasts and Multicast
+ * XXX: move unicast, bssid broadcasts and multicast to mac80211 */
+ rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) |
+ (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST |
+ AR5K_RX_FILTER_MCAST);
+
+ if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
+ if (*new_flags & FIF_PROMISC_IN_BSS) {
+ rfilt |= AR5K_RX_FILTER_PROM;
+ __set_bit(ATH_STAT_PROMISC, sc->status);
+ }
+ else
+ __clear_bit(ATH_STAT_PROMISC, sc->status);
+ }
+
+ /* Note, AR5K_RX_FILTER_MCAST is already enabled */
+ if (*new_flags & FIF_ALLMULTI) {
+ mfilt[0] = ~0;
+ mfilt[1] = ~0;
+ } else {
+ for (i = 0; i < mc_count; i++) {
+ if (!mclist)
+ break;
+ /* calculate XOR of eight 6-bit values */
+ val = LE_READ_4(mclist->dmi_addr + 0);
+ pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ val = LE_READ_4(mclist->dmi_addr + 3);
+ pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
+ pos &= 0x3f;
+ mfilt[pos / 32] |= (1 << (pos % 32));
+ /* XXX: we might be able to just do this instead,
+ * but not sure, needs testing, if we do use this we'd
+ * neet to inform below to not reset the mcast */
+ /* ath5k_hw_set_mcast_filterindex(ah,
+ * mclist->dmi_addr[5]); */
+ mclist = mclist->next;
+ }
+ }
+
+ /* This is the best we can do */
+ if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL))
+ rfilt |= AR5K_RX_FILTER_PHYERR;
+
+ /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons
+ * and probes for any BSSID, this needs testing */
+ if (*new_flags & FIF_BCN_PRBRESP_PROMISC)
+ rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ;
+
+ /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not
+ * set we should only pass on control frames for this
+ * station. This needs testing. I believe right now this
+ * enables *all* control frames, which is OK.. but
+ * but we should see if we can improve on granularity */
+ if (*new_flags & FIF_CONTROL)
+ rfilt |= AR5K_RX_FILTER_CONTROL;
+
+ /* Additional settings per mode -- this is per ath5k */
+
+ /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */
+
+ if (sc->opmode == IEEE80211_IF_TYPE_MNTR)
+ rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
+ AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
+ if (sc->opmode != IEEE80211_IF_TYPE_STA)
+ rfilt |= AR5K_RX_FILTER_PROBEREQ;
+ if (sc->opmode != IEEE80211_IF_TYPE_AP &&
+ test_bit(ATH_STAT_PROMISC, sc->status))
+ rfilt |= AR5K_RX_FILTER_PROM;
+ if (sc->opmode == IEEE80211_IF_TYPE_STA ||
+ sc->opmode == IEEE80211_IF_TYPE_IBSS) {
+ rfilt |= AR5K_RX_FILTER_BEACON;
+ }
+
+ /* Set filters */
+ ath5k_hw_set_rx_filter(ah,rfilt);
+
+ /* Set multicast bits */
+ ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
+ /* Set the cached hw filter flags, this will alter actually
+ * be set in HW */
+ sc->filter_flags = rfilt;
+}
+
+static int
+ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_addr, const u8 *addr,
+ struct ieee80211_key_conf *key)
+{
+ struct ath5k_softc *sc = hw->priv;
+ int ret = 0;
+
+ switch(key->alg) {
+ case ALG_WEP:
+ break;
+ case ALG_TKIP:
+ case ALG_CCMP:
+ return -EOPNOTSUPP;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ mutex_lock(&sc->lock);
+
+ switch (cmd) {
+ case SET_KEY:
+ ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr);
+ if (ret) {
+ ATH5K_ERR(sc, "can't set the key\n");
+ goto unlock;
+ }
+ __set_bit(key->keyidx, sc->keymap);
+ key->hw_key_idx = key->keyidx;
+ break;
+ case DISABLE_KEY:
+ ath5k_hw_reset_key(sc->ah, key->keyidx);
+ __clear_bit(key->keyidx, sc->keymap);
+ break;
+ default:
+ ret = -EINVAL;
+ goto unlock;
+ }
+
+unlock:
+ mutex_unlock(&sc->lock);
+ return ret;
+}
+
+static int
+ath5k_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats));
+
+ return 0;
+}
+
+static int
+ath5k_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats));
+
+ return 0;
+}
+
+static u64
+ath5k_get_tsf(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ return ath5k_hw_get_tsf64(sc->ah);
+}
+
+static void
+ath5k_reset_tsf(struct ieee80211_hw *hw)
+{
+ struct ath5k_softc *sc = hw->priv;
+
+ /*
+ * in IBSS mode we need to update the beacon timers too.
+ * this will also reset the TSF if we call it with 0
+ */
+ if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
+ ath5k_beacon_update_timers(sc, 0);
+ else
+ ath5k_hw_reset_tsf(sc->ah);
+}
+
+static int
+ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
+{
+ struct ath5k_softc *sc = hw->priv;
+ int ret;
+
+ ath5k_debug_dump_skb(sc, skb, "BC ", 1);
+
+ mutex_lock(&sc->lock);
+
+ if (sc->opmode != IEEE80211_IF_TYPE_IBSS) {
+ ret = -EIO;
+ goto end;
+ }
+
+ ath5k_txbuf_free(sc, sc->bbuf);
+ sc->bbuf->skb = skb;
+ ret = ath5k_beacon_setup(sc, sc->bbuf, ctl);
+ if (ret)
+ sc->bbuf->skb = NULL;
+ else
+ ath5k_beacon_config(sc);
+
+end:
+ mutex_unlock(&sc->lock);
+ return ret;
+}
+
diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h
new file mode 100644
index 000000000000..8287ae787f12
--- /dev/null
+++ b/drivers/net/wireless/ath5k/base.h
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ */
+
+/*
+ * Defintions for the Atheros Wireless LAN controller driver.
+ */
+#ifndef _DEV_ATH_ATHVAR_H
+#define _DEV_ATH_ATHVAR_H
+
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/wireless.h>
+#include <linux/if_ether.h>
+
+#include "ath5k.h"
+#include "debug.h"
+
+#define ATH_RXBUF 40 /* number of RX buffers */
+#define ATH_TXBUF 200 /* number of TX buffers */
+#define ATH_BCBUF 1 /* number of beacon buffers */
+
+struct ath5k_buf {
+ struct list_head list;
+ unsigned int flags; /* tx descriptor flags */
+ struct ath5k_desc *desc; /* virtual addr of desc */
+ dma_addr_t daddr; /* physical addr of desc */
+ struct sk_buff *skb; /* skbuff for buf */
+ dma_addr_t skbaddr;/* physical addr of skb data */
+ struct ieee80211_tx_control ctl;
+};
+
+/*
+ * Data transmit queue state. One of these exists for each
+ * hardware transmit queue. Packets sent to us from above
+ * are assigned to queues based on their priority. Not all
+ * devices support a complete set of hardware transmit queues.
+ * For those devices the array sc_ac2q will map multiple
+ * priorities to fewer hardware queues (typically all to one
+ * hardware queue).
+ */
+struct ath5k_txq {
+ unsigned int qnum; /* hardware q number */
+ u32 *link; /* link ptr in last TX desc */
+ struct list_head q; /* transmit queue */
+ spinlock_t lock; /* lock on q and link */
+ bool setup;
+};
+
+#if CHAN_DEBUG
+#define ATH_CHAN_MAX (26+26+26+200+200)
+#else
+#define ATH_CHAN_MAX (14+14+14+252+20) /* XXX what's the max? */
+#endif
+
+/* Software Carrier, keeps track of the driver state
+ * associated with an instance of a device */
+struct ath5k_softc {
+ struct pci_dev *pdev; /* for dma mapping */
+ void __iomem *iobase; /* address of the device */
+ struct mutex lock; /* dev-level lock */
+ struct ieee80211_tx_queue_stats tx_stats;
+ struct ieee80211_low_level_stats ll_stats;
+ struct ieee80211_hw *hw; /* IEEE 802.11 common */
+ struct ieee80211_hw_mode modes[NUM_DRIVER_MODES];
+ struct ieee80211_channel channels[ATH_CHAN_MAX];
+ struct ieee80211_rate rates[AR5K_MAX_RATES * NUM_DRIVER_MODES];
+ enum ieee80211_if_types opmode;
+ struct ath5k_hw *ah; /* Atheros HW */
+
+#if ATH5K_DEBUG
+ struct ath5k_dbg_info debug; /* debug info */
+#endif
+
+ struct ath5k_buf *bufptr; /* allocated buffer ptr */
+ struct ath5k_desc *desc; /* TX/RX descriptors */
+ dma_addr_t desc_daddr; /* DMA (physical) address */
+ size_t desc_len; /* size of TX/RX descriptors */
+ u16 cachelsz; /* cache line size */
+
+ DECLARE_BITMAP(status, 6);
+#define ATH_STAT_INVALID 0 /* disable hardware accesses */
+#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */
+#define ATH_STAT_PROMISC 2
+#define ATH_STAT_LEDBLINKING 3 /* LED blink operation active */
+#define ATH_STAT_LEDENDBLINK 4 /* finish LED blink operation */
+#define ATH_STAT_LEDSOFT 5 /* enable LED gpio status */
+
+ unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */
+ unsigned int curmode; /* current phy mode */
+ struct ieee80211_channel *curchan; /* current h/w channel */
+
+ struct ieee80211_vif *vif;
+
+ struct {
+ u8 rxflags; /* radiotap rx flags */
+ u8 txflags; /* radiotap tx flags */
+ u16 ledon; /* softled on time */
+ u16 ledoff; /* softled off time */
+ } hwmap[32]; /* h/w rate ix mappings */
+
+ enum ath5k_int imask; /* interrupt mask copy */
+
+ DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
+
+ u8 bssidmask[ETH_ALEN];
+
+ unsigned int led_pin, /* GPIO pin for driving LED */
+ led_on, /* pin setting for LED on */
+ led_off; /* off time for current blink */
+ struct timer_list led_tim; /* led off timer */
+ u8 led_rxrate; /* current rx rate for LED */
+ u8 led_txrate; /* current tx rate for LED */
+
+ struct tasklet_struct restq; /* reset tasklet */
+
+ unsigned int rxbufsize; /* rx size based on mtu */
+ struct list_head rxbuf; /* receive buffer */
+ spinlock_t rxbuflock;
+ u32 *rxlink; /* link ptr in last RX desc */
+ struct tasklet_struct rxtq; /* rx intr tasklet */
+
+ struct list_head txbuf; /* transmit buffer */
+ spinlock_t txbuflock;
+ unsigned int txbuf_len; /* buf count in txbuf list */
+ struct ath5k_txq txqs[2]; /* beacon and tx */
+
+ struct ath5k_txq *txq; /* beacon and tx*/
+ struct tasklet_struct txtq; /* tx intr tasklet */
+
+ struct ath5k_buf *bbuf; /* beacon buffer */
+ unsigned int bhalq, /* SW q for outgoing beacons */
+ bmisscount, /* missed beacon transmits */
+ bintval, /* beacon interval in TU */
+ bsent;
+ unsigned int nexttbtt; /* next beacon time in TU */
+
+ struct timer_list calib_tim; /* calibration timer */
+};
+
+#define ath5k_hw_hasbssidmask(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
+#define ath5k_hw_hasveol(_ah) \
+ (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
+
+#endif
diff --git a/drivers/net/wireless/ath5k/debug.c b/drivers/net/wireless/ath5k/debug.c
new file mode 100644
index 000000000000..4ba649e20269
--- /dev/null
+++ b/drivers/net/wireless/ath5k/debug.c
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
+ *
+ * This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include "debug.h"
+#include "base.h"
+
+static unsigned int ath5k_debug;
+module_param_named(debug, ath5k_debug, uint, 0);
+
+
+#if ATH5K_DEBUG
+
+#include <linux/seq_file.h>
+#include "reg.h"
+
+static struct dentry *ath5k_global_debugfs;
+
+static int ath5k_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+
+/* debugfs: registers */
+
+struct reg {
+ char *name;
+ int addr;
+};
+
+#define REG_STRUCT_INIT(r) { #r, r }
+
+/* just a few random registers, might want to add more */
+static struct reg regs[] = {
+ REG_STRUCT_INIT(AR5K_CR),
+ REG_STRUCT_INIT(AR5K_RXDP),
+ REG_STRUCT_INIT(AR5K_CFG),
+ REG_STRUCT_INIT(AR5K_IER),
+ REG_STRUCT_INIT(AR5K_BCR),
+ REG_STRUCT_INIT(AR5K_RTSD0),
+ REG_STRUCT_INIT(AR5K_RTSD1),
+ REG_STRUCT_INIT(AR5K_TXCFG),
+ REG_STRUCT_INIT(AR5K_RXCFG),
+ REG_STRUCT_INIT(AR5K_RXJLA),
+ REG_STRUCT_INIT(AR5K_MIBC),
+ REG_STRUCT_INIT(AR5K_TOPS),
+ REG_STRUCT_INIT(AR5K_RXNOFRM),
+ REG_STRUCT_INIT(AR5K_TXNOFRM),
+ REG_STRUCT_INIT(AR5K_RPGTO),
+ REG_STRUCT_INIT(AR5K_RFCNT),
+ REG_STRUCT_INIT(AR5K_MISC),
+ REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT),
+ REG_STRUCT_INIT(AR5K_ISR),
+ REG_STRUCT_INIT(AR5K_PISR),
+ REG_STRUCT_INIT(AR5K_SISR0),
+ REG_STRUCT_INIT(AR5K_SISR1),
+ REG_STRUCT_INIT(AR5K_SISR2),
+ REG_STRUCT_INIT(AR5K_SISR3),
+ REG_STRUCT_INIT(AR5K_SISR4),
+ REG_STRUCT_INIT(AR5K_IMR),
+ REG_STRUCT_INIT(AR5K_PIMR),
+ REG_STRUCT_INIT(AR5K_SIMR0),
+ REG_STRUCT_INIT(AR5K_SIMR1),
+ REG_STRUCT_INIT(AR5K_SIMR2),
+ REG_STRUCT_INIT(AR5K_SIMR3),
+ REG_STRUCT_INIT(AR5K_SIMR4),
+ REG_STRUCT_INIT(AR5K_DCM_ADDR),
+ REG_STRUCT_INIT(AR5K_DCCFG),
+ REG_STRUCT_INIT(AR5K_CCFG),
+ REG_STRUCT_INIT(AR5K_CPC0),
+ REG_STRUCT_INIT(AR5K_CPC1),
+ REG_STRUCT_INIT(AR5K_CPC2),
+ REG_STRUCT_INIT(AR5K_CPC3),
+ REG_STRUCT_INIT(AR5K_CPCORN),
+ REG_STRUCT_INIT(AR5K_RESET_CTL),
+ REG_STRUCT_INIT(AR5K_SLEEP_CTL),
+ REG_STRUCT_INIT(AR5K_INTPEND),
+ REG_STRUCT_INIT(AR5K_SFR),
+ REG_STRUCT_INIT(AR5K_PCICFG),
+ REG_STRUCT_INIT(AR5K_GPIOCR),
+ REG_STRUCT_INIT(AR5K_GPIODO),
+ REG_STRUCT_INIT(AR5K_SREV),
+};
+
+static void *reg_start(struct seq_file *seq, loff_t *pos)
+{
+ return *pos < ARRAY_SIZE(regs) ? &regs[*pos] : NULL;
+}
+
+static void reg_stop(struct seq_file *seq, void *p)
+{
+ /* nothing to do */
+}
+
+static void *reg_next(struct seq_file *seq, void *p, loff_t *pos)
+{
+ ++*pos;
+ return *pos < ARRAY_SIZE(regs) ? &regs[*pos] : NULL;
+}
+
+static int reg_show(struct seq_file *seq, void *p)
+{
+ struct ath5k_softc *sc = seq->private;
+ struct reg *r = p;
+ seq_printf(seq, "%-25s0x%08x\n", r->name,
+ ath5k_hw_reg_read(sc->ah, r->addr));
+ return 0;
+}
+
+static struct seq_operations register_seq_ops = {
+ .start = reg_start,
+ .next = reg_next,
+ .stop = reg_stop,
+ .show = reg_show
+};
+
+static int open_file_registers(struct inode *inode, struct file *file)
+{
+ struct seq_file *s;
+ int res;
+ res = seq_open(file, &register_seq_ops);
+ if (res == 0) {
+ s = file->private_data;
+ s->private = inode->i_private;
+ }
+ return res;
+}
+
+static const struct file_operations fops_registers = {
+ .open = open_file_registers,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+ .owner = THIS_MODULE,
+};
+
+
+/* debugfs: TSF */
+
+static ssize_t read_file_tsf(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ char buf[100];
+ snprintf(buf, 100, "0x%016llx\n", ath5k_hw_get_tsf64(sc->ah));
+ return simple_read_from_buffer(user_buf, count, ppos, buf, 19);
+}
+
+static ssize_t write_file_tsf(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ if (strncmp(userbuf, "reset", 5) == 0) {
+ ath5k_hw_reset_tsf(sc->ah);
+ printk(KERN_INFO "debugfs reset TSF\n");
+ }
+ return count;
+}
+
+static const struct file_operations fops_tsf = {
+ .read = read_file_tsf,
+ .write = write_file_tsf,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+
+/* debugfs: beacons */
+
+static ssize_t read_file_beacon(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+ char buf[1000];
+ int len = 0;
+ unsigned int v;
+ u64 tsf;
+
+ v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n",
+ "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD,
+ (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S);
+
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n",
+ "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP));
+
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n",
+ "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT));
+
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0);
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ "AR5K_TIMER0 (TBTT)", v, v);
+
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1);
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ "AR5K_TIMER1 (DMA)", v, v >> 3);
+
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2);
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ "AR5K_TIMER2 (SWBA)", v, v >> 3);
+
+ v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3);
+ len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n",
+ "AR5K_TIMER3 (ATIM)", v, v);
+
+ tsf = ath5k_hw_get_tsf64(sc->ah);
+ len += snprintf(buf+len, sizeof(buf)-len,
+ "TSF\t\t0x%016llx\tTU: %08x\n", tsf, TSF_TO_TU(tsf));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t write_file_beacon(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ struct ath5k_hw *ah = sc->ah;
+
+ if (strncmp(userbuf, "disable", 7) == 0) {
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
+ printk(KERN_INFO "debugfs disable beacons\n");
+ } else if (strncmp(userbuf, "enable", 6) == 0) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE);
+ printk(KERN_INFO "debugfs enable beacons\n");
+ }
+ return count;
+}
+
+static const struct file_operations fops_beacon = {
+ .read = read_file_beacon,
+ .write = write_file_beacon,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+
+/* debugfs: reset */
+
+static ssize_t write_file_reset(struct file *file,
+ const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ struct ath5k_softc *sc = file->private_data;
+ tasklet_schedule(&sc->restq);
+ return count;
+}
+
+static const struct file_operations fops_reset = {
+ .write = write_file_reset,
+ .open = ath5k_debugfs_open,
+ .owner = THIS_MODULE,
+};
+
+
+/* init */
+
+void
+ath5k_debug_init(void)
+{
+ ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL);
+}
+
+void
+ath5k_debug_init_device(struct ath5k_softc *sc)
+{
+ sc->debug.level = ath5k_debug;
+ sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
+ ath5k_global_debugfs);
+ sc->debug.debugfs_debug = debugfs_create_u32("debug",
+ 0666, sc->debug.debugfs_phydir, &sc->debug.level);
+
+ sc->debug.debugfs_registers = debugfs_create_file("registers", 0444,
+ sc->debug.debugfs_phydir,
+ sc, &fops_registers);
+
+ sc->debug.debugfs_tsf = debugfs_create_file("tsf", 0666,
+ sc->debug.debugfs_phydir,
+ sc, &fops_tsf);
+
+ sc->debug.debugfs_beacon = debugfs_create_file("beacon", 0666,
+ sc->debug.debugfs_phydir,
+ sc, &fops_beacon);
+
+ sc->debug.debugfs_reset = debugfs_create_file("reset", 0222,
+ sc->debug.debugfs_phydir,
+ sc, &fops_reset);
+}
+
+void
+ath5k_debug_finish(void)
+{
+ debugfs_remove(ath5k_global_debugfs);
+}
+
+void
+ath5k_debug_finish_device(struct ath5k_softc *sc)
+{
+ debugfs_remove(sc->debug.debugfs_debug);
+ debugfs_remove(sc->debug.debugfs_registers);
+ debugfs_remove(sc->debug.debugfs_tsf);
+ debugfs_remove(sc->debug.debugfs_beacon);
+ debugfs_remove(sc->debug.debugfs_reset);
+ debugfs_remove(sc->debug.debugfs_phydir);
+}
+
+
+/* functions used in other places */
+
+void
+ath5k_debug_dump_modes(struct ath5k_softc *sc, struct ieee80211_hw_mode *modes)
+{
+ unsigned int m, i;
+
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPMODES)))
+ return;
+
+ for (m = 0; m < NUM_DRIVER_MODES; m++) {
+ printk(KERN_DEBUG "Mode %u: channels %d, rates %d\n", m,
+ modes[m].num_channels, modes[m].num_rates);
+ printk(KERN_DEBUG " channels:\n");
+ for (i = 0; i < modes[m].num_channels; i++)
+ printk(KERN_DEBUG " %3d %d %.4x %.4x\n",
+ modes[m].channels[i].chan,
+ modes[m].channels[i].freq,
+ modes[m].channels[i].val,
+ modes[m].channels[i].flag);
+ printk(KERN_DEBUG " rates:\n");
+ for (i = 0; i < modes[m].num_rates; i++)
+ printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n",
+ modes[m].rates[i].rate,
+ modes[m].rates[i].val,
+ modes[m].rates[i].flags,
+ modes[m].rates[i].val2);
+ }
+}
+
+static inline void
+ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done)
+{
+ struct ath5k_desc *ds = bf->desc;
+
+ printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n",
+ ds, (unsigned long long)bf->daddr,
+ ds->ds_link, ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+ ds->ds_hw[0], ds->ds_hw[1],
+ !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
+}
+
+void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah)
+{
+ struct ath5k_desc *ds;
+ struct ath5k_buf *bf;
+ int status;
+
+ if (likely(!(sc->debug.level &
+ (ATH5K_DEBUG_RESET | ATH5K_DEBUG_FATAL))))
+ return;
+
+ printk(KERN_DEBUG "rx queue %x, link %p\n",
+ ath5k_hw_get_rx_buf(ah), sc->rxlink);
+
+ spin_lock_bh(&sc->rxbuflock);
+ list_for_each_entry(bf, &sc->rxbuf, list) {
+ ds = bf->desc;
+ status = ah->ah_proc_rx_desc(ah, ds);
+ if (!status || (sc->debug.level & ATH5K_DEBUG_FATAL))
+ ath5k_debug_printrxbuf(bf, status == 0);
+ }
+ spin_unlock_bh(&sc->rxbuflock);
+}
+
+void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ struct sk_buff *skb, const char *prefix, int tx)
+{
+ char buf[16];
+
+ if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) ||
+ (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX)))))
+ return;
+
+ snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix);
+
+ print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data,
+ min(200U, skb->len));
+
+ printk(KERN_DEBUG "\n");
+}
+
+void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+ struct ath5k_buf *bf, int done)
+{
+ struct ath5k_desc *ds = bf->desc;
+
+ if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET)))
+ return;
+
+ printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x "
+ "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link,
+ ds->ds_data, ds->ds_ctl0, ds->ds_ctl1,
+ ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
+ !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
+}
+
+#endif /* if ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath5k/debug.h b/drivers/net/wireless/ath5k/debug.h
new file mode 100644
index 000000000000..2b491cbc8c80
--- /dev/null
+++ b/drivers/net/wireless/ath5k/debug.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2007 Bruno Randolf <bruno@thinktube.com>
+ *
+ * This file is free software: you may copy, redistribute 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 file 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, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * Copyright (c) 2004-2005 Atheros Communications, Inc.
+ * Copyright (c) 2006 Devicescape Software, Inc.
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _ATH5K_DEBUG_H
+#define _ATH5K_DEBUG_H
+
+/* set this to 1 for debugging output */
+#ifndef ATH5K_DEBUG
+#define ATH5K_DEBUG 0
+#endif
+
+struct ath5k_softc;
+struct ath5k_hw;
+struct ieee80211_hw_mode;
+struct sk_buff;
+struct ath5k_buf;
+
+struct ath5k_dbg_info {
+ unsigned int level; /* debug level */
+ /* debugfs entries */
+ struct dentry *debugfs_phydir;
+ struct dentry *debugfs_debug;
+ struct dentry *debugfs_registers;
+ struct dentry *debugfs_tsf;
+ struct dentry *debugfs_beacon;
+ struct dentry *debugfs_reset;
+};
+
+/**
+ * enum ath5k_debug_level - ath5k debug level
+ *
+ * @ATH5K_DEBUG_RESET: reset processing
+ * @ATH5K_DEBUG_INTR: interrupt handling
+ * @ATH5K_DEBUG_MODE: mode init/setup
+ * @ATH5K_DEBUG_XMIT: basic xmit operation
+ * @ATH5K_DEBUG_BEACON: beacon handling
+ * @ATH5K_DEBUG_BEACON_PROC: beacon ISR proc
+ * @ATH5K_DEBUG_CALIBRATE: periodic calibration
+ * @ATH5K_DEBUG_TXPOWER: transmit power setting
+ * @ATH5K_DEBUG_LED: led management
+ * @ATH5K_DEBUG_DUMP_RX: print received skb content
+ * @ATH5K_DEBUG_DUMP_TX: print transmit skb content
+ * @ATH5K_DEBUG_DUMPMODES: dump modes
+ * @ATH5K_DEBUG_TRACE: trace function calls
+ * @ATH5K_DEBUG_FATAL: fatal errors
+ * @ATH5K_DEBUG_ANY: show at any debug level
+ *
+ * The debug level is used to control the amount and type of debugging output
+ * we want to see. The debug level is given in calls to ATH5K_DBG to specify
+ * where the message should appear, and the user can control the debugging
+ * messages he wants to see, either by the module parameter 'debug' on module
+ * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can
+ * be combined together by bitwise OR.
+ */
+enum ath5k_debug_level {
+ ATH5K_DEBUG_RESET = 0x00000001,
+ ATH5K_DEBUG_INTR = 0x00000002,
+ ATH5K_DEBUG_MODE = 0x00000004,
+ ATH5K_DEBUG_XMIT = 0x00000008,
+ ATH5K_DEBUG_BEACON = 0x00000010,
+ ATH5K_DEBUG_BEACON_PROC = 0x00000020,
+ ATH5K_DEBUG_CALIBRATE = 0x00000100,
+ ATH5K_DEBUG_TXPOWER = 0x00000200,
+ ATH5K_DEBUG_LED = 0x00000400,
+ ATH5K_DEBUG_DUMP_RX = 0x00001000,
+ ATH5K_DEBUG_DUMP_TX = 0x00002000,
+ ATH5K_DEBUG_DUMPMODES = 0x00004000,
+ ATH5K_DEBUG_TRACE = 0x00010000,
+ ATH5K_DEBUG_FATAL = 0x80000000,
+ ATH5K_DEBUG_ANY = 0xffffffff
+};
+
+#if ATH5K_DEBUG
+
+#define ATH5K_TRACE(_sc) do { \
+ if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \
+ printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \
+ } while (0)
+
+#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \
+ if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \
+ ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
+ __func__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+
+#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \
+ if (unlikely((_sc)->debug.level & (_m))) \
+ ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \
+ __func__, __LINE__, ##__VA_ARGS__); \
+ } while (0)
+
+void
+ath5k_debug_init(void);
+
+void
+ath5k_debug_init_device(struct ath5k_softc *sc);
+
+void
+ath5k_debug_finish(void);
+
+void
+ath5k_debug_finish_device(struct ath5k_softc *sc);
+
+void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah);
+
+void
+ath5k_debug_dump_modes(struct ath5k_softc *sc,
+ struct ieee80211_hw_mode *modes);
+
+void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ struct sk_buff *skb, const char *prefix, int tx);
+
+void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+ struct ath5k_buf *bf, int done);
+
+#else /* no debugging */
+
+#define ATH5K_TRACE(_sc) /* empty */
+
+static inline void __attribute__ ((format (printf, 3, 4)))
+ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {}
+
+static inline void __attribute__ ((format (printf, 3, 4)))
+ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...)
+{}
+
+static inline void
+ath5k_debug_init(void) {}
+
+static inline void
+ath5k_debug_init_device(struct ath5k_softc *sc) {}
+
+static inline void
+ath5k_debug_finish(void) {}
+
+static inline void
+ath5k_debug_finish_device(struct ath5k_softc *sc) {}
+
+static inline void
+ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {}
+
+static inline void
+ath5k_debug_dump_modes(struct ath5k_softc *sc,
+ struct ieee80211_hw_mode *modes) {}
+
+static inline void
+ath5k_debug_dump_skb(struct ath5k_softc *sc,
+ struct sk_buff *skb, const char *prefix, int tx) {}
+
+static inline void
+ath5k_debug_printtxbuf(struct ath5k_softc *sc,
+ struct ath5k_buf *bf, int done) {}
+
+#endif /* if ATH5K_DEBUG */
+
+#endif /* ifndef _ATH5K_DEBUG_H */
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
new file mode 100644
index 000000000000..3a4bf4035a23
--- /dev/null
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -0,0 +1,4351 @@
+ /*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
+ * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ * Copyright (c) 2007 Pavel Roskin <proski@gnu.org>
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * HW related functions for Atheros Wireless LAN devices.
+ */
+
+#include <linux/pci.h>
+#include <linux/delay.h>
+
+#include "reg.h"
+#include "base.h"
+#include "debug.h"
+
+/*Rate tables*/
+static const struct ath5k_rate_table ath5k_rt_11a = AR5K_RATES_11A;
+static const struct ath5k_rate_table ath5k_rt_11b = AR5K_RATES_11B;
+static const struct ath5k_rate_table ath5k_rt_11g = AR5K_RATES_11G;
+static const struct ath5k_rate_table ath5k_rt_turbo = AR5K_RATES_TURBO;
+static const struct ath5k_rate_table ath5k_rt_xr = AR5K_RATES_XR;
+
+/*Prototypes*/
+static int ath5k_hw_nic_reset(struct ath5k_hw *, u32);
+static int ath5k_hw_nic_wakeup(struct ath5k_hw *, int, bool);
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+static bool ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int);
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *, struct ath5k_desc *,
+ unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int,
+ unsigned int, unsigned int, unsigned int, unsigned int, unsigned int,
+ unsigned int, unsigned int);
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *, struct ath5k_desc *);
+static int ath5k_hw_get_capabilities(struct ath5k_hw *);
+
+static int ath5k_eeprom_init(struct ath5k_hw *);
+static int ath5k_eeprom_read_mac(struct ath5k_hw *, u8 *);
+
+static int ath5k_hw_enable_pspoll(struct ath5k_hw *, u8 *, u16);
+static int ath5k_hw_disable_pspoll(struct ath5k_hw *);
+
+/*
+ * Enable to overwrite the country code (use "00" for debug)
+ */
+#if 0
+#define COUNTRYCODE "00"
+#endif
+
+/*******************\
+ General Functions
+\*******************/
+
+/*
+ * Functions used internaly
+ */
+
+static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo)
+{
+ return turbo == true ? (usec * 80) : (usec * 40);
+}
+
+static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo)
+{
+ return turbo == true ? (clock / 80) : (clock / 40);
+}
+
+/*
+ * Check if a register write has been completed
+ */
+int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val,
+ bool is_set)
+{
+ int i;
+ u32 data;
+
+ for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) {
+ data = ath5k_hw_reg_read(ah, reg);
+ if ((is_set == true) && (data & flag))
+ break;
+ else if ((data & flag) == val)
+ break;
+ udelay(15);
+ }
+
+ return (i <= 0) ? -EAGAIN : 0;
+}
+
+
+/***************************************\
+ Attach/Detach Functions
+\***************************************/
+
+/*
+ * Check if the device is supported and initialize the needed structs
+ */
+struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
+{
+ struct ath5k_hw *ah;
+ u8 mac[ETH_ALEN];
+ int ret;
+ u32 srev;
+
+ /*If we passed the test malloc a ath5k_hw struct*/
+ ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL);
+ if (ah == NULL) {
+ ret = -ENOMEM;
+ ATH5K_ERR(sc, "out of memory\n");
+ goto err;
+ }
+
+ ah->ah_sc = sc;
+ ah->ah_iobase = sc->iobase;
+
+ /*
+ * HW information
+ */
+
+ /* Get reg domain from eeprom */
+ ath5k_get_regdomain(ah);
+
+ ah->ah_op_mode = IEEE80211_IF_TYPE_STA;
+ ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
+ ah->ah_turbo = false;
+ ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
+ ah->ah_imr = 0;
+ ah->ah_atim_window = 0;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
+ ah->ah_software_retry = false;
+ ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
+
+ /*
+ * Set the mac revision based on the pci id
+ */
+ ah->ah_version = mac_version;
+
+ /*Fill the ath5k_hw struct with the needed functions*/
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5212;
+ else if (ah->ah_version == AR5K_AR5211)
+ ah->ah_magic = AR5K_EEPROM_MAGIC_5211;
+
+ if (ah->ah_version == AR5K_AR5212) {
+ ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
+ ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
+ } else {
+ ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
+ ah->ah_setup_xtx_desc = ath5k_hw_setup_xr_tx_desc;
+ ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
+ }
+
+ if (ah->ah_version == AR5K_AR5212)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_new_rx_status;
+ else if (ah->ah_version <= AR5K_AR5211)
+ ah->ah_proc_rx_desc = ath5k_hw_proc_old_rx_status;
+
+ /* Bring device out of sleep and reset it's units */
+ ret = ath5k_hw_nic_wakeup(ah, AR5K_INIT_MODE, true);
+ if (ret)
+ goto err_free;
+
+ /* Get MAC, PHY and RADIO revisions */
+ srev = ath5k_hw_reg_read(ah, AR5K_SREV);
+ ah->ah_mac_srev = srev;
+ ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
+ ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
+ ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
+ 0xffffffff;
+ ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_5GHZ);
+
+ if (ah->ah_version == AR5K_AR5210)
+ ah->ah_radio_2ghz_revision = 0;
+ else
+ ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
+ CHANNEL_2GHZ);
+
+ /* Return on unsuported chips (unsupported eeprom etc) */
+ if(srev >= AR5K_SREV_VER_AR5416){
+ ATH5K_ERR(sc, "Device not yet supported.\n");
+ ret = -ENODEV;
+ goto err_free;
+ }
+
+ /* Identify single chip solutions */
+ if((srev <= AR5K_SREV_VER_AR5414) &&
+ (srev >= AR5K_SREV_VER_AR2424)) {
+ ah->ah_single_chip = true;
+ } else {
+ ah->ah_single_chip = false;
+ }
+
+ /* Single chip radio */
+ if (ah->ah_radio_2ghz_revision == ah->ah_radio_5ghz_revision)
+ ah->ah_radio_2ghz_revision = 0;
+
+ /* Identify the radio chip*/
+ if (ah->ah_version == AR5K_AR5210) {
+ ah->ah_radio = AR5K_RF5110;
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112) {
+ ah->ah_radio = AR5K_RF5111;
+ } else if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_SC1) {
+ ah->ah_radio = AR5K_RF5112;
+ } else {
+ ah->ah_radio = AR5K_RF5413;
+ }
+
+ ah->ah_phy = AR5K_PHY(0);
+
+ /*
+ * Get card capabilities, values, ...
+ */
+
+ ret = ath5k_eeprom_init(ah);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to init EEPROM\n");
+ goto err_free;
+ }
+
+ /* Get misc capabilities */
+ ret = ath5k_hw_get_capabilities(ah);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ /* Get MAC address */
+ ret = ath5k_eeprom_read_mac(ah, mac);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_free;
+ }
+
+ ath5k_hw_set_lladdr(ah, mac);
+ /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
+ memset(ah->ah_bssid, 0xff, ETH_ALEN);
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+ ath5k_hw_set_opmode(ah);
+
+ ath5k_hw_set_rfgain_opt(ah);
+
+ return ah;
+err_free:
+ kfree(ah);
+err:
+ return ERR_PTR(ret);
+}
+
+/*
+ * Bring up MAC + PHY Chips
+ */
+static int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
+{
+ u32 turbo, mode, clock;
+ int ret;
+
+ turbo = 0;
+ mode = 0;
+ clock = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Wakeup the device */
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
+ return ret;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Get channel mode flags
+ */
+
+ if (ah->ah_radio >= AR5K_RF5112) {
+ mode = AR5K_PHY_MODE_RAD_RF5112;
+ clock = AR5K_PHY_PLL_RF5112;
+ } else {
+ mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/
+ clock = AR5K_PHY_PLL_RF5111; /*Zero*/
+ }
+
+ if (flags & CHANNEL_2GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_2GHZ;
+ clock |= AR5K_PHY_PLL_44MHZ;
+
+ if (flags & CHANNEL_CCK) {
+ mode |= AR5K_PHY_MODE_MOD_CCK;
+ } else if (flags & CHANNEL_OFDM) {
+ /* XXX Dynamic OFDM/CCK is not supported by the
+ * AR5211 so we set MOD_OFDM for plain g (no
+ * CCK headers) operation. We need to test
+ * this, 5211 might support ofdm-only g after
+ * all, there are also initial register values
+ * in the code for g mode (see initvals.c). */
+ if (ah->ah_version == AR5K_AR5211)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else
+ mode |= AR5K_PHY_MODE_MOD_DYN;
+ } else {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else if (flags & CHANNEL_5GHZ) {
+ mode |= AR5K_PHY_MODE_FREQ_5GHZ;
+ clock |= AR5K_PHY_PLL_40MHZ;
+
+ if (flags & CHANNEL_OFDM)
+ mode |= AR5K_PHY_MODE_MOD_OFDM;
+ else {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid radio modulation mode\n");
+ return -EINVAL;
+ }
+ } else {
+ ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n");
+ return -EINVAL;
+ }
+
+ if (flags & CHANNEL_TURBO)
+ turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT;
+ } else { /* Reset the device */
+
+ /* ...enable Atheros turbo mode if requested */
+ if (flags & CHANNEL_TURBO)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE,
+ AR5K_PHY_TURBO);
+ }
+
+ /* ...reset chipset and PCI device */
+ if (ah->ah_single_chip == false && ath5k_hw_nic_reset(ah,
+ AR5K_RESET_CTL_CHIP | AR5K_RESET_CTL_PCI)) {
+ ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip + PCI\n");
+ return -EIO;
+ }
+
+ if (ah->ah_version == AR5K_AR5210)
+ udelay(2300);
+
+ /* ...wakeup again!*/
+ ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
+ return ret;
+ }
+
+ /* ...final warm reset */
+ if (ath5k_hw_nic_reset(ah, 0)) {
+ ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
+ return -EIO;
+ }
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /* ...set the PHY operating mode */
+ ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL);
+ udelay(300);
+
+ ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE);
+ ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO);
+ }
+
+ return 0;
+}
+
+/*
+ * Get the rate table for a specific operation mode
+ */
+const struct ath5k_rate_table *ath5k_hw_get_rate_table(struct ath5k_hw *ah,
+ unsigned int mode)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (!test_bit(mode, ah->ah_capabilities.cap_mode))
+ return NULL;
+
+ /* Get rate tables */
+ switch (mode) {
+ case MODE_IEEE80211A:
+ return &ath5k_rt_11a;
+ case MODE_ATHEROS_TURBO:
+ return &ath5k_rt_turbo;
+ case MODE_IEEE80211B:
+ return &ath5k_rt_11b;
+ case MODE_IEEE80211G:
+ return &ath5k_rt_11g;
+ case MODE_ATHEROS_TURBOG:
+ return &ath5k_rt_xr;
+ }
+
+ return NULL;
+}
+
+/*
+ * Free the ath5k_hw struct
+ */
+void ath5k_hw_detach(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_rf_banks != NULL)
+ kfree(ah->ah_rf_banks);
+
+ /* assume interrupts are down */
+ kfree(ah);
+}
+
+/****************************\
+ Reset function and helpers
+\****************************/
+
+/**
+ * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212
+ *
+ * @ah: the &struct ath5k_hw
+ * @channel: the currently set channel upon reset
+ *
+ * Write the OFDM timings for the AR5212 upon reset. This is a helper for
+ * ath5k_hw_reset(). This seems to tune the PLL a specified frequency
+ * depending on the bandwidth of the channel.
+ *
+ */
+static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ /* Get exponent and mantissa and set it */
+ u32 coef_scaled, coef_exp, coef_man,
+ ds_coef_exp, ds_coef_man, clock;
+
+ if (!(ah->ah_version == AR5K_AR5212) ||
+ !(channel->val & CHANNEL_OFDM))
+ BUG();
+
+ /* Seems there are two PLLs, one for baseband sampling and one
+ * for tuning. Tuning basebands are 40 MHz or 80MHz when in
+ * turbo. */
+ clock = channel->val & CHANNEL_TURBO ? 80 : 40;
+ coef_scaled = ((5 * (clock << 24)) / 2) /
+ channel->freq;
+
+ for (coef_exp = 31; coef_exp > 0; coef_exp--)
+ if ((coef_scaled >> coef_exp) & 0x1)
+ break;
+
+ if (!coef_exp)
+ return -EINVAL;
+
+ coef_exp = 14 - (coef_exp - 24);
+ coef_man = coef_scaled +
+ (1 << (24 - coef_exp - 1));
+ ds_coef_man = coef_man >> (24 - coef_exp);
+ ds_coef_exp = coef_exp - 16;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man);
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3,
+ AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp);
+
+ return 0;
+}
+
+/**
+ * ath5k_hw_write_rate_duration - set rate duration during hw resets
+ *
+ * @ah: the &struct ath5k_hw
+ * @driver_mode: one of enum ieee80211_phymode or our one of our own
+ * vendor modes
+ *
+ * Write the rate duration table for the current mode upon hw reset. This
+ * is a helper for ath5k_hw_reset(). It seems all this is doing is setting
+ * an ACK timeout for the hardware for the current mode for each rate. The
+ * rates which are capable of short preamble (802.11b rates 2Mbps, 5.5Mbps,
+ * and 11Mbps) have another register for the short preamble ACK timeout
+ * calculation.
+ *
+ */
+static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah,
+ unsigned int driver_mode)
+{
+ struct ath5k_softc *sc = ah->ah_sc;
+ const struct ath5k_rate_table *rt;
+ unsigned int i;
+
+ /* Get rate table for the current operating mode */
+ rt = ath5k_hw_get_rate_table(ah,
+ driver_mode);
+
+ /* Write rate duration table */
+ for (i = 0; i < rt->rate_count; i++) {
+ const struct ath5k_rate *rate, *control_rate;
+ u32 reg;
+ u16 tx_time;
+
+ rate = &rt->rates[i];
+ control_rate = &rt->rates[rate->control_rate];
+
+ /* Set ACK timeout */
+ reg = AR5K_RATE_DUR(rate->rate_code);
+
+ /* An ACK frame consists of 10 bytes. If you add the FCS,
+ * which ieee80211_generic_frame_duration() adds,
+ * its 14 bytes. Note we use the control rate and not the
+ * actual rate for this rate. See mac80211 tx.c
+ * ieee80211_duration() for a brief description of
+ * what rate we should choose to TX ACKs. */
+ tx_time = ieee80211_generic_frame_duration(sc->hw,
+ sc->vif, 10, control_rate->rate_kbps/100);
+
+ ath5k_hw_reg_write(ah, tx_time, reg);
+
+ if (!HAS_SHPREAMBLE(i))
+ continue;
+
+ /*
+ * We're not distinguishing short preamble here,
+ * This is true, all we'll get is a longer value here
+ * which is not necessarilly bad. We could use
+ * export ieee80211_frame_duration() but that needs to be
+ * fixed first to be properly used by mac802111 drivers:
+ *
+ * - remove erp stuff and let the routine figure ofdm
+ * erp rates
+ * - remove passing argument ieee80211_local as
+ * drivers don't have access to it
+ * - move drivers using ieee80211_generic_frame_duration()
+ * to this
+ */
+ ath5k_hw_reg_write(ah, tx_time,
+ reg + (AR5K_SET_SHORT_PREAMBLE << 2));
+ }
+}
+
+/*
+ * Main reset function
+ */
+int ath5k_hw_reset(struct ath5k_hw *ah, enum ieee80211_if_types op_mode,
+ struct ieee80211_channel *channel, bool change_channel)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 data, s_seq, s_ant, s_led[3];
+ unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ s_seq = 0;
+ s_ant = 0;
+ ee_mode = 0;
+ freq = 0;
+ mode = 0;
+
+ /*
+ * Save some registers before a reset
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ if (change_channel == true) {
+ /* Seq number for queue 0 -do this for all queues ? */
+ s_seq = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_DFS_SEQNUM(0));
+ /*Default antenna*/
+ s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+ }
+ }
+
+ /*GPIOs*/
+ s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & AR5K_PCICFG_LEDSTATE;
+ s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR);
+ s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ if (change_channel == true && ah->ah_rf_banks != NULL)
+ ath5k_hw_get_rf_gain(ah);
+
+
+ /*Wakeup the device*/
+ ret = ath5k_hw_nic_wakeup(ah, channel->val, false);
+ if (ret)
+ return ret;
+
+ /*
+ * Initialize operating mode
+ */
+ ah->ah_op_mode = op_mode;
+
+ /*
+ * 5111/5112 Settings
+ * 5210 only comes with RF5110
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ if (ah->ah_radio != AR5K_RF5111 &&
+ ah->ah_radio != AR5K_RF5112 &&
+ ah->ah_radio != AR5K_RF5413) {
+ ATH5K_ERR(ah->ah_sc,
+ "invalid phy radio: %u\n", ah->ah_radio);
+ return -EINVAL;
+ }
+
+ switch (channel->val & CHANNEL_MODES) {
+ case CHANNEL_A:
+ mode = AR5K_INI_VAL_11A;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ driver_mode = MODE_IEEE80211A;
+ break;
+ case CHANNEL_G:
+ mode = AR5K_INI_VAL_11G;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ driver_mode = MODE_IEEE80211G;
+ break;
+ case CHANNEL_B:
+ mode = AR5K_INI_VAL_11B;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ driver_mode = MODE_IEEE80211B;
+ break;
+ case CHANNEL_T:
+ mode = AR5K_INI_VAL_11A_TURBO;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ driver_mode = MODE_ATHEROS_TURBO;
+ break;
+ /*Is this ok on 5211 too ?*/
+ case CHANNEL_TG:
+ mode = AR5K_INI_VAL_11G_TURBO;
+ freq = AR5K_INI_RFGAIN_2GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ driver_mode = MODE_ATHEROS_TURBOG;
+ break;
+ case CHANNEL_XR:
+ if (ah->ah_version == AR5K_AR5211) {
+ ATH5K_ERR(ah->ah_sc,
+ "XR mode not available on 5211");
+ return -EINVAL;
+ }
+ mode = AR5K_INI_VAL_XR;
+ freq = AR5K_INI_RFGAIN_5GHZ;
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ driver_mode = MODE_IEEE80211A;
+ break;
+ default:
+ ATH5K_ERR(ah->ah_sc,
+ "invalid channel: %d\n", channel->freq);
+ return -EINVAL;
+ }
+
+ /* PHY access enable */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ }
+
+ ret = ath5k_hw_write_initvals(ah, mode, change_channel);
+ if (ret)
+ return ret;
+
+ /*
+ * 5211/5212 Specific
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ /*
+ * Write initial RF gain settings
+ * This should work for both 5111/5112
+ */
+ ret = ath5k_hw_rfgain(ah, freq);
+ if (ret)
+ return ret;
+
+ mdelay(1);
+
+ /*
+ * Write some more initial register settings
+ */
+ if (ah->ah_version > AR5K_AR5211){ /* found on 5213+ */
+ ath5k_hw_reg_write(ah, 0x0002a002, AR5K_PHY(11));
+
+ if (channel->val == CHANNEL_G)
+ ath5k_hw_reg_write(ah, 0x00f80d80, AR5K_PHY(83)); /* 0x00fc0ec0 */
+ else
+ ath5k_hw_reg_write(ah, 0x00000000, AR5K_PHY(83));
+
+ ath5k_hw_reg_write(ah, 0x000001b5, 0xa228); /* 0x000009b5 */
+ ath5k_hw_reg_write(ah, 0x000009b5, 0xa228);
+ ath5k_hw_reg_write(ah, 0x0000000f, 0x8060);
+ ath5k_hw_reg_write(ah, 0x00000000, 0xa254);
+ ath5k_hw_reg_write(ah, 0x0000000e, AR5K_PHY_SCAL);
+ }
+
+ /* Fix for first revision of the RF5112 RF chipset */
+ if (ah->ah_radio >= AR5K_RF5112 &&
+ ah->ah_radio_5ghz_revision <
+ AR5K_SREV_RAD_5112A) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
+ AR5K_PHY_CCKTXCTL);
+ if (channel->val & CHANNEL_5GHZ)
+ data = 0xffb81020;
+ else
+ data = 0xffb80d20;
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL);
+ }
+
+ /*
+ * Set TX power (FIXME)
+ */
+ ret = ath5k_hw_txpower(ah, channel, AR5K_TUNE_DEFAULT_TXPOWER);
+ if (ret)
+ return ret;
+
+ /* Write rate duration table only on AR5212 and if
+ * virtual interface has already been brought up
+ * XXX: rethink this after new mode changes to
+ * mac80211 are integrated */
+ if (ah->ah_version == AR5K_AR5212 &&
+ ah->ah_sc->vif != NULL)
+ ath5k_hw_write_rate_duration(ah, driver_mode);
+
+ /*
+ * Write RF registers
+ * TODO:Does this work on 5211 (5111) ?
+ */
+ ret = ath5k_hw_rfregs(ah, channel, mode);
+ if (ret)
+ return ret;
+
+ /*
+ * Configure additional registers
+ */
+
+ /* Write OFDM timings on 5212*/
+ if (ah->ah_version == AR5K_AR5212 &&
+ channel->val & CHANNEL_OFDM) {
+ ret = ath5k_hw_write_ofdm_timings(ah, channel);
+ if (ret)
+ return ret;
+ }
+
+ /*Enable/disable 802.11b mode on 5111
+ (enable 2111 frequency converter + CCK)*/
+ if (ah->ah_radio == AR5K_RF5111) {
+ if (driver_mode == MODE_IEEE80211B)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_B_MODE);
+ }
+
+ /*
+ * Set channel and calibrate the PHY
+ */
+ ret = ath5k_hw_channel(ah, channel);
+ if (ret)
+ return ret;
+
+ /* Set antenna mode */
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x44),
+ ah->ah_antenna[ee_mode][0], 0xfffffc06);
+
+ /*
+ * In case a fixed antenna was set as default
+ * write the same settings on both AR5K_PHY_ANT_SWITCH_TABLE
+ * registers.
+ */
+ if (s_ant != 0){
+ if (s_ant == AR5K_ANT_FIXED_A) /* 1 - Main */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_A;
+ else /* 2 - Aux */
+ ant[0] = ant[1] = AR5K_ANT_FIXED_B;
+ } else {
+ ant[0] = AR5K_ANT_FIXED_A;
+ ant[1] = AR5K_ANT_FIXED_B;
+ }
+
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[0]],
+ AR5K_PHY_ANT_SWITCH_TABLE_0);
+ ath5k_hw_reg_write(ah, ah->ah_antenna[ee_mode][ant[1]],
+ AR5K_PHY_ANT_SWITCH_TABLE_1);
+
+ /* Commit values from EEPROM */
+ if (ah->ah_radio == AR5K_RF5111)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
+ AR5K_PHY_FRAME_CTL_TX_CLIP, ee->ee_tx_clip);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]),
+ AR5K_PHY(0x5a));
+
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x11),
+ (ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
+ 0xffffc07f);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x12),
+ (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
+ 0xfffc0fff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x14),
+ (ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
+ ((ee->ee_pga_desired_size[ee_mode] << 8) & 0xff00),
+ 0xffff0000);
+
+ ath5k_hw_reg_write(ah,
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 24) |
+ (ee->ee_tx_end2xpa_disable[ee_mode] << 16) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) |
+ (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY(0x0d));
+
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x0a),
+ ee->ee_tx_end2xlna_enable[ee_mode] << 8, 0xffff00ff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x19),
+ (ee->ee_thr_62[ee_mode] << 12) & 0x7f000, 0xfff80fff);
+ AR5K_REG_MASKED_BITS(ah, AR5K_PHY(0x49), 4, 0xffffff01);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CORR_ENABLE |
+ (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) |
+ ee->ee_q_cal[ee_mode]);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ,
+ AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX,
+ ee->ee_margin_tx_rx[ee_mode]);
+
+ } else {
+ mdelay(1);
+ /* Disable phy and wait */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+ mdelay(1);
+ }
+
+ /*
+ * Restore saved values
+ */
+ /*DCU/Antenna selection not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, s_seq, AR5K_QUEUE_DFS_SEQNUM(0));
+ ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA);
+ }
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]);
+ ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR);
+ ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO);
+
+ /*
+ * Misc
+ */
+ /* XXX: add ah->aid once mac80211 gives this to us */
+ ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
+
+ ath5k_hw_set_opmode(ah);
+ /*PISR/SISR Not available on 5210*/
+ if (ah->ah_version != AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR);
+ /* If we later allow tuning for this, store into sc structure */
+ data = AR5K_TUNE_RSSI_THRES |
+ AR5K_TUNE_BMISS_THRES << AR5K_RSSI_THR_BMISS_S;
+ ath5k_hw_reg_write(ah, data, AR5K_RSSI_THR);
+ }
+
+ /*
+ * Set Rx/Tx DMA Configuration
+ *(passing dma size not available on 5210)
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_SDMAMR,
+ AR5K_DMASIZE_512B | AR5K_TXCFG_DMASIZE);
+ AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_SDMAMW,
+ AR5K_DMASIZE_512B);
+ }
+
+ /*
+ * Enable the PHY and wait until completion
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+
+ /*
+ * 5111/5112 Specific
+ */
+ if (ah->ah_version != AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
+ AR5K_PHY_RX_DELAY_M;
+ data = (channel->val & CHANNEL_CCK) ?
+ ((data << 2) / 22) : (data / 10);
+
+ udelay(100 + data);
+ } else {
+ mdelay(1);
+ }
+
+ /*
+ * Enable calibration and wait until completion
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL);
+
+ if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, false)) {
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+ channel->freq);
+ return -EAGAIN;
+ }
+
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
+ if (ret)
+ return ret;
+
+ ah->ah_calibration = false;
+
+ /* A and G modes can use QAM modulation which requires enabling
+ * I and Q calibration. Don't bother in B mode. */
+ if (!(driver_mode == MODE_IEEE80211B)) {
+ ah->ah_calibration = true;
+ AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ,
+ AR5K_PHY_IQ_RUN);
+ }
+
+ /*
+ * Reset queues and start beacon timers at the end of the reset routine
+ */
+ for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) {
+ /*No QCU on 5210*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(i), i);
+
+ ret = ath5k_hw_reset_tx_queue(ah, i);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "failed to reset TX queue #%d\n", i);
+ return ret;
+ }
+ }
+
+ /* Pre-enable interrupts on 5211/5212*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_set_intr(ah, AR5K_INT_RX | AR5K_INT_TX |
+ AR5K_INT_FATAL);
+
+ /*
+ * Set RF kill flags if supported by the device (read from the EEPROM)
+ * Disable gpio_intr for now since it results system hang.
+ * TODO: Handle this in ath5k_intr
+ */
+#if 0
+ if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) {
+ ath5k_hw_set_gpio_input(ah, 0);
+ ah->ah_gpio[0] = ath5k_hw_get_gpio(ah, 0);
+ if (ah->ah_gpio[0] == 0)
+ ath5k_hw_set_gpio_intr(ah, 0, 1);
+ else
+ ath5k_hw_set_gpio_intr(ah, 0, 0);
+ }
+#endif
+
+ /*
+ * Set the 32MHz reference clock on 5212 phy clock sleep register
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCR_32MHZ, AR5K_PHY_SCR);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ, AR5K_PHY_SCAL);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK);
+ ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY);
+ ath5k_hw_reg_write(ah, ah->ah_radio == AR5K_RF5111 ?
+ AR5K_PHY_SPENDING_RF5111 : AR5K_PHY_SPENDING_RF5112,
+ AR5K_PHY_SPENDING);
+ }
+
+ /*
+ * Disable beacons and reset the register
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE |
+ AR5K_BEACON_RESET_TSF);
+
+ return 0;
+}
+
+/*
+ * Reset chipset
+ */
+static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val)
+{
+ int ret;
+ u32 mask = val ? val : ~0U;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Read-and-clear RX Descriptor Pointer*/
+ ath5k_hw_reg_read(ah, AR5K_RXDP);
+
+ /*
+ * Reset the device and wait until success
+ */
+ ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL);
+
+ /* Wait at least 128 PCI clocks */
+ udelay(15);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ val &= AR5K_RESET_CTL_CHIP;
+ mask &= AR5K_RESET_CTL_CHIP;
+ } else {
+ val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND;
+ }
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false);
+
+ /*
+ * Reset configuration register (for hw byte-swap). Note that this
+ * is only set for big endian. We do the necessary magic in
+ * AR5K_INIT_CFG.
+ */
+ if ((val & AR5K_RESET_CTL_PCU) == 0)
+ ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG);
+
+ return ret;
+}
+
+/*
+ * Power management functions
+ */
+
+/*
+ * Sleep control
+ */
+int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
+ bool set_chip, u16 sleep_duration)
+{
+ unsigned int i;
+ u32 staid;
+
+ ATH5K_TRACE(ah->ah_sc);
+ staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1);
+
+ switch (mode) {
+ case AR5K_PM_AUTO:
+ staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
+ /* fallthrough */
+ case AR5K_PM_NETWORK_SLEEP:
+ if (set_chip == true)
+ ath5k_hw_reg_write(ah,
+ AR5K_SLEEP_CTL_SLE | sleep_duration,
+ AR5K_SLEEP_CTL);
+
+ staid |= AR5K_STA_ID1_PWR_SV;
+ break;
+
+ case AR5K_PM_FULL_SLEEP:
+ if (set_chip == true)
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP,
+ AR5K_SLEEP_CTL);
+
+ staid |= AR5K_STA_ID1_PWR_SV;
+ break;
+
+ case AR5K_PM_AWAKE:
+ if (set_chip == false)
+ goto commit;
+
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
+
+ for (i = 5000; i > 0; i--) {
+ /* Check if the chip did wake up */
+ if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
+ AR5K_PCICFG_SPWR_DN) == 0)
+ break;
+
+ /* Wait a bit and retry */
+ udelay(200);
+ ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_WAKE,
+ AR5K_SLEEP_CTL);
+ }
+
+ /* Fail if the chip didn't wake up */
+ if (i <= 0)
+ return -EIO;
+
+ staid &= ~AR5K_STA_ID1_PWR_SV;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+commit:
+ ah->ah_power_mode = mode;
+ ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/***********************\
+ DMA Related Functions
+\***********************/
+
+/*
+ * Receive functions
+ */
+
+/*
+ * Start DMA receive
+ */
+void ath5k_hw_start_rx(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
+}
+
+/*
+ * Stop DMA receive
+ */
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
+{
+ unsigned int i;
+
+ ATH5K_TRACE(ah->ah_sc);
+ ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
+
+ /*
+ * It may take some time to disable the DMA receive unit
+ */
+ for (i = 2000; i > 0 &&
+ (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
+ i--)
+ udelay(10);
+
+ return i ? 0 : -EBUSY;
+}
+
+/*
+ * Get the address of the RX Descriptor
+ */
+u32 ath5k_hw_get_rx_buf(struct ath5k_hw *ah)
+{
+ return ath5k_hw_reg_read(ah, AR5K_RXDP);
+}
+
+/*
+ * Set the address of the RX Descriptor
+ */
+void ath5k_hw_put_rx_buf(struct ath5k_hw *ah, u32 phys_addr)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*TODO:Shouldn't we check if RX is enabled first ?*/
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
+}
+
+/*
+ * Transmit functions
+ */
+
+/*
+ * Start DMA transmit for a specific queue
+ * (see also QCU/DCU functions)
+ */
+int ath5k_hw_tx_start(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 tx_queue;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /*
+ * Set the queue by type on 5210
+ */
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+ AR5K_BSR);
+ break;
+ case AR5K_TX_QUEUE_CAB:
+ tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V |
+ AR5K_BCR_BDMAE, AR5K_BSR);
+ break;
+ default:
+ return -EINVAL;
+ }
+ /* Start queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ } else {
+ /* Return if queue is disabled */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
+ return -EIO;
+
+ /* Start queue */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
+ }
+
+ return 0;
+}
+
+/*
+ * Stop DMA transmit for a specific queue
+ * (see also QCU/DCU functions)
+ */
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
+{
+ unsigned int i = 100;
+ u32 tx_queue, pending;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
+
+ /*
+ * Set by queue type
+ */
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ /* XXX Fix me... */
+ tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1;
+ ath5k_hw_reg_write(ah, 0, AR5K_BSR);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Stop queue */
+ ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
+ } else {
+ /*
+ * Schedule TX disable and wait until queue is empty
+ */
+ AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
+
+ /*Check for pending frames*/
+ do {
+ pending = ath5k_hw_reg_read(ah,
+ AR5K_QUEUE_STATUS(queue)) &
+ AR5K_QCU_STS_FRMPENDCNT;
+ udelay(100);
+ } while (--i && pending);
+
+ /* Clear register */
+ ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
+ }
+
+ /* TODO: Check for success else return error */
+ return 0;
+}
+
+/*
+ * Get the address of the TX Descriptor for a specific queue
+ * (see also QCU/DCU functions)
+ */
+u32 ath5k_hw_get_tx_buf(struct ath5k_hw *ah, unsigned int queue)
+{
+ u16 tx_reg;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /*
+ * Get the transmit queue descriptor pointer from the selected queue
+ */
+ /*5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_reg = AR5K_NOQCU_TXDP0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ tx_reg = AR5K_NOQCU_TXDP1;
+ break;
+ default:
+ return 0xffffffff;
+ }
+ } else {
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ return ath5k_hw_reg_read(ah, tx_reg);
+}
+
+/*
+ * Set the address of the TX Descriptor for a specific queue
+ * (see also QCU/DCU functions)
+ */
+int ath5k_hw_put_tx_buf(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
+{
+ u16 tx_reg;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /*
+ * Set the transmit queue descriptor pointer register by type
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (ah->ah_txq[queue].tqi_type) {
+ case AR5K_TX_QUEUE_DATA:
+ tx_reg = AR5K_NOQCU_TXDP0;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ tx_reg = AR5K_NOQCU_TXDP1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ /*
+ * Set the transmit queue descriptor pointer for
+ * the selected queue on QCU for 5211+
+ * (this won't work if the queue is still active)
+ */
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
+ return -EIO;
+
+ tx_reg = AR5K_QUEUE_TXDP(queue);
+ }
+
+ /* Set descriptor pointer */
+ ath5k_hw_reg_write(ah, phys_addr, tx_reg);
+
+ return 0;
+}
+
+/*
+ * Update tx trigger level
+ */
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase)
+{
+ u32 trigger_level, imr;
+ int ret = -EIO;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Disable interrupts by setting the mask
+ */
+ imr = ath5k_hw_set_intr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
+
+ /*TODO: Boundary check on trigger_level*/
+ trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
+ AR5K_TXCFG_TXFULL);
+
+ if (increase == false) {
+ if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
+ goto done;
+ } else
+ trigger_level +=
+ ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
+
+ /*
+ * Update trigger level on success
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
+ else
+ AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
+ AR5K_TXCFG_TXFULL, trigger_level);
+
+ ret = 0;
+
+done:
+ /*
+ * Restore interrupt mask
+ */
+ ath5k_hw_set_intr(ah, imr);
+
+ return ret;
+}
+
+/*
+ * Interrupt handling
+ */
+
+/*
+ * Check if we have pending interrupts
+ */
+bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_reg_read(ah, AR5K_INTPEND);
+}
+
+/*
+ * Get interrupt mask (ISR)
+ */
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
+{
+ u32 data;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Read interrupt status from the Interrupt Status register
+ * on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ data = ath5k_hw_reg_read(ah, AR5K_ISR);
+ if (unlikely(data == AR5K_INT_NOCARD)) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
+ } else {
+ /*
+ * Read interrupt status from the Read-And-Clear shadow register
+ * Note: PISR/SISR Not available on 5210
+ */
+ data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+ }
+
+ /*
+ * Get abstract interrupt mask (driver-compatible)
+ */
+ *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
+
+ if (unlikely(data == AR5K_INT_NOCARD))
+ return -ENODEV;
+
+ if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
+ *interrupt_mask |= AR5K_INT_RX;
+
+ if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
+ | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
+ *interrupt_mask |= AR5K_INT_TX;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ /*HIU = Host Interface Unit (PCI etc)*/
+ if (unlikely(data & (AR5K_ISR_HIUERR)))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*Beacon Not Ready*/
+ if (unlikely(data & (AR5K_ISR_BNR)))
+ *interrupt_mask |= AR5K_INT_BNR;
+ }
+
+ /*
+ * XXX: BMISS interrupts may occur after association.
+ * I found this on 5210 code but it needs testing. If this is
+ * true we should disable them before assoc and re-enable them
+ * after a successfull assoc + some jiffies.
+ */
+#if 0
+ interrupt_mask &= ~AR5K_INT_BMISS;
+#endif
+
+ /*
+ * In case we didn't handle anything,
+ * print the register value.
+ */
+ if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
+ ATH5K_PRINTF("0x%08x\n", data);
+
+ return 0;
+}
+
+/*
+ * Set interrupt mask
+ */
+enum ath5k_int ath5k_hw_set_intr(struct ath5k_hw *ah, enum ath5k_int new_mask)
+{
+ enum ath5k_int old_mask, int_mask;
+
+ /*
+ * Disable card interrupts to prevent any race conditions
+ * (they will be re-enabled afterwards).
+ */
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+
+ old_mask = ah->ah_imr;
+
+ /*
+ * Add additional, chipset-dependent interrupt mask flags
+ * and write them to the IMR (interrupt mask register).
+ */
+ int_mask = new_mask & AR5K_INT_COMMON;
+
+ if (new_mask & AR5K_INT_RX)
+ int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
+ AR5K_IMR_RXDESC;
+
+ if (new_mask & AR5K_INT_TX)
+ int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
+ AR5K_IMR_TXURN;
+
+ if (ah->ah_version != AR5K_AR5210) {
+ if (new_mask & AR5K_INT_FATAL) {
+ int_mask |= AR5K_IMR_HIUERR;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
+ AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
+ }
+ }
+
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+
+ /* Store new interrupt mask */
+ ah->ah_imr = new_mask;
+
+ /* ..re-enable interrupts */
+ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
+
+ return old_mask;
+}
+
+
+/*************************\
+ EEPROM access functions
+\*************************/
+
+/*
+ * Read from eeprom
+ */
+static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
+{
+ u32 status, timeout;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Initialize EEPROM access
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_READ);
+ }
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_RDDONE) {
+ if (status & AR5K_EEPROM_STAT_RDERR)
+ return -EIO;
+ *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
+ 0xffff);
+ return 0;
+ }
+ udelay(15);
+ }
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Write to eeprom - currently disabled, use at your own risk
+ */
+static int ath5k_hw_eeprom_write(struct ath5k_hw *ah, u32 offset, u16 data)
+{
+#if 0
+ u32 status, timeout;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Initialize eeprom access
+ */
+
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
+ } else {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_RESET);
+ }
+
+ /*
+ * Write data to data register
+ */
+
+ if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_reg_write(ah, data, AR5K_EEPROM_BASE + (4 * offset));
+ } else {
+ ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
+ ath5k_hw_reg_write(ah, data, AR5K_EEPROM_DATA);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
+ AR5K_EEPROM_CMD_WRITE);
+ }
+
+ /*
+ * Check status
+ */
+
+ for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
+ status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
+ if (status & AR5K_EEPROM_STAT_WRDONE) {
+ if (status & AR5K_EEPROM_STAT_WRERR)
+ return EIO;
+ return 0;
+ }
+ udelay(15);
+ }
+#endif
+ ATH5K_ERR(ah->ah_sc, "EEPROM Write is disabled!");
+ return -EIO;
+}
+
+/*
+ * Translate binary channel representation in EEPROM to frequency
+ */
+static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin, unsigned int mode)
+{
+ u16 val;
+
+ if (bin == AR5K_EEPROM_CHANNEL_DIS)
+ return bin;
+
+ if (mode == AR5K_EEPROM_MODE_11A) {
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = (5 * bin) + 4800;
+ else
+ val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
+ (bin * 10) + 5100;
+ } else {
+ if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ val = bin + 2300;
+ else
+ val = bin + 2400;
+ }
+
+ return val;
+}
+
+/*
+ * Read antenna infos from eeprom
+ */
+static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret, i = 0;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
+ ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 2) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3;
+ ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f;
+ ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f;
+ ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf;
+ ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f;
+ ee->ee_ant_control[mode][i++] = val & 0x3f;
+
+ /* Get antenna modes */
+ ah->ah_antenna[mode][0] =
+ (ee->ee_ant_control[mode][0] << 4) | 0x1;
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
+ ee->ee_ant_control[mode][1] |
+ (ee->ee_ant_control[mode][2] << 6) |
+ (ee->ee_ant_control[mode][3] << 12) |
+ (ee->ee_ant_control[mode][4] << 18) |
+ (ee->ee_ant_control[mode][5] << 24);
+ ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
+ ee->ee_ant_control[mode][6] |
+ (ee->ee_ant_control[mode][7] << 6) |
+ (ee->ee_ant_control[mode][8] << 12) |
+ (ee->ee_ant_control[mode][9] << 18) |
+ (ee->ee_ant_control[mode][10] << 24);
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Read supported modes from eeprom
+ */
+static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
+ unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 o = *offset;
+ u16 val;
+ int ret;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
+ ee->ee_thr_62[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
+ ee->ee_tx_frm2xpa_enable[mode] = val & 0xff;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff;
+
+ if ((val & 0xff) & 0x80)
+ ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
+ else
+ ee->ee_noise_floor_thr[mode] = val & 0xff;
+
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
+ ee->ee_noise_floor_thr[mode] =
+ mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_xlna_gain[mode] = (val >> 5) & 0xff;
+ ee->ee_x_gain[mode] = (val >> 1) & 0xf;
+ ee->ee_xpd[mode] = val & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
+ ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
+
+ if (mode == AR5K_EEPROM_MODE_11A)
+ ee->ee_xr_power[mode] = val & 0x3f;
+ else {
+ ee->ee_ob[mode][0] = val & 0x7;
+ ee->ee_db[mode][0] = (val >> 3) & 0x7;
+ }
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
+ ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
+ ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
+ } else {
+ ee->ee_i_gain[mode] = (val >> 13) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_gain[mode] |= (val << 3) & 0x38;
+
+ if (mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
+ mode == AR5K_EEPROM_MODE_11A) {
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
+ mode == AR5K_EEPROM_MODE_11G)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+/*
+ * Initialize eeprom & capabilities structs
+ */
+static int ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ unsigned int mode, i;
+ int ret;
+ u32 offset;
+ u16 val;
+
+ /* Initial TX thermal adjustment values */
+ ee->ee_tx_clip = 4;
+ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
+ ee->ee_gain_select = 1;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return 0;
+
+#ifdef notyet
+ /*
+ * Validate the checksum of the EEPROM date. There are some
+ * devices with invalid EEPROMs.
+ */
+ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
+ cksum ^= val;
+ }
+ if (cksum != AR5K_EEPROM_INFO_CKSUM) {
+ ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+ return -EIO;
+ }
+#endif
+
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+ ee_ant_gain);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ /*
+ * Get conformance test limit values
+ */
+ offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
+
+ for (i = 0; i < ee->ee_ctls; i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ /*
+ * Get values for 802.11a (5GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11A;
+
+ ee->ee_turbo_max_power[mode] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ }
+
+ /*
+ * Get values for 802.11b (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11B;
+ offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ }
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ /*
+ * Get values for 802.11g (2.4GHz)
+ */
+ mode = AR5K_EEPROM_MODE_11G;
+ offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][0] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ ee->ee_cal_pier[mode][1] =
+ ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cal_pier[mode][2] =
+ ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ }
+
+ /*
+ * Read 5GHz EEPROM channels
+ */
+
+ return 0;
+}
+
+/*
+ * Read the MAC address from eeprom
+ */
+static int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
+{
+ u8 mac_d[ETH_ALEN];
+ u32 total, offset;
+ u16 data;
+ int octet, ret;
+
+ memset(mac, 0, ETH_ALEN);
+ memset(mac_d, 0, ETH_ALEN);
+
+ ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
+ if (ret)
+ return ret;
+
+ for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
+ ret = ath5k_hw_eeprom_read(ah, offset, &data);
+ if (ret)
+ return ret;
+
+ total += data;
+ mac_d[octet + 1] = data & 0xff;
+ mac_d[octet] = data >> 8;
+ octet += 2;
+ }
+
+ memcpy(mac, mac_d, ETH_ALEN);
+
+ if (!total || total == 3 * 0xffff)
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Read/Write regulatory domain
+ */
+static bool ath5k_eeprom_regulation_domain(struct ath5k_hw *ah, bool write,
+ enum ath5k_regdom *regdomain)
+{
+ u16 ee_regdomain;
+
+ /* Read current value */
+ if (write != true) {
+ ee_regdomain = ah->ah_capabilities.cap_eeprom.ee_regdomain;
+ *regdomain = ath5k_regdom_to_ieee(ee_regdomain);
+ return true;
+ }
+
+ ee_regdomain = ath5k_regdom_from_ieee(*regdomain);
+
+ /* Try to write a new value */
+ if (ah->ah_capabilities.cap_eeprom.ee_protect &
+ AR5K_EEPROM_PROTECT_WR_128_191)
+ return false;
+ if (ath5k_hw_eeprom_write(ah, AR5K_EEPROM_REG_DOMAIN, ee_regdomain)!=0)
+ return false;
+
+ ah->ah_capabilities.cap_eeprom.ee_regdomain = ee_regdomain;
+
+ return true;
+}
+
+/*
+ * Use the above to write a new regulatory domain
+ */
+int ath5k_hw_set_regdomain(struct ath5k_hw *ah, u16 regdomain)
+{
+ enum ath5k_regdom ieee_regdomain;
+
+ ieee_regdomain = ath5k_regdom_to_ieee(regdomain);
+
+ if (ath5k_eeprom_regulation_domain(ah, true, &ieee_regdomain) == true)
+ return 0;
+
+ return -EIO;
+}
+
+/*
+ * Fill the capabilities struct
+ */
+static int ath5k_hw_get_capabilities(struct ath5k_hw *ah)
+{
+ u16 ee_header;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Capabilities stored in the EEPROM */
+ ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Set radio capabilities
+ * (The AR5110 only supports the middle 5GHz band)
+ */
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
+ ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
+ ah->ah_capabilities.cap_range.range_2ghz_min = 0;
+ ah->ah_capabilities.cap_range.range_2ghz_max = 0;
+
+ /* Set supported modes */
+ __set_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode);
+ __set_bit(MODE_ATHEROS_TURBO, ah->ah_capabilities.cap_mode);
+ } else {
+ /*
+ * XXX The tranceiver supports frequencies from 4920 to 6100GHz
+ * XXX and from 2312 to 2732GHz. There are problems with the
+ * XXX current ieee80211 implementation because the IEEE
+ * XXX channel mapping does not support negative channel
+ * XXX numbers (2312MHz is channel -19). Of course, this
+ * XXX doesn't matter because these channels are out of range
+ * XXX but some regulation domains like MKK (Japan) will
+ * XXX support frequencies somewhere around 4.8GHz.
+ */
+
+ /*
+ * Set radio capabilities
+ */
+
+ if (AR5K_EEPROM_HDR_11A(ee_header)) {
+ ah->ah_capabilities.cap_range.range_5ghz_min = 5005; /* 4920 */
+ ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
+
+ /* Set supported modes */
+ __set_bit(MODE_IEEE80211A,
+ ah->ah_capabilities.cap_mode);
+ __set_bit(MODE_ATHEROS_TURBO,
+ ah->ah_capabilities.cap_mode);
+ if (ah->ah_version == AR5K_AR5212)
+ __set_bit(MODE_ATHEROS_TURBOG,
+ ah->ah_capabilities.cap_mode);
+ }
+
+ /* Enable 802.11b if a 2GHz capable radio (2111/5112) is
+ * connected */
+ if (AR5K_EEPROM_HDR_11B(ee_header) ||
+ AR5K_EEPROM_HDR_11G(ee_header)) {
+ ah->ah_capabilities.cap_range.range_2ghz_min = 2412; /* 2312 */
+ ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
+
+ if (AR5K_EEPROM_HDR_11B(ee_header))
+ __set_bit(MODE_IEEE80211B,
+ ah->ah_capabilities.cap_mode);
+
+ if (AR5K_EEPROM_HDR_11G(ee_header))
+ __set_bit(MODE_IEEE80211G,
+ ah->ah_capabilities.cap_mode);
+ }
+ }
+
+ /* GPIO */
+ ah->ah_gpio_npins = AR5K_NUM_GPIO;
+
+ /* Set number of supported TX queues */
+ if (ah->ah_version == AR5K_AR5210)
+ ah->ah_capabilities.cap_queues.q_tx_num =
+ AR5K_NUM_TX_QUEUES_NOQCU;
+ else
+ ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
+
+ return 0;
+}
+
+/*********************************\
+ Protocol Control Unit Functions
+\*********************************/
+
+/*
+ * Set Operation mode
+ */
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
+{
+ u32 pcu_reg, beacon_reg, low_id, high_id;
+
+ pcu_reg = 0;
+ beacon_reg = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ switch (ah->ah_op_mode) {
+ case IEEE80211_IF_TYPE_IBSS:
+ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ beacon_reg |= AR5K_BCR_ADHOC;
+ break;
+
+ case IEEE80211_IF_TYPE_AP:
+ pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ beacon_reg |= AR5K_BCR_AP;
+ break;
+
+ case IEEE80211_IF_TYPE_STA:
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_PWR_SV : 0);
+ case IEEE80211_IF_TYPE_MNTR:
+ pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
+ (ah->ah_version == AR5K_AR5210 ?
+ AR5K_STA_ID1_NO_PSPOLL : 0);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /*
+ * Set PCU registers
+ */
+ low_id = AR5K_LOW_ID(ah->ah_sta_id);
+ high_id = AR5K_HIGH_ID(ah->ah_sta_id);
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
+
+ /*
+ * Set Beacon Control Register on 5210
+ */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
+
+ return 0;
+}
+
+/*
+ * BSSID Functions
+ */
+
+/*
+ * Get station id
+ */
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ memcpy(mac, ah->ah_sta_id, ETH_ALEN);
+}
+
+/*
+ * Set station id
+ */
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
+{
+ u32 low_id, high_id;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Set new station ID */
+ memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
+
+ return 0;
+}
+
+/*
+ * Set BSSID
+ */
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
+{
+ u32 low_id, high_id;
+ u16 tim_offset = 0;
+
+ /*
+ * Set simple BSSID mask on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, 0xfffffff, AR5K_BSS_IDM1);
+ }
+
+ /*
+ * Set BSSID which triggers the "SME Join" operation
+ */
+ low_id = AR5K_LOW_ID(bssid);
+ high_id = AR5K_HIGH_ID(bssid);
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
+ ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
+ AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
+
+ if (assoc_id == 0) {
+ ath5k_hw_disable_pspoll(ah);
+ return;
+ }
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM,
+ tim_offset ? tim_offset + 4 : 0);
+
+ ath5k_hw_enable_pspoll(ah, NULL, 0);
+}
+/**
+ * ath5k_hw_set_bssid_mask - set common bits we should listen to
+ *
+ * The bssid_mask is a utility used by AR5212 hardware to inform the hardware
+ * which bits of the interface's MAC address should be looked at when trying
+ * to decide which packets to ACK. In station mode every bit matters. In AP
+ * mode with a single BSS every bit matters as well. In AP mode with
+ * multiple BSSes not every bit matters.
+ *
+ * @ah: the &struct ath5k_hw
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
+ *
+ * Note that this is a simple filter and *does* not filter out all
+ * relevant frames. Some non-relevant frames will get through, probability
+ * jocks are welcomed to compute.
+ *
+ * When handling multiple BSSes (or VAPs) you can get the BSSID mask by
+ * computing the set of:
+ *
+ * ~ ( MAC XOR BSSID )
+ *
+ * When you do this you are essentially computing the common bits. Later it
+ * is assumed the harware will "and" (&) the BSSID mask with the MAC address
+ * to obtain the relevant bits which should match on the destination frame.
+ *
+ * Simple example: on your card you have have two BSSes you have created with
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
+ *
+ * \
+ * MAC: 0001 |
+ * BSSID-01: 0100 | --> Belongs to us
+ * BSSID-02: 1001 |
+ * /
+ * -------------------
+ * BSSID-03: 0110 | --> External
+ * -------------------
+ *
+ * Our bssid_mask would then be:
+ *
+ * On loop iteration for BSSID-01:
+ * ~(0001 ^ 0100) -> ~(0101)
+ * -> 1010
+ * bssid_mask = 1010
+ *
+ * On loop iteration for BSSID-02:
+ * bssid_mask &= ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(0001 ^ 1001)
+ * bssid_mask = (1010) & ~(1001)
+ * bssid_mask = (1010) & (0110)
+ * bssid_mask = 0010
+ *
+ * A bssid_mask of 0010 means "only pay attention to the second least
+ * significant bit". This is because its the only bit common
+ * amongst the MAC and all BSSIDs we support. To findout what the real
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
+ * or our MAC address (we assume the hardware uses the MAC address).
+ *
+ * Now, suppose there's an incoming frame for BSSID-03:
+ *
+ * IFRAME-01: 0110
+ *
+ * An easy eye-inspeciton of this already should tell you that this frame
+ * will not pass our check. This is beacuse the bssid_mask tells the
+ * hardware to only look at the second least significant bit and the
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
+ * as 1, which does not match 0.
+ *
+ * So with IFRAME-01 we *assume* the hardware will do:
+ *
+ * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
+ * --> allow = (0010) == 0000 ? 1 : 0;
+ * --> allow = 0
+ *
+ * Lets now test a frame that should work:
+ *
+ * IFRAME-02: 0001 (we should allow)
+ *
+ * allow = (0001 & 1010) == 1010
+ *
+ * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
+ * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0;
+ * --> allow = (0010) == (0010)
+ * --> allow = 1
+ *
+ * Other examples:
+ *
+ * IFRAME-03: 0100 --> allowed
+ * IFRAME-04: 1001 --> allowed
+ * IFRAME-05: 1101 --> allowed but its not for us!!!
+ *
+ */
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
+{
+ u32 low_id, high_id;
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5212) {
+ low_id = AR5K_LOW_ID(mask);
+ high_id = AR5K_HIGH_ID(mask);
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
+
+ return 0;
+ }
+
+ return -EIO;
+}
+
+/*
+ * Receive start/stop functions
+ */
+
+/*
+ * Start receive on PCU
+ */
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * Stop receive on PCU
+ */
+void ath5k_hw_stop_pcu_recv(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
+}
+
+/*
+ * RX Filter functions
+ */
+
+/*
+ * Set multicast filter
+ */
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /* Set the multicat filter */
+ ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
+ ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
+}
+
+/*
+ * Set multicast filter by index
+ */
+int ath5k_hw_set_mcast_filterindex(struct ath5k_hw *ah, u32 index)
+{
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (index >= 64)
+ return -EINVAL;
+ else if (index >= 32)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1,
+ (1 << (index - 32)));
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+ return 0;
+}
+
+/*
+ * Clear Multicast filter by index
+ */
+int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index)
+{
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (index >= 64)
+ return -EINVAL;
+ else if (index >= 32)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1,
+ (1 << (index - 32)));
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index));
+
+ return 0;
+}
+
+/*
+ * Get current rx filter
+ */
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
+{
+ u32 data, filter = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+ filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
+
+ /*Radar detection for 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
+
+ if (data & AR5K_PHY_ERR_FIL_RADAR)
+ filter |= AR5K_RX_FILTER_RADARERR;
+ if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
+ filter |= AR5K_RX_FILTER_PHYERR;
+ }
+
+ return filter;
+}
+
+/*
+ * Set rx filter
+ */
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
+{
+ u32 data = 0;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* Set PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ if (filter & AR5K_RX_FILTER_RADARERR)
+ data |= AR5K_PHY_ERR_FIL_RADAR;
+ if (filter & AR5K_RX_FILTER_PHYERR)
+ data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
+ }
+
+ /*
+ * The AR5210 uses promiscous mode to detect radar activity
+ */
+ if (ah->ah_version == AR5K_AR5210 &&
+ (filter & AR5K_RX_FILTER_RADARERR)) {
+ filter &= ~AR5K_RX_FILTER_RADARERR;
+ filter |= AR5K_RX_FILTER_PROM;
+ }
+
+ /*Zero length DMA*/
+ if (data)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
+
+ /*Write RX Filter register*/
+ ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
+
+ /*Write PHY error filter register on 5212*/
+ if (ah->ah_version == AR5K_AR5212)
+ ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
+
+}
+
+/*
+ * Beacon related functions
+ */
+
+/*
+ * Get a 32bit TSF
+ */
+u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32);
+}
+
+/*
+ * Get the full 64bit TSF
+ */
+u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah)
+{
+ u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32);
+ ATH5K_TRACE(ah->ah_sc);
+
+ return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32);
+}
+
+/*
+ * Force a TSF reset
+ */
+void ath5k_hw_reset_tsf(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_RESET_TSF);
+}
+
+/*
+ * Initialize beacon timers
+ */
+void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
+{
+ u32 timer1, timer2, timer3;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Set the additional timers by mode
+ */
+ switch (ah->ah_op_mode) {
+ case IEEE80211_IF_TYPE_STA:
+ if (ah->ah_version == AR5K_AR5210) {
+ timer1 = 0xffffffff;
+ timer2 = 0xffffffff;
+ } else {
+ timer1 = 0x0000ffff;
+ timer2 = 0x0007ffff;
+ }
+ break;
+
+ default:
+ timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
+ timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
+ }
+
+ timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
+
+ /*
+ * Set the beacon register and enable all timers.
+ * (next beacon, DMA beacon, software beacon, ATIM window time)
+ */
+ ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+ ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
+ ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
+ ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
+
+ ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
+ AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
+ AR5K_BEACON);
+}
+
+#if 0
+/*
+ * Set beacon timers
+ */
+int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah,
+ const struct ath5k_beacon_state *state)
+{
+ u32 cfp_period, next_cfp, dtim, interval, next_beacon;
+
+ /*
+ * TODO: should be changed through *state
+ * review struct ath5k_beacon_state struct
+ *
+ * XXX: These are used for cfp period bellow, are they
+ * ok ? Is it O.K. for tsf here to be 0 or should we use
+ * get_tsf ?
+ */
+ u32 dtim_count = 0; /* XXX */
+ u32 cfp_count = 0; /* XXX */
+ u32 tsf = 0; /* XXX */
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Return on an invalid beacon state */
+ if (state->bs_interval < 1)
+ return -EINVAL;
+
+ interval = state->bs_interval;
+ dtim = state->bs_dtim_period;
+
+ /*
+ * PCF support?
+ */
+ if (state->bs_cfp_period > 0) {
+ /*
+ * Enable PCF mode and set the CFP
+ * (Contention Free Period) and timer registers
+ */
+ cfp_period = state->bs_cfp_period * state->bs_dtim_period *
+ state->bs_interval;
+ next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) *
+ state->bs_interval;
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_PCF);
+ ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD);
+ ath5k_hw_reg_write(ah, state->bs_cfp_max_duration,
+ AR5K_CFP_DUR);
+ ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period :
+ next_cfp)) << 3, AR5K_TIMER2);
+ } else {
+ /* Disable PCF mode */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA |
+ AR5K_STA_ID1_PCF);
+ }
+
+ /*
+ * Enable the beacon timer register
+ */
+ ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0);
+
+ /*
+ * Start the beacon timers
+ */
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) &~
+ (AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) |
+ AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0,
+ AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval,
+ AR5K_BEACON_PERIOD), AR5K_BEACON);
+
+ /*
+ * Write new beacon miss threshold, if it appears to be valid
+ * XXX: Figure out right values for min <= bs_bmiss_threshold <= max
+ * and return if its not in range. We can test this by reading value and
+ * setting value to a largest value and seeing which values register.
+ */
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS,
+ state->bs_bmiss_threshold);
+
+ /*
+ * Set sleep control register
+ * XXX: Didn't find this in 5210 code but since this register
+ * exists also in ar5k's 5210 headers i leave it as common code.
+ */
+ AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR,
+ (state->bs_sleep_duration - 3) << 3);
+
+ /*
+ * Set enhanced sleep registers on 5212
+ */
+ if (ah->ah_version == AR5K_AR5212) {
+ if (state->bs_sleep_duration > state->bs_interval &&
+ roundup(state->bs_sleep_duration, interval) ==
+ state->bs_sleep_duration)
+ interval = state->bs_sleep_duration;
+
+ if (state->bs_sleep_duration > dtim && (dtim == 0 ||
+ roundup(state->bs_sleep_duration, dtim) ==
+ state->bs_sleep_duration))
+ dtim = state->bs_sleep_duration;
+
+ if (interval > dtim)
+ return -EINVAL;
+
+ next_beacon = interval == dtim ? state->bs_next_dtim :
+ state->bs_next_beacon;
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM((state->bs_next_dtim - 3) << 3,
+ AR5K_SLEEP0_NEXT_DTIM) |
+ AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) |
+ AR5K_SLEEP0_ENH_SLEEP_EN |
+ AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0);
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3,
+ AR5K_SLEEP1_NEXT_TIM) |
+ AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1);
+
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) |
+ AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2);
+ }
+
+ return 0;
+}
+
+/*
+ * Reset beacon timers
+ */
+void ath5k_hw_reset_beacon(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /*
+ * Disable beacon timer
+ */
+ ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+
+ /*
+ * Disable some beacon register values
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF);
+ ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON);
+}
+
+/*
+ * Wait for beacon queue to finish
+ */
+int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
+{
+ unsigned int i;
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* 5210 doesn't have QCU*/
+ if (ah->ah_version == AR5K_AR5210) {
+ /*
+ * Wait for beaconn queue to finish by checking
+ * Control Register and Beacon Status Register.
+ */
+ for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) {
+ if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F)
+ ||
+ !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F))
+ break;
+ udelay(10);
+ }
+
+ /* Timeout... */
+ if (i <= 0) {
+ /*
+ * Re-schedule the beacon queue
+ */
+ ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1);
+ ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE,
+ AR5K_BCR);
+
+ return -EIO;
+ }
+ ret = 0;
+ } else {
+ /*5211/5212*/
+ ret = ath5k_hw_register_timeout(ah,
+ AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON),
+ AR5K_QCU_STS_FRMPENDCNT, 0, false);
+
+ if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON))
+ return -EIO;
+ }
+
+ return ret;
+}
+#endif
+
+/*
+ * Update mib counters (statistics)
+ */
+void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
+ struct ath5k_mib_stats *statistics)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /* Read-And-Clear */
+ statistics->ackrcv_bad += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL);
+ statistics->rts_bad += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL);
+ statistics->rts_good += ath5k_hw_reg_read(ah, AR5K_RTS_OK);
+ statistics->fcs_bad += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL);
+ statistics->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT);
+
+ /* Reset profile count registers on 5212*/
+ if (ah->ah_version == AR5K_AR5212) {
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
+ ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
+ }
+}
+
+/** ath5k_hw_set_ack_bitrate - set bitrate for ACKs
+ *
+ * @ah: the &struct ath5k_hw
+ * @high: determines if to use low bit rate or now
+ */
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high)
+{
+ if (ah->ah_version != AR5K_AR5212)
+ return;
+ else {
+ u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
+ if (high)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
+ }
+}
+
+
+/*
+ * ACK/CTS Timeouts
+ */
+
+/*
+ * Set ACK timeout on PCU
+ */
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+/*
+ * Read the ACK timeout from PCU
+ */
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
+}
+
+/*
+ * Set CTS timeout on PCU
+ */
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
+ ah->ah_turbo) <= timeout)
+ return -EINVAL;
+
+ AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
+ ath5k_hw_htoclock(timeout, ah->ah_turbo));
+
+ return 0;
+}
+
+/*
+ * Read CTS timeout from PCU
+ */
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
+ AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
+}
+
+/*
+ * Key table (WEP) functions
+ */
+
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
+{
+ unsigned int i;
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+
+ /* Set NULL encryption on non-5210*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(entry));
+
+ return 0;
+}
+
+int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ /* Check the validation flag at the end of the entry */
+ return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) &
+ AR5K_KEYTABLE_VALID;
+}
+
+int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
+ const struct ieee80211_key_conf *key, const u8 *mac)
+{
+ unsigned int i;
+ __le32 key_v[5] = {};
+ u32 keytype;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /* key->keylen comes in from mac80211 in bytes */
+
+ if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
+ return -EOPNOTSUPP;
+
+ switch (key->keylen) {
+ /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
+ case 40 / 8:
+ memcpy(&key_v[0], key->key, 5);
+ keytype = AR5K_KEYTABLE_TYPE_40;
+ break;
+
+ /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
+ case 104 / 8:
+ memcpy(&key_v[0], &key->key[0], 6);
+ memcpy(&key_v[2], &key->key[6], 6);
+ memcpy(&key_v[4], &key->key[12], 1);
+ keytype = AR5K_KEYTABLE_TYPE_104;
+ break;
+ /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
+ case 128 / 8:
+ memcpy(&key_v[0], &key->key[0], 6);
+ memcpy(&key_v[2], &key->key[6], 6);
+ memcpy(&key_v[4], &key->key[12], 4);
+ keytype = AR5K_KEYTABLE_TYPE_128;
+ break;
+
+ default:
+ return -EINVAL; /* shouldn't happen */
+ }
+
+ for (i = 0; i < ARRAY_SIZE(key_v); i++)
+ ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+ AR5K_KEYTABLE_OFF(entry, i));
+
+ ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
+
+ return ath5k_hw_set_key_lladdr(ah, entry, mac);
+}
+
+int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac)
+{
+ u32 low_id, high_id;
+
+ ATH5K_TRACE(ah->ah_sc);
+ /* Invalid entry (key table overflow) */
+ AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+
+ /* MAC may be NULL if it's a broadcast key. In this case no need to
+ * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */
+ if (unlikely(mac == NULL)) {
+ low_id = 0xffffffff;
+ high_id = 0xffff | AR5K_KEYTABLE_VALID;
+ } else {
+ low_id = AR5K_LOW_ID(mac);
+ high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID;
+ }
+
+ ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry));
+ ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry));
+
+ return 0;
+}
+
+
+/********************************************\
+Queue Control Unit, DFS Control Unit Functions
+\********************************************/
+
+/*
+ * Initialize a transmit queue
+ */
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
+ struct ath5k_txq_info *queue_info)
+{
+ unsigned int queue;
+ int ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Get queue by type
+ */
+ /*5210 only has 2 queues*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (queue_type) {
+ case AR5K_TX_QUEUE_DATA:
+ queue = AR5K_TX_QUEUE_ID_NOQCU_DATA;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ case AR5K_TX_QUEUE_CAB:
+ queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (queue_type) {
+ case AR5K_TX_QUEUE_DATA:
+ for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
+ ah->ah_txq[queue].tqi_type !=
+ AR5K_TX_QUEUE_INACTIVE; queue++) {
+
+ if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
+ return -EINVAL;
+ }
+ break;
+ case AR5K_TX_QUEUE_UAPSD:
+ queue = AR5K_TX_QUEUE_ID_UAPSD;
+ break;
+ case AR5K_TX_QUEUE_BEACON:
+ queue = AR5K_TX_QUEUE_ID_BEACON;
+ break;
+ case AR5K_TX_QUEUE_CAB:
+ queue = AR5K_TX_QUEUE_ID_CAB;
+ break;
+ case AR5K_TX_QUEUE_XR_DATA:
+ if (ah->ah_version != AR5K_AR5212)
+ ATH5K_ERR(ah->ah_sc,
+ "XR data queues only supported in"
+ " 5212!\n");
+ queue = AR5K_TX_QUEUE_ID_XR_DATA;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Setup internal queue structure
+ */
+ memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info));
+ ah->ah_txq[queue].tqi_type = queue_type;
+
+ if (queue_info != NULL) {
+ queue_info->tqi_type = queue_type;
+ ret = ath5k_hw_setup_tx_queueprops(ah, queue, queue_info);
+ if (ret)
+ return ret;
+ }
+ /*
+ * We use ah_txq_status to hold a temp value for
+ * the Secondary interrupt mask registers on 5211+
+ * check out ath5k_hw_reset_tx_queue
+ */
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue);
+
+ return queue;
+}
+
+/*
+ * Setup a transmit queue
+ */
+int ath5k_hw_setup_tx_queueprops(struct ath5k_hw *ah, int queue,
+ const struct ath5k_txq_info *queue_info)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return -EIO;
+
+ memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info));
+
+ /*XXX: Is this supported on 5210 ?*/
+ if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
+ ((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
+ (queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
+ queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
+ ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
+
+ return 0;
+}
+
+/*
+ * Get properties for a specific transmit queue
+ */
+int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue,
+ struct ath5k_txq_info *queue_info)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info));
+ return 0;
+}
+
+/*
+ * Set a transmit queue inactive
+ */
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num))
+ return;
+
+ /* This queue will be skipped in further operations */
+ ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE;
+ /*For SIMR setup*/
+ AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue);
+}
+
+/*
+ * Set DFS params for a transmit queue
+ */
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
+{
+ u32 cw_min, cw_max, retry_lg, retry_sh;
+ struct ath5k_txq_info *tq = &ah->ah_txq[queue];
+
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ tq = &ah->ah_txq[queue];
+
+ if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return 0;
+
+ if (ah->ah_version == AR5K_AR5210) {
+ /* Only handle data queues, others will be ignored */
+ if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
+ return 0;
+
+ /* Set Slot time */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
+ AR5K_SLOT_TIME);
+ /* Set ACK_CTS timeout */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
+ AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
+ /* Set Transmit Latency */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ AR5K_INIT_TRANSMIT_LATENCY_TURBO :
+ AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
+ /* Set IFS0 */
+ if (ah->ah_turbo == true)
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME_TURBO) <<
+ AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
+ AR5K_IFS0);
+ else
+ ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
+ (ah->ah_aifs + tq->tqi_aifs) *
+ AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
+ AR5K_INIT_SIFS, AR5K_IFS0);
+
+ /* Set IFS1 */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
+ AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
+ /* Set PHY register 0x9844 (??) */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x38 :
+ (ath5k_hw_reg_read(ah, AR5K_PHY(17)) & ~0x7F) | 0x1C,
+ AR5K_PHY(17));
+ /* Set Frame Control Register */
+ ath5k_hw_reg_write(ah, ah->ah_turbo == true ?
+ (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
+ AR5K_PHY_TURBO_SHORT | 0x2020) :
+ (AR5K_PHY_FRAME_CTL_INI | 0x1020),
+ AR5K_PHY_FRAME_CTL_5210);
+ }
+
+ /*
+ * Calculate cwmin/max by channel mode
+ */
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
+ ah->ah_aifs = AR5K_TUNE_AIFS;
+ /*XR is only supported on 5212*/
+ if (IS_CHAN_XR(ah->ah_current_channel) &&
+ ah->ah_version == AR5K_AR5212) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
+ ah->ah_aifs = AR5K_TUNE_AIFS_XR;
+ /*B mode is not supported on 5210*/
+ } else if (IS_CHAN_B(ah->ah_current_channel) &&
+ ah->ah_version != AR5K_AR5210) {
+ cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
+ cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
+ ah->ah_aifs = AR5K_TUNE_AIFS_11B;
+ }
+
+ cw_min = 1;
+ while (cw_min < ah->ah_cw_min)
+ cw_min = (cw_min << 1) | 1;
+
+ cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
+ ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
+ cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
+ ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
+
+ /*
+ * Calculate and set retry limits
+ */
+ if (ah->ah_software_retry == true) {
+ /* XXX Need to test this */
+ retry_lg = ah->ah_limit_tx_retries;
+ retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
+ AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
+ } else {
+ retry_lg = AR5K_INIT_LG_RETRY;
+ retry_sh = AR5K_INIT_SH_RETRY;
+ }
+
+ /*No QCU/DCU [5210]*/
+ if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_reg_write(ah,
+ (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
+ | AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+ | AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+ | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
+ | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
+ AR5K_NODCU_RETRY_LMT);
+ } else {
+ /*QCU/DCU [5211+]*/
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
+ AR5K_DCU_RETRY_LMT_SLG_RETRY) |
+ AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
+ AR5K_DCU_RETRY_LMT_SSH_RETRY) |
+ AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
+ AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
+ AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
+
+ /*===Rest is also for QCU/DCU only [5211+]===*/
+
+ /*
+ * Set initial content window (cw_min/cw_max)
+ * and arbitrated interframe space (aifs)...
+ */
+ ath5k_hw_reg_write(ah,
+ AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
+ AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
+ AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
+ AR5K_DCU_LCL_IFS_AIFS),
+ AR5K_QUEUE_DFS_LOCAL_IFS(queue));
+
+ /*
+ * Set misc registers
+ */
+ ath5k_hw_reg_write(ah, AR5K_QCU_MISC_DCU_EARLY,
+ AR5K_QUEUE_MISC(queue));
+
+ if (tq->tqi_cbr_period) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
+ AR5K_QCU_CBRCFG_INTVAL) |
+ AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
+ AR5K_QCU_CBRCFG_ORN_THRES),
+ AR5K_QUEUE_CBRCFG(queue));
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_CBR);
+ if (tq->tqi_cbr_overflow_limit)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBR_THRES_ENABLE);
+ }
+
+ if (tq->tqi_ready_time)
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
+ AR5K_QCU_RDYTIMECFG_INTVAL) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+
+ if (tq->tqi_burst_time) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
+ AR5K_DCU_CHAN_TIME_DUR) |
+ AR5K_DCU_CHAN_TIME_ENABLE,
+ AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
+ AR5K_REG_ENABLE_BITS(ah,
+ AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_TXE);
+ }
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
+ ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
+ AR5K_QUEUE_DFS_MISC(queue));
+
+ /*
+ * Set registers by queue type
+ */
+ switch (tq->tqi_type) {
+ case AR5K_TX_QUEUE_BEACON:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP_BCN |
+ AR5K_QCU_MISC_BCN_ENABLE);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S) |
+ AR5K_DCU_MISC_POST_FR_BKOFF_DIS |
+ AR5K_DCU_MISC_BCN_ENABLE);
+
+ ath5k_hw_reg_write(ah, ((AR5K_TUNE_BEACON_INTERVAL -
+ (AR5K_TUNE_SW_BEACON_RESP -
+ AR5K_TUNE_DMA_BEACON_RESP) -
+ AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) |
+ AR5K_QCU_RDYTIMECFG_ENABLE,
+ AR5K_QUEUE_RDYTIMECFG(queue));
+ break;
+
+ case AR5K_TX_QUEUE_CAB:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_FRSHED_DBA_GT |
+ AR5K_QCU_MISC_CBREXP |
+ AR5K_QCU_MISC_CBREXP_BCN);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
+ (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL <<
+ AR5K_DCU_MISC_ARBLOCK_CTL_S));
+ break;
+
+ case AR5K_TX_QUEUE_UAPSD:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
+ AR5K_QCU_MISC_CBREXP);
+ break;
+
+ case AR5K_TX_QUEUE_DATA:
+ default:
+ break;
+ }
+
+ /*
+ * Enable interrupts for this tx queue
+ * in the secondary interrupt mask registers
+ */
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+
+
+ /* Update secondary interrupt mask registers */
+ ah->ah_txq_imr_txok &= ah->ah_txq_status;
+ ah->ah_txq_imr_txerr &= ah->ah_txq_status;
+ ah->ah_txq_imr_txurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
+ ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
+ AR5K_SIMR0_QCU_TXOK) |
+ AR5K_REG_SM(ah->ah_txq_imr_txdesc,
+ AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
+ AR5K_SIMR1_QCU_TXERR) |
+ AR5K_REG_SM(ah->ah_txq_imr_txeol,
+ AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
+ }
+
+ return 0;
+}
+
+/*
+ * Get number of pending frames
+ * for a specific queue [5211+]
+ */
+u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) {
+ ATH5K_TRACE(ah->ah_sc);
+ AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num);
+
+ /* Return if queue is declared inactive */
+ if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE)
+ return false;
+
+ /* XXX: How about AR5K_CFG_TXCNT ? */
+ if (ah->ah_version == AR5K_AR5210)
+ return false;
+
+ return AR5K_QUEUE_STATUS(queue) & AR5K_QCU_STS_FRMPENDCNT;
+}
+
+/*
+ * Set slot time
+ */
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
+ return -EINVAL;
+
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
+ ah->ah_turbo), AR5K_SLOT_TIME);
+ else
+ ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
+
+ return 0;
+}
+
+/*
+ * Get slot time
+ */
+unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (ah->ah_version == AR5K_AR5210)
+ return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah,
+ AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo);
+ else
+ return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff;
+}
+
+
+/******************************\
+ Hardware Descriptor Functions
+\******************************/
+
+/*
+ * TX Descriptor
+ */
+
+/*
+ * Initialize the 2-word tx descriptor on 5210/5211
+ */
+static int
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
+ unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0,
+ unsigned int key_index, unsigned int antenna_mode, unsigned int flags,
+ unsigned int rtscts_rate, unsigned int rtscts_duration)
+{
+ u32 frame_type;
+ struct ath5k_hw_2w_tx_desc *tx_desc;
+ unsigned int buff_len;
+
+ tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (unlikely(tx_tries0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ if (unlikely(tx_rate0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Clear status descriptor */
+ memset(desc->ds_hw, 0, sizeof(struct ath5k_hw_tx_status));
+
+ /* Initialize control descriptor */
+ tx_desc->tx_control_0 = 0;
+ tx_desc->tx_control_1 = 0;
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+ if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+ buff_len = pkt_len - FCS_LEN;
+
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ if(type == AR5K_PKT_TYPE_BEACON)
+ buff_len = roundup(buff_len, 4);
+
+ if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
+
+ /*
+ * Verify and set header length
+ * XXX: I only found that on 5210 code, does it work on 5211 ?
+ */
+ if (ah->ah_version == AR5K_AR5210) {
+ if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
+ return -EINVAL;
+ tx_desc->tx_control_0 |=
+ AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
+ }
+
+ /*Diferences between 5210-5211*/
+ if (ah->ah_version == AR5K_AR5210) {
+ switch (type) {
+ case AR5K_PKT_TYPE_BEACON:
+ case AR5K_PKT_TYPE_PROBE_RESP:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
+ case AR5K_PKT_TYPE_PIFS:
+ frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
+ default:
+ frame_type = type /*<< 2 ?*/;
+ }
+
+ tx_desc->tx_control_0 |=
+ AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+ } else {
+ tx_desc->tx_control_0 |=
+ AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
+ AR5K_REG_SM(antenna_mode, AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_desc->tx_control_1 |=
+ AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
+ }
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) \
+ tx_desc->tx_control_##_c |= \
+ AR5K_2W_TX_DESC_CTL##_c##_##_flag
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+ tx_desc->tx_control_0 |=
+ AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+ tx_desc->tx_control_1 |=
+ AR5K_REG_SM(key_index,
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+
+ /*
+ * RTS/CTS Duration [5210 ?]
+ */
+ if ((ah->ah_version == AR5K_AR5210) &&
+ (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
+ tx_desc->tx_control_1 |= rtscts_duration &
+ AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
+
+ return 0;
+}
+
+/*
+ * Initialize the 4-word tx descriptor on 5212
+ */
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
+ struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len,
+ enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
+ unsigned int tx_tries0, unsigned int key_index,
+ unsigned int antenna_mode, unsigned int flags, unsigned int rtscts_rate,
+ unsigned int rtscts_duration)
+{
+ struct ath5k_hw_4w_tx_desc *tx_desc;
+ struct ath5k_hw_tx_status *tx_status;
+ unsigned int buff_len;
+
+ ATH5K_TRACE(ah->ah_sc);
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+
+ /*
+ * Validate input
+ * - Zero retries don't make sense.
+ * - A zero rate will put the HW into a mode where it continously sends
+ * noise on the channel, so it is important to avoid this.
+ */
+ if (unlikely(tx_tries0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero retries\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ if (unlikely(tx_rate0 == 0)) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ /* Clear status descriptor */
+ memset(tx_status, 0, sizeof(struct ath5k_hw_tx_status));
+
+ /* Initialize control descriptor */
+ tx_desc->tx_control_0 = 0;
+ tx_desc->tx_control_1 = 0;
+ tx_desc->tx_control_2 = 0;
+ tx_desc->tx_control_3 = 0;
+
+ /* Setup control descriptor */
+
+ /* Verify and set frame length */
+ if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
+ return -EINVAL;
+
+ tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
+
+ /* Verify and set buffer length */
+ buff_len = pkt_len - FCS_LEN;
+
+ /* NB: beacon's BufLen must be a multiple of 4 bytes */
+ if(type == AR5K_PKT_TYPE_BEACON)
+ buff_len = roundup(buff_len, 4);
+
+ if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
+ return -EINVAL;
+
+ tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
+
+ tx_desc->tx_control_0 |=
+ AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
+ AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
+ tx_desc->tx_control_1 |= AR5K_REG_SM(type,
+ AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
+ tx_desc->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
+ tx_desc->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+
+#define _TX_FLAGS(_c, _flag) \
+ if (flags & AR5K_TXDESC_##_flag) \
+ tx_desc->tx_control_##_c |= \
+ AR5K_4W_TX_DESC_CTL##_c##_##_flag
+
+ _TX_FLAGS(0, CLRDMASK);
+ _TX_FLAGS(0, VEOL);
+ _TX_FLAGS(0, INTREQ);
+ _TX_FLAGS(0, RTSENA);
+ _TX_FLAGS(0, CTSENA);
+ _TX_FLAGS(1, NOACK);
+
+#undef _TX_FLAGS
+
+ /*
+ * WEP crap
+ */
+ if (key_index != AR5K_TXKEYIX_INVALID) {
+ tx_desc->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID;
+ tx_desc->tx_control_1 |= AR5K_REG_SM(key_index,
+ AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX);
+ }
+
+ /*
+ * RTS/CTS
+ */
+ if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
+ if ((flags & AR5K_TXDESC_RTSENA) &&
+ (flags & AR5K_TXDESC_CTSENA))
+ return -EINVAL;
+ tx_desc->tx_control_2 |= rtscts_duration &
+ AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
+ tx_desc->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
+ AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
+ }
+
+ return 0;
+}
+
+/*
+ * Initialize a 4-word multirate tx descriptor on 5212
+ */
+static bool
+ath5k_hw_setup_xr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, u_int tx_tries2,
+ unsigned int tx_rate3, u_int tx_tries3)
+{
+ struct ath5k_hw_4w_tx_desc *tx_desc;
+
+ /*
+ * Rates can be 0 as long as the retry count is 0 too.
+ * A zero rate and nonzero retry count will put the HW into a mode where
+ * it continously sends noise on the channel, so it is important to
+ * avoid this.
+ */
+ if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
+ (tx_rate2 == 0 && tx_tries2 != 0) ||
+ (tx_rate3 == 0 && tx_tries3 != 0))) {
+ ATH5K_ERR(ah->ah_sc, "zero rate\n");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (ah->ah_version == AR5K_AR5212) {
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+
+#define _XTX_TRIES(_n) \
+ if (tx_tries##_n) { \
+ tx_desc->tx_control_2 |= \
+ AR5K_REG_SM(tx_tries##_n, \
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \
+ tx_desc->tx_control_3 |= \
+ AR5K_REG_SM(tx_rate##_n, \
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \
+ }
+
+ _XTX_TRIES(1);
+ _XTX_TRIES(2);
+ _XTX_TRIES(3);
+
+#undef _XTX_TRIES
+
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Proccess the tx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc)
+{
+ struct ath5k_hw_tx_status *tx_status;
+ struct ath5k_hw_2w_tx_desc *tx_desc;
+
+ tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[0];
+
+ /* No frame has been send or error */
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ /*TODO: desc->ds_us.tx.ts_virtcol + test*/
+ desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ desc->ds_us.tx.ts_antenna = 1;
+ desc->ds_us.tx.ts_status = 0;
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_0,
+ AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
+
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess a tx descriptor on 5212
+ */
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc)
+{
+ struct ath5k_hw_tx_status *tx_status;
+ struct ath5k_hw_4w_tx_desc *tx_desc;
+
+ ATH5K_TRACE(ah->ah_sc);
+ tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
+ tx_status = (struct ath5k_hw_tx_status *)&desc->ds_hw[2];
+
+ /* No frame has been send or error */
+ if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Get descriptor status
+ */
+ desc->ds_us.tx.ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
+ desc->ds_us.tx.ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
+ desc->ds_us.tx.ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
+ AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
+ desc->ds_us.tx.ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_SEQ_NUM);
+ desc->ds_us.tx.ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
+ desc->ds_us.tx.ts_antenna = (tx_status->tx_status_1 &
+ AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
+ desc->ds_us.tx.ts_status = 0;
+
+ switch (AR5K_REG_MS(tx_status->tx_status_1,
+ AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) {
+ case 0:
+ desc->ds_us.tx.ts_rate = tx_desc->tx_control_3 &
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
+ break;
+ case 1:
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE1);
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1);
+ break;
+ case 2:
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE2);
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2);
+ break;
+ case 3:
+ desc->ds_us.tx.ts_rate = AR5K_REG_MS(tx_desc->tx_control_3,
+ AR5K_4W_TX_DESC_CTL3_XMIT_RATE3);
+ desc->ds_us.tx.ts_longretry +=AR5K_REG_MS(tx_desc->tx_control_2,
+ AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3);
+ break;
+ }
+
+ if ((tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK) == 0){
+ if (tx_status->tx_status_0 &
+ AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_XRETRY;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FIFO;
+
+ if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
+ desc->ds_us.tx.ts_status |= AR5K_TXERR_FILT;
+ }
+
+ return 0;
+}
+
+/*
+ * RX Descriptor
+ */
+
+/*
+ * Initialize an rx descriptor
+ */
+int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
+ u32 size, unsigned int flags)
+{
+ struct ath5k_rx_desc *rx_desc;
+
+ ATH5K_TRACE(ah->ah_sc);
+ rx_desc = (struct ath5k_rx_desc *)&desc->ds_ctl0;
+
+ /*
+ *Clear ds_hw
+ * If we don't clean the status descriptor,
+ * while scanning we get too many results,
+ * most of them virtual, after some secs
+ * of scanning system hangs. M.F.
+ */
+ memset(desc->ds_hw, 0, sizeof(desc->ds_hw));
+
+ /*Initialize rx descriptor*/
+ rx_desc->rx_control_0 = 0;
+ rx_desc->rx_control_1 = 0;
+
+ /* Setup descriptor */
+ rx_desc->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
+ if (unlikely(rx_desc->rx_control_1 != size))
+ return -EINVAL;
+
+ if (flags & AR5K_RXDESC_INTREQ)
+ rx_desc->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5210/5211
+ */
+static int ath5k_hw_proc_old_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc)
+{
+ struct ath5k_hw_old_rx_status *rx_status;
+
+ rx_status = (struct ath5k_hw_old_rx_status *)&desc->ds_hw[0];
+
+ /* No frame received / not ready */
+ if (unlikely((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_DONE)
+ == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+ AR5K_OLD_RX_DESC_STATUS0_DATA_LEN;
+ desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE);
+ desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+ AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+ AR5K_OLD_RX_DESC_STATUS0_MORE;
+ desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ desc->ds_us.rx.rs_status = 0;
+
+ /*
+ * Key table status
+ */
+ if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX);
+ else
+ desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if ((rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK)
+ == 0) {
+ if (rx_status->rx_status_1 & AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_FIFO;
+
+ if (rx_status->rx_status_1 &
+ AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR) {
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+ desc->ds_us.rx.rs_phyerr =
+ AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+ }
+
+ return 0;
+}
+
+/*
+ * Proccess the rx status descriptor on 5212
+ */
+static int ath5k_hw_proc_new_rx_status(struct ath5k_hw *ah,
+ struct ath5k_desc *desc)
+{
+ struct ath5k_hw_new_rx_status *rx_status;
+ struct ath5k_hw_rx_error *rx_err;
+
+ ATH5K_TRACE(ah->ah_sc);
+ rx_status = (struct ath5k_hw_new_rx_status *)&desc->ds_hw[0];
+
+ /* Overlay on error */
+ rx_err = (struct ath5k_hw_rx_error *)&desc->ds_hw[0];
+
+ /* No frame received / not ready */
+ if (unlikely((rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_DONE)
+ == 0))
+ return -EINPROGRESS;
+
+ /*
+ * Frame receive status
+ */
+ desc->ds_us.rx.rs_datalen = rx_status->rx_status_0 &
+ AR5K_NEW_RX_DESC_STATUS0_DATA_LEN;
+ desc->ds_us.rx.rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL);
+ desc->ds_us.rx.rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE);
+ desc->ds_us.rx.rs_antenna = rx_status->rx_status_0 &
+ AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA;
+ desc->ds_us.rx.rs_more = rx_status->rx_status_0 &
+ AR5K_NEW_RX_DESC_STATUS0_MORE;
+ desc->ds_us.rx.rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
+ desc->ds_us.rx.rs_status = 0;
+
+ /*
+ * Key table status
+ */
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID)
+ desc->ds_us.rx.rs_keyix = AR5K_REG_MS(rx_status->rx_status_1,
+ AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX);
+ else
+ desc->ds_us.rx.rs_keyix = AR5K_RXKEYIX_INVALID;
+
+ /*
+ * Receive/descriptor errors
+ */
+ if ((rx_status->rx_status_1 &
+ AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK) == 0) {
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_CRC;
+
+ if (rx_status->rx_status_1 &
+ AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR) {
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_PHY;
+ desc->ds_us.rx.rs_phyerr =
+ AR5K_REG_MS(rx_err->rx_error_1,
+ AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
+ }
+
+ if (rx_status->rx_status_1 &
+ AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_DECRYPT;
+
+ if (rx_status->rx_status_1 & AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR)
+ desc->ds_us.rx.rs_status |= AR5K_RXERR_MIC;
+ }
+
+ return 0;
+}
+
+
+/****************\
+ GPIO Functions
+\****************/
+
+/*
+ * Set led state
+ */
+void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state)
+{
+ u32 led;
+ /*5210 has different led mode handling*/
+ u32 led_5210;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*Reset led status*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG,
+ AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED);
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED);
+
+ /*
+ * Some blinking values, define at your wish
+ */
+ switch (state) {
+ case AR5K_LED_SCAN:
+ case AR5K_LED_AUTH:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND;
+ led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL;
+ break;
+
+ case AR5K_LED_INIT:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE;
+ led_5210 = AR5K_PCICFG_LED_PEND;
+ break;
+
+ case AR5K_LED_ASSOC:
+ case AR5K_LED_RUN:
+ led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC;
+ led_5210 = AR5K_PCICFG_LED_ASSOC;
+ break;
+
+ default:
+ led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE;
+ led_5210 = AR5K_PCICFG_LED_PEND;
+ break;
+ }
+
+ /*Write new status to the register*/
+ if (ah->ah_version != AR5K_AR5210)
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led);
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210);
+}
+
+/*
+ * Set GPIO outputs
+ */
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
+ AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Set GPIO inputs
+ */
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &~
+ AR5K_GPIOCR_OUT(gpio)) | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
+
+ return 0;
+}
+
+/*
+ * Get GPIO state
+ */
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return 0xffffffff;
+
+ /* GPIO input magic */
+ return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
+ 0x1;
+}
+
+/*
+ * Set GPIO state
+ */
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
+{
+ u32 data;
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (gpio > AR5K_NUM_GPIO)
+ return -EINVAL;
+
+ /* GPIO output magic */
+ data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
+
+ data &= ~(1 << gpio);
+ data |= (val & 1) << gpio;
+
+ ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
+
+ return 0;
+}
+
+/*
+ * Initialize the GPIO interrupt (RFKill switch)
+ */
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
+ u32 interrupt_level)
+{
+ u32 data;
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (gpio > AR5K_NUM_GPIO)
+ return;
+
+ /*
+ * Set the GPIO interrupt
+ */
+ data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
+ ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
+ AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
+ (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
+
+ ath5k_hw_reg_write(ah, interrupt_level ? data :
+ (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
+
+ ah->ah_imr |= AR5K_IMR_GPIO;
+
+ /* Enable GPIO interrupts */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
+}
+
+
+/*********************************\
+ Regulatory Domain/Channels Setup
+\*********************************/
+
+u16 ath5k_get_regdomain(struct ath5k_hw *ah)
+{
+ u16 regdomain;
+ enum ath5k_regdom ieee_regdomain;
+#ifdef COUNTRYCODE
+ u16 code;
+#endif
+
+ ath5k_eeprom_regulation_domain(ah, false, &ieee_regdomain);
+ ah->ah_capabilities.cap_regdomain.reg_hw = ieee_regdomain;
+
+#ifdef COUNTRYCODE
+ /*
+ * Get the regulation domain by country code. This will ignore
+ * the settings found in the EEPROM.
+ */
+ code = ieee80211_name2countrycode(COUNTRYCODE);
+ ieee_regdomain = ieee80211_countrycode2regdomain(code);
+#endif
+
+ regdomain = ath5k_regdom_from_ieee(ieee_regdomain);
+ ah->ah_capabilities.cap_regdomain.reg_current = regdomain;
+
+ return regdomain;
+}
+
+
+/****************\
+ Misc functions
+\****************/
+
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
+ enum ath5k_capability_type cap_type,
+ u32 capability, u32 *result)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ switch (cap_type) {
+ case AR5K_CAP_NUM_TXQUEUES:
+ if (result) {
+ if (ah->ah_version == AR5K_AR5210)
+ *result = AR5K_NUM_TX_QUEUES_NOQCU;
+ else
+ *result = AR5K_NUM_TX_QUEUES;
+ goto yes;
+ }
+ case AR5K_CAP_VEOL:
+ goto yes;
+ case AR5K_CAP_COMPRESSION:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_BURST:
+ goto yes;
+ case AR5K_CAP_TPC:
+ goto yes;
+ case AR5K_CAP_BSSIDMASK:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ case AR5K_CAP_XR:
+ if (ah->ah_version == AR5K_AR5212)
+ goto yes;
+ else
+ goto no;
+ default:
+ goto no;
+ }
+
+no:
+ return -EINVAL;
+yes:
+ return 0;
+}
+
+static int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid,
+ u16 assoc_id)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+ return 0;
+ }
+
+ return -EIO;
+}
+
+static int ath5k_hw_disable_pspoll(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_version == AR5K_AR5210) {
+ AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1,
+ AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA);
+ return 0;
+ }
+
+ return -EIO;
+}
diff --git a/drivers/net/wireless/ath5k/hw.h b/drivers/net/wireless/ath5k/hw.h
new file mode 100644
index 000000000000..d9a7c0973f53
--- /dev/null
+++ b/drivers/net/wireless/ath5k/hw.h
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2004-2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006-2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007 Matthew W. S. Bell <mentor@madwifi.org>
+ * Copyright (c) 2007 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/delay.h>
+
+/*
+ * Gain settings
+ */
+
+enum ath5k_rfgain {
+ AR5K_RFGAIN_INACTIVE = 0,
+ AR5K_RFGAIN_READ_REQUESTED,
+ AR5K_RFGAIN_NEED_CHANGE,
+};
+
+#define AR5K_GAIN_CRN_FIX_BITS_5111 4
+#define AR5K_GAIN_CRN_FIX_BITS_5112 7
+#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20
+#define AR5K_GAIN_CCK_PROBE_CORR 5
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15
+#define AR5K_GAIN_STEP_COUNT 10
+#define AR5K_GAIN_PARAM_TX_CLIP 0
+#define AR5K_GAIN_PARAM_PD_90 1
+#define AR5K_GAIN_PARAM_PD_84 2
+#define AR5K_GAIN_PARAM_GAIN_SEL 3
+#define AR5K_GAIN_PARAM_MIX_ORN 0
+#define AR5K_GAIN_PARAM_PD_138 1
+#define AR5K_GAIN_PARAM_PD_137 2
+#define AR5K_GAIN_PARAM_PD_136 3
+#define AR5K_GAIN_PARAM_PD_132 4
+#define AR5K_GAIN_PARAM_PD_131 5
+#define AR5K_GAIN_PARAM_PD_130 6
+#define AR5K_GAIN_CHECK_ADJUST(_g) \
+ ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
+
+struct ath5k_gain_opt_step {
+ s16 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
+ s32 gos_gain;
+};
+
+struct ath5k_gain {
+ u32 g_step_idx;
+ u32 g_current;
+ u32 g_target;
+ u32 g_low;
+ u32 g_high;
+ u32 g_f_corr;
+ u32 g_active;
+ const struct ath5k_gain_opt_step *g_step;
+};
+
+
+/*
+ * HW SPECIFIC STRUCTS
+ */
+
+/* Some EEPROM defines */
+#define AR5K_EEPROM_EEP_SCALE 100
+#define AR5K_EEPROM_EEP_DELTA 10
+#define AR5K_EEPROM_N_MODES 3
+#define AR5K_EEPROM_N_5GHZ_CHAN 10
+#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_TEST_FREQ 8
+#define AR5K_EEPROM_N_EDGES 8
+#define AR5K_EEPROM_N_INTERCEPTS 11
+#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
+#define AR5K_EEPROM_PCDAC_M 0x3f
+#define AR5K_EEPROM_PCDAC_START 1
+#define AR5K_EEPROM_PCDAC_STOP 63
+#define AR5K_EEPROM_PCDAC_STEP 1
+#define AR5K_EEPROM_NON_EDGE_M 0x40
+#define AR5K_EEPROM_CHANNEL_POWER 8
+#define AR5K_EEPROM_N_OBDB 4
+#define AR5K_EEPROM_OBDB_DIS 0xffff
+#define AR5K_EEPROM_CHANNEL_DIS 0xff
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10)
+#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32)
+#define AR5K_EEPROM_MAX_CTLS 32
+#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
+#define AR5K_EEPROM_N_XPD0_POINTS 4
+#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
+#define AR5K_EEPROM_POWER_M 0x3f
+#define AR5K_EEPROM_POWER_MIN 0
+#define AR5K_EEPROM_POWER_MAX 3150
+#define AR5K_EEPROM_POWER_STEP 50
+#define AR5K_EEPROM_POWER_TABLE_SIZE 64
+#define AR5K_EEPROM_N_POWER_LOC_11B 4
+#define AR5K_EEPROM_N_POWER_LOC_11G 6
+#define AR5K_EEPROM_I_GAIN 10
+#define AR5K_EEPROM_CCK_OFDM_DELTA 15
+#define AR5K_EEPROM_N_IQ_CAL 2
+
+/* Struct to hold EEPROM calibration data */
+struct ath5k_eeprom_info {
+ u16 ee_magic;
+ u16 ee_protect;
+ u16 ee_regdomain;
+ u16 ee_version;
+ u16 ee_header;
+ u16 ee_ant_gain;
+ u16 ee_misc0;
+ u16 ee_misc1;
+ u16 ee_cck_ofdm_gain_delta;
+ u16 ee_cck_ofdm_power_delta;
+ u16 ee_scaled_cck_delta;
+
+ /* Used for tx thermal adjustment (eeprom_init, rfregs) */
+ u16 ee_tx_clip;
+ u16 ee_pwd_84;
+ u16 ee_pwd_90;
+ u16 ee_gain_select;
+
+ /* RF Calibration settings (reset, rfregs) */
+ u16 ee_i_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_q_cal[AR5K_EEPROM_N_MODES];
+ u16 ee_fixed_bias[AR5K_EEPROM_N_MODES];
+ u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
+ u16 ee_xr_power[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
+ u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
+ u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
+ u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
+ u16 ee_thr_62[AR5K_EEPROM_N_MODES];
+ u16 ee_xlna_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_xpd[AR5K_EEPROM_N_MODES];
+ u16 ee_x_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_i_gain[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+
+ /* Unused */
+ u16 ee_false_detect[AR5K_EEPROM_N_MODES];
+ u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
+ u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
+
+ /* Conformance test limits (Unused) */
+ u16 ee_ctls;
+ u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
+
+ /* Noise Floor Calibration settings */
+ s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+};
+
+/*
+ * Internal RX/TX descriptor structures
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
+ */
+
+struct ath5k_rx_desc {
+ u32 rx_control_0; /* RX control word 0 */
+
+#define AR5K_DESC_RX_CTL0 0x00000000
+
+ u32 rx_control_1; /* RX control word 1 */
+
+#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff
+#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000
+} __packed;
+
+/*
+ * 5210/5211 rx status descriptor
+ */
+struct ath5k_hw_old_rx_status {
+ u32 rx_status_0; /* RX status word 0 */
+
+#define AR5K_OLD_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_OLD_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000
+#define AR5K_OLD_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27
+
+ u32 rx_status_1; /* RX status word 1 */
+
+#define AR5K_OLD_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_OLD_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_OLD_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_OLD_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008
+#define AR5K_OLD_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010
+#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR 0x000000e0
+#define AR5K_OLD_RX_DESC_STATUS1_PHY_ERROR_S 5
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX 0x00007e00
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000
+#define AR5K_OLD_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15
+#define AR5K_OLD_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000
+} __packed;
+
+/*
+ * 5212 rx status descriptor
+ */
+struct ath5k_hw_new_rx_status {
+ u32 rx_status_0; /* RX status word 0 */
+
+#define AR5K_NEW_RX_DESC_STATUS0_DATA_LEN 0x00000fff
+#define AR5K_NEW_RX_DESC_STATUS0_MORE 0x00001000
+#define AR5K_NEW_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_RATE_S 15
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000
+#define AR5K_NEW_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28
+
+ u32 rx_status_1; /* RX status word 1 */
+
+#define AR5K_NEW_RX_DESC_STATUS1_DONE 0x00000001
+#define AR5K_NEW_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002
+#define AR5K_NEW_RX_DESC_STATUS1_CRC_ERROR 0x00000004
+#define AR5K_NEW_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008
+#define AR5K_NEW_RX_DESC_STATUS1_PHY_ERROR 0x00000010
+#define AR5K_NEW_RX_DESC_STATUS1_MIC_ERROR 0x00000020
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_INDEX_S 9
+#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000
+#define AR5K_NEW_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16
+#define AR5K_NEW_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000
+} __packed;
+
+struct ath5k_hw_rx_error {
+ u32 rx_error_0; /* RX error word 0 */
+
+#define AR5K_RX_DESC_ERROR0 0x00000000
+
+ u32 rx_error_1; /* RX error word 1 */
+
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8
+} __packed;
+
+#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00
+#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20
+#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40
+#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80
+#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0
+
+struct ath5k_hw_2w_tx_desc {
+ u32 tx_control_0; /* TX control word 0 */
+
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18
+#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \
+ AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+
+ u32 tx_control_1; /* TX control word 1 */
+
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \
+ AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/
+} __packed;
+
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10
+
+/*
+ * 5212 4-word tx control descriptor
+ */
+struct ath5k_hw_4w_tx_desc {
+ u32 tx_control_0; /* TX control word 0 */
+
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16
+#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000
+#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25
+#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000
+#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000
+
+ u32 tx_control_1; /* TX control word 1 */
+
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff
+#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20
+#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29
+
+ u32 tx_control_2; /* TX control word 2 */
+
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28
+
+ u32 tx_control_3; /* TX control word 3 */
+
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20
+} __packed;
+
+/*
+ * Common tx status descriptor
+ */
+struct ath5k_hw_tx_status {
+ u32 tx_status_0; /* TX status word 0 */
+
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004
+#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008
+/*???
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4
+*/
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4
+/*???
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8
+*/
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16
+
+ u32 tx_status_1; /* TX status word 1 */
+
+#define AR5K_DESC_TX_STATUS1_DONE 0x00000001
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000
+} __packed;
+
+
+/*
+ * AR5K REGISTER ACCESS
+ */
+
+/*Swap RX/TX Descriptor for big endian archs*/
+#if defined(__BIG_ENDIAN)
+#define AR5K_INIT_CFG ( \
+ AR5K_CFG_SWTD | AR5K_CFG_SWRD \
+)
+#else
+#define AR5K_INIT_CFG 0x00000000
+#endif
+
+/*#define AR5K_REG_READ(_reg) ath5k_hw_reg_read(ah, _reg)
+
+#define AR5K_REG_WRITE(_reg, _val) ath5k_hw_reg_write(ah, _val, _reg)*/
+
+#define AR5K_REG_SM(_val, _flags) \
+ (((_val) << _flags##_S) & (_flags))
+
+#define AR5K_REG_MS(_val, _flags) \
+ (((_val) & (_flags)) >> _flags##_S)
+
+/* Some registers can hold multiple values of interest. For this
+ * reason when we want to write to these registers we must first
+ * retrieve the values which we do not want to clear (lets call this
+ * old_data) and then set the register with this and our new_value:
+ * ( old_data | new_value) */
+#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \
+ (((_val) << _flags##_S) & (_flags)), _reg)
+
+#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \
+ ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \
+ (_mask)) | (_flags), _reg)
+
+#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg)
+
+#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
+ ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
+
+#define AR5K_PHY_WRITE(ah, _reg, _val) \
+ ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_PHY_READ(ah, _reg) \
+ ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
+
+#define AR5K_REG_WAIT(_i) do { \
+ if (_i % 64) \
+ udelay(1); \
+} while (0)
+
+#define AR5K_EEPROM_READ(_o, _v) do { \
+ if ((ret = ath5k_hw_eeprom_read(ah, (_o), &(_v))) != 0) \
+ return (ret); \
+} while (0)
+
+#define AR5K_EEPROM_READ_HDR(_o, _v) \
+ AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
+
+/* Read status of selected queue */
+#define AR5K_REG_READ_Q(ah, _reg, _queue) \
+ (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
+
+#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \
+ ath5k_hw_reg_write(ah, (1 << _queue), _reg)
+
+#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \
+ _reg |= 1 << _queue; \
+} while (0)
+
+#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \
+ _reg &= ~(1 << _queue); \
+} while (0)
+
+#define AR5K_LOW_ID(_a)( \
+(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \
+)
+
+#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8)
+
+/*
+ * Initial register values
+ */
+
+/*
+ * Common initial register values
+ */
+#define AR5K_INIT_MODE CHANNEL_B
+
+#define AR5K_INIT_TX_LATENCY 502
+#define AR5K_INIT_USEC 39
+#define AR5K_INIT_USEC_TURBO 79
+#define AR5K_INIT_USEC_32 31
+#define AR5K_INIT_CARR_SENSE_EN 1
+#define AR5K_INIT_PROG_IFS 920
+#define AR5K_INIT_PROG_IFS_TURBO 960
+#define AR5K_INIT_EIFS 3440
+#define AR5K_INIT_EIFS_TURBO 6880
+#define AR5K_INIT_SLOT_TIME 396
+#define AR5K_INIT_SLOT_TIME_TURBO 480
+#define AR5K_INIT_ACK_CTS_TIMEOUT 1024
+#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800
+#define AR5K_INIT_SIFS 560
+#define AR5K_INIT_SIFS_TURBO 480
+#define AR5K_INIT_SH_RETRY 10
+#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY
+#define AR5K_INIT_SSH_RETRY 32
+#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY
+#define AR5K_INIT_TX_RETRY 10
+#define AR5K_INIT_TOPS 8
+#define AR5K_INIT_RXNOFRM 8
+#define AR5K_INIT_RPGTO 0
+#define AR5K_INIT_TXNOFRM 0
+#define AR5K_INIT_BEACON_PERIOD 65535
+#define AR5K_INIT_TIM_OFFSET 0
+#define AR5K_INIT_BEACON_EN 0
+#define AR5K_INIT_RESET_TSF 0
+
+#define AR5K_INIT_TRANSMIT_LATENCY ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC) \
+)
+#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \
+ (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \
+ (AR5K_INIT_USEC_TURBO) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \
+ (AR5K_INIT_PROG_IFS) \
+)
+#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \
+ (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \
+ (AR5K_INIT_PROG_IFS_TURBO) \
+)
+#define AR5K_INIT_BEACON_CONTROL ( \
+ (AR5K_INIT_RESET_TSF << 24) | (AR5K_INIT_BEACON_EN << 23) | \
+ (AR5K_INIT_TIM_OFFSET << 16) | (AR5K_INIT_BEACON_PERIOD) \
+)
+
+/*
+ * Non-common initial register values which have to be loaded into the
+ * card at boot time and after each reset.
+ */
+
+/* Register dumps are done per operation mode */
+#define AR5K_INI_RFGAIN_5GHZ 0
+#define AR5K_INI_RFGAIN_2GHZ 1
+
+#define AR5K_INI_VAL_11A 0
+#define AR5K_INI_VAL_11A_TURBO 1
+#define AR5K_INI_VAL_11B 2
+#define AR5K_INI_VAL_11G 3
+#define AR5K_INI_VAL_11G_TURBO 4
+#define AR5K_INI_VAL_XR 0
+#define AR5K_INI_VAL_MAX 5
+
+#define AR5K_RF5111_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+#define AR5K_RF5112_INI_RF_MAX_BANKS AR5K_MAX_RF_BANKS
+
+static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
+{
+ u32 retval = 0, bit, i;
+
+ for (i = 0; i < bits; i++) {
+ bit = (val >> i) & 1;
+ retval = (retval << 1) | bit;
+ }
+
+ return retval;
+}
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
new file mode 100644
index 000000000000..2c22f1d4ee64
--- /dev/null
+++ b/drivers/net/wireless/ath5k/initvals.c
@@ -0,0 +1,1347 @@
+/*
+ * Initial register settings functions
+ *
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include "ath5k.h"
+#include "base.h"
+#include "reg.h"
+
+/*
+ * MAC/PHY REGISTERS
+ */
+
+
+/*
+ * Mode-independent initial register writes
+ */
+
+struct ath5k_ini {
+ u16 ini_register;
+ u32 ini_value;
+
+ enum {
+ AR5K_INI_WRITE = 0, /* Default */
+ AR5K_INI_READ = 1, /* Cleared on read */
+ } ini_mode;
+};
+
+/*
+ * Mode specific initial register values
+ */
+
+struct ath5k_ini_mode {
+ u16 mode_register;
+ u32 mode_value[5];
+};
+
+/* Initial register settings for AR5210 */
+static const struct ath5k_ini ar5210_ini[] = {
+ /* PCU and MAC registers */
+ { AR5K_NOQCU_TXDP0, 0 },
+ { AR5K_NOQCU_TXDP1, 0 },
+ { AR5K_RXDP, 0 },
+ { AR5K_CR, 0 },
+ { AR5K_ISR, 0, AR5K_INI_READ },
+ { AR5K_IMR, 0 },
+ { AR5K_IER, AR5K_IER_DISABLE },
+ { AR5K_BSR, 0, AR5K_INI_READ },
+ { AR5K_TXCFG, AR5K_DMASIZE_128B },
+ { AR5K_RXCFG, AR5K_DMASIZE_128B },
+ { AR5K_CFG, AR5K_INIT_CFG },
+ { AR5K_TOPS, AR5K_INIT_TOPS },
+ { AR5K_RXNOFRM, AR5K_INIT_RXNOFRM },
+ { AR5K_RPGTO, AR5K_INIT_RPGTO },
+ { AR5K_TXNOFRM, AR5K_INIT_TXNOFRM },
+ { AR5K_SFR, 0 },
+ { AR5K_MIBC, 0 },
+ { AR5K_MISC, 0 },
+ { AR5K_RX_FILTER_5210, 0 },
+ { AR5K_MCAST_FILTER0_5210, 0 },
+ { AR5K_MCAST_FILTER1_5210, 0 },
+ { AR5K_TX_MASK0, 0 },
+ { AR5K_TX_MASK1, 0 },
+ { AR5K_CLR_TMASK, 0 },
+ { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES },
+ { AR5K_DIAG_SW_5210, 0 },
+ { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES },
+ { AR5K_TSF_L32_5210, 0 },
+ { AR5K_TIMER0_5210, 0 },
+ { AR5K_TIMER1_5210, 0xffffffff },
+ { AR5K_TIMER2_5210, 0xffffffff },
+ { AR5K_TIMER3_5210, 1 },
+ { AR5K_CFP_DUR_5210, 0 },
+ { AR5K_CFP_PERIOD_5210, 0 },
+ /* PHY registers */
+ { AR5K_PHY(0), 0x00000047 },
+ { AR5K_PHY_AGC, 0x00000000 },
+ { AR5K_PHY(3), 0x09848ea6 },
+ { AR5K_PHY(4), 0x3d32e000 },
+ { AR5K_PHY(5), 0x0000076b },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE },
+ { AR5K_PHY(8), 0x02020200 },
+ { AR5K_PHY(9), 0x00000e0e },
+ { AR5K_PHY(10), 0x0a020201 },
+ { AR5K_PHY(11), 0x00036ffc },
+ { AR5K_PHY(12), 0x00000000 },
+ { AR5K_PHY(13), 0x00000e0e },
+ { AR5K_PHY(14), 0x00000007 },
+ { AR5K_PHY(15), 0x00020100 },
+ { AR5K_PHY(16), 0x89630000 },
+ { AR5K_PHY(17), 0x1372169c },
+ { AR5K_PHY(18), 0x0018b633 },
+ { AR5K_PHY(19), 0x1284613c },
+ { AR5K_PHY(20), 0x0de8b8e0 },
+ { AR5K_PHY(21), 0x00074859 },
+ { AR5K_PHY(22), 0x7e80beba },
+ { AR5K_PHY(23), 0x313a665e },
+ { AR5K_PHY_AGCCTL, 0x00001d08 },
+ { AR5K_PHY(25), 0x0001ce00 },
+ { AR5K_PHY(26), 0x409a4190 },
+ { AR5K_PHY(28), 0x0000000f },
+ { AR5K_PHY(29), 0x00000080 },
+ { AR5K_PHY(30), 0x00000004 },
+ { AR5K_PHY(31), 0x00000018 }, /* 0x987c */
+ { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */
+ { AR5K_PHY(65), 0x00000000 },
+ { AR5K_PHY(66), 0x00000000 },
+ { AR5K_PHY(67), 0x00800000 },
+ { AR5K_PHY(68), 0x00000003 },
+ /* BB gain table (64bytes) */
+ { AR5K_BB_GAIN(0), 0x00000000 },
+ { AR5K_BB_GAIN(1), 0x00000020 },
+ { AR5K_BB_GAIN(2), 0x00000010 },
+ { AR5K_BB_GAIN(3), 0x00000030 },
+ { AR5K_BB_GAIN(4), 0x00000008 },
+ { AR5K_BB_GAIN(5), 0x00000028 },
+ { AR5K_BB_GAIN(6), 0x00000028 },
+ { AR5K_BB_GAIN(7), 0x00000004 },
+ { AR5K_BB_GAIN(8), 0x00000024 },
+ { AR5K_BB_GAIN(9), 0x00000014 },
+ { AR5K_BB_GAIN(10), 0x00000034 },
+ { AR5K_BB_GAIN(11), 0x0000000c },
+ { AR5K_BB_GAIN(12), 0x0000002c },
+ { AR5K_BB_GAIN(13), 0x00000002 },
+ { AR5K_BB_GAIN(14), 0x00000022 },
+ { AR5K_BB_GAIN(15), 0x00000012 },
+ { AR5K_BB_GAIN(16), 0x00000032 },
+ { AR5K_BB_GAIN(17), 0x0000000a },
+ { AR5K_BB_GAIN(18), 0x0000002a },
+ { AR5K_BB_GAIN(19), 0x00000001 },
+ { AR5K_BB_GAIN(20), 0x00000021 },
+ { AR5K_BB_GAIN(21), 0x00000011 },
+ { AR5K_BB_GAIN(22), 0x00000031 },
+ { AR5K_BB_GAIN(23), 0x00000009 },
+ { AR5K_BB_GAIN(24), 0x00000029 },
+ { AR5K_BB_GAIN(25), 0x00000005 },
+ { AR5K_BB_GAIN(26), 0x00000025 },
+ { AR5K_BB_GAIN(27), 0x00000015 },
+ { AR5K_BB_GAIN(28), 0x00000035 },
+ { AR5K_BB_GAIN(29), 0x0000000d },
+ { AR5K_BB_GAIN(30), 0x0000002d },
+ { AR5K_BB_GAIN(31), 0x00000003 },
+ { AR5K_BB_GAIN(32), 0x00000023 },
+ { AR5K_BB_GAIN(33), 0x00000013 },
+ { AR5K_BB_GAIN(34), 0x00000033 },
+ { AR5K_BB_GAIN(35), 0x0000000b },
+ { AR5K_BB_GAIN(36), 0x0000002b },
+ { AR5K_BB_GAIN(37), 0x00000007 },
+ { AR5K_BB_GAIN(38), 0x00000027 },
+ { AR5K_BB_GAIN(39), 0x00000017 },
+ { AR5K_BB_GAIN(40), 0x00000037 },
+ { AR5K_BB_GAIN(41), 0x0000000f },
+ { AR5K_BB_GAIN(42), 0x0000002f },
+ { AR5K_BB_GAIN(43), 0x0000002f },
+ { AR5K_BB_GAIN(44), 0x0000002f },
+ { AR5K_BB_GAIN(45), 0x0000002f },
+ { AR5K_BB_GAIN(46), 0x0000002f },
+ { AR5K_BB_GAIN(47), 0x0000002f },
+ { AR5K_BB_GAIN(48), 0x0000002f },
+ { AR5K_BB_GAIN(49), 0x0000002f },
+ { AR5K_BB_GAIN(50), 0x0000002f },
+ { AR5K_BB_GAIN(51), 0x0000002f },
+ { AR5K_BB_GAIN(52), 0x0000002f },
+ { AR5K_BB_GAIN(53), 0x0000002f },
+ { AR5K_BB_GAIN(54), 0x0000002f },
+ { AR5K_BB_GAIN(55), 0x0000002f },
+ { AR5K_BB_GAIN(56), 0x0000002f },
+ { AR5K_BB_GAIN(57), 0x0000002f },
+ { AR5K_BB_GAIN(58), 0x0000002f },
+ { AR5K_BB_GAIN(59), 0x0000002f },
+ { AR5K_BB_GAIN(60), 0x0000002f },
+ { AR5K_BB_GAIN(61), 0x0000002f },
+ { AR5K_BB_GAIN(62), 0x0000002f },
+ { AR5K_BB_GAIN(63), 0x0000002f },
+ /* 5110 RF gain table (64btes) */
+ { AR5K_RF_GAIN(0), 0x0000001d },
+ { AR5K_RF_GAIN(1), 0x0000005d },
+ { AR5K_RF_GAIN(2), 0x0000009d },
+ { AR5K_RF_GAIN(3), 0x000000dd },
+ { AR5K_RF_GAIN(4), 0x0000011d },
+ { AR5K_RF_GAIN(5), 0x00000021 },
+ { AR5K_RF_GAIN(6), 0x00000061 },
+ { AR5K_RF_GAIN(7), 0x000000a1 },
+ { AR5K_RF_GAIN(8), 0x000000e1 },
+ { AR5K_RF_GAIN(9), 0x00000031 },
+ { AR5K_RF_GAIN(10), 0x00000071 },
+ { AR5K_RF_GAIN(11), 0x000000b1 },
+ { AR5K_RF_GAIN(12), 0x0000001c },
+ { AR5K_RF_GAIN(13), 0x0000005c },
+ { AR5K_RF_GAIN(14), 0x00000029 },
+ { AR5K_RF_GAIN(15), 0x00000069 },
+ { AR5K_RF_GAIN(16), 0x000000a9 },
+ { AR5K_RF_GAIN(17), 0x00000020 },
+ { AR5K_RF_GAIN(18), 0x00000019 },
+ { AR5K_RF_GAIN(19), 0x00000059 },
+ { AR5K_RF_GAIN(20), 0x00000099 },
+ { AR5K_RF_GAIN(21), 0x00000030 },
+ { AR5K_RF_GAIN(22), 0x00000005 },
+ { AR5K_RF_GAIN(23), 0x00000025 },
+ { AR5K_RF_GAIN(24), 0x00000065 },
+ { AR5K_RF_GAIN(25), 0x000000a5 },
+ { AR5K_RF_GAIN(26), 0x00000028 },
+ { AR5K_RF_GAIN(27), 0x00000068 },
+ { AR5K_RF_GAIN(28), 0x0000001f },
+ { AR5K_RF_GAIN(29), 0x0000001e },
+ { AR5K_RF_GAIN(30), 0x00000018 },
+ { AR5K_RF_GAIN(31), 0x00000058 },
+ { AR5K_RF_GAIN(32), 0x00000098 },
+ { AR5K_RF_GAIN(33), 0x00000003 },
+ { AR5K_RF_GAIN(34), 0x00000004 },
+ { AR5K_RF_GAIN(35), 0x00000044 },
+ { AR5K_RF_GAIN(36), 0x00000084 },
+ { AR5K_RF_GAIN(37), 0x00000013 },
+ { AR5K_RF_GAIN(38), 0x00000012 },
+ { AR5K_RF_GAIN(39), 0x00000052 },
+ { AR5K_RF_GAIN(40), 0x00000092 },
+ { AR5K_RF_GAIN(41), 0x000000d2 },
+ { AR5K_RF_GAIN(42), 0x0000002b },
+ { AR5K_RF_GAIN(43), 0x0000002a },
+ { AR5K_RF_GAIN(44), 0x0000006a },
+ { AR5K_RF_GAIN(45), 0x000000aa },
+ { AR5K_RF_GAIN(46), 0x0000001b },
+ { AR5K_RF_GAIN(47), 0x0000001a },
+ { AR5K_RF_GAIN(48), 0x0000005a },
+ { AR5K_RF_GAIN(49), 0x0000009a },
+ { AR5K_RF_GAIN(50), 0x000000da },
+ { AR5K_RF_GAIN(51), 0x00000006 },
+ { AR5K_RF_GAIN(52), 0x00000006 },
+ { AR5K_RF_GAIN(53), 0x00000006 },
+ { AR5K_RF_GAIN(54), 0x00000006 },
+ { AR5K_RF_GAIN(55), 0x00000006 },
+ { AR5K_RF_GAIN(56), 0x00000006 },
+ { AR5K_RF_GAIN(57), 0x00000006 },
+ { AR5K_RF_GAIN(58), 0x00000006 },
+ { AR5K_RF_GAIN(59), 0x00000006 },
+ { AR5K_RF_GAIN(60), 0x00000006 },
+ { AR5K_RF_GAIN(61), 0x00000006 },
+ { AR5K_RF_GAIN(62), 0x00000006 },
+ { AR5K_RF_GAIN(63), 0x00000006 },
+ /* PHY activation */
+ { AR5K_PHY(53), 0x00000020 },
+ { AR5K_PHY(51), 0x00000004 },
+ { AR5K_PHY(50), 0x00060106 },
+ { AR5K_PHY(39), 0x0000006d },
+ { AR5K_PHY(48), 0x00000000 },
+ { AR5K_PHY(52), 0x00000014 },
+ { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE },
+};
+
+/* Initial register settings for AR5211 */
+static const struct ath5k_ini ar5211_ini[] = {
+ { AR5K_RXDP, 0x00000000 },
+ { AR5K_RTSD0, 0x84849c9c },
+ { AR5K_RTSD1, 0x7c7c7c7c },
+ { AR5K_RXCFG, 0x00000005 },
+ { AR5K_MIBC, 0x00000000 },
+ { AR5K_TOPS, 0x00000008 },
+ { AR5K_RXNOFRM, 0x00000008 },
+ { AR5K_TXNOFRM, 0x00000010 },
+ { AR5K_RPGTO, 0x00000000 },
+ { AR5K_RFCNT, 0x0000001f },
+ { AR5K_QUEUE_TXDP(0), 0x00000000 },
+ { AR5K_QUEUE_TXDP(1), 0x00000000 },
+ { AR5K_QUEUE_TXDP(2), 0x00000000 },
+ { AR5K_QUEUE_TXDP(3), 0x00000000 },
+ { AR5K_QUEUE_TXDP(4), 0x00000000 },
+ { AR5K_QUEUE_TXDP(5), 0x00000000 },
+ { AR5K_QUEUE_TXDP(6), 0x00000000 },
+ { AR5K_QUEUE_TXDP(7), 0x00000000 },
+ { AR5K_QUEUE_TXDP(8), 0x00000000 },
+ { AR5K_QUEUE_TXDP(9), 0x00000000 },
+ { AR5K_DCU_FP, 0x00000000 },
+ { AR5K_STA_ID1, 0x00000000 },
+ { AR5K_BSS_ID0, 0x00000000 },
+ { AR5K_BSS_ID1, 0x00000000 },
+ { AR5K_RSSI_THR, 0x00000000 },
+ { AR5K_CFP_PERIOD_5211, 0x00000000 },
+ { AR5K_TIMER0_5211, 0x00000030 },
+ { AR5K_TIMER1_5211, 0x0007ffff },
+ { AR5K_TIMER2_5211, 0x01ffffff },
+ { AR5K_TIMER3_5211, 0x00000031 },
+ { AR5K_CFP_DUR_5211, 0x00000000 },
+ { AR5K_RX_FILTER_5211, 0x00000000 },
+ { AR5K_MCAST_FILTER0_5211, 0x00000000 },
+ { AR5K_MCAST_FILTER1_5211, 0x00000002 },
+ { AR5K_DIAG_SW_5211, 0x00000000 },
+ { AR5K_ADDAC_TEST, 0x00000000 },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000 },
+ /* PHY registers */
+ { AR5K_PHY_AGC, 0x00000000 },
+ { AR5K_PHY(3), 0x2d849093 },
+ { AR5K_PHY(4), 0x7d32e000 },
+ { AR5K_PHY(5), 0x00000f6b },
+ { AR5K_PHY_ACT, 0x00000000 },
+ { AR5K_PHY(11), 0x00026ffe },
+ { AR5K_PHY(12), 0x00000000 },
+ { AR5K_PHY(15), 0x00020100 },
+ { AR5K_PHY(16), 0x206a017a },
+ { AR5K_PHY(19), 0x1284613c },
+ { AR5K_PHY(21), 0x00000859 },
+ { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */
+ { AR5K_PHY(27), 0x050cb081 },
+ { AR5K_PHY(28), 0x0000000f },
+ { AR5K_PHY(29), 0x00000080 },
+ { AR5K_PHY(30), 0x0000000c },
+ { AR5K_PHY(64), 0x00000000 },
+ { AR5K_PHY(65), 0x00000000 },
+ { AR5K_PHY(66), 0x00000000 },
+ { AR5K_PHY(67), 0x00800000 },
+ { AR5K_PHY(68), 0x00000001 },
+ { AR5K_PHY(71), 0x0000092a },
+ { AR5K_PHY_IQ, 0x00000000 },
+ { AR5K_PHY(73), 0x00058a05 },
+ { AR5K_PHY(74), 0x00000001 },
+ { AR5K_PHY(75), 0x00000000 },
+ { AR5K_PHY_PAPD_PROBE, 0x00000000 },
+ { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */
+ { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */
+ { AR5K_PHY(79), 0x0000003f }, /* 0x993c */
+ { AR5K_PHY(80), 0x00000004 },
+ { AR5K_PHY(82), 0x00000000 },
+ { AR5K_PHY(83), 0x00000000 },
+ { AR5K_PHY(84), 0x00000000 },
+ { AR5K_PHY_RADAR, 0x5d50f14c },
+ { AR5K_PHY(86), 0x00000018 },
+ { AR5K_PHY(87), 0x004b6a8e },
+ /* Initial Power table (32bytes)
+ * common on all cards/modes.
+ * Note: Table is rewritten during
+ * txpower setup later using calibration
+ * data etc. so next write is non-common
+ { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff },
+ { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff },
+ { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff },
+ { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff },
+ { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff },
+ { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff },
+ { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff },
+ { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff },
+ { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff },
+ { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff },
+ { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff },
+ { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff },
+ { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff },
+ { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff },
+ { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff },
+ { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff },
+ { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff },
+ { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff },
+ { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff },
+ { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff },
+ { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff },
+ { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff },*/
+ { AR5K_PHY_CCKTXCTL, 0x00000000 },
+ { AR5K_PHY(642), 0x503e4646 },
+ { AR5K_PHY_GAIN_2GHZ, 0x6480416c },
+ { AR5K_PHY(644), 0x0199a003 },
+ { AR5K_PHY(645), 0x044cd610 },
+ { AR5K_PHY(646), 0x13800040 },
+ { AR5K_PHY(647), 0x1be00060 },
+ { AR5K_PHY(648), 0x0c53800a },
+ { AR5K_PHY(649), 0x0014df3b },
+ { AR5K_PHY(650), 0x000001b5 },
+ { AR5K_PHY(651), 0x00000020 },
+};
+
+/* Initial mode-specific settings for AR5211
+ * XXX: how about g / gTurbo ? RF5111 supports it, how about AR5211 ?
+ * Maybe 5211 supports OFDM-only g but we need to test it !
+ */
+static const struct ath5k_ini_mode ar5211_ini_mode[] = {
+ { AR5K_TXCFG,
+ /* a aTurbo b */
+ { 0x00000015, 0x00000015, 0x0000001d } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8 } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000d98, 0x00001180, 0x00001f48 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880 } },
+ { AR5K_TIME_OUT,
+ { 0x04000400, 0x08000800, 0x20003000 } },
+ { AR5K_USEC_5211,
+ { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200 } },
+ { AR5K_PHY(9),
+ { 0x00000e0e, 0x00000e0e, 0x00000707 } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05010000 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b } },
+ { AR5K_PHY(17),
+ { 0x1372169c, 0x137216a5, 0x137216a8 } },
+ { AR5K_PHY(18),
+ { 0x0018ba67, 0x0018ba67, 0x0018ba69 } },
+ { AR5K_PHY(20),
+ { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x31375d5e, 0x31375d5e, 0x313a5d5e } },
+ { AR5K_PHY_AGCCTL,
+ { 0x0000bd10, 0x0000bd10, 0x0000bd38 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c } },
+ { AR5K_PHY(70),
+ { 0x00000190, 0x00000190, 0x00000084 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0x6fe01020, 0x6fe01020, 0x6fe00920 } },
+ { AR5K_PHY_PCDAC_TXPOWER_BASE_5211,
+ { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff } },
+ { AR5K_RF_BUFFER_CONTROL_4,
+ { 0x00000010, 0x00000014, 0x00000010 } },
+};
+
+/* Initial register settings for AR5212 */
+static const struct ath5k_ini ar5212_ini[] = {
+ { AR5K_RXDP, 0x00000000 },
+ { AR5K_RXCFG, 0x00000005 },
+ { AR5K_MIBC, 0x00000000 },
+ { AR5K_TOPS, 0x00000008 },
+ { AR5K_RXNOFRM, 0x00000008 },
+ { AR5K_TXNOFRM, 0x00000010 },
+ { AR5K_RPGTO, 0x00000000 },
+ { AR5K_RFCNT, 0x0000001f },
+ { AR5K_QUEUE_TXDP(0), 0x00000000 },
+ { AR5K_QUEUE_TXDP(1), 0x00000000 },
+ { AR5K_QUEUE_TXDP(2), 0x00000000 },
+ { AR5K_QUEUE_TXDP(3), 0x00000000 },
+ { AR5K_QUEUE_TXDP(4), 0x00000000 },
+ { AR5K_QUEUE_TXDP(5), 0x00000000 },
+ { AR5K_QUEUE_TXDP(6), 0x00000000 },
+ { AR5K_QUEUE_TXDP(7), 0x00000000 },
+ { AR5K_QUEUE_TXDP(8), 0x00000000 },
+ { AR5K_QUEUE_TXDP(9), 0x00000000 },
+ { AR5K_DCU_FP, 0x00000000 },
+ { AR5K_DCU_TXP, 0x00000000 },
+ { AR5K_DCU_TX_FILTER, 0x00000000 },
+ /* Unknown table */
+ { 0x1078, 0x00000000 },
+ { 0x10b8, 0x00000000 },
+ { 0x10f8, 0x00000000 },
+ { 0x1138, 0x00000000 },
+ { 0x1178, 0x00000000 },
+ { 0x11b8, 0x00000000 },
+ { 0x11f8, 0x00000000 },
+ { 0x1238, 0x00000000 },
+ { 0x1278, 0x00000000 },
+ { 0x12b8, 0x00000000 },
+ { 0x12f8, 0x00000000 },
+ { 0x1338, 0x00000000 },
+ { 0x1378, 0x00000000 },
+ { 0x13b8, 0x00000000 },
+ { 0x13f8, 0x00000000 },
+ { 0x1438, 0x00000000 },
+ { 0x1478, 0x00000000 },
+ { 0x14b8, 0x00000000 },
+ { 0x14f8, 0x00000000 },
+ { 0x1538, 0x00000000 },
+ { 0x1578, 0x00000000 },
+ { 0x15b8, 0x00000000 },
+ { 0x15f8, 0x00000000 },
+ { 0x1638, 0x00000000 },
+ { 0x1678, 0x00000000 },
+ { 0x16b8, 0x00000000 },
+ { 0x16f8, 0x00000000 },
+ { 0x1738, 0x00000000 },
+ { 0x1778, 0x00000000 },
+ { 0x17b8, 0x00000000 },
+ { 0x17f8, 0x00000000 },
+ { 0x103c, 0x00000000 },
+ { 0x107c, 0x00000000 },
+ { 0x10bc, 0x00000000 },
+ { 0x10fc, 0x00000000 },
+ { 0x113c, 0x00000000 },
+ { 0x117c, 0x00000000 },
+ { 0x11bc, 0x00000000 },
+ { 0x11fc, 0x00000000 },
+ { 0x123c, 0x00000000 },
+ { 0x127c, 0x00000000 },
+ { 0x12bc, 0x00000000 },
+ { 0x12fc, 0x00000000 },
+ { 0x133c, 0x00000000 },
+ { 0x137c, 0x00000000 },
+ { 0x13bc, 0x00000000 },
+ { 0x13fc, 0x00000000 },
+ { 0x143c, 0x00000000 },
+ { 0x147c, 0x00000000 },
+ { AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
+ { AR5K_DCU_TX_FILTER_SET, 0x00000000 },
+ { AR5K_STA_ID1, 0x00000000 },
+ { AR5K_BSS_ID0, 0x00000000 },
+ { AR5K_BSS_ID1, 0x00000000 },
+ /*{ AR5K_RSSI_THR, 0x00000000 },*/ /* Found on SuperAG cards */
+ { AR5K_BEACON_5211, 0x00000000 }, /* Found on SuperAG cards */
+ { AR5K_CFP_PERIOD_5211, 0x00000000 }, /* Found on SuperAG cards */
+ { AR5K_TIMER0_5211, 0x00000030 }, /* Found on SuperAG cards */
+ { AR5K_TIMER1_5211, 0x0007ffff }, /* Found on SuperAG cards */
+ { AR5K_TIMER2_5211, 0x01ffffff }, /* Found on SuperAG cards */
+ { AR5K_TIMER3_5211, 0x00000031 }, /* Found on SuperAG cards */
+ { AR5K_CFP_DUR_5211, 0x00000000 }, /* Found on SuperAG cards */
+ { AR5K_RX_FILTER_5211, 0x00000000 },
+ { AR5K_DIAG_SW_5211, 0x00000000 },
+ { AR5K_ADDAC_TEST, 0x00000000 },
+ { AR5K_DEFAULT_ANTENNA, 0x00000000 },
+ { 0x8080, 0x00000000 },
+ /*{ 0x805c, 0xffffc7ff },*/ /* Old value */
+ { 0x805c, 0x000fc78f },
+ { AR5K_NAV_5211, 0x00000000 }, /* Not found on recent */
+ { AR5K_RTS_OK_5211, 0x00000000 }, /* dumps but it makes */
+ { AR5K_RTS_FAIL_5211, 0x00000000 }, /* sense to reset counters */
+ { AR5K_ACK_FAIL_5211, 0x00000000 }, /* since pcu registers */
+ { AR5K_FCS_FAIL_5211, 0x00000000 }, /* are skiped during chan*/
+ { AR5K_BEACON_CNT_5211, 0x00000000 }, /* change */
+ { AR5K_XRMODE, 0x2a82301a },
+ { AR5K_XRDELAY, 0x05dc01e0 },
+ { AR5K_XRTIMEOUT, 0x1f402710 },
+ { AR5K_XRCHIRP, 0x01f40000 },
+ { AR5K_XRSTOMP, 0x00001e1c },
+ { AR5K_SLEEP0, 0x0002aaaa }, /* Found on SuperAG cards */
+ { AR5K_SLEEP1, 0x02005555 }, /* Found on SuperAG cards */
+ { AR5K_SLEEP2, 0x00000000 }, /* Found on SuperAG cards */
+ { AR5K_BSS_IDM0, 0xffffffff },
+ { AR5K_BSS_IDM1, 0x0000ffff },
+ { AR5K_TXPC, 0x00000000 },
+ { AR5K_PROFCNT_TX, 0x00000000 },
+ { AR5K_PROFCNT_RX, 0x00000000 },
+ { AR5K_PROFCNT_RXCLR, 0x00000000 },
+ { AR5K_PROFCNT_CYCLE, 0x00000000 },
+ { 0x80fc, 0x00000088 },
+ { AR5K_RATE_DUR(0), 0x00000000 },
+ { AR5K_RATE_DUR(1), 0x0000008c },
+ { AR5K_RATE_DUR(2), 0x000000e4 },
+ { AR5K_RATE_DUR(3), 0x000002d5 },
+ { AR5K_RATE_DUR(4), 0x00000000 },
+ { AR5K_RATE_DUR(5), 0x00000000 },
+ { AR5K_RATE_DUR(6), 0x000000a0 },
+ { AR5K_RATE_DUR(7), 0x000001c9 },
+ { AR5K_RATE_DUR(8), 0x0000002c },
+ { AR5K_RATE_DUR(9), 0x0000002c },
+ { AR5K_RATE_DUR(10), 0x00000030 },
+ { AR5K_RATE_DUR(11), 0x0000003c },
+ { AR5K_RATE_DUR(12), 0x0000002c },
+ { AR5K_RATE_DUR(13), 0x0000002c },
+ { AR5K_RATE_DUR(14), 0x00000030 },
+ { AR5K_RATE_DUR(15), 0x0000003c },
+ { AR5K_RATE_DUR(16), 0x00000000 },
+ { AR5K_RATE_DUR(17), 0x00000000 },
+ { AR5K_RATE_DUR(18), 0x00000000 },
+ { AR5K_RATE_DUR(19), 0x00000000 },
+ { AR5K_RATE_DUR(20), 0x00000000 },
+ { AR5K_RATE_DUR(21), 0x00000000 },
+ { AR5K_RATE_DUR(22), 0x00000000 },
+ { AR5K_RATE_DUR(23), 0x00000000 },
+ { AR5K_RATE_DUR(24), 0x000000d5 },
+ { AR5K_RATE_DUR(25), 0x000000df },
+ { AR5K_RATE_DUR(26), 0x00000102 },
+ { AR5K_RATE_DUR(27), 0x0000013a },
+ { AR5K_RATE_DUR(28), 0x00000075 },
+ { AR5K_RATE_DUR(29), 0x0000007f },
+ { AR5K_RATE_DUR(30), 0x000000a2 },
+ { AR5K_RATE_DUR(31), 0x00000000 },
+ { 0x8100, 0x00010002},
+ { AR5K_TSF_PARM, 0x00000001 },
+ { 0x8108, 0x000000c0 },
+ { AR5K_PHY_ERR_FIL, 0x00000000 },
+ { 0x8110, 0x00000168 },
+ { 0x8114, 0x00000000 },
+ /* Some kind of table
+ * also notice ...03<-02<-01<-00) */
+ { 0x87c0, 0x03020100 },
+ { 0x87c4, 0x07060504 },
+ { 0x87c8, 0x0b0a0908 },
+ { 0x87cc, 0x0f0e0d0c },
+ { 0x87d0, 0x13121110 },
+ { 0x87d4, 0x17161514 },
+ { 0x87d8, 0x1b1a1918 },
+ { 0x87dc, 0x1f1e1d1c },
+ /* loop ? */
+ { 0x87e0, 0x03020100 },
+ { 0x87e4, 0x07060504 },
+ { 0x87e8, 0x0b0a0908 },
+ { 0x87ec, 0x0f0e0d0c },
+ { 0x87f0, 0x13121110 },
+ { 0x87f4, 0x17161514 },
+ { 0x87f8, 0x1b1a1918 },
+ { 0x87fc, 0x1f1e1d1c },
+ /* PHY registers */
+ /*{ AR5K_PHY_AGC, 0x00000000 },*/
+ { AR5K_PHY(3), 0xad848e19 },
+ { AR5K_PHY(4), 0x7d28e000 },
+ { AR5K_PHY_TIMING_3, 0x9c0a9f6b },
+ { AR5K_PHY_ACT, 0x00000000 },
+ /*{ AR5K_PHY(11), 0x00022ffe },*/
+ /*{ AR5K_PHY(15), 0x00020100 },*/
+ { AR5K_PHY(16), 0x206a017a },
+ /*{ AR5K_PHY(19), 0x1284613c },*/
+ { AR5K_PHY(21), 0x00000859 },
+ { AR5K_PHY(64), 0x00000000 },
+ { AR5K_PHY(65), 0x00000000 },
+ { AR5K_PHY(66), 0x00000000 },
+ { AR5K_PHY(67), 0x00800000 },
+ { AR5K_PHY(68), 0x00000001 },
+ /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */
+ { AR5K_PHY(71), 0x00000c80 },
+ { AR5K_PHY_IQ, 0x05100000 },
+ { AR5K_PHY(74), 0x00000001 },
+ { AR5K_PHY(75), 0x00000004 },
+ { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 },
+ { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d },
+ { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f },
+ /*{ AR5K_PHY(80), 0x00000004 },*/
+ { AR5K_PHY(82), 0x9280b212 },
+ { AR5K_PHY_RADAR, 0x5d50e188 },
+ /*{ AR5K_PHY(86), 0x000000ff },*/
+ { AR5K_PHY(87), 0x004b6a8e },
+ { AR5K_PHY(90), 0x000003ce },
+ { AR5K_PHY(92), 0x192fb515 },
+ /*{ AR5K_PHY(93), 0x00000000 },*/
+ { AR5K_PHY(94), 0x00000001 },
+ { AR5K_PHY(95), 0x00000000 },
+ /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */
+ /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */
+ { AR5K_PHY(644), 0x00806333 },
+ { AR5K_PHY(645), 0x00106c10 },
+ { AR5K_PHY(646), 0x009c4060 },
+ /*{ AR5K_PHY(647), 0x1483800a },*/ /* Old value */
+ { AR5K_PHY(647), 0x1483800a },
+ { AR5K_PHY(648), 0x01831061 },
+ { AR5K_PHY(649), 0x00000400 },
+ /*{ AR5K_PHY(650), 0x000001b5 },*/
+ { AR5K_PHY(651), 0x00000000 },
+ { AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
+ { AR5K_PHY_TXPOWER_RATE2, 0x20202020 },
+ /*{ AR5K_PHY(655), 0x13c889af },*/
+ { AR5K_PHY(656), 0x38490a20 },
+ { AR5K_PHY(657), 0x00007bb6 },
+ { AR5K_PHY(658), 0x0fff3ffc },
+ /*{ AR5K_PHY_CCKTXCTL, 0x00000000 },*/
+};
+
+/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */
+static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
+ { AR5K_PHY(640),
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000008, 0x00000008, 0x0000000b, 0x0000000e, 0x0000000e } },
+ { AR5K_PHY(0),
+ { 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(0),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(1),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(2),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(3),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(4),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(5),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(6),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(7),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(8),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_QUEUE_DFS_LOCAL_IFS(9),
+ { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } },
+ { AR5K_DCU_GBL_IFS_SIFS,
+ { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_SLOT,
+ { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } },
+ { AR5K_DCU_GBL_IFS_EIFS,
+ { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } },
+ { AR5K_DCU_GBL_IFS_MISC,
+ { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } },
+ { AR5K_TIME_OUT,
+ { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } },
+ { AR5K_PHY_TURBO,
+ { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } },
+ { AR5K_PHY(8),
+ { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } },
+ { AR5K_PHY(9),
+ { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(17),
+ { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
+ { AR5K_PHY_AGCCTL,
+ { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
+ { AR5K_PHY_NF,
+ { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
+ { AR5K_PHY(26),
+ { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } },
+ { AR5K_PHY(70),
+ { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } },
+ { AR5K_PHY(73),
+ { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } },
+ { 0xa230,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */
+/* New dump pending */
+static const struct ath5k_ini_mode ar5212_rf5111_ini_mode_end[] = {
+ { AR5K_PHY(640), /* This one differs from ar5212_ini_mode_start ! */
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000006, 0x00000006 } },
+ { AR5K_TXCFG,
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY(18),
+ { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } },
+ { AR5K_PHY(20),
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } },
+ { AR5K_PHY(27),
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } },
+ { 0xa21c,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+ { AR5K_DCU_FP,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_AGC,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(11),
+ { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } },
+ { AR5K_PHY(15),
+ { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } },
+ { AR5K_PHY(19),
+ { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } },
+ { AR5K_PHY_PAPD_PROBE,
+ { 0x00004883, 0x00004883, 0x00004883, 0x00004883, 0x00004883 } },
+ { AR5K_PHY(80),
+ { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } },
+ { AR5K_PHY(86),
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
+ { AR5K_PHY(93),
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_SPENDING,
+ { 0x00000018, 0x00000018, 0x00000018, 0x00000018, 0x00000018 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(642),
+ { 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { 0xa23c,
+ { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } },
+};
+
+/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */
+/* XXX: No dumps for turbog yet, but i found settings from old values so it should be ok */
+static const struct ath5k_ini_mode ar5212_rf5112_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g (DYN) gTurbo */
+ { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY(18),
+ { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } },
+ { AR5K_PHY(20),
+ { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
+ { AR5K_PHY_SIG,
+ { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
+ { AR5K_PHY(27),
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } },
+ { AR5K_PHY(642),
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } },
+ { 0xa21c,
+ { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } },
+ { AR5K_DCU_FP,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_AGC,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(11),
+ { 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe, 0x00022ffe } },
+ { AR5K_PHY(15),
+ { 0x00020100, 0x00020100, 0x00020100, 0x00020100, 0x00020100 } },
+ { AR5K_PHY(19),
+ { 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c, 0x1284613c } },
+ { AR5K_PHY_PAPD_PROBE,
+ { 0x00004882, 0x00004882, 0x00004882, 0x00004882, 0x00004882 } },
+ { AR5K_PHY(80),
+ { 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 } },
+ { AR5K_PHY(86),
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
+ { AR5K_PHY(93),
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa228,
+ { 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5, 0x000001b5 } },
+ { 0xa23c,
+ { 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af } },
+};
+
+/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */
+/* XXX: No dumps for turbog yet, so turbog is the same with g here with some
+ * minor tweaking based on dumps from other chips */
+static const struct ath5k_ini_mode rf5413_ini_mode_end[] = {
+ { AR5K_TXCFG,
+ /* a/XR aTurbo b g gTurbo */
+ { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } },
+ { AR5K_USEC_5211,
+ { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } },
+ { AR5K_PHY(10),
+ { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } },
+ { AR5K_PHY(13),
+ { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } },
+ { AR5K_PHY(14),
+ { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } },
+ { AR5K_PHY(18),
+ { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } },
+ { AR5K_PHY(20),
+ { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } },
+ { AR5K_PHY_SIG,
+ { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } },
+ { AR5K_PHY_AGCCOARSE,
+ { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } },
+ { AR5K_PHY(27),
+ { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } },
+ { AR5K_PHY_RX_DELAY,
+ { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } },
+ { AR5K_PHY_FRAME_CTL_5211,
+ { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } },
+ { AR5K_PHY_CCKTXCTL,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(642),
+ { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } },
+ { AR5K_PHY_GAIN_2GHZ,
+ { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } },
+ { 0xa21c,
+ { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } },
+ { 0xa300,
+ { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } },
+ { 0xa304,
+ { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } },
+ { 0xa308,
+ { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } },
+ { 0xa30c,
+ { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } },
+ { 0xa310,
+ { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } },
+ { 0xa314,
+ { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } },
+ { 0xa318,
+ { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } },
+ { 0xa31c,
+ { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } },
+ { 0xa320,
+ { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } },
+ { 0xa324,
+ { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } },
+ { 0xa328,
+ { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } },
+ { 0xa32c,
+ { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } },
+ { 0xa330,
+ { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } },
+ { 0xa334,
+ { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } },
+ { AR5K_DCU_FP,
+ { 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0, 0x000003e0 } },
+ { 0x4068,
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
+ { 0x8060,
+ { 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f } },
+ { 0x809c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x80a0,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8118,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x811c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8120,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8124,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8128,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x812c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8130,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8134,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8138,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x813c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0x8140,
+ { 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9, 0x800003f9 } },
+ { 0x8144,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY_AGC,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(11),
+ { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } },
+ { AR5K_PHY(15),
+ { 0x00200400, 0x00200400, 0x00200400, 0x00200400, 0x00200400 } },
+ { AR5K_PHY(19),
+ { 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c } },
+ { AR5K_PHY_SCR,
+ { 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f } },
+ { AR5K_PHY_SLMT,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { AR5K_PHY_SCAL,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+ { AR5K_PHY(86),
+ { 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff } },
+ { AR5K_PHY(96),
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(97),
+ { 0x02800000, 0x02800000, 0x02800000, 0x02800000, 0x02800000 } },
+ { AR5K_PHY(104),
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(120),
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { AR5K_PHY(121),
+ { 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa } },
+ { AR5K_PHY(122),
+ { 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478, 0x3c466478 } },
+ { AR5K_PHY(123),
+ { 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa } },
+ { AR5K_PHY_SCLOCK,
+ { 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c } },
+ { AR5K_PHY_SDELAY,
+ { 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff } },
+ { AR5K_PHY_SPENDING,
+ { 0x00000014, 0x00000014, 0x00000014, 0x00000014, 0x00000014 } },
+ { 0xa228,
+ { 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5 } },
+ { 0xa23c,
+ { 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af, 0x93c889af } },
+ { 0xa24c,
+ { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } },
+ { 0xa250,
+ { 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000 } },
+ { 0xa254,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa258,
+ { 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380 } },
+ { 0xa25c,
+ { 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01 } },
+ { 0xa260,
+ { 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01, 0x5f690f01 } },
+ { 0xa264,
+ { 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11 } },
+ { 0xa268,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa26c,
+ { 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a, 0x0c30c16a } },
+ { 0xa270,
+ { 0x00820820, 0x00820820, 0x00820820, 0x00820820, 0x00820820 } },
+ { 0xa274,
+ { 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa, 0x081b7caa } },
+ { 0xa278,
+ { 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce } },
+ { 0xa27c,
+ { 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce } },
+ { 0xa338,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa33c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa340,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa344,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0xa348,
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
+ { 0xa34c,
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
+ { 0xa350,
+ { 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff } },
+ { 0xa354,
+ { 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff } },
+ { 0xa358,
+ { 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f } },
+ { 0xa35c,
+ { 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f } },
+ { 0xa360,
+ { 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207 } },
+ { 0xa364,
+ { 0x17601685, 0x17601685, 0x17601685, 0x17601685, 0x17601685 } },
+ { 0xa368,
+ { 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104 } },
+ { 0xa36c,
+ { 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03 } },
+ { 0xa370,
+ { 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883 } },
+ { 0xa374,
+ { 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803 } },
+ { 0xa378,
+ { 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682 } },
+ { 0xa37c,
+ { 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482 } },
+ { 0xa380,
+ { 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba } },
+ { 0xa384,
+ { 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0 } },
+};
+
+/*
+ * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with
+ * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI)
+ */
+
+/* RF5111 Initial BaseBand Gain settings */
+static const struct ath5k_ini rf5111_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000 },
+ { AR5K_BB_GAIN(1), 0x00000020 },
+ { AR5K_BB_GAIN(2), 0x00000010 },
+ { AR5K_BB_GAIN(3), 0x00000030 },
+ { AR5K_BB_GAIN(4), 0x00000008 },
+ { AR5K_BB_GAIN(5), 0x00000028 },
+ { AR5K_BB_GAIN(6), 0x00000004 },
+ { AR5K_BB_GAIN(7), 0x00000024 },
+ { AR5K_BB_GAIN(8), 0x00000014 },
+ { AR5K_BB_GAIN(9), 0x00000034 },
+ { AR5K_BB_GAIN(10), 0x0000000c },
+ { AR5K_BB_GAIN(11), 0x0000002c },
+ { AR5K_BB_GAIN(12), 0x00000002 },
+ { AR5K_BB_GAIN(13), 0x00000022 },
+ { AR5K_BB_GAIN(14), 0x00000012 },
+ { AR5K_BB_GAIN(15), 0x00000032 },
+ { AR5K_BB_GAIN(16), 0x0000000a },
+ { AR5K_BB_GAIN(17), 0x0000002a },
+ { AR5K_BB_GAIN(18), 0x00000006 },
+ { AR5K_BB_GAIN(19), 0x00000026 },
+ { AR5K_BB_GAIN(20), 0x00000016 },
+ { AR5K_BB_GAIN(21), 0x00000036 },
+ { AR5K_BB_GAIN(22), 0x0000000e },
+ { AR5K_BB_GAIN(23), 0x0000002e },
+ { AR5K_BB_GAIN(24), 0x00000001 },
+ { AR5K_BB_GAIN(25), 0x00000021 },
+ { AR5K_BB_GAIN(26), 0x00000011 },
+ { AR5K_BB_GAIN(27), 0x00000031 },
+ { AR5K_BB_GAIN(28), 0x00000009 },
+ { AR5K_BB_GAIN(29), 0x00000029 },
+ { AR5K_BB_GAIN(30), 0x00000005 },
+ { AR5K_BB_GAIN(31), 0x00000025 },
+ { AR5K_BB_GAIN(32), 0x00000015 },
+ { AR5K_BB_GAIN(33), 0x00000035 },
+ { AR5K_BB_GAIN(34), 0x0000000d },
+ { AR5K_BB_GAIN(35), 0x0000002d },
+ { AR5K_BB_GAIN(36), 0x00000003 },
+ { AR5K_BB_GAIN(37), 0x00000023 },
+ { AR5K_BB_GAIN(38), 0x00000013 },
+ { AR5K_BB_GAIN(39), 0x00000033 },
+ { AR5K_BB_GAIN(40), 0x0000000b },
+ { AR5K_BB_GAIN(41), 0x0000002b },
+ { AR5K_BB_GAIN(42), 0x0000002b },
+ { AR5K_BB_GAIN(43), 0x0000002b },
+ { AR5K_BB_GAIN(44), 0x0000002b },
+ { AR5K_BB_GAIN(45), 0x0000002b },
+ { AR5K_BB_GAIN(46), 0x0000002b },
+ { AR5K_BB_GAIN(47), 0x0000002b },
+ { AR5K_BB_GAIN(48), 0x0000002b },
+ { AR5K_BB_GAIN(49), 0x0000002b },
+ { AR5K_BB_GAIN(50), 0x0000002b },
+ { AR5K_BB_GAIN(51), 0x0000002b },
+ { AR5K_BB_GAIN(52), 0x0000002b },
+ { AR5K_BB_GAIN(53), 0x0000002b },
+ { AR5K_BB_GAIN(54), 0x0000002b },
+ { AR5K_BB_GAIN(55), 0x0000002b },
+ { AR5K_BB_GAIN(56), 0x0000002b },
+ { AR5K_BB_GAIN(57), 0x0000002b },
+ { AR5K_BB_GAIN(58), 0x0000002b },
+ { AR5K_BB_GAIN(59), 0x0000002b },
+ { AR5K_BB_GAIN(60), 0x0000002b },
+ { AR5K_BB_GAIN(61), 0x0000002b },
+ { AR5K_BB_GAIN(62), 0x00000002 },
+ { AR5K_BB_GAIN(63), 0x00000016 },
+};
+
+/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414) */
+static const struct ath5k_ini rf5112_ini_bbgain[] = {
+ { AR5K_BB_GAIN(0), 0x00000000 },
+ { AR5K_BB_GAIN(1), 0x00000001 },
+ { AR5K_BB_GAIN(2), 0x00000002 },
+ { AR5K_BB_GAIN(3), 0x00000003 },
+ { AR5K_BB_GAIN(4), 0x00000004 },
+ { AR5K_BB_GAIN(5), 0x00000005 },
+ { AR5K_BB_GAIN(6), 0x00000008 },
+ { AR5K_BB_GAIN(7), 0x00000009 },
+ { AR5K_BB_GAIN(8), 0x0000000a },
+ { AR5K_BB_GAIN(9), 0x0000000b },
+ { AR5K_BB_GAIN(10), 0x0000000c },
+ { AR5K_BB_GAIN(11), 0x0000000d },
+ { AR5K_BB_GAIN(12), 0x00000010 },
+ { AR5K_BB_GAIN(13), 0x00000011 },
+ { AR5K_BB_GAIN(14), 0x00000012 },
+ { AR5K_BB_GAIN(15), 0x00000013 },
+ { AR5K_BB_GAIN(16), 0x00000014 },
+ { AR5K_BB_GAIN(17), 0x00000015 },
+ { AR5K_BB_GAIN(18), 0x00000018 },
+ { AR5K_BB_GAIN(19), 0x00000019 },
+ { AR5K_BB_GAIN(20), 0x0000001a },
+ { AR5K_BB_GAIN(21), 0x0000001b },
+ { AR5K_BB_GAIN(22), 0x0000001c },
+ { AR5K_BB_GAIN(23), 0x0000001d },
+ { AR5K_BB_GAIN(24), 0x00000020 },
+ { AR5K_BB_GAIN(25), 0x00000021 },
+ { AR5K_BB_GAIN(26), 0x00000022 },
+ { AR5K_BB_GAIN(27), 0x00000023 },
+ { AR5K_BB_GAIN(28), 0x00000024 },
+ { AR5K_BB_GAIN(29), 0x00000025 },
+ { AR5K_BB_GAIN(30), 0x00000028 },
+ { AR5K_BB_GAIN(31), 0x00000029 },
+ { AR5K_BB_GAIN(32), 0x0000002a },
+ { AR5K_BB_GAIN(33), 0x0000002b },
+ { AR5K_BB_GAIN(34), 0x0000002c },
+ { AR5K_BB_GAIN(35), 0x0000002d },
+ { AR5K_BB_GAIN(36), 0x00000030 },
+ { AR5K_BB_GAIN(37), 0x00000031 },
+ { AR5K_BB_GAIN(38), 0x00000032 },
+ { AR5K_BB_GAIN(39), 0x00000033 },
+ { AR5K_BB_GAIN(40), 0x00000034 },
+ { AR5K_BB_GAIN(41), 0x00000035 },
+ { AR5K_BB_GAIN(42), 0x00000035 },
+ { AR5K_BB_GAIN(43), 0x00000035 },
+ { AR5K_BB_GAIN(44), 0x00000035 },
+ { AR5K_BB_GAIN(45), 0x00000035 },
+ { AR5K_BB_GAIN(46), 0x00000035 },
+ { AR5K_BB_GAIN(47), 0x00000035 },
+ { AR5K_BB_GAIN(48), 0x00000035 },
+ { AR5K_BB_GAIN(49), 0x00000035 },
+ { AR5K_BB_GAIN(50), 0x00000035 },
+ { AR5K_BB_GAIN(51), 0x00000035 },
+ { AR5K_BB_GAIN(52), 0x00000035 },
+ { AR5K_BB_GAIN(53), 0x00000035 },
+ { AR5K_BB_GAIN(54), 0x00000035 },
+ { AR5K_BB_GAIN(55), 0x00000035 },
+ { AR5K_BB_GAIN(56), 0x00000035 },
+ { AR5K_BB_GAIN(57), 0x00000035 },
+ { AR5K_BB_GAIN(58), 0x00000035 },
+ { AR5K_BB_GAIN(59), 0x00000035 },
+ { AR5K_BB_GAIN(60), 0x00000035 },
+ { AR5K_BB_GAIN(61), 0x00000035 },
+ { AR5K_BB_GAIN(62), 0x00000010 },
+ { AR5K_BB_GAIN(63), 0x0000001a },
+};
+
+
+/*
+ * Write initial register dump
+ */
+static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size,
+ const struct ath5k_ini *ini_regs, bool change_channel)
+{
+ unsigned int i;
+
+ /* Write initial registers */
+ for (i = 0; i < size; i++) {
+ /* On channel change there is
+ * no need to mess with PCU */
+ if (change_channel &&
+ ini_regs[i].ini_register >= AR5K_PCU_MIN &&
+ ini_regs[i].ini_register <= AR5K_PCU_MAX)
+ continue;
+
+ switch (ini_regs[i].ini_mode) {
+ case AR5K_INI_READ:
+ /* Cleared on read */
+ ath5k_hw_reg_read(ah, ini_regs[i].ini_register);
+ break;
+ case AR5K_INI_WRITE:
+ default:
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_regs[i].ini_value,
+ ini_regs[i].ini_register);
+ }
+ }
+}
+
+static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah,
+ unsigned int size, const struct ath5k_ini_mode *ini_mode,
+ u8 mode)
+{
+ unsigned int i;
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode],
+ (u32)ini_mode[i].mode_register);
+ }
+
+}
+
+int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
+{
+ /*
+ * Write initial register settings
+ */
+
+ /* For AR5212 and combatible */
+ if (ah->ah_version == AR5K_AR5212){
+
+ /* First set of mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_ini_mode_start),
+ ar5212_ini_mode_start, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini),
+ ar5212_ini, change_channel);
+
+ /* Second set of mode-specific settings */
+ if (ah->ah_radio == AR5K_RF5111){
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
+ ar5212_rf5111_ini_mode_end, mode);
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+ } else if (ah->ah_radio == AR5K_RF5112){
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
+ ar5212_rf5112_ini_mode_end, mode);
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ } else if (ah->ah_radio == AR5K_RF5413){
+ ath5k_hw_ini_mode_registers(ah,
+ ARRAY_SIZE(rf5413_ini_mode_end),
+ rf5413_ini_mode_end, mode);
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah,
+ ARRAY_SIZE(rf5112_ini_bbgain),
+ rf5112_ini_bbgain, change_channel);
+ }
+ /* For AR5211 */
+ } else if (ah->ah_version == AR5K_AR5211) {
+
+ if(mode > 2){ /* AR5K_INI_VAL_11B */
+ ATH5K_ERR(ah->ah_sc,"unsupported channel mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ /* Mode-specific settings */
+ ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode),
+ ar5211_ini_mode, mode);
+
+ /*
+ * Write initial settings common for all modes
+ */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini),
+ ar5211_ini, change_channel);
+
+ /* AR5211 only comes with 5111 */
+
+ /* Baseband gain table */
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain),
+ rf5111_ini_bbgain, change_channel);
+ /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */
+ } else if (ah->ah_version == AR5K_AR5210) {
+ ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini),
+ ar5210_ini, change_channel);
+ }
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
new file mode 100644
index 000000000000..b95941797141
--- /dev/null
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -0,0 +1,2071 @@
+/*
+ * PHY functions
+ *
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2006, 2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+#include <linux/delay.h>
+
+#include "ath5k.h"
+#include "reg.h"
+#include "base.h"
+
+/* Struct to hold initial RF register values (RF Banks) */
+struct ath5k_ini_rf {
+ u8 rf_bank; /* check out ath5k_reg.h */
+ u16 rf_register; /* register address */
+ u32 rf_value[5]; /* register value for different modes (above) */
+};
+
+/*
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
+ * RF Gain values are included in AR5K_AR5210_INI)
+ */
+struct ath5k_ini_rfgain {
+ u16 rfg_register; /* RF Gain register address */
+ u32 rfg_value[2]; /* [freq (see below)] */
+};
+
+struct ath5k_gain_opt {
+ u32 go_default;
+ u32 go_steps_count;
+ const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT];
+};
+
+/* RF5111 mode-specific init registers */
+static const struct ath5k_ini_rf rfregs_5111[] = {
+ { 0, 0x989c,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 0, 0x989c,
+ { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } },
+ { 0, 0x989c,
+ { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } },
+ { 0, 0x98d4,
+ { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } },
+ { 1, 0x98d4,
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d4,
+ { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } },
+ { 3, 0x98d8,
+ { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } },
+ { 6, 0x989c,
+ { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } },
+ { 6, 0x989c,
+ { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } },
+ { 6, 0x989c,
+ { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } },
+ { 6, 0x989c,
+ { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } },
+ { 6, 0x989c,
+ { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } },
+ { 6, 0x98d4,
+ { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } },
+ { 7, 0x989c,
+ { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } },
+ { 7, 0x989c,
+ { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } },
+ { 7, 0x989c,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 7, 0x989c,
+ { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } },
+ { 7, 0x989c,
+ { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } },
+ { 7, 0x989c,
+ { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } },
+ { 7, 0x989c,
+ { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } },
+};
+
+/* Initial RF Gain settings for RF5111 */
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } },
+ { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } },
+ { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } },
+ { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } },
+ { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } },
+ { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } },
+ { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } },
+ { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } },
+ { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } },
+ { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } },
+ { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } },
+ { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } },
+ { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } },
+ { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } },
+ { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } },
+ { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } },
+ { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } },
+ { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } },
+ { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } },
+ { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } },
+ { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } },
+ { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } },
+ { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } },
+ { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } },
+ { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } },
+ { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } },
+ { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } },
+ { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } },
+ { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } },
+ { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } },
+ { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } },
+ { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } },
+ { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } },
+ { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } },
+ { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } },
+ { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } },
+ { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } },
+ { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } },
+ { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } },
+ { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } },
+ { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } },
+ { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } },
+ { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } },
+ { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } },
+ { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } },
+ { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } },
+ { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } },
+};
+
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
+ 4,
+ 9,
+ {
+ { { 4, 1, 1, 1 }, 6 },
+ { { 4, 0, 1, 1 }, 4 },
+ { { 3, 1, 1, 1 }, 3 },
+ { { 4, 0, 0, 1 }, 1 },
+ { { 4, 1, 1, 0 }, 0 },
+ { { 4, 0, 1, 0 }, -2 },
+ { { 3, 1, 1, 0 }, -3 },
+ { { 4, 0, 0, 0 }, -4 },
+ { { 2, 1, 1, 0 }, -6 }
+ }
+};
+
+/* RF5112 mode-specific init registers */
+static const struct ath5k_ini_rf rfregs_5112[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+ { 6, 0x989c,
+ { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } },
+ { 6, 0x989c,
+ { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } },
+ { 6, 0x989c,
+ { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } },
+ { 6, 0x989c,
+ { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } },
+ { 6, 0x989c,
+ { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } },
+ { 6, 0x989c,
+ { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } },
+ { 6, 0x989c,
+ { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } },
+ { 6, 0x989c,
+ { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } },
+ { 6, 0x989c,
+ { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } },
+ { 6, 0x989c,
+ { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } },
+ { 6, 0x989c,
+ { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } },
+ { 6, 0x989c,
+ { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } },
+ { 6, 0x989c,
+ { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } },
+ { 6, 0x989c,
+ { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } },
+ { 6, 0x989c,
+ { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } },
+ { 6, 0x989c,
+ { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } },
+ { 6, 0x98d0,
+ { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } },
+ { 7, 0x989c,
+ { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+/* RF5112A mode-specific init registers */
+static const struct ath5k_ini_rf rfregs_5112a[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, 0x98dc,
+ { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } },
+ { 6, 0x989c,
+ { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } },
+ { 6, 0x989c,
+ { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } },
+ { 6, 0x989c,
+ { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } },
+ { 6, 0x989c,
+ { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } },
+ { 6, 0x989c,
+ { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } },
+ { 6, 0x989c,
+ { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } },
+ { 6, 0x989c,
+ { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } },
+ { 6, 0x989c,
+ { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } },
+ { 6, 0x989c,
+ { 0x00190000, 0x00190000, 0x00190000, 0x00190000, 0x00190000 } },
+ { 6, 0x989c,
+ { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, 0x989c,
+ { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } },
+ { 6, 0x989c,
+ { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } },
+ { 6, 0x989c,
+ { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } },
+ { 6, 0x989c,
+ { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, 0x989c,
+ { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, 0x989c,
+ { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } },
+ { 6, 0x989c,
+ { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } },
+ { 6, 0x989c,
+ { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, 0x989c,
+ { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } },
+ { 6, 0x989c,
+ { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } },
+ { 6, 0x989c,
+ { 0x00020080, 0x00020080, 0x00020080, 0x00020080, 0x00020080 } },
+ { 6, 0x989c,
+ { 0x00080009, 0x00080009, 0x00080009, 0x00080009, 0x00080009 } },
+ { 6, 0x989c,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } },
+ { 6, 0x989c,
+ { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } },
+ { 6, 0x989c,
+ { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } },
+ { 6, 0x989c,
+ { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } },
+ { 6, 0x989c,
+ { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } },
+ { 6, 0x98d8,
+ { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } },
+ { 7, 0x989c,
+ { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, 0x989c,
+ { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, 0x989c,
+ { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, 0x989c,
+ { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, 0x989c,
+ { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } },
+ { 7, 0x989c,
+ { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, 0x989c,
+ { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, 0x989c,
+ { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } },
+ { 7, 0x989c,
+ { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } },
+ { 7, 0x989c,
+ { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, 0x989c,
+ { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, 0x989c,
+ { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, 0x98c4,
+ { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+
+static const struct ath5k_ini_rf rfregs_2112a[] = {
+ { 1, AR5K_RF_BUFFER_CONTROL_4,
+ /* mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, AR5K_RF_BUFFER_CONTROL_3,
+ { 0x03060408, 0x03060408, 0x03070408 } },
+ { 3, AR5K_RF_BUFFER_CONTROL_6,
+ { 0x00e020c0, 0x00e020c0, 0x00e020c0 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x0a000000, 0x0a000000, 0x0a000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00800000, 0x00800000, 0x00800000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00010000, 0x00010000, 0x00010000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00180000, 0x00180000, 0x00180000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x006e0000, 0x006e0000, 0x006e0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00c70000, 0x00c70000, 0x00c70000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x004b0000, 0x004b0000, 0x004b0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x04480000, 0x04480000, 0x04480000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00e40000, 0x00e40000, 0x00e40000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00fc0000, 0x00fc0000, 0x00fc0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x043f0000, 0x043f0000, 0x043f0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x0c0c0000, 0x0c0c0000, 0x0c0c0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x02190000, 0x02190000, 0x02190000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00240000, 0x00240000, 0x00240000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00b40000, 0x00b40000, 0x00b40000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00990000, 0x00990000, 0x00990000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00500000, 0x00500000, 0x00500000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x002a0000, 0x002a0000, 0x002a0000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00120000, 0x00120000, 0x00120000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0xc0320000, 0xc0320000, 0xc0320000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x01740000, 0x01740000, 0x01740000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00110000, 0x00110000, 0x00110000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x86280000, 0x86280000, 0x86280000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x31840000, 0x31840000, 0x31840000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00f20080, 0x00f20080, 0x00f20080 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00070019, 0x00070019, 0x00070019 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x000000b2, 0x000000b2, 0x000000b2 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00b02184, 0x00b02184, 0x00b02184 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x004125a4, 0x004125a4, 0x004125a4 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x00119220, 0x00119220, 0x00119220 } },
+ { 6, AR5K_RF_BUFFER,
+ { 0x001a4800, 0x001a4800, 0x001a4800 } },
+ { 6, AR5K_RF_BUFFER_CONTROL_5,
+ { 0x000b0230, 0x000b0230, 0x000b0230 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000094, 0x00000094, 0x00000094 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000091, 0x00000091, 0x00000091 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000012, 0x00000012, 0x00000012 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000080, 0x00000080, 0x00000080 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x000000d9, 0x000000d9, 0x000000d9 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000060, 0x00000060, 0x00000060 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x000000f0, 0x000000f0, 0x000000f0 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x000000a2, 0x000000a2, 0x000000a2 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x00000052, 0x00000052, 0x00000052 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x000000d4, 0x000000d4, 0x000000d4 } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x000014cc, 0x000014cc, 0x000014cc } },
+ { 7, AR5K_RF_BUFFER,
+ { 0x0000048c, 0x0000048c, 0x0000048c } },
+ { 7, AR5K_RF_BUFFER_CONTROL_1,
+ { 0x00000003, 0x00000003, 0x00000003 } },
+};
+
+/* RF5413/5414 mode-specific init registers */
+static const struct ath5k_ini_rf rfregs_5413[] = {
+ { 1, 0x98d4,
+ /* mode a/XR mode aTurbo mode b mode g mode gTurbo */
+ { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } },
+ { 2, 0x98d0,
+ { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } },
+ { 3, 0x98dc,
+ { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } },
+ { 6, 0x989c,
+ { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } },
+ { 6, 0x989c,
+ { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } },
+ { 6, 0x989c,
+ { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } },
+ { 6, 0x989c,
+ { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } },
+ { 6, 0x989c,
+ { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } },
+ { 6, 0x989c,
+ { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } },
+ { 6, 0x989c,
+ { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } },
+ { 6, 0x989c,
+ { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } },
+ { 6, 0x989c,
+ { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } },
+ { 6, 0x989c,
+ { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } },
+ { 6, 0x989c,
+ { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } },
+ { 6, 0x989c,
+ { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } },
+ { 6, 0x989c,
+ { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } },
+ { 6, 0x989c,
+ { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } },
+ { 6, 0x989c,
+ { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } },
+ { 6, 0x989c,
+ { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } },
+ { 6, 0x989c,
+ { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } },
+ { 6, 0x989c,
+ { 0x00510040, 0x00510040, 0x005100a0, 0x005100a0, 0x005100a0 } },
+ { 6, 0x989c,
+ { 0x0050006a, 0x0050006a, 0x005000dd, 0x005000dd, 0x005000dd } },
+ { 6, 0x989c,
+ { 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } },
+ { 6, 0x989c,
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } },
+ { 6, 0x989c,
+ { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } },
+ { 6, 0x989c,
+ { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00003600 } },
+ { 6, 0x98c8,
+ { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } },
+ { 7, 0x989c,
+ { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } },
+ { 7, 0x989c,
+ { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } },
+ { 7, 0x98cc,
+ { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } },
+};
+
+
+/* Initial RF Gain settings for RF5112 */
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } },
+ { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } },
+ { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } },
+ { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } },
+ { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } },
+ { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } },
+ { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } },
+ { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } },
+ { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } },
+ { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } },
+ { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } },
+ { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } },
+ { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } },
+ { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } },
+ { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } },
+ { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } },
+ { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } },
+ { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } },
+ { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } },
+ { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } },
+ { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } },
+ { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } },
+ { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } },
+ { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } },
+ { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } },
+ { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } },
+ { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } },
+ { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } },
+ { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } },
+ { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } },
+ { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } },
+ { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } },
+ { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } },
+ { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } },
+ { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } },
+ { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } },
+ { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } },
+ { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } },
+ { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } },
+ { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } },
+ { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } },
+ { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } },
+ { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } },
+ { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } },
+ { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } },
+ { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } },
+ { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } },
+ { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } },
+ { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } },
+ { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } },
+ { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } },
+ { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } },
+ { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } },
+ { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } },
+ { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } },
+ { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } },
+};
+
+/* Initial RF Gain settings for RF5413 */
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
+ /* 5Ghz 2Ghz */
+ { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } },
+ { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } },
+ { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } },
+ { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } },
+ { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } },
+ { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } },
+ { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } },
+ { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } },
+ { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } },
+ { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } },
+ { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } },
+ { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } },
+ { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } },
+ { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } },
+ { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } },
+ { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } },
+ { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } },
+ { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } },
+ { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } },
+ { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } },
+ { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } },
+ { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } },
+ { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } },
+ { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } },
+ { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } },
+ { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } },
+ { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } },
+ { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } },
+ { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } },
+ { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } },
+ { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } },
+ { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } },
+ { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } },
+ { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } },
+ { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } },
+ { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } },
+ { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } },
+ { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } },
+ { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } },
+ { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } },
+ { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } },
+};
+
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
+ 1,
+ 8,
+ {
+ { { 3, 0, 0, 0, 0, 0, 0 }, 6 },
+ { { 2, 0, 0, 0, 0, 0, 0 }, 0 },
+ { { 1, 0, 0, 0, 0, 0, 0 }, -3 },
+ { { 0, 0, 0, 0, 0, 0, 0 }, -6 },
+ { { 0, 1, 1, 0, 0, 0, 0 }, -8 },
+ { { 0, 1, 1, 0, 1, 1, 0 }, -10 },
+ { { 0, 1, 0, 1, 1, 1, 0 }, -13 },
+ { { 0, 1, 0, 1, 1, 0, 1 }, -16 },
+ }
+};
+
+/*
+ * Used to modify RF Banks before writing them to AR5K_RF_BUFFER
+ */
+static unsigned int ath5k_hw_rfregs_op(u32 *rf, u32 offset, u32 reg, u32 bits,
+ u32 first, u32 col, bool set)
+{
+ u32 mask, entry, last, data, shift, position;
+ s32 left;
+ int i;
+
+ data = 0;
+
+ if (rf == NULL)
+ /* should not happen */
+ return 0;
+
+ if (!(col <= 3 && bits <= 32 && first + bits <= 319)) {
+ ATH5K_PRINTF("invalid values at offset %u\n", offset);
+ return 0;
+ }
+
+ entry = ((first - 1) / 8) + offset;
+ position = (first - 1) % 8;
+
+ if (set == true)
+ data = ath5k_hw_bitswap(reg, bits);
+
+ for (i = shift = 0, left = bits; left > 0; position = 0, entry++, i++) {
+ last = (position + left > 8) ? 8 : position + left;
+ mask = (((1 << last) - 1) ^ ((1 << position) - 1)) << (col * 8);
+
+ if (set == true) {
+ rf[entry] &= ~mask;
+ rf[entry] |= ((data << position) << (col * 8)) & mask;
+ data >>= (8 - position);
+ } else {
+ data = (((rf[entry] & mask) >> (col * 8)) >> position)
+ << shift;
+ shift += last - position;
+ }
+
+ left -= 8 - position;
+ }
+
+ data = set == true ? 1 : ath5k_hw_bitswap(data, bits);
+
+ return data;
+}
+
+static u32 ath5k_hw_rfregs_gainf_corr(struct ath5k_hw *ah)
+{
+ u32 mix, step;
+ u32 *rf;
+
+ if (ah->ah_rf_banks == NULL)
+ return 0;
+
+ rf = ah->ah_rf_banks;
+ ah->ah_gain.g_f_corr = 0;
+
+ if (ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0, false) != 1)
+ return 0;
+
+ step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 4, 32, 0, false);
+ mix = ah->ah_gain.g_step->gos_param[0];
+
+ switch (mix) {
+ case 3:
+ ah->ah_gain.g_f_corr = step * 2;
+ break;
+ case 2:
+ ah->ah_gain.g_f_corr = (step - 5) * 2;
+ break;
+ case 1:
+ ah->ah_gain.g_f_corr = step;
+ break;
+ default:
+ ah->ah_gain.g_f_corr = 0;
+ break;
+ }
+
+ return ah->ah_gain.g_f_corr;
+}
+
+static bool ath5k_hw_rfregs_gain_readback(struct ath5k_hw *ah)
+{
+ u32 step, mix, level[4];
+ u32 *rf;
+
+ if (ah->ah_rf_banks == NULL)
+ return false;
+
+ rf = ah->ah_rf_banks;
+
+ if (ah->ah_radio == AR5K_RF5111) {
+ step = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 6, 37, 0,
+ false);
+ level[0] = 0;
+ level[1] = (step == 0x3f) ? 0x32 : step + 4;
+ level[2] = (step != 0x3f) ? 0x40 : level[0];
+ level[3] = level[2] + 0x32;
+
+ ah->ah_gain.g_high = level[3] -
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5);
+ ah->ah_gain.g_low = level[0] +
+ (step == 0x3f ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0);
+ } else {
+ mix = ath5k_hw_rfregs_op(rf, ah->ah_offset[7], 0, 1, 36, 0,
+ false);
+ level[0] = level[2] = 0;
+
+ if (mix == 1) {
+ level[1] = level[3] = 83;
+ } else {
+ level[1] = level[3] = 107;
+ ah->ah_gain.g_high = 55;
+ }
+ }
+
+ return (ah->ah_gain.g_current >= level[0] &&
+ ah->ah_gain.g_current <= level[1]) ||
+ (ah->ah_gain.g_current >= level[2] &&
+ ah->ah_gain.g_current <= level[3]);
+}
+
+static s32 ath5k_hw_rfregs_gain_adjust(struct ath5k_hw *ah)
+{
+ const struct ath5k_gain_opt *go;
+ int ret = 0;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ go = &rfgain_opt_5111;
+ break;
+ case AR5K_RF5112:
+ case AR5K_RF5413: /* ??? */
+ go = &rfgain_opt_5112;
+ break;
+ default:
+ return 0;
+ }
+
+ ah->ah_gain.g_step = &go->go_step[ah->ah_gain.g_step_idx];
+
+ if (ah->ah_gain.g_current >= ah->ah_gain.g_high) {
+ if (ah->ah_gain.g_step_idx == 0)
+ return -1;
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target >= ah->ah_gain.g_high &&
+ ah->ah_gain.g_step_idx > 0;
+ ah->ah_gain.g_step =
+ &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain -
+ ah->ah_gain.g_step->gos_gain);
+
+ ret = 1;
+ goto done;
+ }
+
+ if (ah->ah_gain.g_current <= ah->ah_gain.g_low) {
+ if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1))
+ return -2;
+ for (ah->ah_gain.g_target = ah->ah_gain.g_current;
+ ah->ah_gain.g_target <= ah->ah_gain.g_low &&
+ ah->ah_gain.g_step_idx < go->go_steps_count-1;
+ ah->ah_gain.g_step =
+ &go->go_step[ah->ah_gain.g_step_idx])
+ ah->ah_gain.g_target -= 2 *
+ (go->go_step[++ah->ah_gain.g_step_idx].gos_gain -
+ ah->ah_gain.g_step->gos_gain);
+
+ ret = 2;
+ goto done;
+ }
+
+done:
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ "ret %d, gain step %u, current gain %u, target gain %u\n",
+ ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current,
+ ah->ah_gain.g_target);
+
+ return ret;
+}
+
+/*
+ * Read EEPROM Calibration data, modify RF Banks and Initialize RF5111
+ */
+static int ath5k_hw_rf5111_rfregs(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 *rf;
+ const unsigned int rf_size = ARRAY_SIZE(rfregs_5111);
+ unsigned int i;
+ int obdb = -1, bank = -1;
+ u32 ee_mode;
+
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
+
+ rf = ah->ah_rf_banks;
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+ if (rfregs_5111[i].rf_bank >= AR5K_RF5111_INI_RF_MAX_BANKS) {
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+ return -EINVAL;
+ }
+
+ if (bank != rfregs_5111[i].rf_bank) {
+ bank = rfregs_5111[i].rf_bank;
+ ah->ah_offset[bank] = i;
+ }
+
+ rf[i] = rfregs_5111[i].rf_value[mode];
+ }
+
+ /* Modify bank 0 */
+ if (channel->val & CHANNEL_2GHZ) {
+ if (channel->val & CHANNEL_CCK)
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ obdb = 0;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
+ ee->ee_ob[ee_mode][obdb], 3, 119, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[0],
+ ee->ee_ob[ee_mode][obdb], 3, 122, 0, true))
+ return -EINVAL;
+
+ obdb = 1;
+ /* Modify bank 6 */
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->freq >= 5725 ? 3 :
+ (channel->freq >= 5500 ? 2 :
+ (channel->freq >= 5260 ? 1 :
+ (channel->freq > 4000 ? 0 : -1)));
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_pwd_84, 1, 51, 3, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_pwd_90, 1, 45, 3, true))
+ return -EINVAL;
+ }
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ !ee->ee_xpd[ee_mode], 1, 95, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 4, 96, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
+ ee->ee_ob[ee_mode][obdb] : 0, 3, 104, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6], obdb >= 0 ?
+ ee->ee_db[ee_mode][obdb] : 0, 3, 107, 0, true))
+ return -EINVAL;
+
+ /* Modify bank 7 */
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
+ ee->ee_i_gain[ee_mode], 6, 29, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
+ ee->ee_xpd[ee_mode], 1, 4, 0, true))
+ return -EINVAL;
+
+ /* Write RF values */
+ for (i = 0; i < rf_size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, rf[i], rfregs_5111[i].rf_register);
+ }
+
+ return 0;
+}
+
+/*
+ * Read EEPROM Calibration data, modify RF Banks and Initialize RF5112
+ */
+static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, unsigned int mode)
+{
+ const struct ath5k_ini_rf *rf_ini;
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 *rf;
+ unsigned int rf_size, i;
+ int obdb = -1, bank = -1;
+ u32 ee_mode;
+
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
+
+ rf = ah->ah_rf_banks;
+
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_2112A
+ && !test_bit(MODE_IEEE80211A, ah->ah_capabilities.cap_mode)){
+ rf_ini = rfregs_2112a;
+ rf_size = ARRAY_SIZE(rfregs_5112a);
+ if (mode < 2) {
+ ATH5K_ERR(ah->ah_sc,"invalid channel mode: %i\n",mode);
+ return -EINVAL;
+ }
+ mode = mode - 2; /*no a/turboa modes for 2112*/
+ } else if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) {
+ rf_ini = rfregs_5112a;
+ rf_size = ARRAY_SIZE(rfregs_5112a);
+ } else {
+ rf_ini = rfregs_5112;
+ rf_size = ARRAY_SIZE(rfregs_5112);
+ }
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+ if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+ return -EINVAL;
+ }
+
+ if (bank != rf_ini[i].rf_bank) {
+ bank = rf_ini[i].rf_bank;
+ ah->ah_offset[bank] = i;
+ }
+
+ rf[i] = rf_ini[i].rf_value[mode];
+ }
+
+ /* Modify bank 6 */
+ if (channel->val & CHANNEL_2GHZ) {
+ if (channel->val & CHANNEL_OFDM)
+ ee_mode = AR5K_EEPROM_MODE_11G;
+ else
+ ee_mode = AR5K_EEPROM_MODE_11B;
+ obdb = 0;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 287, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 290, 0, true))
+ return -EINVAL;
+ } else {
+ /* For 11a, Turbo and XR */
+ ee_mode = AR5K_EEPROM_MODE_11A;
+ obdb = channel->freq >= 5725 ? 3 :
+ (channel->freq >= 5500 ? 2 :
+ (channel->freq >= 5260 ? 1 :
+ (channel->freq > 4000 ? 0 : -1)));
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 279, 0, true))
+ return -EINVAL;
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_ob[ee_mode][obdb], 3, 282, 0, true))
+ return -EINVAL;
+ }
+
+ ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 2, 270, 0, true);
+ ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_x_gain[ee_mode], 2, 257, 0, true);
+
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[6],
+ ee->ee_xpd[ee_mode], 1, 302, 0, true))
+ return -EINVAL;
+
+ /* Modify bank 7 */
+ if (!ath5k_hw_rfregs_op(rf, ah->ah_offset[7],
+ ee->ee_i_gain[ee_mode], 6, 14, 0, true))
+ return -EINVAL;
+
+ /* Write RF values */
+ for (i = 0; i < rf_size; i++)
+ ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register);
+
+ return 0;
+}
+
+/*
+ * Initialize RF5413/5414
+ */
+static int ath5k_hw_rf5413_rfregs(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, unsigned int mode)
+{
+ const struct ath5k_ini_rf *rf_ini;
+ u32 *rf;
+ unsigned int rf_size, i;
+ int bank = -1;
+
+ AR5K_ASSERT_ENTRY(mode, AR5K_INI_VAL_MAX);
+
+ rf = ah->ah_rf_banks;
+
+ rf_ini = rfregs_5413;
+ rf_size = ARRAY_SIZE(rfregs_5413);
+
+ /* Copy values to modify them */
+ for (i = 0; i < rf_size; i++) {
+ if (rf_ini[i].rf_bank >= AR5K_RF5112_INI_RF_MAX_BANKS) {
+ ATH5K_ERR(ah->ah_sc, "invalid bank\n");
+ return -EINVAL;
+ }
+
+ if (bank != rf_ini[i].rf_bank) {
+ bank = rf_ini[i].rf_bank;
+ ah->ah_offset[bank] = i;
+ }
+
+ rf[i] = rf_ini[i].rf_value[mode];
+ }
+
+ /*
+ * After compairing dumps from different cards
+ * we get the same RF_BUFFER settings (diff returns
+ * 0 lines). It seems that RF_BUFFER settings are static
+ * and are written unmodified (no EEPROM stuff
+ * is used because calibration data would be
+ * different between different cards and would result
+ * different RF_BUFFER settings)
+ */
+
+ /* Write RF values */
+ for (i = 0; i < rf_size; i++)
+ ath5k_hw_reg_write(ah, rf[i], rf_ini[i].rf_register);
+
+ return 0;
+}
+
+/*
+ * Initialize RF
+ */
+int ath5k_hw_rfregs(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ unsigned int mode)
+{
+ int (*func)(struct ath5k_hw *, struct ieee80211_channel *, unsigned int);
+ int ret;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ah->ah_rf_banks_size = sizeof(rfregs_5111);
+ func = ath5k_hw_rf5111_rfregs;
+ break;
+ case AR5K_RF5112:
+ if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A)
+ ah->ah_rf_banks_size = sizeof(rfregs_5112a);
+ else
+ ah->ah_rf_banks_size = sizeof(rfregs_5112);
+ func = ath5k_hw_rf5112_rfregs;
+ break;
+ case AR5K_RF5413:
+ ah->ah_rf_banks_size = sizeof(rfregs_5413);
+ func = ath5k_hw_rf5413_rfregs;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (ah->ah_rf_banks == NULL) {
+ /* XXX do extra checks? */
+ ah->ah_rf_banks = kmalloc(ah->ah_rf_banks_size, GFP_KERNEL);
+ if (ah->ah_rf_banks == NULL) {
+ ATH5K_ERR(ah->ah_sc, "out of memory\n");
+ return -ENOMEM;
+ }
+ }
+
+ ret = func(ah, channel, mode);
+ if (!ret)
+ ah->ah_rf_gain = AR5K_RFGAIN_INACTIVE;
+
+ return ret;
+}
+
+int ath5k_hw_rfgain(struct ath5k_hw *ah, unsigned int freq)
+{
+ const struct ath5k_ini_rfgain *ath5k_rfg;
+ unsigned int i, size;
+
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ath5k_rfg = rfgain_5111;
+ size = ARRAY_SIZE(rfgain_5111);
+ break;
+ case AR5K_RF5112:
+ ath5k_rfg = rfgain_5112;
+ size = ARRAY_SIZE(rfgain_5112);
+ break;
+ case AR5K_RF5413:
+ ath5k_rfg = rfgain_5413;
+ size = ARRAY_SIZE(rfgain_5413);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case AR5K_INI_RFGAIN_2GHZ:
+ case AR5K_INI_RFGAIN_5GHZ:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < size; i++) {
+ AR5K_REG_WAIT(i);
+ ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq],
+ (u32)ath5k_rfg[i].rfg_register);
+ }
+
+ return 0;
+}
+
+enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah)
+{
+ u32 data, type;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_rf_banks == NULL || !ah->ah_gain.g_active ||
+ ah->ah_version <= AR5K_AR5211)
+ return AR5K_RFGAIN_INACTIVE;
+
+ if (ah->ah_rf_gain != AR5K_RFGAIN_READ_REQUESTED)
+ goto done;
+
+ data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE);
+
+ if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) {
+ ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S;
+ type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE);
+
+ if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK)
+ ah->ah_gain.g_current += AR5K_GAIN_CCK_PROBE_CORR;
+
+ if (ah->ah_radio >= AR5K_RF5112) {
+ ath5k_hw_rfregs_gainf_corr(ah);
+ ah->ah_gain.g_current =
+ ah->ah_gain.g_current>=ah->ah_gain.g_f_corr ?
+ (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
+ 0;
+ }
+
+ if (ath5k_hw_rfregs_gain_readback(ah) &&
+ AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) &&
+ ath5k_hw_rfregs_gain_adjust(ah))
+ ah->ah_rf_gain = AR5K_RFGAIN_NEED_CHANGE;
+ }
+
+done:
+ return ah->ah_rf_gain;
+}
+
+int ath5k_hw_set_rfgain_opt(struct ath5k_hw *ah)
+{
+ /* Initialize the gain optimization values */
+ switch (ah->ah_radio) {
+ case AR5K_RF5111:
+ ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default;
+ ah->ah_gain.g_step =
+ &rfgain_opt_5111.go_step[ah->ah_gain.g_step_idx];
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 35;
+ ah->ah_gain.g_active = 1;
+ break;
+ case AR5K_RF5112:
+ case AR5K_RF5413: /* ??? */
+ ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default;
+ ah->ah_gain.g_step =
+ &rfgain_opt_5112.go_step[ah->ah_gain.g_step_idx];
+ ah->ah_gain.g_low = 20;
+ ah->ah_gain.g_high = 85;
+ ah->ah_gain.g_active = 1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**************************\
+ PHY/RF channel functions
+\**************************/
+
+/*
+ * Check if a channel is supported
+ */
+bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags)
+{
+ /* Check if the channel is in our supported range */
+ if (flags & CHANNEL_2GHZ) {
+ if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
+ return true;
+ } else if (flags & CHANNEL_5GHZ)
+ if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
+ (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
+ return true;
+
+ return false;
+}
+
+/*
+ * Convertion needed for RF5110
+ */
+static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
+{
+ u32 athchan;
+
+ /*
+ * Convert IEEE channel/MHz to an internal channel value used
+ * by the AR5210 chipset. This has not been verified with
+ * newer chipsets like the AR5212A who have a completely
+ * different RF/PHY part.
+ */
+ athchan = (ath5k_hw_bitswap((channel->chan - 24) / 2, 5) << 1) |
+ (1 << 6) | 0x1;
+
+ return athchan;
+}
+
+/*
+ * Set channel on RF5110
+ */
+static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u32 data;
+
+ /*
+ * Set the channel and wait
+ */
+ data = ath5k_hw_rf5110_chan2athchan(channel);
+ ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0);
+ mdelay(1);
+
+ return 0;
+}
+
+/*
+ * Convertion needed for 5111
+ */
+static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
+ struct ath5k_athchan_2ghz *athchan)
+{
+ int channel;
+
+ /* Cast this value to catch negative channel numbers (>= -19) */
+ channel = (int)ieee;
+
+ /*
+ * Map 2GHz IEEE channel to 5GHz Atheros channel
+ */
+ if (channel <= 13) {
+ athchan->a2_athchan = 115 + channel;
+ athchan->a2_flags = 0x46;
+ } else if (channel == 14) {
+ athchan->a2_athchan = 124;
+ athchan->a2_flags = 0x44;
+ } else if (channel >= 15 && channel <= 26) {
+ athchan->a2_athchan = ((channel - 14) * 4) + 132;
+ athchan->a2_flags = 0x46;
+ } else
+ return -EINVAL;
+
+ return 0;
+}
+
+/*
+ * Set channel on 5111
+ */
+static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ struct ath5k_athchan_2ghz ath5k_channel_2ghz;
+ unsigned int ath5k_channel = channel->chan;
+ u32 data0, data1, clock;
+ int ret;
+
+ /*
+ * Set the channel on the RF5111 radio
+ */
+ data0 = data1 = 0;
+
+ if (channel->val & CHANNEL_2GHZ) {
+ /* Map 2GHz channel to 5GHz Atheros channel ID */
+ ret = ath5k_hw_rf5111_chan2athchan(channel->chan,
+ &ath5k_channel_2ghz);
+ if (ret)
+ return ret;
+
+ ath5k_channel = ath5k_channel_2ghz.a2_athchan;
+ data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff)
+ << 5) | (1 << 4);
+ }
+
+ if (ath5k_channel < 145 || !(ath5k_channel & 1)) {
+ clock = 1;
+ data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) |
+ (clock << 1) | (1 << 10) | 1;
+ } else {
+ clock = 0;
+ data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff)
+ << 2) | (clock << 1) | (1 << 10) | 1;
+ }
+
+ ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8),
+ AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00),
+ AR5K_RF_BUFFER_CONTROL_3);
+
+ return 0;
+}
+
+/*
+ * Set channel on 5112 and newer
+ */
+static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u32 data, data0, data1, data2;
+ u16 c;
+
+ data = data0 = data1 = data2 = 0;
+ c = channel->freq;
+
+ /*
+ * Set the channel on the RF5112 or newer
+ */
+ if (c < 4800) {
+ if (!((c - 2224) % 5)) {
+ data0 = ((2 * (c - 704)) - 3040) / 10;
+ data1 = 1;
+ } else if (!((c - 2192) % 5)) {
+ data0 = ((2 * (c - 672)) - 3040) / 10;
+ data1 = 0;
+ } else
+ return -EINVAL;
+
+ data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8);
+ } else {
+ if (!(c % 20) && c >= 5120) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8);
+ data2 = ath5k_hw_bitswap(3, 2);
+ } else if (!(c % 10)) {
+ data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8);
+ data2 = ath5k_hw_bitswap(2, 2);
+ } else if (!(c % 5)) {
+ data0 = ath5k_hw_bitswap((c - 4800) / 5, 8);
+ data2 = ath5k_hw_bitswap(1, 2);
+ } else
+ return -EINVAL;
+ }
+
+ data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001;
+
+ ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER);
+ ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5);
+
+ return 0;
+}
+
+/*
+ * Set a channel on the radio chip
+ */
+int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
+{
+ int ret;
+
+ /*
+ * Check bounds supported by the PHY
+ * (don't care about regulation restrictions at this point)
+ */
+ if ((channel->freq < ah->ah_capabilities.cap_range.range_2ghz_min ||
+ channel->freq > ah->ah_capabilities.cap_range.range_2ghz_max) &&
+ (channel->freq < ah->ah_capabilities.cap_range.range_5ghz_min ||
+ channel->freq > ah->ah_capabilities.cap_range.range_5ghz_max)) {
+ ATH5K_ERR(ah->ah_sc,
+ "channel out of supported range (%u MHz)\n",
+ channel->freq);
+ return -EINVAL;
+ }
+
+ /*
+ * Set the channel and wait
+ */
+ switch (ah->ah_radio) {
+ case AR5K_RF5110:
+ ret = ath5k_hw_rf5110_channel(ah, channel);
+ break;
+ case AR5K_RF5111:
+ ret = ath5k_hw_rf5111_channel(ah, channel);
+ break;
+ default:
+ ret = ath5k_hw_rf5112_channel(ah, channel);
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ ah->ah_current_channel.freq = channel->freq;
+ ah->ah_current_channel.val = channel->val;
+ ah->ah_turbo = channel->val == CHANNEL_T ? true : false;
+
+ return 0;
+}
+
+/*****************\
+ PHY calibration
+\*****************/
+
+/**
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
+ *
+ * @ah: struct ath5k_hw pointer we are operating on
+ * @freq: the channel frequency, just used for error logging
+ *
+ * This function performs a noise floor calibration of the PHY and waits for
+ * it to complete. Then the noise floor value is compared to some maximum
+ * noise floor we consider valid.
+ *
+ * Note that this is different from what the madwifi HAL does: it reads the
+ * noise floor and afterwards initiates the calibration. Since the noise floor
+ * calibration can take some time to finish, depending on the current channel
+ * use, that avoids the occasional timeout warnings we are seeing now.
+ *
+ * See the following link for an Atheros patent on noise floor calibration:
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+ *
+ */
+int
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+{
+ int ret;
+ unsigned int i;
+ s32 noise_floor;
+
+ /*
+ * Enable noise floor calibration and wait until completion
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_NF, 0, false);
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc,
+ "noise floor calibration timeout (%uMHz)\n", freq);
+ return ret;
+ }
+
+ /* Wait until the noise floor is calibrated and read the value */
+ for (i = 20; i > 0; i--) {
+ mdelay(1);
+ noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+ noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
+ if (noise_floor & AR5K_PHY_NF_ACTIVE) {
+ noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
+
+ if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+ break;
+ }
+ }
+
+ ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+ "noise floor %d\n", noise_floor);
+
+ if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+ ATH5K_ERR(ah->ah_sc,
+ "noise floor calibration failed (%uMHz)\n", freq);
+ return -EIO;
+ }
+
+ ah->ah_noise_floor = noise_floor;
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5110
+ * -Fix BPSK/QAM Constellation (I/Q correction)
+ * -Calculate Noise Floor
+ */
+static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u32 phy_sig, phy_agc, phy_sat, beacon;
+ int ret;
+
+ /*
+ * Disable beacons and RX/TX queues, wait
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210);
+ ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210);
+
+ udelay(2300);
+
+ /*
+ * Set the channel (with AGC turned off)
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ret = ath5k_hw_channel(ah, channel);
+
+ /*
+ * Activate PHY and wait
+ */
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT);
+ mdelay(1);
+
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ if (ret)
+ return ret;
+
+ /*
+ * Calibrate the radio chip
+ */
+
+ /* Remember normal state */
+ phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG);
+ phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE);
+ phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT);
+
+ /* Update radio registers */
+ ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) |
+ AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG);
+
+ ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI |
+ AR5K_PHY_AGCCOARSE_LO)) |
+ AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) |
+ AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE);
+
+ ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT |
+ AR5K_PHY_ADCSAT_THR)) |
+ AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) |
+ AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT);
+
+ udelay(20);
+
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+ udelay(10);
+ ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG);
+ AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE);
+
+ mdelay(1);
+
+ /*
+ * Enable calibration and wait until completion
+ */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL);
+
+ ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+ AR5K_PHY_AGCCTL_CAL, 0, false);
+
+ /* Reset to normal state */
+ ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG);
+ ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE);
+ ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT);
+
+ if (ret) {
+ ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n",
+ channel->freq);
+ return ret;
+ }
+
+ ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
+ if (ret)
+ return ret;
+
+ /*
+ * Re-enable RX/TX and beacons
+ */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210,
+ AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210);
+ ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210);
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration on RF5111/5112
+ */
+static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ u32 i_pwr, q_pwr;
+ s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd;
+ ATH5K_TRACE(ah->ah_sc);
+
+ if (ah->ah_calibration == false ||
+ ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN)
+ goto done;
+
+ ah->ah_calibration = false;
+
+ iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR);
+ i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I);
+ q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q);
+ i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7;
+ q_coffd = q_pwr >> 6;
+
+ if (i_coffd == 0 || q_coffd == 0)
+ goto done;
+
+ i_coff = ((-iq_corr) / i_coffd) & 0x3f;
+ q_coff = (((s32)i_pwr / q_coffd) - 64) & 0x1f;
+
+ /* Commit new IQ value */
+ AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE |
+ ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S));
+
+done:
+ ath5k_hw_noise_floor_calibration(ah, channel->freq);
+
+ /* Request RF gain */
+ if (channel->val & CHANNEL_5GHZ) {
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_max,
+ AR5K_PHY_PAPD_PROBE_TXPOWER) |
+ AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE);
+ ah->ah_rf_gain = AR5K_RFGAIN_READ_REQUESTED;
+ }
+
+ return 0;
+}
+
+/*
+ * Perform a PHY calibration
+ */
+int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel)
+{
+ int ret;
+
+ if (ah->ah_radio == AR5K_RF5110)
+ ret = ath5k_hw_rf5110_calibrate(ah, channel);
+ else
+ ret = ath5k_hw_rf511x_calibrate(ah, channel);
+
+ return ret;
+}
+
+int ath5k_hw_phy_disable(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /*Just a try M.F.*/
+ ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT);
+
+ return 0;
+}
+
+/********************\
+ Misc PHY functions
+\********************/
+
+/*
+ * Get the PHY Chip revision
+ */
+u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
+{
+ unsigned int i;
+ u32 srev;
+ u16 ret;
+
+ ATH5K_TRACE(ah->ah_sc);
+
+ /*
+ * Set the radio chip access register
+ */
+ switch (chan) {
+ case CHANNEL_2GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
+ break;
+ case CHANNEL_5GHZ:
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+ break;
+ default:
+ return 0;
+ }
+
+ mdelay(2);
+
+ /* ...wait until PHY is ready and read the selected radio revision */
+ ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34));
+
+ for (i = 0; i < 8; i++)
+ ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20));
+
+ if (ah->ah_version == AR5K_AR5210) {
+ srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf;
+ ret = (u16)ath5k_hw_bitswap(srev, 4) + 1;
+ } else {
+ srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff;
+ ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) |
+ ((srev & 0x0f) << 4), 8);
+ }
+
+ /* Reset to the 5GHz mode */
+ ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
+
+ return ret;
+}
+
+void /*TODO:Boundary check*/
+ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /*Just a try M.F.*/
+ if (ah->ah_version != AR5K_AR5210)
+ ath5k_hw_reg_write(ah, ant, AR5K_DEFAULT_ANTENNA);
+}
+
+unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah)
+{
+ ATH5K_TRACE(ah->ah_sc);
+ /*Just a try M.F.*/
+ if (ah->ah_version != AR5K_AR5210)
+ return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA);
+
+ return false; /*XXX: What do we return for 5210 ?*/
+}
+
+/*
+ * TX power setup
+ */
+
+/*
+ * Initialize the tx power table (not fully implemented)
+ */
+static void ath5k_txpower_table(struct ath5k_hw *ah,
+ struct ieee80211_channel *channel, s16 max_power)
+{
+ unsigned int i, min, max, n;
+ u16 txpower, *rates;
+
+ rates = ah->ah_txpower.txp_rates;
+
+ txpower = AR5K_TUNE_DEFAULT_TXPOWER * 2;
+ if (max_power > txpower)
+ txpower = max_power > AR5K_TUNE_MAX_TXPOWER ?
+ AR5K_TUNE_MAX_TXPOWER : max_power;
+
+ for (i = 0; i < AR5K_MAX_RATES; i++)
+ rates[i] = txpower;
+
+ /* XXX setup target powers by rate */
+
+ ah->ah_txpower.txp_min = rates[7];
+ ah->ah_txpower.txp_max = rates[0];
+ ah->ah_txpower.txp_ofdm = rates[0];
+
+ /* Calculate the power table */
+ n = ARRAY_SIZE(ah->ah_txpower.txp_pcdac);
+ min = AR5K_EEPROM_PCDAC_START;
+ max = AR5K_EEPROM_PCDAC_STOP;
+ for (i = 0; i < n; i += AR5K_EEPROM_PCDAC_STEP)
+ ah->ah_txpower.txp_pcdac[i] =
+#ifdef notyet
+ min + ((i * (max - min)) / n);
+#else
+ min;
+#endif
+}
+
+/*
+ * Set transmition power
+ */
+int /*O.K. - txpower_table is unimplemented so this doesn't work*/
+ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
+ unsigned int txpower)
+{
+ bool tpc = ah->ah_txpower.txp_tpc;
+ unsigned int i;
+
+ ATH5K_TRACE(ah->ah_sc);
+ if (txpower > AR5K_TUNE_MAX_TXPOWER) {
+ ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
+ return -EINVAL;
+ }
+
+ /* Reset TX power values */
+ memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
+ ah->ah_txpower.txp_tpc = tpc;
+
+ /* Initialize TX power table */
+ ath5k_txpower_table(ah, channel, txpower);
+
+ /*
+ * Write TX power values
+ */
+ for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) {
+ ath5k_hw_reg_write(ah,
+ ((((ah->ah_txpower.txp_pcdac[(i << 1) + 1] << 8) | 0xff) & 0xffff) << 16) |
+ (((ah->ah_txpower.txp_pcdac[(i << 1) ] << 8) | 0xff) & 0xffff),
+ AR5K_PHY_PCDAC_TXPOWER(i));
+ }
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) |
+ AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) |
+ AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) |
+ AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) |
+ AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) |
+ AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) |
+ AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3);
+
+ ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) |
+ AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) |
+ AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4);
+
+ if (ah->ah_txpower.txp_tpc == true)
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+ else
+ ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX |
+ AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX);
+
+ return 0;
+}
+
+int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power)
+{
+ /*Just a try M.F.*/
+ struct ieee80211_channel *channel = &ah->ah_current_channel;
+
+ ATH5K_TRACE(ah->ah_sc);
+ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER,
+ "changing txpower to %d\n", power);
+
+ return ath5k_hw_txpower(ah, channel, power);
+}
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
new file mode 100644
index 000000000000..2f41c8398602
--- /dev/null
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -0,0 +1,1987 @@
+/*
+ * Copyright (c) 2007 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2004, 2005, 2006, 2007 Reyk Floeter <reyk@openbsd.org>
+ * Copyright (c) 2007 Michael Taylor <mike.taylor@apprion.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/*
+ * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k
+ * maintained by Reyk Floeter
+ *
+ * I tried to document those registers by looking at ar5k code, some
+ * 802.11 (802.11e mostly) papers and by reading various public available
+ * Atheros presentations and papers like these:
+ *
+ * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf
+ * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf
+ *
+ * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf
+ */
+
+
+
+/*====MAC DMA REGISTERS====*/
+
+/*
+ * AR5210-Specific TXDP registers
+ * 5210 has only 2 transmit queues so no DCU/QCU, just
+ * 2 transmit descriptor pointers...
+ */
+#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */
+#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */
+
+/*
+ * Mac Control Register
+ */
+#define AR5K_CR 0x0008 /* Register Address */
+#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */
+#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */
+#define AR5K_CR_RXE 0x00000004 /* RX Enable */
+#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */
+#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */
+#define AR5K_CR_RXD 0x00000020 /* RX Disable */
+#define AR5K_CR_SWI 0x00000040
+
+/*
+ * RX Descriptor Pointer register
+ */
+#define AR5K_RXDP 0x000c
+
+/*
+ * Configuration and status register
+ */
+#define AR5K_CFG 0x0014 /* Register Address */
+#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */
+#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer (?) */
+#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */
+#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer (?) */
+#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register values (?) */
+#define AR5K_CFG_ADHOC 0x00000020 /* [5211+] */
+#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */
+#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */
+#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (?) */
+#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */
+#define AR5K_CFG_TXCNT_S 11
+#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */
+#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */
+#define AR5K_CFG_PCI_THRES 0x00060000 /* [5211+] */
+#define AR5K_CFG_PCI_THRES_S 17
+
+/*
+ * Interrupt enable register
+ */
+#define AR5K_IER 0x0024 /* Register Address */
+#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */
+#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */
+
+
+/*
+ * 0x0028 is Beacon Control Register on 5210
+ * and first RTS duration register on 5211
+ */
+
+/*
+ * Beacon control register [5210]
+ */
+#define AR5K_BCR 0x0028 /* Register Address */
+#define AR5K_BCR_AP 0x00000000 /* AP mode */
+#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */
+#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */
+#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */
+#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */
+#define AR5K_BCR_BCGET 0x00000010
+
+/*
+ * First RTS duration register [5211]
+ */
+#define AR5K_RTSD0 0x0028 /* Register Address */
+#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */
+#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */
+#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/
+#define AR5K_RTSD0_9_S 8
+#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/
+#define AR5K_RTSD0_12_S 16
+#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/
+#define AR5K_RTSD0_18_S 24
+
+
+/*
+ * 0x002c is Beacon Status Register on 5210
+ * and second RTS duration register on 5211
+ */
+
+/*
+ * Beacon status register [5210]
+ *
+ * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR
+ * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning
+ * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR).
+ * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i
+ * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what
+ * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
+ */
+#define AR5K_BSR 0x002c /* Register Address */
+#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */
+#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */
+#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */
+#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */
+#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */
+#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */
+#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */
+#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */
+#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */
+#define AR5K_BSR_SWBA_CNT 0x00ff0000
+
+/*
+ * Second RTS duration register [5211]
+ */
+#define AR5K_RTSD1 0x002c /* Register Address */
+#define AR5K_RTSD1_24 0x000000ff /* 24Mb */
+#define AR5K_RTSD1_24_S 0
+#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */
+#define AR5K_RTSD1_36_S 8
+#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */
+#define AR5K_RTSD1_48_S 16
+#define AR5K_RTSD1_54 0xff000000 /* 54Mb */
+#define AR5K_RTSD1_54_S 24
+
+
+/*
+ * Transmit configuration register
+ */
+#define AR5K_TXCFG 0x0030 /* Register Address */
+#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size */
+#define AR5K_TXCFG_SDMAMR_S 0
+#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */
+#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */
+#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */
+#define AR5K_TXCFG_TXFULL_S 4
+#define AR5K_TXCFG_TXFULL_0B 0x00000000
+#define AR5K_TXCFG_TXFULL_64B 0x00000010
+#define AR5K_TXCFG_TXFULL_128B 0x00000020
+#define AR5K_TXCFG_TXFULL_192B 0x00000030
+#define AR5K_TXCFG_TXFULL_256B 0x00000040
+#define AR5K_TXCFG_TXCONT_EN 0x00000080
+#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */
+#define AR5K_TXCFG_JUMBO_TXE 0x00000400 /* Enable jumbo frames transmition (?) [5211+] */
+#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */
+#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */
+#define AR5K_TXCFG_RDY_DIS 0x00004000 /* [5211+] */
+
+/*
+ * Receive configuration register
+ */
+#define AR5K_RXCFG 0x0034 /* Register Address */
+#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size */
+#define AR5K_RXCFG_SDMAMW_S 0
+#define AR5K_RXCFG_DEF_ANTENNA 0x00000008 /* Default antenna */
+#define AR5K_RXCFG_ZLFDMA 0x00000010 /* Zero-length DMA */
+#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo frames reception (?) [5211+] */
+#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames (?) [5211+] */
+
+/*
+ * Receive jumbo descriptor last address register
+ * Only found in 5211 (?)
+ */
+#define AR5K_RXJLA 0x0038
+
+/*
+ * MIB control register
+ */
+#define AR5K_MIBC 0x0040 /* Register Address */
+#define AR5K_MIBC_COW 0x00000001
+#define AR5K_MIBC_FMC 0x00000002 /* Freeze Mib Counters (?) */
+#define AR5K_MIBC_CMC 0x00000004 /* Clean Mib Counters (?) */
+#define AR5K_MIBC_MCS 0x00000008
+
+/*
+ * Timeout prescale register
+ */
+#define AR5K_TOPS 0x0044
+#define AR5K_TOPS_M 0x0000ffff /* [5211+] (?) */
+
+/*
+ * Receive timeout register (no frame received)
+ */
+#define AR5K_RXNOFRM 0x0048
+#define AR5K_RXNOFRM_M 0x000003ff /* [5211+] (?) */
+
+/*
+ * Transmit timeout register (no frame sent)
+ */
+#define AR5K_TXNOFRM 0x004c
+#define AR5K_TXNOFRM_M 0x000003ff /* [5211+] (?) */
+#define AR5K_TXNOFRM_QCU 0x000ffc00 /* [5211+] (?) */
+
+/*
+ * Receive frame gap timeout register
+ */
+#define AR5K_RPGTO 0x0050
+#define AR5K_RPGTO_M 0x000003ff /* [5211+] (?) */
+
+/*
+ * Receive frame count limit register
+ */
+#define AR5K_RFCNT 0x0054
+#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */
+#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */
+
+/*
+ * Misc settings register
+ */
+#define AR5K_MISC 0x0058 /* Register Address */
+#define AR5K_MISC_DMA_OBS_M 0x000001e0
+#define AR5K_MISC_DMA_OBS_S 5
+#define AR5K_MISC_MISC_OBS_M 0x00000e00
+#define AR5K_MISC_MISC_OBS_S 9
+#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000
+#define AR5K_MISC_MAC_OBS_LSB_S 12
+#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000
+#define AR5K_MISC_MAC_OBS_MSB_S 15
+#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */
+#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */
+
+/*
+ * QCU/DCU clock gating register (5311)
+ */
+#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */
+#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */
+#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */
+
+/*
+ * Interrupt Status Registers
+ *
+ * For 5210 there is only one status register but for
+ * 5211/5212 we have one primary and 4 secondary registers.
+ * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212.
+ * Most of these bits are common for all chipsets.
+ */
+#define AR5K_ISR 0x001c /* Register Address [5210] */
+#define AR5K_PISR 0x0080 /* Register Address [5211+] */
+#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */
+#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */
+#define AR5K_ISR_RXERR 0x00000004 /* Receive error */
+#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */
+#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */
+#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */
+#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */
+#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */
+#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */
+#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */
+#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */
+#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */
+#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */
+#define AR5K_ISR_SWI 0x00002000 /* Software interrupt (?) */
+#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */
+#define AR5K_ISR_RXKCM 0x00008000
+#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */
+#define AR5K_ISR_BRSSI 0x00020000
+#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */
+#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_ISR_MCABT 0x00100000 /* [5210] */
+#define AR5K_ISR_RXCHIRP 0x00200000 /* [5212+] */
+#define AR5K_ISR_SSERR 0x00200000 /* [5210] */
+#define AR5K_ISR_DPERR 0x00400000 /* [5210] */
+#define AR5K_ISR_TIM 0x00800000 /* [5210] */
+#define AR5K_ISR_BCNMISC 0x00800000 /* [5212+] */
+#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill)*/
+#define AR5K_ISR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
+#define AR5K_ISR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
+#define AR5K_ISR_QTRIG 0x08000000 /* [5211+] */
+
+/*
+ * Secondary status registers [5211+] (0 - 4)
+ *
+ * I guess from the names that these give the status for each
+ * queue, that's why only masks are defined here, haven't got
+ * any info about them (couldn't find them anywhere in ar5k code).
+ */
+#define AR5K_SISR0 0x0084 /* Register Address [5211+] */
+#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+
+#define AR5K_SISR1 0x0088 /* Register Address [5211+] */
+#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+
+#define AR5K_SISR2 0x008c /* Register Address [5211+] */
+#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SISR2_MCABT 0x00100000
+#define AR5K_SISR2_SSERR 0x00200000
+#define AR5K_SISR2_DPERR 0x00400000
+#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* [5212+] */
+#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* [5212+] */
+#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* [5212+] */
+#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */
+
+#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
+#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+
+#define AR5K_SISR4 0x0094 /* Register Address [5211+] */
+#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */
+
+/*
+ * Shadow read-and-clear interrupt status registers [5211+]
+ */
+#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */
+#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */
+#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */
+#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */
+#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */
+#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */
+
+/*
+ * Interrupt Mask Registers
+ *
+ * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
+ * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match.
+ */
+#define AR5K_IMR 0x0020 /* Register Address [5210] */
+#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */
+#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/
+#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/
+#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/
+#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/
+#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/
+#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/
+#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/
+#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/
+#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/
+#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/
+#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/
+#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/
+#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/
+#define AR5K_IMR_SWI 0x00002000
+#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/
+#define AR5K_IMR_RXKCM 0x00008000
+#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/
+#define AR5K_IMR_BRSSI 0x00020000
+#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/
+#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */
+#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */
+#define AR5K_IMR_MCABT 0x00100000 /* [5210] */
+#define AR5K_IMR_RXCHIRP 0x00200000 /* [5212+]*/
+#define AR5K_IMR_SSERR 0x00200000 /* [5210] */
+#define AR5K_IMR_DPERR 0x00400000 /* [5210] */
+#define AR5K_IMR_TIM 0x00800000 /* [5211+] */
+#define AR5K_IMR_BCNMISC 0x00800000 /* [5212+] */
+#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/
+#define AR5K_IMR_QCBRORN 0x02000000 /* CBR overrun (?) [5211+] */
+#define AR5K_IMR_QCBRURN 0x04000000 /* CBR underrun (?) [5211+] */
+#define AR5K_IMR_QTRIG 0x08000000 /* [5211+] */
+
+/*
+ * Secondary interrupt mask registers [5211+] (0 - 4)
+ */
+#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */
+#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */
+#define AR5K_SIMR0_QCU_TXOK_S 0
+#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */
+#define AR5K_SIMR0_QCU_TXDESC_S 16
+
+#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */
+#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */
+#define AR5K_SIMR1_QCU_TXERR_S 0
+#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */
+#define AR5K_SIMR1_QCU_TXEOL_S 16
+
+#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */
+#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */
+#define AR5K_SIMR2_QCU_TXURN_S 0
+#define AR5K_SIMR2_MCABT 0x00100000
+#define AR5K_SIMR2_SSERR 0x00200000
+#define AR5K_SIMR2_DPERR 0x00400000
+#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */
+#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */
+#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* [5212+] */
+#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* [5212+] */
+#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* [5212+] */
+#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */
+
+#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */
+#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
+#define AR5K_SIMR3_QCBRORN_S 0
+#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
+#define AR5K_SIMR3_QCBRURN_S 16
+
+#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */
+#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */
+#define AR5K_SIMR4_QTRIG_S 0
+
+
+/*
+ * Decompression mask registers [5212+]
+ */
+#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (?)*/
+#define AR5K_DCM_DATA 0x0404 /*Decompression mask data (?)*/
+
+/*
+ * Decompression configuration registers [5212+]
+ */
+#define AR5K_DCCFG 0x0420
+
+/*
+ * Compression configuration registers [5212+]
+ */
+#define AR5K_CCFG 0x0600
+#define AR5K_CCFG_CUP 0x0604
+
+/*
+ * Compression performance counter registers [5212+]
+ */
+#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */
+#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/
+#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */
+#define AR5K_CPC3 0x061c /* Compression performance counter 3 */
+#define AR5K_CPCORN 0x0620 /* Compression performance overrun (?) */
+
+
+/*
+ * Queue control unit (QCU) registers [5211+]
+ *
+ * Card has 12 TX Queues but i see that only 0-9 are used (?)
+ * both in binary HAL (see ah.h) and ar5k. Each queue has it's own
+ * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate)
+ * configuration register (0x08c0 - 0x08ec), a ready time configuration
+ * register (0x0900 - 0x092c), a misc configuration register (0x09c0 -
+ * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some
+ * global registers, QCU transmit enable/disable and "one shot arm (?)"
+ * set/clear, which contain status for all queues (we shift by 1 for each
+ * queue). To access these registers easily we define some macros here
+ * that are used inside HAL. For more infos check out *_tx_queue functs.
+ *
+ * TODO: Boundary checking on macros (here?)
+ */
+
+/*
+ * Generic QCU Register access macros
+ */
+#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r)
+#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q))
+#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q))
+
+/*
+ * QCU Transmit descriptor pointer registers
+ */
+#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */
+#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q)
+
+/*
+ * QCU Transmit enable register
+ */
+#define AR5K_QCU_TXE 0x0840
+#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q)
+#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q)
+
+/*
+ * QCU Transmit disable register
+ */
+#define AR5K_QCU_TXD 0x0880
+#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q)
+#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q)
+
+/*
+ * QCU Constant Bit Rate configuration registers
+ */
+#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */
+#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */
+#define AR5K_QCU_CBRCFG_INTVAL_S 0
+#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */
+#define AR5K_QCU_CBRCFG_ORN_THRES_S 24
+#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q)
+
+/*
+ * QCU Ready time configuration registers
+ */
+#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */
+#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */
+#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0
+#define AR5K_QCU_RDYTIMECFG_DURATION 0x00ffffff /* Ready time duration mask */
+#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */
+#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q)
+
+/*
+ * QCU one shot arm set registers
+ */
+#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */
+#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff
+
+/*
+ * QCU one shot arm clear registers
+ */
+#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */
+#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff
+
+/*
+ * QCU misc registers
+ */
+#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */
+#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */
+#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */
+#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */
+#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated (?) */
+#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* Time gated (?) */
+#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated (?) */
+#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */
+#define AR5K_QCU_MISC_CBREXP 0x00000020 /* CBR expired (normal queue) */
+#define AR5K_QCU_MISC_CBREXP_BCN 0x00000040 /* CBR expired (beacon queue) */
+#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Beacons enabled */
+#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR threshold enabled (?) */
+#define AR5K_QCU_MISC_TXE 0x00000200 /* TXE reset when RDYTIME enalbed (?) */
+#define AR5K_QCU_MISC_CBR 0x00000400 /* CBR threshold reset (?) */
+#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU reset (?) */
+#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q)
+
+
+/*
+ * QCU status registers
+ */
+#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */
+#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */
+#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter (?) */
+#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q)
+
+/*
+ * QCU ready time shutdown register
+ */
+#define AR5K_QCU_RDYTIMESHDN 0x0a40
+#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff
+
+/*
+ * QCU compression buffer base registers [5212+]
+ */
+#define AR5K_QCU_CBB_SELECT 0x0b00
+#define AR5K_QCU_CBB_ADDR 0x0b04
+
+/*
+ * QCU compression buffer configuration register [5212+]
+ */
+#define AR5K_QCU_CBCFG 0x0b08
+
+
+
+/*
+ * Distributed Coordination Function (DCF) control unit (DCU)
+ * registers [5211+]
+ *
+ * These registers control the various characteristics of each queue
+ * for 802.11e (WME) combatibility so they go together with
+ * QCU registers in pairs. For each queue we have a QCU mask register,
+ * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c),
+ * a retry limit register (0x1080 - 0x10ac), a channel time register
+ * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and
+ * a sequence number register (0x1140 - 0x116c). It seems that "global"
+ * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k).
+ * We use the same macros here for easier register access.
+ *
+ */
+
+/*
+ * DCU QCU mask registers
+ */
+#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */
+#define AR5K_DCU_QCUMASK_M 0x000003ff
+#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q)
+
+/*
+ * DCU local Inter Frame Space settings register
+ */
+#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */
+#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MIN_S 0
+#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */
+#define AR5K_DCU_LCL_IFS_CW_MAX_S 10
+#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */
+#define AR5K_DCU_LCL_IFS_AIFS_S 20
+#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q)
+
+/*
+ * DCU retry limit registers
+ */
+#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */
+#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */
+#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
+
+/*
+ * DCU channel time registers
+ */
+#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */
+#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */
+#define AR5K_DCU_CHAN_TIME_DUR_S 0
+#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */
+#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q)
+
+/*
+ * DCU misc registers [5211+]
+ *
+ * For some of the registers i couldn't find in the code
+ * (only backoff stuff is there realy) i tried to match the
+ * names with 802.11e parameters etc, so i guess VIRTCOL here
+ * means Virtual Collision and HCFPOLL means Hybrid Coordination
+ * factor Poll (CF- Poll). Arbiter lockout control controls the
+ * behaviour on low priority queues when we have multiple queues
+ * with pending frames. Intra-frame lockout means we wait until
+ * the queue's current frame transmits (with post frame backoff and bursting)
+ * before we transmit anything else and global lockout means we
+ * wait for the whole queue to finish before higher priority queues
+ * can transmit (this is used on beacon and CAB queues).
+ * No lockout means there is no special handling.
+ */
+#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */
+#define AR5K_DCU_MISC_BACKOFF 0x000007ff /* Mask for backoff setting (?) */
+#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */
+#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll (?) */
+#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff (?) */
+#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch (?) */
+#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */
+#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0
+#define AR5K_DCU_MISC_VIRTCOL_MODIFIED 1
+#define AR5K_DCU_MISC_VIRTCOL_IGNORE 2
+#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Beacon enable (?) */
+#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17
+#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */
+#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */
+#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000
+#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment (?) */
+#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff (?) */
+#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision policy (?) */
+#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000
+#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */
+#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q)
+
+/*
+ * DCU frame sequence number registers
+ */
+#define AR5K_DCU_SEQNUM_BASE 0x1140
+#define AR5K_DCU_SEQNUM_M 0x00000fff
+#define AR5K_QUEUE_DFS_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q)
+
+/*
+ * DCU global IFS SIFS registers
+ */
+#define AR5K_DCU_GBL_IFS_SIFS 0x1030
+#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS slot interval registers
+ */
+#define AR5K_DCU_GBL_IFS_SLOT 0x1070
+#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff
+
+/*
+ * DCU global IFS EIFS registers
+ */
+#define AR5K_DCU_GBL_IFS_EIFS 0x10b0
+#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff
+
+/*
+ * DCU global IFS misc registers
+ */
+#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */
+#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007
+#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode (?) */
+#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask (?) */
+#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00
+#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000
+
+/*
+ * DCU frame prefetch control register
+ */
+#define AR5K_DCU_FP 0x1230
+
+/*
+ * DCU transmit pause control/status register
+ */
+#define AR5K_DCU_TXP 0x1270 /* Register Address */
+#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask (?) */
+#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status (?) */
+
+/*
+ * DCU transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER 0x1038
+
+/*
+ * DCU clear transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_CLR 0x143c
+
+/*
+ * DCU set transmit filter register
+ */
+#define AR5K_DCU_TX_FILTER_SET 0x147c
+
+/*
+ * Reset control register
+ *
+ * 4 and 8 are not used in 5211/5212 and
+ * 2 means "baseband reset" on 5211/5212.
+ */
+#define AR5K_RESET_CTL 0x4000 /* Register Address */
+#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */
+#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */
+#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */
+#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */
+#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */
+#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */
+#define AR5K_RESET_CTL_CHIP (AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA | \
+ AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY)
+
+/*
+ * Sleep control register
+ */
+#define AR5K_SLEEP_CTL 0x4004 /* Register Address */
+#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */
+#define AR5K_SLEEP_CTL_SLDUR_S 0
+#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */
+#define AR5K_SLEEP_CTL_SLE_S 16
+#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */
+#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */
+#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000
+#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */
+
+/*
+ * Interrupt pending register
+ */
+#define AR5K_INTPEND 0x4008
+#define AR5K_INTPEND_M 0x00000001
+
+/*
+ * Sleep force register
+ */
+#define AR5K_SFR 0x400c
+#define AR5K_SFR_M 0x00000001
+
+/*
+ * PCI configuration register
+ */
+#define AR5K_PCICFG 0x4010 /* Register Address */
+#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */
+#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */
+#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */
+#define AR5K_PCICFG_EESIZE_S 3
+#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */
+#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */
+#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */
+#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size (?) [5211+] */
+#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */
+#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */
+#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */
+#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */
+#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */
+#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix (?) */
+#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep (?) */
+#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */
+#define AR5K_PCICFG_SL_INPEN 0x00002800 /* Sleep even whith pending interrupts (?) */
+#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */
+#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */
+#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */
+#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */
+#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */
+#define AR5K_PCICFG_LEDBLINK 0x00700000
+#define AR5K_PCICFG_LEDBLINK_S 20
+#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slow led blink rate (?) [5211+] */
+#define AR5K_PCICFG_LEDSTATE \
+ (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \
+ AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW)
+
+/*
+ * "General Purpose Input/Output" (GPIO) control register
+ *
+ * I'm not sure about this but after looking at the code
+ * for all chipsets here is what i got.
+ *
+ * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits)
+ * Mode 0 -> always input
+ * Mode 1 -> output when GPIODO for this GPIO is set to 0
+ * Mode 2 -> output when GPIODO for this GPIO is set to 1
+ * Mode 3 -> always output
+ *
+ * For more infos check out get_gpio/set_gpio and
+ * set_gpio_input/set_gpio_output functs.
+ * For more infos on gpio interrupt check out set_gpio_intr.
+ */
+#define AR5K_NUM_GPIO 6
+
+#define AR5K_GPIOCR 0x4014 /* Register Address */
+#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */
+#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is off (?) */
+#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is on */
+#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */
+#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */
+#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */
+#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */
+#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */
+
+/*
+ * "General Purpose Input/Output" (GPIO) data output register
+ */
+#define AR5K_GPIODO 0x4018
+
+/*
+ * "General Purpose Input/Output" (GPIO) data input register
+ */
+#define AR5K_GPIODI 0x401c
+#define AR5K_GPIODI_M 0x0000002f
+
+
+/*
+ * Silicon revision register
+ */
+#define AR5K_SREV 0x4020 /* Register Address */
+#define AR5K_SREV_REV 0x0000000f /* Mask for revision */
+#define AR5K_SREV_REV_S 0
+#define AR5K_SREV_VER 0x000000ff /* Mask for version */
+#define AR5K_SREV_VER_S 4
+
+
+
+/*====EEPROM REGISTERS====*/
+
+/*
+ * EEPROM access registers
+ *
+ * Here we got a difference between 5210/5211-12
+ * read data register for 5210 is at 0x6800 and
+ * status register is at 0x6c00. There is also
+ * no eeprom command register on 5210 and the
+ * offsets are different.
+ *
+ * To read eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * read AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * 5211 - write offset to AR5K_EEPROM_BASE
+ * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ * and read eeprom data register.
+ *
+ * To write eeprom data for a specific offset:
+ * 5210 - enable eeprom access (AR5K_PCICFG_EEAE)
+ * write data to AR5K_EEPROM_BASE +(4 * offset)
+ * check the eeprom status register
+ * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD
+ * 5212 write offset to AR5K_EEPROM_BASE
+ * write data to data register
+ * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD
+ * check the eeprom status register
+ *
+ * For more infos check eeprom_* functs and the ar5k.c
+ * file posted in madwifi-devel mailing list.
+ * http://sourceforge.net/mailarchive/message.php?msg_id=8966525
+ *
+ */
+#define AR5K_EEPROM_BASE 0x6000
+
+/*
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
+ */
+#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
+#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
+#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
+#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
+#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
+
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
+#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
+#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
+#define AR5K_EEPROM_INFO_CKSUM 0xffff
+#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n))
+
+#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */
+#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */
+#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
+#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
+#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
+#define AR5K_EEPROM_VERSION_4_3 0x4003
+#define AR5K_EEPROM_VERSION_4_4 0x4004
+#define AR5K_EEPROM_VERSION_4_5 0x4005
+#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
+#define AR5K_EEPROM_VERSION_4_7 0x3007
+
+#define AR5K_EEPROM_MODE_11A 0
+#define AR5K_EEPROM_MODE_11B 1
+#define AR5K_EEPROM_MODE_11G 2
+
+#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */
+#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
+#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
+#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
+#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
+#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
+
+#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
+#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002
+#define AR5K_EEPROM_RFKILL_POLARITY_S 1
+
+/* Newer EEPROMs are using a different offset */
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
+ (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
+
+#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
+
+/* calibration settings */
+#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
+#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
+#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
+#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
+
+/* [3.1 - 3.3] */
+#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
+#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 0x00c4
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+#define AR5K_EEPROM_MISC1 0x00c5
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+
+/*
+ * EEPROM data register
+ */
+#define AR5K_EEPROM_DATA_5211 0x6004
+#define AR5K_EEPROM_DATA_5210 0x6800
+#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211)
+
+/*
+ * EEPROM command register
+ */
+#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */
+#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */
+#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */
+#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */
+
+/*
+ * EEPROM status register
+ */
+#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */
+#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */
+#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211)
+#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */
+#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */
+#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */
+#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */
+
+/*
+ * EEPROM config register (?)
+ */
+#define AR5K_EEPROM_CFG 0x6010
+
+
+
+/*
+ * Protocol Control Unit (PCU) registers
+ */
+/*
+ * Used for checking initial register writes
+ * during channel reset (see reset func)
+ */
+#define AR5K_PCU_MIN 0x8000
+#define AR5K_PCU_MAX 0x8fff
+
+/*
+ * First station id register (MAC address in lower 32 bits)
+ */
+#define AR5K_STA_ID0 0x8000
+
+/*
+ * Second station id register (MAC address in upper 16 bits)
+ */
+#define AR5K_STA_ID1 0x8004 /* Register Address */
+#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
+#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
+#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting (?) */
+#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */
+#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */
+#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */
+#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/
+#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211)
+#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */
+#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */
+#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS (?) */
+#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS (?) */
+#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate (for ACK/CTS ?) [5211+] */
+
+/*
+ * First BSSID register (MAC address, lower 32bits)
+ */
+#define AR5K_BSS_ID0 0x8008
+
+/*
+ * Second BSSID register (MAC address in upper 16 bits)
+ *
+ * AID: Association ID
+ */
+#define AR5K_BSS_ID1 0x800c
+#define AR5K_BSS_ID1_AID 0xffff0000
+#define AR5K_BSS_ID1_AID_S 16
+
+/*
+ * Backoff slot time register
+ */
+#define AR5K_SLOT_TIME 0x8010
+
+/*
+ * ACK/CTS timeout register
+ */
+#define AR5K_TIME_OUT 0x8014 /* Register Address */
+#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */
+#define AR5K_TIME_OUT_ACK_S 0
+#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */
+#define AR5K_TIME_OUT_CTS_S 16
+
+/*
+ * RSSI threshold register
+ */
+#define AR5K_RSSI_THR 0x8018 /* Register Address */
+#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */
+#define AR5K_RSSI_THR_BMISS_5210_S 8
+#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */
+#define AR5K_RSSI_THR_BMISS_5211_S 8
+#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211)
+#define AR5K_RSSI_THR_BMISS_S 8
+
+/*
+ * 5210 has more PCU registers because there is no QCU/DCU
+ * so queue parameters are set here, this way a lot common
+ * registers have different address for 5210. To make things
+ * easier we define a macro based on ah->ah_version for common
+ * registers with different addresses and common flags.
+ */
+
+/*
+ * Retry limit register
+ *
+ * Retry limit register for 5210 (no QCU/DCU so it's done in PCU)
+ */
+#define AR5K_NODCU_RETRY_LMT 0x801c /*Register Address */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */
+#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */
+#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14
+#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */
+#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20
+
+/*
+ * Transmit latency register
+ */
+#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */
+#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */
+#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_USEC_5210 : AR5K_USEC_5211)
+#define AR5K_USEC_1 0x0000007f
+#define AR5K_USEC_1_S 0
+#define AR5K_USEC_32 0x00003f80
+#define AR5K_USEC_32_S 7
+#define AR5K_USEC_TX_LATENCY_5211 0x007fc000
+#define AR5K_USEC_TX_LATENCY_5211_S 14
+#define AR5K_USEC_RX_LATENCY_5211 0x1f800000
+#define AR5K_USEC_RX_LATENCY_5211_S 23
+#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */
+#define AR5K_USEC_TX_LATENCY_5210_S 14
+#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */
+#define AR5K_USEC_RX_LATENCY_5210_S 20
+
+/*
+ * PCU beacon control register
+ */
+#define AR5K_BEACON_5210 0x8024
+#define AR5K_BEACON_5211 0x8020
+#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_5210 : AR5K_BEACON_5211)
+#define AR5K_BEACON_PERIOD 0x0000ffff
+#define AR5K_BEACON_PERIOD_S 0
+#define AR5K_BEACON_TIM 0x007f0000
+#define AR5K_BEACON_TIM_S 16
+#define AR5K_BEACON_ENABLE 0x00800000
+#define AR5K_BEACON_RESET_TSF 0x01000000
+
+/*
+ * CFP period register
+ */
+#define AR5K_CFP_PERIOD_5210 0x8028
+#define AR5K_CFP_PERIOD_5211 0x8024
+#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211)
+
+/*
+ * Next beacon time register
+ */
+#define AR5K_TIMER0_5210 0x802c
+#define AR5K_TIMER0_5211 0x8028
+#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER0_5210 : AR5K_TIMER0_5211)
+
+/*
+ * Next DMA beacon alert register
+ */
+#define AR5K_TIMER1_5210 0x8030
+#define AR5K_TIMER1_5211 0x802c
+#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER1_5210 : AR5K_TIMER1_5211)
+
+/*
+ * Next software beacon alert register
+ */
+#define AR5K_TIMER2_5210 0x8034
+#define AR5K_TIMER2_5211 0x8030
+#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER2_5210 : AR5K_TIMER2_5211)
+
+/*
+ * Next ATIM window time register
+ */
+#define AR5K_TIMER3_5210 0x8038
+#define AR5K_TIMER3_5211 0x8034
+#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TIMER3_5210 : AR5K_TIMER3_5211)
+
+
+/*
+ * 5210 First inter frame spacing register (IFS)
+ */
+#define AR5K_IFS0 0x8040
+#define AR5K_IFS0_SIFS 0x000007ff
+#define AR5K_IFS0_SIFS_S 0
+#define AR5K_IFS0_DIFS 0x007ff800
+#define AR5K_IFS0_DIFS_S 11
+
+/*
+ * 5210 Second inter frame spacing register (IFS)
+ */
+#define AR5K_IFS1 0x8044
+#define AR5K_IFS1_PIFS 0x00000fff
+#define AR5K_IFS1_PIFS_S 0
+#define AR5K_IFS1_EIFS 0x03fff000
+#define AR5K_IFS1_EIFS_S 12
+#define AR5K_IFS1_CS_EN 0x04000000
+
+
+/*
+ * CFP duration register
+ */
+#define AR5K_CFP_DUR_5210 0x8048
+#define AR5K_CFP_DUR_5211 0x8038
+#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211)
+
+/*
+ * Receive filter register
+ * TODO: Get these out of ar5xxx.h on ath5k
+ */
+#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */
+#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */
+#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211)
+#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */
+#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */
+#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */
+#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */
+#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */
+#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */
+#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */
+#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */
+#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */
+#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */
+#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */
+#define AR5K_RX_FILTER_PHYERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212))
+#define AR5K_RX_FILTER_RADARERR \
+ ((ah->ah_version == AR5K_AR5211 ? \
+ AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212))
+
+/*
+ * Multicast filter register (lower 32 bits)
+ */
+#define AR5K_MCAST_FILTER0_5210 0x8050
+#define AR5K_MCAST_FILTER0_5211 0x8040
+#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211)
+
+/*
+ * Multicast filter register (higher 16 bits)
+ */
+#define AR5K_MCAST_FILTER1_5210 0x8054
+#define AR5K_MCAST_FILTER1_5211 0x8044
+#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211)
+
+
+/*
+ * Transmit mask register (lower 32 bits) [5210]
+ */
+#define AR5K_TX_MASK0 0x8058
+
+/*
+ * Transmit mask register (higher 16 bits) [5210]
+ */
+#define AR5K_TX_MASK1 0x805c
+
+/*
+ * Clear transmit mask [5210]
+ */
+#define AR5K_CLR_TMASK 0x8060
+
+/*
+ * Trigger level register (before transmission) [5210]
+ */
+#define AR5K_TRIG_LVL 0x8064
+
+
+/*
+ * PCU control register
+ *
+ * Only DIS_RX is used in the code, the rest i guess are
+ * for tweaking/diagnostics.
+ */
+#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */
+#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */
+#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211)
+#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001
+#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs (?) */
+#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs (?) */
+#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption (?) */
+#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption (?) */
+#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */
+#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */
+#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020
+#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211)
+#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */
+#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040
+#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211)
+#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100
+#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080
+#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211)
+#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200
+#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100
+#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211)
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 /* Scrambler seed (?) */
+#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400
+#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211)
+#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */
+#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */
+#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask (?) */
+#define AR5K_DIAG_SW_SCRAM_SEED_S 10
+#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */
+#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000
+#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000
+#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211)
+#define AR5K_DIAG_SW_OBSPT_M 0x000c0000
+#define AR5K_DIAG_SW_OBSPT_S 18
+
+/*
+ * TSF (clock) register (lower 32 bits)
+ */
+#define AR5K_TSF_L32_5210 0x806c
+#define AR5K_TSF_L32_5211 0x804c
+#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211)
+
+/*
+ * TSF (clock) register (higher 32 bits)
+ */
+#define AR5K_TSF_U32_5210 0x8070
+#define AR5K_TSF_U32_5211 0x8050
+#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211)
+
+/*
+ * Last beacon timestamp register
+ */
+#define AR5K_LAST_TSTP 0x8080
+
+/*
+ * ADDAC test register [5211+]
+ */
+#define AR5K_ADDAC_TEST 0x8054
+#define AR5K_ADDAC_TEST_TXCONT 0x00000001
+
+/*
+ * Default antenna register [5211+]
+ */
+#define AR5K_DEFAULT_ANTENNA 0x8058
+
+
+
+/*
+ * Retry count register [5210]
+ */
+#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */
+#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */
+#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */
+
+/*
+ * Back-off status register [5210]
+ */
+#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */
+#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */
+#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */
+
+
+
+/*
+ * NAV register (current)
+ */
+#define AR5K_NAV_5210 0x808c
+#define AR5K_NAV_5211 0x8084
+#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_NAV_5210 : AR5K_NAV_5211)
+
+/*
+ * RTS success register
+ */
+#define AR5K_RTS_OK_5210 0x8090
+#define AR5K_RTS_OK_5211 0x8088
+#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211)
+
+/*
+ * RTS failure register
+ */
+#define AR5K_RTS_FAIL_5210 0x8094
+#define AR5K_RTS_FAIL_5211 0x808c
+#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211)
+
+/*
+ * ACK failure register
+ */
+#define AR5K_ACK_FAIL_5210 0x8098
+#define AR5K_ACK_FAIL_5211 0x8090
+#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211)
+
+/*
+ * FCS failure register
+ */
+#define AR5K_FCS_FAIL_5210 0x809c
+#define AR5K_FCS_FAIL_5211 0x8094
+#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211)
+
+/*
+ * Beacon count register
+ */
+#define AR5K_BEACON_CNT_5210 0x80a0
+#define AR5K_BEACON_CNT_5211 0x8098
+#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211)
+
+
+/*===5212 Specific PCU registers===*/
+
+/*
+ * XR (eXtended Range) mode register
+ */
+#define AR5K_XRMODE 0x80c0
+#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f
+#define AR5K_XRMODE_POLL_TYPE_S 0
+#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c
+#define AR5K_XRMODE_POLL_SUBTYPE_S 2
+#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080
+#define AR5K_XRMODE_SIFS_DELAY 0x000fff00
+#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000
+#define AR5K_XRMODE_FRAME_HOLD_S 20
+
+/*
+ * XR delay register
+ */
+#define AR5K_XRDELAY 0x80c4
+#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff
+#define AR5K_XRDELAY_SLOT_DELAY_S 0
+#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000
+#define AR5K_XRDELAY_CHIRP_DELAY_S 16
+
+/*
+ * XR timeout register
+ */
+#define AR5K_XRTIMEOUT 0x80c8
+#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff
+#define AR5K_XRTIMEOUT_CHIRP_S 0
+#define AR5K_XRTIMEOUT_POLL_M 0xffff0000
+#define AR5K_XRTIMEOUT_POLL_S 16
+
+/*
+ * XR chirp register
+ */
+#define AR5K_XRCHIRP 0x80cc
+#define AR5K_XRCHIRP_SEND 0x00000001
+#define AR5K_XRCHIRP_GAP 0xffff0000
+
+/*
+ * XR stomp register
+ */
+#define AR5K_XRSTOMP 0x80d0
+#define AR5K_XRSTOMP_TX 0x00000001
+#define AR5K_XRSTOMP_RX_ABORT 0x00000002
+#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00
+
+/*
+ * First enhanced sleep register
+ */
+#define AR5K_SLEEP0 0x80d4
+#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff
+#define AR5K_SLEEP0_NEXT_DTIM_S 0
+#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000
+#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000
+#define AR5K_SLEEP0_CABTO 0xff000000
+#define AR5K_SLEEP0_CABTO_S 24
+
+/*
+ * Second enhanced sleep register
+ */
+#define AR5K_SLEEP1 0x80d8
+#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff
+#define AR5K_SLEEP1_NEXT_TIM_S 0
+#define AR5K_SLEEP1_BEACON_TO 0xff000000
+#define AR5K_SLEEP1_BEACON_TO_S 24
+
+/*
+ * Third enhanced sleep register
+ */
+#define AR5K_SLEEP2 0x80dc
+#define AR5K_SLEEP2_TIM_PER 0x0000ffff
+#define AR5K_SLEEP2_TIM_PER_S 0
+#define AR5K_SLEEP2_DTIM_PER 0xffff0000
+#define AR5K_SLEEP2_DTIM_PER_S 16
+
+/*
+ * BSSID mask registers
+ */
+#define AR5K_BSS_IDM0 0x80e0
+#define AR5K_BSS_IDM1 0x80e4
+
+/*
+ * TX power control (TPC) register
+ */
+#define AR5K_TXPC 0x80e8
+#define AR5K_TXPC_ACK_M 0x0000003f
+#define AR5K_TXPC_ACK_S 0
+#define AR5K_TXPC_CTS_M 0x00003f00
+#define AR5K_TXPC_CTS_S 8
+#define AR5K_TXPC_CHIRP_M 0x003f0000
+#define AR5K_TXPC_CHIRP_S 22
+
+/*
+ * Profile count registers
+ */
+#define AR5K_PROFCNT_TX 0x80ec
+#define AR5K_PROFCNT_RX 0x80f0
+#define AR5K_PROFCNT_RXCLR 0x80f4
+#define AR5K_PROFCNT_CYCLE 0x80f8
+
+/*
+ * TSF parameter register
+ */
+#define AR5K_TSF_PARM 0x8104
+#define AR5K_TSF_PARM_INC_M 0x000000ff
+#define AR5K_TSF_PARM_INC_S 0
+
+/*
+ * PHY error filter register
+ */
+#define AR5K_PHY_ERR_FIL 0x810c
+#define AR5K_PHY_ERR_FIL_RADAR 0x00000020
+#define AR5K_PHY_ERR_FIL_OFDM 0x00020000
+#define AR5K_PHY_ERR_FIL_CCK 0x02000000
+
+/*
+ * Rate duration register
+ */
+#define AR5K_RATE_DUR_BASE 0x8700
+#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2))
+
+/*===5212 end===*/
+
+/*
+ * Key table (WEP) register
+ */
+#define AR5K_KEYTABLE_0_5210 0x9000
+#define AR5K_KEYTABLE_0_5211 0x8800
+#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5))
+#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5))
+#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n))
+#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2))
+#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5)
+#define AR5K_KEYTABLE_TYPE_40 0x00000000
+#define AR5K_KEYTABLE_TYPE_104 0x00000001
+#define AR5K_KEYTABLE_TYPE_128 0x00000003
+#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */
+#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */
+#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */
+#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */
+#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6)
+#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
+#define AR5K_KEYTABLE_VALID 0x00008000
+
+/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
+ * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
+ * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
+ *
+ * Some vendors have introduced bigger WEP keys to address
+ * security vulnerabilities in WEP. This includes:
+ *
+ * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit
+ *
+ * We can expand this if we find ar5k Atheros cards with a larger
+ * key table size.
+ */
+#define AR5K_KEYTABLE_SIZE_5210 64
+#define AR5K_KEYTABLE_SIZE_5211 128
+#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211)
+
+
+/*===PHY REGISTERS===*/
+
+/*
+ * PHY register
+ */
+#define AR5K_PHY_BASE 0x9800
+#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2))
+#define AR5K_PHY_SHIFT_2GHZ 0x00004007
+#define AR5K_PHY_SHIFT_5GHZ 0x00000007
+
+/*
+ * PHY frame control register [5110] /turbo mode register [5111+]
+ *
+ * There is another frame control register for [5111+]
+ * at address 0x9944 (see below) but the 2 first flags
+ * are common here between 5110 frame control register
+ * and [5111+] turbo mode register, so this also works as
+ * a "turbo mode register" for 5110. We treat this one as
+ * a frame control register for 5110 below.
+ */
+#define AR5K_PHY_TURBO 0x9804
+#define AR5K_PHY_TURBO_MODE 0x00000001
+#define AR5K_PHY_TURBO_SHORT 0x00000002
+
+/*
+ * PHY agility command register
+ */
+#define AR5K_PHY_AGC 0x9808
+#define AR5K_PHY_AGC_DISABLE 0x08000000
+
+/*
+ * PHY timing register [5112+]
+ */
+#define AR5K_PHY_TIMING_3 0x9814
+#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000
+#define AR5K_PHY_TIMING_3_DSC_MAN_S 17
+#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000
+#define AR5K_PHY_TIMING_3_DSC_EXP_S 13
+
+/*
+ * PHY chip revision register
+ */
+#define AR5K_PHY_CHIP_ID 0x9818
+
+/*
+ * PHY activation register
+ */
+#define AR5K_PHY_ACT 0x981c
+#define AR5K_PHY_ACT_ENABLE 0x00000001
+#define AR5K_PHY_ACT_DISABLE 0x00000002
+
+/*
+ * PHY signal register
+ */
+#define AR5K_PHY_SIG 0x9858
+#define AR5K_PHY_SIG_FIRSTEP 0x0003f000
+#define AR5K_PHY_SIG_FIRSTEP_S 12
+#define AR5K_PHY_SIG_FIRPWR 0x03fc0000
+#define AR5K_PHY_SIG_FIRPWR_S 18
+
+/*
+ * PHY coarse agility control register
+ */
+#define AR5K_PHY_AGCCOARSE 0x985c
+#define AR5K_PHY_AGCCOARSE_LO 0x00007f80
+#define AR5K_PHY_AGCCOARSE_LO_S 7
+#define AR5K_PHY_AGCCOARSE_HI 0x003f8000
+#define AR5K_PHY_AGCCOARSE_HI_S 15
+
+/*
+ * PHY agility control register
+ */
+#define AR5K_PHY_AGCCTL 0x9860 /* Register address */
+#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */
+#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */
+
+/*
+ * PHY noise floor status register
+ */
+#define AR5K_PHY_NF 0x9864
+#define AR5K_PHY_NF_M 0x000001ff
+#define AR5K_PHY_NF_ACTIVE 0x00000100
+#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M)
+#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1)
+#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9))
+
+/*
+ * PHY ADC saturation register [5110]
+ */
+#define AR5K_PHY_ADCSAT 0x9868
+#define AR5K_PHY_ADCSAT_ICNT 0x0001f800
+#define AR5K_PHY_ADCSAT_ICNT_S 11
+#define AR5K_PHY_ADCSAT_THR 0x000007e0
+#define AR5K_PHY_ADCSAT_THR_S 5
+
+/*
+ * PHY sleep registers [5112+]
+ */
+#define AR5K_PHY_SCR 0x9870
+#define AR5K_PHY_SCR_32MHZ 0x0000001f
+#define AR5K_PHY_SLMT 0x9874
+#define AR5K_PHY_SLMT_32MHZ 0x0000007f
+#define AR5K_PHY_SCAL 0x9878
+#define AR5K_PHY_SCAL_32MHZ 0x0000000e
+
+/*
+ * PHY PLL (Phase Locked Loop) control register
+ */
+#define AR5K_PHY_PLL 0x987c
+#define AR5K_PHY_PLL_20MHZ 0x13 /* For half rate (?) [5111+] */
+#define AR5K_PHY_PLL_40MHZ_5211 0x18 /* For 802.11a */
+#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa
+#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212)
+#define AR5K_PHY_PLL_44MHZ_5211 0x19 /* For 802.11b/g */
+#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab
+#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \
+ AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212)
+#define AR5K_PHY_PLL_RF5111 0x00000000
+#define AR5K_PHY_PLL_RF5112 0x00000040
+
+/*
+ * RF Buffer register
+ *
+ * There are some special control registers on the RF chip
+ * that hold various operation settings related mostly to
+ * the analog parts (channel, gain adjustment etc).
+ *
+ * We don't write on those registers directly but
+ * we send a data packet on the buffer register and
+ * then write on another special register to notify hw
+ * to apply the settings. This is done so that control registers
+ * can be dynamicaly programmed during operation and the settings
+ * are applied faster on the hw.
+ *
+ * We sent such data packets during rf initialization and channel change
+ * through ath5k_hw_rf*_rfregs and ath5k_hw_rf*_channel functions.
+ *
+ * The data packets we send during initializadion are inside ath5k_ini_rf
+ * struct (see ath5k_hw.h) and each one is related to an "rf register bank".
+ * We use *rfregs functions to modify them acording to current operation
+ * mode and eeprom values and pass them all together to the chip.
+ *
+ * It's obvious from the code that 0x989c is the buffer register but
+ * for the other special registers that we write to after sending each
+ * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers
+ * for now. It's interesting that they are also used for some other operations.
+ *
+ * Also check out hw.h and U.S. Patent 6677779 B1 (about buffer
+ * registers and control registers):
+ *
+ * http://www.google.com/patents?id=qNURAAAAEBAJ
+ */
+
+#define AR5K_RF_BUFFER 0x989c
+#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */
+#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */
+#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */
+ /* Channel set on 5111 */
+ /* Used to read radio revision*/
+
+#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */
+ /* Bank 0,1,2,6 on 5111 */
+ /* Bank 1 on 5112 */
+ /* Used during activation on 5111 */
+
+#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */
+ /* Used during activation on 5111 */
+ /* Channel on 5112 */
+ /* Bank 6 on 5112 */
+
+#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */
+
+/*
+ * PHY RF stage register [5210]
+ */
+#define AR5K_PHY_RFSTG 0x98d4
+#define AR5K_PHY_RFSTG_DISABLE 0x00000021
+
+/*
+ * PHY receiver delay register [5111+]
+ */
+#define AR5K_PHY_RX_DELAY 0x9914
+#define AR5K_PHY_RX_DELAY_M 0x00003fff
+
+/*
+ * PHY timing I(nphase) Q(adrature) control register [5111+]
+ */
+#define AR5K_PHY_IQ 0x9920 /* Register address */
+#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */
+#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5
+#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000
+#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12
+#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */
+
+
+/*
+ * PHY PAPD probe register [5111+ (?)]
+ * Is this only present in 5212 ?
+ * Because it's always 0 in 5211 initialization code
+ */
+#define AR5K_PHY_PAPD_PROBE 0x9930
+#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00
+#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9
+#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000
+#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */
+#define AR5K_PHY_PAPD_PROBE_TYPE_S 23
+#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0
+#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1
+#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2
+#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000
+#define AR5K_PHY_PAPD_PROBE_GAINF_S 25
+#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */
+#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */
+
+
+/*
+ * PHY TX rate power registers [5112+]
+ */
+#define AR5K_PHY_TXPOWER_RATE1 0x9934
+#define AR5K_PHY_TXPOWER_RATE2 0x9938
+#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c
+#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040
+#define AR5K_PHY_TXPOWER_RATE3 0xa234
+#define AR5K_PHY_TXPOWER_RATE4 0xa238
+
+/*
+ * PHY frame control register [5111+]
+ */
+#define AR5K_PHY_FRAME_CTL_5210 0x9804
+#define AR5K_PHY_FRAME_CTL_5211 0x9944
+#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \
+ AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211)
+/*---[5111+]---*/
+#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038
+#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3
+/*---[5110/5111]---*/
+#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000
+#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000
+#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* illegal rate */
+#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* illegal length */
+#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000
+#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* tx underrun */
+#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \
+ AR5K_PHY_FRAME_CTL_TXURN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \
+ AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \
+ AR5K_PHY_FRAME_CTL_PARITY_ERR | \
+ AR5K_PHY_FRAME_CTL_TIMING_ERR
+
+/*
+ * PHY radar detection register [5111+]
+ */
+#define AR5K_PHY_RADAR 0x9954
+
+/* Radar enable ........ ........ ........ .......1 */
+#define AR5K_PHY_RADAR_ENABLE 0x00000001
+#define AR5K_PHY_RADAR_DISABLE 0x00000000
+#define AR5K_PHY_RADAR_ENABLE_S 0
+
+/* This is the value found on the card .1.111.1 .1.1.... 111....1 1...1...
+at power on. */
+#define AR5K_PHY_RADAR_PWONDEF_AR5213 0x5d50e188
+
+/* This is the value found on the card .1.1.111 ..11...1 .1...1.1 1...11.1
+after DFS is enabled */
+#define AR5K_PHY_RADAR_ENABLED_AR5213 0x5731458d
+
+/* Finite Impulse Response (FIR) filter .1111111 ........ ........ ........
+ * power out threshold.
+ * 7-bits, standard power range {0..127} in 1/2 dBm units. */
+#define AR5K_PHY_RADAR_FIRPWROUTTHR 0x7f000000
+#define AR5K_PHY_RADAR_FIRPWROUTTHR_S 24
+
+/* Radar RSSI/SNR threshold. ........ 111111.. ........ ........
+ * 6-bits, dBm range {0..63} in dBm units. */
+#define AR5K_PHY_RADAR_RADARRSSITHR 0x00fc0000
+#define AR5K_PHY_RADAR_RADARRSSITHR_S 18
+
+/* Pulse height threshold ........ ......11 1111.... ........
+ * 6-bits, dBm range {0..63} in dBm units. */
+#define AR5K_PHY_RADAR_PULSEHEIGHTTHR 0x0003f000
+#define AR5K_PHY_RADAR_PULSEHEIGHTTHR_S 12
+
+/* Pulse RSSI/SNR threshold ........ ........ ....1111 11......
+ * 6-bits, dBm range {0..63} in dBm units. */
+#define AR5K_PHY_RADAR_PULSERSSITHR 0x00000fc0
+#define AR5K_PHY_RADAR_PULSERSSITHR_S 6
+
+/* Inband threshold ........ ........ ........ ..11111.
+ * 5-bits, units unknown {0..31} (? MHz ?) */
+#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e
+#define AR5K_PHY_RADAR_INBANDTHR_S 1
+
+/*
+ * PHY antenna switch table registers [5110]
+ */
+#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960
+#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964
+
+/*
+ * PHY clock sleep registers [5112+]
+ */
+#define AR5K_PHY_SCLOCK 0x99f0
+#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c
+#define AR5K_PHY_SDELAY 0x99f4
+#define AR5K_PHY_SDELAY_32MHZ 0x000000ff
+#define AR5K_PHY_SPENDING 0x99f8
+#define AR5K_PHY_SPENDING_RF5111 0x00000018
+#define AR5K_PHY_SPENDING_RF5112 0x00000014
+
+/*
+ * Misc PHY/radio registers [5110 - 5111]
+ */
+#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */
+#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2))
+#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */
+#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2))
+
+/*
+ * PHY timing IQ calibration result register [5111+]
+ */
+#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */
+#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */
+#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */
+
+/*
+ * PHY current RSSI register [5111+]
+ */
+#define AR5K_PHY_CURRENT_RSSI 0x9c1c
+
+/*
+ * PHY PCDAC TX power table
+ */
+#define AR5K_PHY_PCDAC_TXPOWER_BASE_5211 0xa180
+#define AR5K_PHY_PCDAC_TXPOWER_BASE_5413 0xa280
+#define AR5K_PHY_PCDAC_TXPOWER_BASE (ah->ah_radio >= AR5K_RF5413 ? \
+ AR5K_PHY_PCDAC_TXPOWER_BASE_5413 :\
+ AR5K_PHY_PCDAC_TXPOWER_BASE_5211)
+#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2))
+
+/*
+ * PHY mode register [5111+]
+ */
+#define AR5K_PHY_MODE 0x0a200 /* Register address */
+#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation mask*/
+#define AR5K_PHY_MODE_MOD_OFDM 0
+#define AR5K_PHY_MODE_MOD_CCK 1
+#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode mask */
+#define AR5K_PHY_MODE_FREQ_5GHZ 0
+#define AR5K_PHY_MODE_FREQ_2GHZ 2
+#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Dynamic OFDM/CCK mode mask [5112+] */
+#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */
+#define AR5K_PHY_MODE_RAD_RF5111 0
+#define AR5K_PHY_MODE_RAD_RF5112 8
+#define AR5K_PHY_MODE_XR 0x00000010 /* [5112+] */
+
+/*
+ * PHY CCK transmit control register [5111+ (?)]
+ */
+#define AR5K_PHY_CCKTXCTL 0xa204
+#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000
+#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010
+
+/*
+ * PHY 2GHz gain register [5111+]
+ */
+#define AR5K_PHY_GAIN_2GHZ 0xa20c
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000
+#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18
+#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c
diff --git a/drivers/net/wireless/ath5k/regdom.c b/drivers/net/wireless/ath5k/regdom.c
new file mode 100644
index 000000000000..e851957dacfd
--- /dev/null
+++ b/drivers/net/wireless/ath5k/regdom.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2004, 2005 Reyk Floeter <reyk@vantronix.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Basic regulation domain extensions for the IEEE 802.11 stack
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "regdom.h"
+
+static const struct ath5k_regdommap {
+ enum ath5k_regdom dmn;
+ enum ath5k_regdom dmn5;
+ enum ath5k_regdom dmn2;
+} r_map[] = {
+ { DMN_DEFAULT, DMN_DEBUG, DMN_DEBUG },
+ { DMN_NULL_WORLD, DMN_NULL, DMN_WORLD },
+ { DMN_NULL_ETSIB, DMN_NULL, DMN_ETSIB },
+ { DMN_NULL_ETSIC, DMN_NULL, DMN_ETSIC },
+ { DMN_FCC1_FCCA, DMN_FCC1, DMN_FCCA },
+ { DMN_FCC1_WORLD, DMN_FCC1, DMN_WORLD },
+ { DMN_FCC2_FCCA, DMN_FCC2, DMN_FCCA },
+ { DMN_FCC2_WORLD, DMN_FCC2, DMN_WORLD },
+ { DMN_FCC2_ETSIC, DMN_FCC2, DMN_ETSIC },
+ { DMN_FRANCE_NULL, DMN_ETSI3, DMN_ETSI3 },
+ { DMN_FCC3_FCCA, DMN_FCC3, DMN_WORLD },
+ { DMN_ETSI1_WORLD, DMN_ETSI1, DMN_WORLD },
+ { DMN_ETSI3_ETSIA, DMN_ETSI3, DMN_WORLD },
+ { DMN_ETSI2_WORLD, DMN_ETSI2, DMN_WORLD },
+ { DMN_ETSI3_WORLD, DMN_ETSI3, DMN_WORLD },
+ { DMN_ETSI4_WORLD, DMN_ETSI4, DMN_WORLD },
+ { DMN_ETSI4_ETSIC, DMN_ETSI4, DMN_ETSIC },
+ { DMN_ETSI5_WORLD, DMN_ETSI5, DMN_WORLD },
+ { DMN_ETSI6_WORLD, DMN_ETSI6, DMN_WORLD },
+ { DMN_ETSI_NULL, DMN_ETSI1, DMN_ETSI1 },
+ { DMN_MKK1_MKKA, DMN_MKK1, DMN_MKKA },
+ { DMN_MKK1_MKKB, DMN_MKK1, DMN_MKKA },
+ { DMN_APL4_WORLD, DMN_APL4, DMN_WORLD },
+ { DMN_MKK2_MKKA, DMN_MKK2, DMN_MKKA },
+ { DMN_APL_NULL, DMN_APL1, DMN_NULL },
+ { DMN_APL2_WORLD, DMN_APL2, DMN_WORLD },
+ { DMN_APL2_APLC, DMN_APL2, DMN_WORLD },
+ { DMN_APL3_WORLD, DMN_APL3, DMN_WORLD },
+ { DMN_MKK1_FCCA, DMN_MKK1, DMN_FCCA },
+ { DMN_APL2_APLD, DMN_APL2, DMN_APLD },
+ { DMN_MKK1_MKKA1, DMN_MKK1, DMN_MKKA },
+ { DMN_MKK1_MKKA2, DMN_MKK1, DMN_MKKA },
+ { DMN_APL1_WORLD, DMN_APL1, DMN_WORLD },
+ { DMN_APL1_FCCA, DMN_APL1, DMN_FCCA },
+ { DMN_APL1_APLA, DMN_APL1, DMN_WORLD },
+ { DMN_APL1_ETSIC, DMN_APL1, DMN_ETSIC },
+ { DMN_APL2_ETSIC, DMN_APL2, DMN_ETSIC },
+ { DMN_APL5_WORLD, DMN_APL5, DMN_WORLD },
+ { DMN_WOR0_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR1_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR2_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR3_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR4_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR5_ETSIC, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR01_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WOR02_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_EU1_WORLD, DMN_ETSI1, DMN_WORLD },
+ { DMN_WOR9_WORLD, DMN_WORLD, DMN_WORLD },
+ { DMN_WORA_WORLD, DMN_WORLD, DMN_WORLD },
+};
+
+enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom dmn, u16 mhz)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(r_map); i++) {
+ if (r_map[i].dmn == dmn) {
+ if (mhz >= 2000 && mhz <= 3000)
+ return r_map[i].dmn2;
+ if (mhz >= IEEE80211_CHANNELS_5GHZ_MIN &&
+ mhz <= IEEE80211_CHANNELS_5GHZ_MAX)
+ return r_map[i].dmn5;
+ }
+ }
+
+ return DMN_DEBUG;
+}
+
+u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee)
+{
+ u32 regdomain = (u32)ieee;
+
+ /*
+ * Use the default regulation domain if the value is empty
+ * or not supported by the net80211 regulation code.
+ */
+ if (ath5k_regdom2flag(regdomain, IEEE80211_CHANNELS_5GHZ_MIN) ==
+ DMN_DEBUG)
+ return (u16)AR5K_TUNE_REGDOMAIN;
+
+ /* It is supported, just return the value */
+ return regdomain;
+}
+
+enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain)
+{
+ enum ath5k_regdom ieee = (enum ath5k_regdom)regdomain;
+
+ return ieee;
+}
+
diff --git a/drivers/net/wireless/ath5k/regdom.h b/drivers/net/wireless/ath5k/regdom.h
new file mode 100644
index 000000000000..f7d3c66e594e
--- /dev/null
+++ b/drivers/net/wireless/ath5k/regdom.h
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 2004, 2005 Reyk Floeter <reyk@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _IEEE80211_REGDOMAIN_H_
+#define _IEEE80211_REGDOMAIN_H_
+
+#include <linux/types.h>
+
+/* Default regulation domain if stored value EEPROM value is invalid */
+#define AR5K_TUNE_REGDOMAIN DMN_FCC2_FCCA /* Canada */
+#define AR5K_TUNE_CTRY CTRY_DEFAULT
+
+
+enum ath5k_regdom {
+ DMN_DEFAULT = 0x00,
+ DMN_NULL_WORLD = 0x03,
+ DMN_NULL_ETSIB = 0x07,
+ DMN_NULL_ETSIC = 0x08,
+ DMN_FCC1_FCCA = 0x10,
+ DMN_FCC1_WORLD = 0x11,
+ DMN_FCC2_FCCA = 0x20,
+ DMN_FCC2_WORLD = 0x21,
+ DMN_FCC2_ETSIC = 0x22,
+ DMN_FRANCE_NULL = 0x31,
+ DMN_FCC3_FCCA = 0x3A,
+ DMN_ETSI1_WORLD = 0x37,
+ DMN_ETSI3_ETSIA = 0x32,
+ DMN_ETSI2_WORLD = 0x35,
+ DMN_ETSI3_WORLD = 0x36,
+ DMN_ETSI4_WORLD = 0x30,
+ DMN_ETSI4_ETSIC = 0x38,
+ DMN_ETSI5_WORLD = 0x39,
+ DMN_ETSI6_WORLD = 0x34,
+ DMN_ETSI_NULL = 0x33,
+ DMN_MKK1_MKKA = 0x40,
+ DMN_MKK1_MKKB = 0x41,
+ DMN_APL4_WORLD = 0x42,
+ DMN_MKK2_MKKA = 0x43,
+ DMN_APL_NULL = 0x44,
+ DMN_APL2_WORLD = 0x45,
+ DMN_APL2_APLC = 0x46,
+ DMN_APL3_WORLD = 0x47,
+ DMN_MKK1_FCCA = 0x48,
+ DMN_APL2_APLD = 0x49,
+ DMN_MKK1_MKKA1 = 0x4A,
+ DMN_MKK1_MKKA2 = 0x4B,
+ DMN_APL1_WORLD = 0x52,
+ DMN_APL1_FCCA = 0x53,
+ DMN_APL1_APLA = 0x54,
+ DMN_APL1_ETSIC = 0x55,
+ DMN_APL2_ETSIC = 0x56,
+ DMN_APL5_WORLD = 0x58,
+ DMN_WOR0_WORLD = 0x60,
+ DMN_WOR1_WORLD = 0x61,
+ DMN_WOR2_WORLD = 0x62,
+ DMN_WOR3_WORLD = 0x63,
+ DMN_WOR4_WORLD = 0x64,
+ DMN_WOR5_ETSIC = 0x65,
+ DMN_WOR01_WORLD = 0x66,
+ DMN_WOR02_WORLD = 0x67,
+ DMN_EU1_WORLD = 0x68,
+ DMN_WOR9_WORLD = 0x69,
+ DMN_WORA_WORLD = 0x6A,
+
+ DMN_APL1 = 0xf0000001,
+ DMN_APL2 = 0xf0000002,
+ DMN_APL3 = 0xf0000004,
+ DMN_APL4 = 0xf0000008,
+ DMN_APL5 = 0xf0000010,
+ DMN_ETSI1 = 0xf0000020,
+ DMN_ETSI2 = 0xf0000040,
+ DMN_ETSI3 = 0xf0000080,
+ DMN_ETSI4 = 0xf0000100,
+ DMN_ETSI5 = 0xf0000200,
+ DMN_ETSI6 = 0xf0000400,
+ DMN_ETSIA = 0xf0000800,
+ DMN_ETSIB = 0xf0001000,
+ DMN_ETSIC = 0xf0002000,
+ DMN_FCC1 = 0xf0004000,
+ DMN_FCC2 = 0xf0008000,
+ DMN_FCC3 = 0xf0010000,
+ DMN_FCCA = 0xf0020000,
+ DMN_APLD = 0xf0040000,
+ DMN_MKK1 = 0xf0080000,
+ DMN_MKK2 = 0xf0100000,
+ DMN_MKKA = 0xf0200000,
+ DMN_NULL = 0xf0400000,
+ DMN_WORLD = 0xf0800000,
+ DMN_DEBUG = 0xf1000000 /* used for debugging */
+};
+
+#define IEEE80211_DMN(_d) ((_d) & ~0xf0000000)
+
+enum ath5k_countrycode {
+ CTRY_DEFAULT = 0, /* Default domain (NA) */
+ CTRY_ALBANIA = 8, /* Albania */
+ CTRY_ALGERIA = 12, /* Algeria */
+ CTRY_ARGENTINA = 32, /* Argentina */
+ CTRY_ARMENIA = 51, /* Armenia */
+ CTRY_AUSTRALIA = 36, /* Australia */
+ CTRY_AUSTRIA = 40, /* Austria */
+ CTRY_AZERBAIJAN = 31, /* Azerbaijan */
+ CTRY_BAHRAIN = 48, /* Bahrain */
+ CTRY_BELARUS = 112, /* Belarus */
+ CTRY_BELGIUM = 56, /* Belgium */
+ CTRY_BELIZE = 84, /* Belize */
+ CTRY_BOLIVIA = 68, /* Bolivia */
+ CTRY_BRAZIL = 76, /* Brazil */
+ CTRY_BRUNEI_DARUSSALAM = 96, /* Brunei Darussalam */
+ CTRY_BULGARIA = 100, /* Bulgaria */
+ CTRY_CANADA = 124, /* Canada */
+ CTRY_CHILE = 152, /* Chile */
+ CTRY_CHINA = 156, /* People's Republic of China */
+ CTRY_COLOMBIA = 170, /* Colombia */
+ CTRY_COSTA_RICA = 188, /* Costa Rica */
+ CTRY_CROATIA = 191, /* Croatia */
+ CTRY_CYPRUS = 196, /* Cyprus */
+ CTRY_CZECH = 203, /* Czech Republic */
+ CTRY_DENMARK = 208, /* Denmark */
+ CTRY_DOMINICAN_REPUBLIC = 214, /* Dominican Republic */
+ CTRY_ECUADOR = 218, /* Ecuador */
+ CTRY_EGYPT = 818, /* Egypt */
+ CTRY_EL_SALVADOR = 222, /* El Salvador */
+ CTRY_ESTONIA = 233, /* Estonia */
+ CTRY_FAEROE_ISLANDS = 234, /* Faeroe Islands */
+ CTRY_FINLAND = 246, /* Finland */
+ CTRY_FRANCE = 250, /* France */
+ CTRY_FRANCE2 = 255, /* France2 */
+ CTRY_GEORGIA = 268, /* Georgia */
+ CTRY_GERMANY = 276, /* Germany */
+ CTRY_GREECE = 300, /* Greece */
+ CTRY_GUATEMALA = 320, /* Guatemala */
+ CTRY_HONDURAS = 340, /* Honduras */
+ CTRY_HONG_KONG = 344, /* Hong Kong S.A.R., P.R.C. */
+ CTRY_HUNGARY = 348, /* Hungary */
+ CTRY_ICELAND = 352, /* Iceland */
+ CTRY_INDIA = 356, /* India */
+ CTRY_INDONESIA = 360, /* Indonesia */
+ CTRY_IRAN = 364, /* Iran */
+ CTRY_IRAQ = 368, /* Iraq */
+ CTRY_IRELAND = 372, /* Ireland */
+ CTRY_ISRAEL = 376, /* Israel */
+ CTRY_ITALY = 380, /* Italy */
+ CTRY_JAMAICA = 388, /* Jamaica */
+ CTRY_JAPAN = 392, /* Japan */
+ CTRY_JAPAN1 = 393, /* Japan (JP1) */
+ CTRY_JAPAN2 = 394, /* Japan (JP0) */
+ CTRY_JAPAN3 = 395, /* Japan (JP1-1) */
+ CTRY_JAPAN4 = 396, /* Japan (JE1) */
+ CTRY_JAPAN5 = 397, /* Japan (JE2) */
+ CTRY_JORDAN = 400, /* Jordan */
+ CTRY_KAZAKHSTAN = 398, /* Kazakhstan */
+ CTRY_KENYA = 404, /* Kenya */
+ CTRY_KOREA_NORTH = 408, /* North Korea */
+ CTRY_KOREA_ROC = 410, /* South Korea */
+ CTRY_KOREA_ROC2 = 411, /* South Korea */
+ CTRY_KUWAIT = 414, /* Kuwait */
+ CTRY_LATVIA = 428, /* Latvia */
+ CTRY_LEBANON = 422, /* Lebanon */
+ CTRY_LIBYA = 434, /* Libya */
+ CTRY_LIECHTENSTEIN = 438, /* Liechtenstein */
+ CTRY_LITHUANIA = 440, /* Lithuania */
+ CTRY_LUXEMBOURG = 442, /* Luxembourg */
+ CTRY_MACAU = 446, /* Macau */
+ CTRY_MACEDONIA = 807, /* Republic of Macedonia */
+ CTRY_MALAYSIA = 458, /* Malaysia */
+ CTRY_MEXICO = 484, /* Mexico */
+ CTRY_MONACO = 492, /* Principality of Monaco */
+ CTRY_MOROCCO = 504, /* Morocco */
+ CTRY_NETHERLANDS = 528, /* Netherlands */
+ CTRY_NEW_ZEALAND = 554, /* New Zealand */
+ CTRY_NICARAGUA = 558, /* Nicaragua */
+ CTRY_NORWAY = 578, /* Norway */
+ CTRY_OMAN = 512, /* Oman */
+ CTRY_PAKISTAN = 586, /* Islamic Republic of Pakistan */
+ CTRY_PANAMA = 591, /* Panama */
+ CTRY_PARAGUAY = 600, /* Paraguay */
+ CTRY_PERU = 604, /* Peru */
+ CTRY_PHILIPPINES = 608, /* Republic of the Philippines */
+ CTRY_POLAND = 616, /* Poland */
+ CTRY_PORTUGAL = 620, /* Portugal */
+ CTRY_PUERTO_RICO = 630, /* Puerto Rico */
+ CTRY_QATAR = 634, /* Qatar */
+ CTRY_ROMANIA = 642, /* Romania */
+ CTRY_RUSSIA = 643, /* Russia */
+ CTRY_SAUDI_ARABIA = 682, /* Saudi Arabia */
+ CTRY_SINGAPORE = 702, /* Singapore */
+ CTRY_SLOVAKIA = 703, /* Slovak Republic */
+ CTRY_SLOVENIA = 705, /* Slovenia */
+ CTRY_SOUTH_AFRICA = 710, /* South Africa */
+ CTRY_SPAIN = 724, /* Spain */
+ CTRY_SRI_LANKA = 728, /* Sri Lanka */
+ CTRY_SWEDEN = 752, /* Sweden */
+ CTRY_SWITZERLAND = 756, /* Switzerland */
+ CTRY_SYRIA = 760, /* Syria */
+ CTRY_TAIWAN = 158, /* Taiwan */
+ CTRY_THAILAND = 764, /* Thailand */
+ CTRY_TRINIDAD_Y_TOBAGO = 780, /* Trinidad y Tobago */
+ CTRY_TUNISIA = 788, /* Tunisia */
+ CTRY_TURKEY = 792, /* Turkey */
+ CTRY_UAE = 784, /* U.A.E. */
+ CTRY_UKRAINE = 804, /* Ukraine */
+ CTRY_UNITED_KINGDOM = 826, /* United Kingdom */
+ CTRY_UNITED_STATES = 840, /* United States */
+ CTRY_URUGUAY = 858, /* Uruguay */
+ CTRY_UZBEKISTAN = 860, /* Uzbekistan */
+ CTRY_VENEZUELA = 862, /* Venezuela */
+ CTRY_VIET_NAM = 704, /* Viet Nam */
+ CTRY_YEMEN = 887, /* Yemen */
+ CTRY_ZIMBABWE = 716, /* Zimbabwe */
+};
+
+#define IEEE80211_CHANNELS_2GHZ_MIN 2412 /* 2GHz channel 1 */
+#define IEEE80211_CHANNELS_2GHZ_MAX 2732 /* 2GHz channel 26 */
+#define IEEE80211_CHANNELS_5GHZ_MIN 5005 /* 5GHz channel 1 */
+#define IEEE80211_CHANNELS_5GHZ_MAX 6100 /* 5GHz channel 220 */
+
+struct ath5k_regchannel {
+ u16 chan;
+ enum ath5k_regdom domain;
+ u32 mode;
+};
+
+#define IEEE80211_CHANNELS_2GHZ { \
+/*2412*/ { 1, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2417*/ { 2, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2422*/ { 3, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2427*/ { 4, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2432*/ { 5, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2442*/ { 7, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2447*/ { 8, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2452*/ { 9, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2457*/ { 10, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2462*/ { 11, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2467*/ { 12, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2472*/ { 13, DMN_APLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+ \
+/*2432*/ { 5, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*2442*/ { 7, DMN_ETSIB, CHANNEL_CCK|CHANNEL_OFDM }, \
+ \
+/*2412*/ { 1, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2417*/ { 2, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2422*/ { 3, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2427*/ { 4, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2432*/ { 5, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*2442*/ { 7, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2447*/ { 8, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2452*/ { 9, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2457*/ { 10, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2462*/ { 11, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2467*/ { 12, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2472*/ { 13, DMN_ETSIC, CHANNEL_CCK|CHANNEL_OFDM }, \
+ \
+/*2412*/ { 1, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2417*/ { 2, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2422*/ { 3, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2427*/ { 4, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2432*/ { 5, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*2442*/ { 7, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2447*/ { 8, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2452*/ { 9, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2457*/ { 10, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2462*/ { 11, DMN_FCCA, CHANNEL_CCK|CHANNEL_OFDM }, \
+ \
+/*2412*/ { 1, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2417*/ { 2, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2422*/ { 3, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2427*/ { 4, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2432*/ { 5, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2442*/ { 7, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2447*/ { 8, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2452*/ { 9, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2457*/ { 10, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2462*/ { 11, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2467*/ { 12, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2472*/ { 13, DMN_MKKA, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2484*/ { 14, DMN_MKKA, CHANNEL_CCK }, \
+ \
+/*2412*/ { 1, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2417*/ { 2, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2422*/ { 3, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2427*/ { 4, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2432*/ { 5, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2437*/ { 6, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*2442*/ { 7, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2447*/ { 8, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2452*/ { 9, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2457*/ { 10, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2462*/ { 11, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2467*/ { 12, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+/*2472*/ { 13, DMN_WORLD, CHANNEL_CCK|CHANNEL_OFDM }, \
+}
+
+#define IEEE80211_CHANNELS_5GHZ { \
+/*5745*/ { 149, DMN_APL1, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_APL1, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_APL1, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_APL1, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_APL1, CHANNEL_OFDM }, \
+ \
+/*5745*/ { 149, DMN_APL2, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_APL2, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_APL2, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_APL2, CHANNEL_OFDM }, \
+ \
+/*5280*/ { 56, DMN_APL3, CHANNEL_OFDM }, \
+/*5300*/ { 60, DMN_APL3, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_APL3, CHANNEL_OFDM }, \
+/*5745*/ { 149, DMN_APL3, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_APL3, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_APL3, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_APL3, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_APL4, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_APL4, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_APL4, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_APL4, CHANNEL_OFDM }, \
+/*5745*/ { 149, DMN_APL4, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_APL4, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_APL4, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_APL4, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_APL4, CHANNEL_OFDM }, \
+ \
+/*5745*/ { 149, DMN_APL5, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_APL5, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_APL5, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_APL5, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_APL5, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5260*/ { 52, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5300*/ { 60, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5500*/ { 100, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5520*/ { 104, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5540*/ { 108, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5560*/ { 112, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5580*/ { 116, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5600*/ { 120, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5620*/ { 124, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5640*/ { 128, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5660*/ { 132, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5680*/ { 136, DMN_ETSI1, CHANNEL_OFDM }, \
+/*5700*/ { 140, DMN_ETSI1, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI2, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI2, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI2, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI2, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5260*/ { 52, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5300*/ { 60, DMN_ETSI3, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_ETSI3, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5260*/ { 52, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5300*/ { 60, DMN_ETSI4, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_ETSI4, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI5, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI5, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI5, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI5, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5260*/ { 52, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5500*/ { 100, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5520*/ { 104, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5540*/ { 108, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5560*/ { 112, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5580*/ { 116, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5600*/ { 120, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5620*/ { 124, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5640*/ { 128, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5660*/ { 132, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5680*/ { 136, DMN_ETSI6, CHANNEL_OFDM }, \
+/*5700*/ { 140, DMN_ETSI6, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_FCC1, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_FCC1, CHANNEL_OFDM }, \
+/*5210*/ { 42, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5220*/ { 44, DMN_FCC1, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_FCC1, CHANNEL_OFDM }, \
+/*5250*/ { 50, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5260*/ { 52, DMN_FCC1, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_FCC1, CHANNEL_OFDM }, \
+/*5290*/ { 58, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5300*/ { 60, DMN_FCC1, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_FCC1, CHANNEL_OFDM }, \
+/*5745*/ { 149, DMN_FCC1, CHANNEL_OFDM }, \
+/*5760*/ { 152, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5765*/ { 153, DMN_FCC1, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_FCC1, CHANNEL_OFDM }, \
+/*5800*/ { 160, DMN_FCC1, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5805*/ { 161, DMN_FCC1, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_FCC1, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_FCC2, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_FCC2, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_FCC2, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_FCC2, CHANNEL_OFDM }, \
+/*5260*/ { 52, DMN_FCC2, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_FCC2, CHANNEL_OFDM }, \
+/*5300*/ { 60, DMN_FCC2, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_FCC2, CHANNEL_OFDM }, \
+/*5745*/ { 149, DMN_FCC2, CHANNEL_OFDM }, \
+/*5765*/ { 153, DMN_FCC2, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_FCC2, CHANNEL_OFDM }, \
+/*5805*/ { 161, DMN_FCC2, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_FCC2, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_FCC3, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_FCC3, CHANNEL_OFDM }, \
+/*5210*/ { 42, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5220*/ { 44, DMN_FCC3, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_FCC3, CHANNEL_OFDM }, \
+/*5250*/ { 50, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5260*/ { 52, DMN_FCC3, CHANNEL_OFDM }, \
+/*5280*/ { 56, DMN_FCC3, CHANNEL_OFDM }, \
+/*5290*/ { 58, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5300*/ { 60, DMN_FCC3, CHANNEL_OFDM }, \
+/*5320*/ { 64, DMN_FCC3, CHANNEL_OFDM }, \
+/*5500*/ { 100, DMN_FCC3, CHANNEL_OFDM }, \
+/*5520*/ { 104, DMN_FCC3, CHANNEL_OFDM }, \
+/*5540*/ { 108, DMN_FCC3, CHANNEL_OFDM }, \
+/*5560*/ { 112, DMN_FCC3, CHANNEL_OFDM }, \
+/*5580*/ { 116, DMN_FCC3, CHANNEL_OFDM }, \
+/*5600*/ { 120, DMN_FCC3, CHANNEL_OFDM }, \
+/*5620*/ { 124, DMN_FCC3, CHANNEL_OFDM }, \
+/*5640*/ { 128, DMN_FCC3, CHANNEL_OFDM }, \
+/*5660*/ { 132, DMN_FCC3, CHANNEL_OFDM }, \
+/*5680*/ { 136, DMN_FCC3, CHANNEL_OFDM }, \
+/*5700*/ { 140, DMN_FCC3, CHANNEL_OFDM }, \
+/*5745*/ { 149, DMN_FCC3, CHANNEL_OFDM }, \
+/*5760*/ { 152, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5765*/ { 153, DMN_FCC3, CHANNEL_OFDM }, \
+/*5785*/ { 157, DMN_FCC3, CHANNEL_OFDM }, \
+/*5800*/ { 160, DMN_FCC3, CHANNEL_OFDM|CHANNEL_TURBO }, \
+/*5805*/ { 161, DMN_FCC3, CHANNEL_OFDM }, \
+/*5825*/ { 165, DMN_FCC3, CHANNEL_OFDM }, \
+ \
+/*5170*/ { 34, DMN_MKK1, CHANNEL_OFDM }, \
+/*5190*/ { 38, DMN_MKK1, CHANNEL_OFDM }, \
+/*5210*/ { 42, DMN_MKK1, CHANNEL_OFDM }, \
+/*5230*/ { 46, DMN_MKK1, CHANNEL_OFDM }, \
+ \
+/*5040*/ { 8, DMN_MKK2, CHANNEL_OFDM }, \
+/*5060*/ { 12, DMN_MKK2, CHANNEL_OFDM }, \
+/*5080*/ { 16, DMN_MKK2, CHANNEL_OFDM }, \
+/*5170*/ { 34, DMN_MKK2, CHANNEL_OFDM }, \
+/*5190*/ { 38, DMN_MKK2, CHANNEL_OFDM }, \
+/*5210*/ { 42, DMN_MKK2, CHANNEL_OFDM }, \
+/*5230*/ { 46, DMN_MKK2, CHANNEL_OFDM }, \
+ \
+/*5180*/ { 36, DMN_WORLD, CHANNEL_OFDM }, \
+/*5200*/ { 40, DMN_WORLD, CHANNEL_OFDM }, \
+/*5220*/ { 44, DMN_WORLD, CHANNEL_OFDM }, \
+/*5240*/ { 48, DMN_WORLD, CHANNEL_OFDM }, \
+}
+
+enum ath5k_regdom ath5k_regdom2flag(enum ath5k_regdom, u16);
+u16 ath5k_regdom_from_ieee(enum ath5k_regdom ieee);
+enum ath5k_regdom ath5k_regdom_to_ieee(u16 regdomain);
+
+#endif
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index 059ce3f07dba..63ec7a70ee76 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -1759,9 +1759,8 @@ static int atmel_set_encode(struct net_device *dev,
priv->default_key = index;
} else
/* Don't complain if only change the mode */
- if (!dwrq->flags & IW_ENCODE_MODE) {
+ if (!(dwrq->flags & IW_ENCODE_MODE))
return -EINVAL;
- }
}
/* Read the flags */
if (dwrq->flags & IW_ENCODE_DISABLED) {
@@ -2676,9 +2675,9 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
}
struct auth_body {
- u16 alg;
- u16 trans_seq;
- u16 status;
+ __le16 alg;
+ __le16 trans_seq;
+ __le16 status;
u8 el_id;
u8 chall_text_len;
u8 chall_text[253];
@@ -2713,9 +2712,9 @@ static void atmel_scan(struct atmel_private *priv, int specific_ssid)
u8 SSID[MAX_SSID_LENGTH];
u8 scan_type;
u8 channel;
- u16 BSS_type;
- u16 min_channel_time;
- u16 max_channel_time;
+ __le16 BSS_type;
+ __le16 min_channel_time;
+ __le16 max_channel_time;
u8 options;
u8 SSID_size;
} cmd;
@@ -2758,7 +2757,7 @@ static void join(struct atmel_private *priv, int type)
u8 SSID[MAX_SSID_LENGTH];
u8 BSS_type; /* this is a short in a scan command - weird */
u8 channel;
- u16 timeout;
+ __le16 timeout;
u8 SSID_size;
u8 reserved;
} cmd;
@@ -2863,8 +2862,8 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
int bodysize;
struct ieee80211_hdr_4addr header;
struct ass_req_format {
- u16 capability;
- u16 listen_interval;
+ __le16 capability;
+ __le16 listen_interval;
u8 ap[6]; /* nothing after here directly accessible */
u8 ssid_el_id;
u8 ssid_len;
@@ -3085,9 +3084,9 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
{
struct ass_resp_format {
- u16 capability;
- u16 status;
- u16 ass_id;
+ __le16 capability;
+ __le16 status;
+ __le16 ass_id;
u8 el_id;
u8 length;
u8 rates[4];
@@ -3294,9 +3293,9 @@ static void atmel_management_frame(struct atmel_private *priv,
never let an engineer loose with a data structure design. */
{
struct beacon_format {
- u64 timestamp;
- u16 interval;
- u16 capability;
+ __le64 timestamp;
+ __le16 interval;
+ __le16 capability;
u8 ssid_el_id;
u8 ssid_length;
/* ssid here */
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index fdbc351ac333..1a2141dabdc7 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -61,6 +61,16 @@ config B43_PCMCIA
If unsure, say N.
+config B43_NPHY
+ bool "Pre IEEE 802.11n support (BROKEN)"
+ depends on B43 && EXPERIMENTAL && BROKEN
+ ---help---
+ Support for the IEEE 802.11n draft.
+
+ THIS IS BROKEN AND DOES NOT WORK YET.
+
+ SAY N.
+
# This config option automatically enables b43 LEDS support,
# if it's possible.
config B43_LEDS
@@ -83,51 +93,3 @@ config B43_DEBUG
Say Y, if you want to find out why the driver does not
work for you.
-
-config B43_DMA
- bool
- depends on B43
-config B43_PIO
- bool
- depends on B43
-
-choice
- prompt "Broadcom 43xx data transfer mode"
- depends on B43
- default B43_DMA_AND_PIO_MODE
-
-config B43_DMA_AND_PIO_MODE
- bool "DMA + PIO"
- select B43_DMA
- select B43_PIO
- ---help---
- Include both, Direct Memory Access (DMA) and Programmed I/O (PIO)
- data transfer modes.
- The actually used mode is selectable through the module
- parameter "pio". If the module parameter is pio=0, DMA is used.
- Otherwise PIO is used. DMA is default.
-
- If unsure, choose this option.
-
-config B43_DMA_MODE
- bool "DMA (Direct Memory Access) only"
- select B43_DMA
- ---help---
- Only include Direct Memory Access (DMA).
- This reduces the size of the driver module, by omitting the PIO code.
-
-config B43_PIO_MODE
- bool "PIO (Programmed I/O) only"
- select B43_PIO
- ---help---
- Only include Programmed I/O (PIO).
- This reduces the size of the driver module, by omitting the DMA code.
- Please note that PIO transfers are slow (compared to DMA).
-
- Also note that not all devices of the 43xx series support PIO.
- The 4306 (Apple Airport Extreme and others) supports PIO, while
- the 4318 is known to _not_ support PIO.
-
- Only use PIO, if DMA does not work for you.
-
-endchoice
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile
index 485e59e2dfab..ac1329dba045 100644
--- a/drivers/net/wireless/b43/Makefile
+++ b/drivers/net/wireless/b43/Makefile
@@ -1,20 +1,16 @@
-# b43 core
b43-y += main.o
b43-y += tables.o
+b43-y += tables_nphy.o
b43-y += phy.o
+b43-y += nphy.o
b43-y += sysfs.o
b43-y += xmit.o
b43-y += lo.o
-# b43 RFKILL button support
+b43-y += wa.o
+b43-y += dma.o
b43-$(CONFIG_B43_RFKILL) += rfkill.o
-# b43 LED support
b43-$(CONFIG_B43_LEDS) += leds.o
-# b43 PCMCIA support
b43-$(CONFIG_B43_PCMCIA) += pcmcia.o
-# b43 debugging
b43-$(CONFIG_B43_DEBUG) += debugfs.o
-# b43 DMA and PIO
-b43-$(CONFIG_B43_DMA) += dma.o
-b43-$(CONFIG_B43_PIO) += pio.o
obj-$(CONFIG_B43) += b43.o
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 7b6fc1ab2b90..32a24f5c4fa6 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -35,8 +35,8 @@
#define B43_MMIO_DMA4_IRQ_MASK 0x44
#define B43_MMIO_DMA5_REASON 0x48
#define B43_MMIO_DMA5_IRQ_MASK 0x4C
-#define B43_MMIO_MACCTL 0x120
-#define B43_MMIO_STATUS2_BITFIELD 0x124
+#define B43_MMIO_MACCTL 0x120 /* MAC control */
+#define B43_MMIO_MACCMD 0x124 /* MAC command */
#define B43_MMIO_GEN_IRQ_REASON 0x128
#define B43_MMIO_GEN_IRQ_MASK 0x12C
#define B43_MMIO_RAM_CONTROL 0x130
@@ -50,6 +50,9 @@
#define B43_MMIO_XMITSTAT_1 0x174
#define B43_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */
#define B43_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */
+#define B43_MMIO_TSF_CFP_REP 0x188
+#define B43_MMIO_TSF_CFP_START 0x18C
+#define B43_MMIO_TSF_CFP_MAXDUR 0x190
/* 32-bit DMA */
#define B43_MMIO_DMA32_BASE0 0x200
@@ -65,11 +68,6 @@
#define B43_MMIO_DMA64_BASE3 0x2C0
#define B43_MMIO_DMA64_BASE4 0x300
#define B43_MMIO_DMA64_BASE5 0x340
-/* PIO */
-#define B43_MMIO_PIO1_BASE 0x300
-#define B43_MMIO_PIO2_BASE 0x310
-#define B43_MMIO_PIO3_BASE 0x320
-#define B43_MMIO_PIO4_BASE 0x330
#define B43_MMIO_PHY_VER 0x3E0
#define B43_MMIO_PHY_RADIO 0x3E2
@@ -88,6 +86,8 @@
#define B43_MMIO_RADIO_HWENABLED_LO 0x49A
#define B43_MMIO_GPIO_CONTROL 0x49C
#define B43_MMIO_GPIO_MASK 0x49E
+#define B43_MMIO_TSF_CFP_START_LOW 0x604
+#define B43_MMIO_TSF_CFP_START_HIGH 0x606
#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */
#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */
#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */
@@ -170,14 +170,17 @@ enum {
#define B43_SHM_SH_SLOTT 0x0010 /* Slot time */
#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */
#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */
-/* SHM_SHARED beacon variables */
+/* SHM_SHARED beacon/AP variables */
#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */
#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */
#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */
#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */
+#define B43_SHM_SH_DTIMP 0x0012 /* DTIP period */
+#define B43_SHM_SH_MCASTCOOKIE 0x00A8 /* Last bcast/mcast frame ID */
#define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */
#define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */
#define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */
+#define B43_SHM_SH_EXTNPHYCTL 0x00B0 /* Extended bytes for beacon PHY control (N) */
/* SHM_SHARED ACK/CTS control */
#define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */
/* SHM_SHARED probe response variables */
@@ -321,17 +324,29 @@ enum {
#define B43_MACCTL_DISCPMQ 0x40000000 /* Discard Power Management Queue */
#define B43_MACCTL_GMODE 0x80000000 /* G Mode */
-/* 802.11 core specific TM State Low flags */
+/* MAC Command bitfield */
+#define B43_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */
+#define B43_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */
+#define B43_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */
+#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */
+#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */
+
+/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */
#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */
-#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select */
+#define B43_TMSLOW_PHYCLKSPEED 0x00C00000 /* PHY clock speed mask (N-PHY only) */
+#define B43_TMSLOW_PHYCLKSPEED_40MHZ 0x00000000 /* 40 MHz PHY */
+#define B43_TMSLOW_PHYCLKSPEED_80MHZ 0x00400000 /* 80 MHz PHY */
+#define B43_TMSLOW_PHYCLKSPEED_160MHZ 0x00800000 /* 160 MHz PHY */
+#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */
#define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */
#define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */
#define B43_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */
-/* 802.11 core specific TM State High flags */
+/* 802.11 core specific TM State High (SSB_TMSHIGH) flags */
+#define B43_TMSHIGH_DUALBAND_PHY 0x00080000 /* Dualband PHY available */
#define B43_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available (rev >= 5) */
-#define B43_TMSHIGH_APHY 0x00020000 /* A-PHY available (rev >= 5) */
-#define B43_TMSHIGH_GPHY 0x00010000 /* G-PHY available (rev >= 5) */
+#define B43_TMSHIGH_HAVE_5GHZ_PHY 0x00020000 /* 5 GHz PHY available (rev >= 5) */
+#define B43_TMSHIGH_HAVE_2GHZ_PHY 0x00010000 /* 2.4 GHz PHY available (rev >= 5) */
/* Generic-Interrupt reasons. */
#define B43_IRQ_MAC_SUSPENDED 0x00000001
@@ -393,6 +408,8 @@ enum {
#define B43_DEFAULT_SHORT_RETRY_LIMIT 7
#define B43_DEFAULT_LONG_RETRY_LIMIT 4
+#define B43_PHY_TX_BADNESS_LIMIT 1000
+
/* Max size of a security key */
#define B43_SEC_KEYSIZE 16
/* Security algorithms. */
@@ -462,7 +479,6 @@ struct b43_phy {
u16 radio_ver; /* Radio version */
u8 radio_rev; /* Radio revision */
- bool locked; /* Only used in b43_phy_{un}lock() */
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
/* ACI (adjacent channel interference) flags. */
@@ -499,11 +515,6 @@ struct b43_phy {
s16 lna_gain; /* LNA */
s16 pga_gain; /* PGA */
- /* PHY lock for core.rev < 3
- * This lock is only used by b43_phy_{un}lock()
- */
- spinlock_t lock;
-
/* Desired TX power level (in dBm).
* This is set by the user and adjusted in b43_phy_xmitpower(). */
u8 power_level;
@@ -514,9 +525,7 @@ struct b43_phy {
struct b43_bbatt bbatt;
struct b43_rfatt rfatt;
u8 tx_control; /* B43_TXCTL_XXX */
-#ifdef CONFIG_B43_DEBUG
- bool manual_txpower_control; /* Manual TX-power control enabled? */
-#endif
+
/* Hardware Power Control enabled? */
bool hardware_power_control;
@@ -544,6 +553,26 @@ struct b43_phy {
u16 lofcal;
u16 initval; //FIXME rename?
+
+ /* PHY TX errors counter. */
+ atomic_t txerr_cnt;
+
+ /* The device does address auto increment for the OFDM tables.
+ * We cache the previously used address here and omit the address
+ * write on the next table access, if possible. */
+ u16 ofdmtab_addr; /* The address currently set in hardware. */
+ enum { /* The last data flow direction. */
+ B43_OFDMTAB_DIRECTION_UNKNOWN = 0,
+ B43_OFDMTAB_DIRECTION_READ,
+ B43_OFDMTAB_DIRECTION_WRITE,
+ } ofdmtab_addr_direction;
+
+#if B43_DEBUG
+ /* Manual TX-power control enabled? */
+ bool manual_txpower_control;
+ /* PHY registers locked by b43_phy_lock()? */
+ bool phy_locked;
+#endif /* B43_DEBUG */
};
/* Data structures for DMA transmission, per 80211 core. */
@@ -559,14 +588,6 @@ struct b43_dma {
struct b43_dmaring *rx_ring3; /* only available on core.rev < 5 */
};
-/* Data structures for PIO transmission, per 80211 core. */
-struct b43_pio {
- struct b43_pioqueue *queue0;
- struct b43_pioqueue *queue1;
- struct b43_pioqueue *queue2;
- struct b43_pioqueue *queue3;
-};
-
/* Context information for a noise calculation (Link Quality). */
struct b43_noise_calculation {
u8 channel_at_start;
@@ -599,18 +620,18 @@ struct b43_wl {
/* Pointer to the ieee80211 hardware data structure */
struct ieee80211_hw *hw;
- spinlock_t irq_lock;
struct mutex mutex;
+ spinlock_t irq_lock;
+ /* Lock for LEDs access. */
spinlock_t leds_lock;
+ /* Lock for SHM access. */
+ spinlock_t shm_lock;
/* We can only have one operating interface (802.11 core)
* at a time. General information about this interface follows.
*/
- /* Opaque ID of the operating interface from the ieee80211
- * subsystem. Do not modify.
- */
- int if_id;
+ struct ieee80211_vif *vif;
/* The MAC address of the operating interface. */
u8 mac_addr[ETH_ALEN];
/* Current BSSID */
@@ -634,18 +655,33 @@ struct b43_wl {
/* List of all wireless devices on this chip */
struct list_head devlist;
u8 nr_devs;
+
+ bool radiotap_enabled;
+
+ /* The beacon we are currently using (AP or IBSS mode).
+ * This beacon stuff is protected by the irq_lock. */
+ struct sk_buff *current_beacon;
+ bool beacon0_uploaded;
+ bool beacon1_uploaded;
+};
+
+/* In-memory representation of a cached microcode file. */
+struct b43_firmware_file {
+ const char *filename;
+ const struct firmware *data;
};
/* Pointers to the firmware data and meta information about it. */
struct b43_firmware {
/* Microcode */
- const struct firmware *ucode;
+ struct b43_firmware_file ucode;
/* PCM code */
- const struct firmware *pcm;
+ struct b43_firmware_file pcm;
/* Initial MMIO values for the firmware */
- const struct firmware *initvals;
+ struct b43_firmware_file initvals;
/* Initial MMIO values for the firmware, band-specific */
- const struct firmware *initvals_band;
+ struct b43_firmware_file initvals_band;
+
/* Firmware revision */
u16 rev;
/* Firmware patchlevel */
@@ -683,21 +719,17 @@ struct b43_wldev {
/* Saved init status for handling suspend. */
int suspend_init_status;
- bool __using_pio; /* Internal, use b43_using_pio(). */
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
- bool reg124_set_0x4; /* Some variable to keep track of IRQ stuff. */
+ bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
bool short_preamble; /* TRUE, if short preamble is enabled. */
bool short_slot; /* TRUE, if short slot timing is enabled. */
bool radio_hw_enable; /* saved state of radio hardware enabled state */
/* PHY/Radio device. */
struct b43_phy phy;
- union {
- /* DMA engines. */
- struct b43_dma dma;
- /* PIO engines. */
- struct b43_pio pio;
- };
+
+ /* DMA engines. */
+ struct b43_dma dma;
/* Various statistics about the physical device. */
struct b43_stats stats;
@@ -732,9 +764,6 @@ struct b43_wldev {
u8 max_nr_keys;
struct b43_key key[58];
- /* Cached beacon template while uploading the template. */
- struct sk_buff *cached_beacon;
-
/* Firmware data */
struct b43_firmware fw;
@@ -752,28 +781,6 @@ static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw)
return hw->priv;
}
-/* Helper function, which returns a boolean.
- * TRUE, if PIO is used; FALSE, if DMA is used.
- */
-#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_PIO)
-static inline int b43_using_pio(struct b43_wldev *dev)
-{
- return dev->__using_pio;
-}
-#elif defined(CONFIG_B43_DMA)
-static inline int b43_using_pio(struct b43_wldev *dev)
-{
- return 0;
-}
-#elif defined(CONFIG_B43_PIO)
-static inline int b43_using_pio(struct b43_wldev *dev)
-{
- return 1;
-}
-#else
-# error "Using neither DMA nor PIO? Confused..."
-#endif
-
static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev)
{
struct ssb_device *ssb_dev = dev_to_ssb_dev(dev);
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index ef0075d9f9cb..e38ed0fe72e9 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -34,7 +34,6 @@
#include "main.h"
#include "debugfs.h"
#include "dma.h"
-#include "pio.h"
#include "xmit.h"
@@ -223,8 +222,6 @@ out:
static int txpower_g_write_file(struct b43_wldev *dev,
const char *buf, size_t count)
{
- unsigned long phy_flags;
-
if (dev->phy.type != B43_PHYTYPE_G)
return -ENODEV;
if ((count >= 4) && (memcmp(buf, "auto", 4) == 0)) {
@@ -248,12 +245,12 @@ static int txpower_g_write_file(struct b43_wldev *dev,
dev->phy.tx_control |= B43_TXCTL_PA2DB;
if (pa3db)
dev->phy.tx_control |= B43_TXCTL_PA3DB;
- b43_phy_lock(dev, phy_flags);
+ b43_phy_lock(dev);
b43_radio_lock(dev);
b43_set_txpower_g(dev, &dev->phy.bbatt,
&dev->phy.rfatt, dev->phy.tx_control);
b43_radio_unlock(dev);
- b43_phy_unlock(dev, phy_flags);
+ b43_phy_unlock(dev);
}
return 0;
@@ -352,7 +349,7 @@ static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf,
struct b43_wldev *dev;
struct b43_debugfs_fops *dfops;
struct b43_dfs_file *dfile;
- ssize_t ret;
+ ssize_t uninitialized_var(ret);
char *buf;
const size_t bufsize = 1024 * 128;
const size_t buforder = get_order(bufsize);
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 5e8f8ac0f1dd..3e73d2a523aa 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -37,6 +37,8 @@
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
+#include <linux/etherdevice.h>
+
/* 32bit DMA ops. */
static
@@ -165,7 +167,7 @@ static void op64_fill_descriptor(struct b43_dmaring *ring,
addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
>> SSB_DMA_TRANSLATION_SHIFT;
- addrhi |= ssb_dma_translation(ring->dev->dev);
+ addrhi |= (ssb_dma_translation(ring->dev->dev) << 1);
if (slot == ring->nr_slots - 1)
ctl0 |= B43_DMA64_DCTL0_DTABLEEND;
if (start)
@@ -315,26 +317,24 @@ static struct b43_dmaring *priority_to_txring(struct b43_wldev *dev,
case 3:
ring = dev->dma.tx_ring0;
break;
- case 4:
- ring = dev->dma.tx_ring4;
- break;
- case 5:
- ring = dev->dma.tx_ring5;
- break;
}
return ring;
}
-/* Bcm43xx-ring to mac80211-queue mapping */
+/* b43-ring to mac80211-queue mapping */
static inline int txring_to_priority(struct b43_dmaring *ring)
{
- static const u8 idx_to_prio[] = { 3, 2, 1, 0, 4, 5, };
+ static const u8 idx_to_prio[] = { 3, 2, 1, 0, };
+ unsigned int index;
/*FIXME: have only one queue, for now */
return 0;
- return idx_to_prio[ring->index];
+ index = ring->index;
+ if (B43_WARN_ON(index >= ARRAY_SIZE(idx_to_prio)))
+ index = 0;
+ return idx_to_prio[index];
}
u16 b43_dmacontroller_base(int dma64bit, int controller_idx)
@@ -426,9 +426,21 @@ static inline
static int alloc_ringmemory(struct b43_dmaring *ring)
{
struct device *dev = ring->dev->dev->dev;
-
+ gfp_t flags = GFP_KERNEL;
+
+ /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K
+ * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing
+ * has shown that 4K is sufficient for the latter as long as the buffer
+ * does not cross an 8K boundary.
+ *
+ * For unknown reasons - possibly a hardware error - the BCM4311 rev
+ * 02, which uses 64-bit DMA, needs the ring buffer in very low memory,
+ * which accounts for the GFP_DMA flag below.
+ */
+ if (ring->dma64)
+ flags |= GFP_DMA;
ring->descbase = dma_alloc_coherent(dev, B43_DMA_RINGMEMSIZE,
- &(ring->dmabase), GFP_KERNEL);
+ &(ring->dmabase), flags);
if (!ring->descbase) {
b43err(ring->dev->wl, "DMA ringmemory allocation failed\n");
return -ENOMEM;
@@ -483,7 +495,7 @@ int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
return 0;
}
-/* Reset the RX DMA channel */
+/* Reset the TX DMA channel */
int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, int dma64)
{
int i;
@@ -647,7 +659,7 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
b43_dma_write(ring, B43_DMA64_TXRINGHI,
((ringbase >> 32) &
~SSB_DMA_TRANSLATION_MASK)
- | trans);
+ | (trans << 1));
} else {
u32 ringbase = (u32) (ring->dmabase);
@@ -680,8 +692,9 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
b43_dma_write(ring, B43_DMA64_RXRINGHI,
((ringbase >> 32) &
~SSB_DMA_TRANSLATION_MASK)
- | trans);
- b43_dma_write(ring, B43_DMA64_RXINDEX, 200);
+ | (trans << 1));
+ b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots *
+ sizeof(struct b43_dmadesc64));
} else {
u32 ringbase = (u32) (ring->dmabase);
@@ -695,11 +708,12 @@ static int dmacontroller_setup(struct b43_dmaring *ring)
b43_dma_write(ring, B43_DMA32_RXRING,
(ringbase & ~SSB_DMA_TRANSLATION_MASK)
| trans);
- b43_dma_write(ring, B43_DMA32_RXINDEX, 200);
+ b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots *
+ sizeof(struct b43_dmadesc32));
}
}
- out:
+out:
return err;
}
@@ -793,7 +807,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
goto err_kfree_ring;
if (for_tx) {
ring->txhdr_cache = kcalloc(nr_slots,
- sizeof(struct b43_txhdr_fw4),
+ b43_txhdr_size(dev),
GFP_KERNEL);
if (!ring->txhdr_cache)
goto err_kfree_meta;
@@ -801,22 +815,21 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
/* test for ability to dma to txhdr_cache */
dma_test = dma_map_single(dev->dev->dev,
ring->txhdr_cache,
- sizeof(struct b43_txhdr_fw4),
+ b43_txhdr_size(dev),
DMA_TO_DEVICE);
if (dma_mapping_error(dma_test)) {
/* ugh realloc */
kfree(ring->txhdr_cache);
ring->txhdr_cache = kcalloc(nr_slots,
- sizeof(struct
- b43_txhdr_fw4),
+ b43_txhdr_size(dev),
GFP_KERNEL | GFP_DMA);
if (!ring->txhdr_cache)
goto err_kfree_meta;
dma_test = dma_map_single(dev->dev->dev,
ring->txhdr_cache,
- sizeof(struct b43_txhdr_fw4),
+ b43_txhdr_size(dev),
DMA_TO_DEVICE);
if (dma_mapping_error(dma_test))
@@ -824,7 +837,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
}
dma_unmap_single(dev->dev->dev,
- dma_test, sizeof(struct b43_txhdr_fw4),
+ dma_test, b43_txhdr_size(dev),
DMA_TO_DEVICE);
}
@@ -901,11 +914,7 @@ static void b43_destroy_dmaring(struct b43_dmaring *ring)
void b43_dma_free(struct b43_wldev *dev)
{
- struct b43_dma *dma;
-
- if (b43_using_pio(dev))
- return;
- dma = &dev->dma;
+ struct b43_dma *dma = &dev->dma;
b43_destroy_dmaring(dma->rx_ring3);
dma->rx_ring3 = NULL;
@@ -940,16 +949,11 @@ int b43_dma_init(struct b43_wldev *dev)
err = ssb_dma_set_mask(dev->dev, dmamask);
if (err) {
-#ifdef B43_PIO
- b43warn(dev->wl, "DMA for this device not supported. "
- "Falling back to PIO\n");
- dev->__using_pio = 1;
- return -EAGAIN;
-#else
- b43err(dev->wl, "DMA for this device not supported and "
- "no PIO support compiled in\n");
+ b43err(dev->wl, "The machine/kernel does not support "
+ "the required DMA mask (0x%08X%08X)\n",
+ (unsigned int)((dmamask & 0xFFFFFFFF00000000ULL) >> 32),
+ (unsigned int)(dmamask & 0x00000000FFFFFFFFULL));
return -EOPNOTSUPP;
-#endif
}
err = -ENOMEM;
@@ -1038,26 +1042,30 @@ static u16 generate_cookie(struct b43_dmaring *ring, int slot)
* in the lower 12 bits.
* Note that the cookie must never be 0, as this
* is a special value used in RX path.
+ * It can also not be 0xFFFF because that is special
+ * for multicast frames.
*/
switch (ring->index) {
case 0:
- cookie = 0xA000;
+ cookie = 0x1000;
break;
case 1:
- cookie = 0xB000;
+ cookie = 0x2000;
break;
case 2:
- cookie = 0xC000;
+ cookie = 0x3000;
break;
case 3:
- cookie = 0xD000;
+ cookie = 0x4000;
break;
case 4:
- cookie = 0xE000;
+ cookie = 0x5000;
break;
case 5:
- cookie = 0xF000;
+ cookie = 0x6000;
break;
+ default:
+ B43_WARN_ON(1);
}
B43_WARN_ON(slot & ~0x0FFF);
cookie |= (u16) slot;
@@ -1073,22 +1081,22 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
struct b43_dmaring *ring = NULL;
switch (cookie & 0xF000) {
- case 0xA000:
+ case 0x1000:
ring = dma->tx_ring0;
break;
- case 0xB000:
+ case 0x2000:
ring = dma->tx_ring1;
break;
- case 0xC000:
+ case 0x3000:
ring = dma->tx_ring2;
break;
- case 0xD000:
+ case 0x4000:
ring = dma->tx_ring3;
break;
- case 0xE000:
+ case 0x5000:
ring = dma->tx_ring4;
break;
- case 0xF000:
+ case 0x6000:
ring = dma->tx_ring5;
break;
default:
@@ -1112,6 +1120,8 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
struct b43_dmadesc_meta *meta;
struct b43_dmadesc_meta *meta_hdr;
struct sk_buff *bounce_skb;
+ u16 cookie;
+ size_t hdrsize = b43_txhdr_size(ring->dev);
#define SLOTS_PER_PACKET 2
B43_WARN_ON(skb_shinfo(skb)->nr_frags);
@@ -1121,17 +1131,17 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
desc = ops->idx2desc(ring, slot, &meta_hdr);
memset(meta_hdr, 0, sizeof(*meta_hdr));
- header = &(ring->txhdr_cache[slot * sizeof(struct b43_txhdr_fw4)]);
+ header = &(ring->txhdr_cache[slot * hdrsize]);
+ cookie = generate_cookie(ring, slot);
b43_generate_txhdr(ring->dev, header,
- skb->data, skb->len, ctl,
- generate_cookie(ring, slot));
+ skb->data, skb->len, ctl, cookie);
meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
- sizeof(struct b43_txhdr_fw4), 1);
+ hdrsize, 1);
if (dma_mapping_error(meta_hdr->dmaaddr))
return -EIO;
ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr,
- sizeof(struct b43_txhdr_fw4), 1, 0, 0);
+ hdrsize, 1, 0, 0);
/* Get a slot for the payload. */
slot = request_slot(ring);
@@ -1164,16 +1174,22 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1);
+ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+ /* Tell the firmware about the cookie of the last
+ * mcast frame, so it can clear the more-data bit in it. */
+ b43_shm_write16(ring->dev, B43_SHM_SHARED,
+ B43_SHM_SH_MCASTCOOKIE, cookie);
+ }
/* Now transfer the whole frame. */
wmb();
ops->poke_tx(ring, next_slot(ring, slot));
return 0;
- out_free_bounce:
+out_free_bounce:
dev_kfree_skb_any(skb);
- out_unmap_hdr:
+out_unmap_hdr:
unmap_descbuffer(ring, meta_hdr->dmaaddr,
- sizeof(struct b43_txhdr_fw4), 1);
+ hdrsize, 1);
return err;
}
@@ -1202,10 +1218,27 @@ int b43_dma_tx(struct b43_wldev *dev,
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
{
struct b43_dmaring *ring;
+ struct ieee80211_hdr *hdr;
int err = 0;
unsigned long flags;
- ring = priority_to_txring(dev, ctl->queue);
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
+ return -EINVAL;
+ }
+
+ hdr = (struct ieee80211_hdr *)skb->data;
+ if (ctl->flags & IEEE80211_TXCTL_SEND_AFTER_DTIM) {
+ /* The multicast ring will be sent after the DTIM */
+ ring = dev->dma.tx_ring4;
+ /* Set the more-data bit. Ucode will clear it on
+ * the last frame for us. */
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+ } else {
+ /* Decide by priority where to put this frame. */
+ ring = priority_to_txring(dev, ctl->queue);
+ }
+
spin_lock_irqsave(&ring->lock, flags);
B43_WARN_ON(!ring->tx);
if (unlikely(free_slots(ring) < SLOTS_PER_PACKET)) {
@@ -1233,7 +1266,7 @@ int b43_dma_tx(struct b43_wldev *dev,
b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index);
}
}
- out_unlock:
+out_unlock:
spin_unlock_irqrestore(&ring->lock, flags);
return err;
@@ -1265,7 +1298,7 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
1);
else
unmap_descbuffer(ring, meta->dmaaddr,
- sizeof(struct b43_txhdr_fw4), 1);
+ b43_txhdr_size(dev), 1);
if (meta->is_last_fragment) {
B43_WARN_ON(!meta->skb);
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index 3eed185be725..58db03ac536e 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -170,8 +170,6 @@ struct b43_dmadesc_generic {
#define B43_DMA0_RX_BUFFERSIZE (2304 + 100)
#define B43_DMA3_RX_BUFFERSIZE 16
-#ifdef CONFIG_B43_DMA
-
struct sk_buff;
struct b43_private;
struct b43_txstatus;
@@ -286,52 +284,4 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
void b43_dma_rx(struct b43_dmaring *ring);
-#else /* CONFIG_B43_DMA */
-
-static inline int b43_dma_init(struct b43_wldev *dev)
-{
- return 0;
-}
-static inline void b43_dma_free(struct b43_wldev *dev)
-{
-}
-static inline
- int b43_dmacontroller_rx_reset(struct b43_wldev *dev,
- u16 dmacontroller_mmio_base, int dma64)
-{
- return 0;
-}
-static inline
- int b43_dmacontroller_tx_reset(struct b43_wldev *dev,
- u16 dmacontroller_mmio_base, int dma64)
-{
- return 0;
-}
-static inline
- void b43_dma_get_tx_stats(struct b43_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
-}
-static inline
- int b43_dma_tx(struct b43_wldev *dev,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-{
- return 0;
-}
-static inline
- void b43_dma_handle_txstatus(struct b43_wldev *dev,
- const struct b43_txstatus *status)
-{
-}
-static inline void b43_dma_rx(struct b43_dmaring *ring)
-{
-}
-static inline void b43_dma_tx_suspend(struct b43_wldev *dev)
-{
-}
-static inline void b43_dma_tx_resume(struct b43_wldev *dev)
-{
-}
-
-#endif /* CONFIG_B43_DMA */
#endif /* B43_DMA_H_ */
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 6c0e2b9f7760..4b590d8c65ff 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -4,7 +4,7 @@
LED control
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -190,10 +190,10 @@ void b43_leds_init(struct b43_wldev *dev)
enum b43_led_behaviour behaviour;
bool activelow;
- sprom[0] = bus->sprom.r1.gpio0;
- sprom[1] = bus->sprom.r1.gpio1;
- sprom[2] = bus->sprom.r1.gpio2;
- sprom[3] = bus->sprom.r1.gpio3;
+ sprom[0] = bus->sprom.gpio0;
+ sprom[1] = bus->sprom.gpio1;
+ sprom[2] = bus->sprom.gpio2;
+ sprom[3] = bus->sprom.gpio3;
for (i = 0; i < 4; i++) {
if (sprom[i] == 0xFF) {
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c
index b14a1753a0d7..d890f366a23b 100644
--- a/drivers/net/wireless/b43/lo.c
+++ b/drivers/net/wireless/b43/lo.c
@@ -5,7 +5,7 @@
G PHY LO (LocalOscillator) Measuring and Control routines
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005, 2006 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -264,8 +264,8 @@ static u16 lo_measure_feedthrough(struct b43_wldev *dev,
rfover |= pga;
rfover |= lna;
rfover |= trsw_rx;
- if ((dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) &&
- phy->rev > 6)
+ if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA)
+ && phy->rev > 6)
rfover |= B43_PHY_RFOVERVAL_EXTLNA;
b43_phy_write(dev, B43_PHY_PGACTL, 0xE300);
@@ -555,20 +555,20 @@ struct lo_g_saved_values {
u16 phy_extg_01;
u16 phy_dacctl_hwpctl;
u16 phy_dacctl;
- u16 phy_base_14;
+ u16 phy_cck_14;
u16 phy_hpwr_tssictl;
u16 phy_analogover;
u16 phy_analogoverval;
u16 phy_rfover;
u16 phy_rfoverval;
u16 phy_classctl;
- u16 phy_base_3E;
+ u16 phy_cck_3E;
u16 phy_crs0;
u16 phy_pgactl;
- u16 phy_base_2A;
+ u16 phy_cck_2A;
u16 phy_syncctl;
- u16 phy_base_30;
- u16 phy_base_06;
+ u16 phy_cck_30;
+ u16 phy_cck_06;
/* Radio registers */
u16 radio_43;
@@ -588,7 +588,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK);
sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01));
sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL);
- sav->phy_base_14 = b43_phy_read(dev, B43_PHY_BASE(0x14));
+ sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14));
sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL);
b43_phy_write(dev, B43_PHY_HPWR_TSSICTL,
@@ -600,14 +600,14 @@ static void lo_measure_setup(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_DACCTL,
b43_phy_read(dev, B43_PHY_DACCTL)
| 0x40);
- b43_phy_write(dev, B43_PHY_BASE(0x14),
- b43_phy_read(dev, B43_PHY_BASE(0x14))
+ b43_phy_write(dev, B43_PHY_CCK(0x14),
+ b43_phy_read(dev, B43_PHY_CCK(0x14))
| 0x200);
}
if (phy->type == B43_PHYTYPE_B &&
phy->radio_ver == 0x2050 && phy->radio_rev < 6) {
- b43_phy_write(dev, B43_PHY_BASE(0x16), 0x410);
- b43_phy_write(dev, B43_PHY_BASE(0x17), 0x820);
+ b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410);
+ b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820);
}
if (!lo->rebuild && b43_has_hardware_pctl(phy))
lo_read_power_vector(dev);
@@ -618,7 +618,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL);
sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL);
- sav->phy_base_3E = b43_phy_read(dev, B43_PHY_BASE(0x3E));
+ sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E));
sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0);
b43_phy_write(dev, B43_PHY_CLASSCTL,
@@ -634,7 +634,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
& 0xFFFC);
if (phy->type == B43_PHYTYPE_G) {
if ((phy->rev >= 7) &&
- (sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+ (sprom->boardflags_lo & B43_BFL_EXTLNA)) {
b43_phy_write(dev, B43_PHY_RFOVER, 0x933);
} else {
b43_phy_write(dev, B43_PHY_RFOVER, 0x133);
@@ -642,14 +642,14 @@ static void lo_measure_setup(struct b43_wldev *dev,
} else {
b43_phy_write(dev, B43_PHY_RFOVER, 0);
}
- b43_phy_write(dev, B43_PHY_BASE(0x3E), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x3E), 0);
}
sav->reg_3F4 = b43_read16(dev, 0x3F4);
sav->reg_3E2 = b43_read16(dev, 0x3E2);
sav->radio_43 = b43_radio_read16(dev, 0x43);
sav->radio_7A = b43_radio_read16(dev, 0x7A);
sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
- sav->phy_base_2A = b43_phy_read(dev, B43_PHY_BASE(0x2A));
+ sav->phy_cck_2A = b43_phy_read(dev, B43_PHY_CCK(0x2A));
sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL);
sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL);
@@ -658,10 +658,10 @@ static void lo_measure_setup(struct b43_wldev *dev,
sav->radio_52 &= 0x00F0;
}
if (phy->type == B43_PHYTYPE_B) {
- sav->phy_base_30 = b43_phy_read(dev, B43_PHY_BASE(0x30));
- sav->phy_base_06 = b43_phy_read(dev, B43_PHY_BASE(0x06));
- b43_phy_write(dev, B43_PHY_BASE(0x30), 0x00FF);
- b43_phy_write(dev, B43_PHY_BASE(0x06), 0x3F3F);
+ sav->phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30));
+ sav->phy_cck_06 = b43_phy_read(dev, B43_PHY_CCK(0x06));
+ b43_phy_write(dev, B43_PHY_CCK(0x30), 0x00FF);
+ b43_phy_write(dev, B43_PHY_CCK(0x06), 0x3F3F);
} else {
b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2)
| 0x8000);
@@ -670,7 +670,7 @@ static void lo_measure_setup(struct b43_wldev *dev,
& 0xF000);
tmp =
- (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_BASE(0x2E);
+ (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_CCK(0x2E);
b43_phy_write(dev, tmp, 0x007F);
tmp = sav->phy_syncctl;
@@ -678,26 +678,26 @@ static void lo_measure_setup(struct b43_wldev *dev,
tmp = sav->radio_7A;
b43_radio_write16(dev, 0x007A, tmp & 0xFFF0);
- b43_phy_write(dev, B43_PHY_BASE(0x2A), 0x8A3);
+ b43_phy_write(dev, B43_PHY_CCK(0x2A), 0x8A3);
if (phy->type == B43_PHYTYPE_G ||
(phy->type == B43_PHYTYPE_B &&
phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) {
- b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x1003);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1003);
} else
- b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x0802);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802);
if (phy->rev >= 2)
b43_dummy_transmission(dev);
b43_radio_selectchannel(dev, 6, 0);
b43_radio_read16(dev, 0x51); /* dummy read */
if (phy->type == B43_PHYTYPE_G)
- b43_phy_write(dev, B43_PHY_BASE(0x2F), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0);
if (lo->rebuild)
lo_measure_txctl_values(dev);
if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) {
b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078);
} else {
if (phy->type == B43_PHYTYPE_B)
- b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8078);
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078);
else
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
@@ -732,17 +732,17 @@ static void lo_measure_restore(struct b43_wldev *dev,
}
if (phy->type == B43_PHYTYPE_G) {
if (phy->rev >= 3)
- b43_phy_write(dev, B43_PHY_BASE(0x2E), 0xC078);
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078);
else
- b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8078);
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078);
if (phy->rev >= 2)
- b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x0202);
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0202);
else
- b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x0101);
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0101);
}
b43_write16(dev, 0x3F4, sav->reg_3F4);
b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl);
- b43_phy_write(dev, B43_PHY_BASE(0x2A), sav->phy_base_2A);
+ b43_phy_write(dev, B43_PHY_CCK(0x2A), sav->phy_cck_2A);
b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl);
b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl);
b43_radio_write16(dev, 0x43, sav->radio_43);
@@ -755,8 +755,8 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_write16(dev, 0x3E2, sav->reg_3E2);
if (phy->type == B43_PHYTYPE_B &&
phy->radio_ver == 0x2050 && phy->radio_rev <= 5) {
- b43_phy_write(dev, B43_PHY_BASE(0x30), sav->phy_base_30);
- b43_phy_write(dev, B43_PHY_BASE(0x06), sav->phy_base_06);
+ b43_phy_write(dev, B43_PHY_CCK(0x30), sav->phy_cck_30);
+ b43_phy_write(dev, B43_PHY_CCK(0x06), sav->phy_cck_06);
}
if (phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover);
@@ -765,7 +765,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl);
b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover);
b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval);
- b43_phy_write(dev, B43_PHY_BASE(0x3E), sav->phy_base_3E);
+ b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E);
b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0);
}
if (b43_has_hardware_pctl(phy)) {
@@ -773,7 +773,7 @@ static void lo_measure_restore(struct b43_wldev *dev,
b43_phy_write(dev, B43_PHY_LO_MASK, tmp);
b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01);
b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl);
- b43_phy_write(dev, B43_PHY_BASE(0x14), sav->phy_base_14);
+ b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14);
b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl);
}
b43_radio_selectchannel(dev, sav->old_channel, 1);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 1c93b4f4bfe3..88d2c15d3fbe 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
- Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -46,7 +46,6 @@
#include "debugfs.h"
#include "phy.h"
#include "dma.h"
-#include "pio.h"
#include "sysfs.h"
#include "xmit.h"
#include "lo.h"
@@ -58,31 +57,12 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
-extern char *nvram_get(char *name);
-
-#if defined(CONFIG_B43_DMA) && defined(CONFIG_B43_PIO)
-static int modparam_pio;
-module_param_named(pio, modparam_pio, int, 0444);
-MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode");
-#elif defined(CONFIG_B43_DMA)
-# define modparam_pio 0
-#elif defined(CONFIG_B43_PIO)
-# define modparam_pio 1
-#endif
static int modparam_bad_frames_preempt;
module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt,
"enable(1) / disable(0) Bad Frames Preemption");
-static int modparam_short_retry = B43_DEFAULT_SHORT_RETRY_LIMIT;
-module_param_named(short_retry, modparam_short_retry, int, 0444);
-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
-
-static int modparam_long_retry = B43_DEFAULT_LONG_RETRY_LIMIT;
-module_param_named(long_retry, modparam_long_retry, int, 0444);
-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-
static char modparam_fwpostfix[16];
module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
@@ -101,6 +81,8 @@ static const struct ssb_device_id b43_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9),
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11),
+ SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13),
SSB_DEVTABLE_END
};
@@ -150,7 +132,7 @@ static struct ieee80211_rate __b43_ratetable[] = {
.power_level = 0xFF, \
.antenna_max = 0xFF, \
}
-static struct ieee80211_channel b43_bg_chantable[] = {
+static struct ieee80211_channel b43_2ghz_chantable[] = {
CHANTAB_ENT(1, 2412),
CHANTAB_ENT(2, 2417),
CHANTAB_ENT(3, 2422),
@@ -166,9 +148,10 @@ static struct ieee80211_channel b43_bg_chantable[] = {
CHANTAB_ENT(13, 2472),
CHANTAB_ENT(14, 2484),
};
+#define b43_2ghz_chantable_size ARRAY_SIZE(b43_2ghz_chantable)
-#define b43_bg_chantable_size ARRAY_SIZE(b43_bg_chantable)
-static struct ieee80211_channel b43_a_chantable[] = {
+#if 0
+static struct ieee80211_channel b43_5ghz_chantable[] = {
CHANTAB_ENT(36, 5180),
CHANTAB_ENT(40, 5200),
CHANTAB_ENT(44, 5220),
@@ -183,8 +166,8 @@ static struct ieee80211_channel b43_a_chantable[] = {
CHANTAB_ENT(161, 5805),
CHANTAB_ENT(165, 5825),
};
-
-#define b43_a_chantable_size ARRAY_SIZE(b43_a_chantable)
+#define b43_5ghz_chantable_size ARRAY_SIZE(b43_5ghz_chantable)
+#endif
static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
@@ -269,13 +252,12 @@ static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val)
b43_write32(dev, B43_MMIO_RAM_DATA, val);
}
-static inline
- void b43_shm_control_word(struct b43_wldev *dev, u16 routing, u16 offset)
+static inline void b43_shm_control_word(struct b43_wldev *dev,
+ u16 routing, u16 offset)
{
u32 control;
/* "offset" is the WORD offset. */
-
control = routing;
control <<= 16;
control |= offset;
@@ -284,8 +266,11 @@ static inline
u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
{
+ struct b43_wl *wl = dev->wl;
+ unsigned long flags;
u32 ret;
+ spin_lock_irqsave(&wl->shm_lock, flags);
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
@@ -296,20 +281,25 @@ u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset)
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
ret |= b43_read16(dev, B43_MMIO_SHM_DATA);
- return ret;
+ goto out;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
ret = b43_read32(dev, B43_MMIO_SHM_DATA);
+out:
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
return ret;
}
u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
{
+ struct b43_wl *wl = dev->wl;
+ unsigned long flags;
u16 ret;
+ spin_lock_irqsave(&wl->shm_lock, flags);
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
@@ -317,55 +307,63 @@ u16 b43_shm_read16(struct b43_wldev * dev, u16 routing, u16 offset)
b43_shm_control_word(dev, routing, offset >> 2);
ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED);
- return ret;
+ goto out;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
ret = b43_read16(dev, B43_MMIO_SHM_DATA);
+out:
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
return ret;
}
void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value)
{
+ struct b43_wl *wl = dev->wl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->shm_lock, flags);
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
/* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2);
- mmiowb();
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED,
(value >> 16) & 0xffff);
- mmiowb();
b43_shm_control_word(dev, routing, (offset >> 2) + 1);
- mmiowb();
b43_write16(dev, B43_MMIO_SHM_DATA, value & 0xffff);
- return;
+ goto out;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
- mmiowb();
b43_write32(dev, B43_MMIO_SHM_DATA, value);
+out:
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
}
void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value)
{
+ struct b43_wl *wl = dev->wl;
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->shm_lock, flags);
if (routing == B43_SHM_SHARED) {
B43_WARN_ON(offset & 0x0001);
if (offset & 0x0003) {
/* Unaligned access */
b43_shm_control_word(dev, routing, offset >> 2);
- mmiowb();
b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value);
- return;
+ goto out;
}
offset >>= 2;
}
b43_shm_control_word(dev, routing, offset);
- mmiowb();
b43_write16(dev, B43_MMIO_SHM_DATA, value);
+out:
+ spin_unlock_irqrestore(&wl->shm_lock, flags);
}
/* Read HostFlags */
@@ -1012,9 +1010,8 @@ static void b43_jssi_write(struct b43_wldev *dev, u32 jssi)
static void b43_generate_noise_sample(struct b43_wldev *dev)
{
b43_jssi_write(dev, 0x7F7F7F7F);
- b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,
- b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)
- | (1 << 4));
+ b43_write32(dev, B43_MMIO_MACCMD,
+ b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE);
B43_WARN_ON(dev->noisecalc.channel_at_start != dev->phy.channel);
}
@@ -1100,18 +1097,18 @@ static void handle_irq_tbtt_indication(struct b43_wldev *dev)
if (1 /*FIXME: the last PSpoll frame was sent successfully */ )
b43_power_saving_ctl_bits(dev, 0);
}
- dev->reg124_set_0x4 = 0;
if (b43_is_mode(dev->wl, IEEE80211_IF_TYPE_IBSS))
- dev->reg124_set_0x4 = 1;
+ dev->dfq_valid = 1;
}
static void handle_irq_atim_end(struct b43_wldev *dev)
{
- if (!dev->reg124_set_0x4 /*FIXME rename this variable */ )
- return;
- b43_write32(dev, B43_MMIO_STATUS2_BITFIELD,
- b43_read32(dev, B43_MMIO_STATUS2_BITFIELD)
- | 0x4);
+ if (dev->dfq_valid) {
+ b43_write32(dev, B43_MMIO_MACCMD,
+ b43_read32(dev, B43_MMIO_MACCMD)
+ | B43_MACCMD_DFQ_VALID);
+ dev->dfq_valid = 0;
+ }
}
static void handle_irq_pmq(struct b43_wldev *dev)
@@ -1166,15 +1163,59 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
{
- int len;
- const u8 *data;
+ unsigned int i, len, variable_len;
+ const struct ieee80211_mgmt *bcn;
+ const u8 *ie;
+ bool tim_found = 0;
- B43_WARN_ON(!dev->cached_beacon);
- len = min((size_t) dev->cached_beacon->len,
+ bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
+ len = min((size_t) dev->wl->current_beacon->len,
0x200 - sizeof(struct b43_plcp_hdr6));
- data = (const u8 *)(dev->cached_beacon->data);
- b43_write_template_common(dev, data,
+
+ b43_write_template_common(dev, (const u8 *)bcn,
len, ram_offset, shm_size_offset, rate);
+
+ /* Find the position of the TIM and the DTIM_period value
+ * and write them to SHM. */
+ ie = bcn->u.beacon.variable;
+ variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ for (i = 0; i < variable_len - 2; ) {
+ uint8_t ie_id, ie_len;
+
+ ie_id = ie[i];
+ ie_len = ie[i + 1];
+ if (ie_id == 5) {
+ u16 tim_position;
+ u16 dtim_period;
+ /* This is the TIM Information Element */
+
+ /* Check whether the ie_len is in the beacon data range. */
+ if (variable_len < ie_len + 2 + i)
+ break;
+ /* A valid TIM is at least 4 bytes long. */
+ if (ie_len < 4)
+ break;
+ tim_found = 1;
+
+ tim_position = sizeof(struct b43_plcp_hdr6);
+ tim_position += offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ tim_position += i;
+
+ dtim_period = ie[i + 3];
+
+ b43_shm_write16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_TIMBPOS, tim_position);
+ b43_shm_write16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_DTIMPER, dtim_period);
+ break;
+ }
+ i += ie_len + 2;
+ }
+ if (!tim_found) {
+ b43warn(dev->wl, "Did not find a valid TIM IE in "
+ "the beacon template packet. AP or IBSS operation "
+ "may be broken.\n");
+ }
}
static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
@@ -1187,7 +1228,7 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
plcp.data = 0;
b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id, size,
+ dev->wl->vif, size,
B43_RATE_TO_BASE100KBPS(rate));
/* Write PLCP in two parts and timing for packet transfer */
tmp = le32_to_cpu(plcp.data);
@@ -1202,40 +1243,43 @@ static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
* 2) Patching duration field
* 3) Stripping TIM
*/
-static u8 *b43_generate_probe_resp(struct b43_wldev *dev,
- u16 * dest_size, u8 rate)
+static const u8 * b43_generate_probe_resp(struct b43_wldev *dev,
+ u16 *dest_size, u8 rate)
{
const u8 *src_data;
u8 *dest_data;
u16 src_size, elem_size, src_pos, dest_pos;
__le16 dur;
struct ieee80211_hdr *hdr;
+ size_t ie_start;
- B43_WARN_ON(!dev->cached_beacon);
- src_size = dev->cached_beacon->len;
- src_data = (const u8 *)dev->cached_beacon->data;
+ src_size = dev->wl->current_beacon->len;
+ src_data = (const u8 *)dev->wl->current_beacon->data;
- if (unlikely(src_size < 0x24)) {
- b43dbg(dev->wl, "b43_generate_probe_resp: " "invalid beacon\n");
+ /* Get the start offset of the variable IEs in the packet. */
+ ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ B43_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, u.beacon.variable));
+
+ if (B43_WARN_ON(src_size < ie_start))
return NULL;
- }
dest_data = kmalloc(src_size, GFP_ATOMIC);
if (unlikely(!dest_data))
return NULL;
- /* 0x24 is offset of first variable-len Information-Element
- * in beacon frame.
- */
- memcpy(dest_data, src_data, 0x24);
- src_pos = dest_pos = 0x24;
- for (; src_pos < src_size - 2; src_pos += elem_size) {
+ /* Copy the static data and all Information Elements, except the TIM. */
+ memcpy(dest_data, src_data, ie_start);
+ src_pos = ie_start;
+ dest_pos = ie_start;
+ for ( ; src_pos < src_size - 2; src_pos += elem_size) {
elem_size = src_data[src_pos + 1] + 2;
- if (src_data[src_pos] != 0x05) { /* TIM */
- memcpy(dest_data + dest_pos, src_data + src_pos,
- elem_size);
- dest_pos += elem_size;
+ if (src_data[src_pos] == 5) {
+ /* This is the TIM. */
+ continue;
}
+ memcpy(dest_data + dest_pos, src_data + src_pos,
+ elem_size);
+ dest_pos += elem_size;
}
*dest_size = dest_pos;
hdr = (struct ieee80211_hdr *)dest_data;
@@ -1244,7 +1288,7 @@ static u8 *b43_generate_probe_resp(struct b43_wldev *dev,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id, *dest_size,
+ dev->wl->vif, *dest_size,
B43_RATE_TO_BASE100KBPS(rate));
hdr->duration_id = dur;
@@ -1255,11 +1299,10 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
u16 ram_offset,
u16 shm_size_offset, u8 rate)
{
- u8 *probe_resp_data;
+ const u8 *probe_resp_data;
u16 size;
- B43_WARN_ON(!dev->cached_beacon);
- size = dev->cached_beacon->len;
+ size = dev->wl->current_beacon->len;
probe_resp_data = b43_generate_probe_resp(dev, &size, rate);
if (unlikely(!probe_resp_data))
return;
@@ -1278,39 +1321,21 @@ static void b43_write_probe_resp_template(struct b43_wldev *dev,
kfree(probe_resp_data);
}
-static int b43_refresh_cached_beacon(struct b43_wldev *dev,
- struct sk_buff *beacon)
-{
- if (dev->cached_beacon)
- kfree_skb(dev->cached_beacon);
- dev->cached_beacon = beacon;
-
- return 0;
-}
-
-static void b43_update_templates(struct b43_wldev *dev)
+/* Asynchronously update the packet templates in template RAM.
+ * Locking: Requires wl->irq_lock to be locked. */
+static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
{
- u32 status;
-
- B43_WARN_ON(!dev->cached_beacon);
+ /* This is the top half of the ansynchronous beacon update.
+ * The bottom half is the beacon IRQ.
+ * Beacon update must be asynchronous to avoid sending an
+ * invalid beacon. This can happen for example, if the firmware
+ * transmits a beacon while we are updating it. */
- b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);
- b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);
- b43_write_probe_resp_template(dev, 0x268, 0x4A, B43_CCK_RATE_11MB);
-
- status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);
- status |= 0x03;
- b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
-}
-
-static void b43_refresh_templates(struct b43_wldev *dev, struct sk_buff *beacon)
-{
- int err;
-
- err = b43_refresh_cached_beacon(dev, beacon);
- if (unlikely(err))
- return;
- b43_update_templates(dev);
+ if (wl->current_beacon)
+ dev_kfree_skb_any(wl->current_beacon);
+ wl->current_beacon = beacon;
+ wl->beacon0_uploaded = 0;
+ wl->beacon1_uploaded = 0;
}
static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
@@ -1346,33 +1371,34 @@ static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
static void handle_irq_beacon(struct b43_wldev *dev)
{
- u32 status;
+ struct b43_wl *wl = dev->wl;
+ u32 cmd;
- if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ if (!b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
return;
- dev->irq_savedstate &= ~B43_IRQ_BEACON;
- status = b43_read32(dev, B43_MMIO_STATUS2_BITFIELD);
+ /* This is the bottom half of the asynchronous beacon update. */
- if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
- /* ACK beacon IRQ. */
- b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
- dev->irq_savedstate |= B43_IRQ_BEACON;
- if (dev->cached_beacon)
- kfree_skb(dev->cached_beacon);
- dev->cached_beacon = NULL;
- return;
- }
- if (!(status & 0x1)) {
- b43_write_beacon_template(dev, 0x68, 0x18, B43_CCK_RATE_1MB);
- status |= 0x1;
- b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
+ cmd = b43_read32(dev, B43_MMIO_MACCMD);
+ if (!(cmd & B43_MACCMD_BEACON0_VALID)) {
+ if (!wl->beacon0_uploaded) {
+ b43_write_beacon_template(dev, 0x68, 0x18,
+ B43_CCK_RATE_1MB);
+ b43_write_probe_resp_template(dev, 0x268, 0x4A,
+ B43_CCK_RATE_11MB);
+ wl->beacon0_uploaded = 1;
+ }
+ cmd |= B43_MACCMD_BEACON0_VALID;
}
- if (!(status & 0x2)) {
- b43_write_beacon_template(dev, 0x468, 0x1A, B43_CCK_RATE_1MB);
- status |= 0x2;
- b43_write32(dev, B43_MMIO_STATUS2_BITFIELD, status);
+ if (!(cmd & B43_MACCMD_BEACON1_VALID)) {
+ if (!wl->beacon1_uploaded) {
+ b43_write_beacon_template(dev, 0x468, 0x1A,
+ B43_CCK_RATE_1MB);
+ wl->beacon1_uploaded = 1;
+ }
+ cmd |= B43_MACCMD_BEACON1_VALID;
}
+ b43_write32(dev, B43_MMIO_MACCMD, cmd);
}
static void handle_irq_ucode_debug(struct b43_wldev *dev)
@@ -1402,8 +1428,17 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
if (unlikely(reason & B43_IRQ_MAC_TXERR))
b43err(dev->wl, "MAC transmission error\n");
- if (unlikely(reason & B43_IRQ_PHY_TXERR))
+ if (unlikely(reason & B43_IRQ_PHY_TXERR)) {
b43err(dev->wl, "PHY transmission error\n");
+ rmb();
+ if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+ atomic_set(&dev->phy.txerr_cnt,
+ B43_PHY_TX_BADNESS_LIMIT);
+ b43err(dev->wl, "Too many PHY TX errors, "
+ "restarting the controller\n");
+ b43_controller_restart(dev, "PHY TX errors");
+ }
+ }
if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
B43_DMAIRQ_NONFATALMASK))) {
@@ -1445,20 +1480,12 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
handle_irq_noise(dev);
/* Check the DMA reason registers for received data. */
- if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
- if (b43_using_pio(dev))
- b43_pio_rx(dev->pio.queue0);
- else
- b43_dma_rx(dev->dma.rx_ring0);
- }
+ if (dma_reason[0] & B43_DMAIRQ_RX_DONE)
+ b43_dma_rx(dev->dma.rx_ring0);
+ if (dma_reason[3] & B43_DMAIRQ_RX_DONE)
+ b43_dma_rx(dev->dma.rx_ring3);
B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE);
- if (dma_reason[3] & B43_DMAIRQ_RX_DONE) {
- if (b43_using_pio(dev))
- b43_pio_rx(dev->pio.queue3);
- else
- b43_dma_rx(dev->dma.rx_ring3);
- }
B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE);
B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE);
@@ -1470,29 +1497,8 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
}
-static void pio_irq_workaround(struct b43_wldev *dev, u16 base, int queueidx)
-{
- u16 rxctl;
-
- rxctl = b43_read16(dev, base + B43_PIO_RXCTL);
- if (rxctl & B43_PIO_RXCTL_DATAAVAILABLE)
- dev->dma_reason[queueidx] |= B43_DMAIRQ_RX_DONE;
- else
- dev->dma_reason[queueidx] &= ~B43_DMAIRQ_RX_DONE;
-}
-
static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
{
- if (b43_using_pio(dev) &&
- (dev->dev->id.revision < 3) &&
- (!(reason & B43_IRQ_PIO_WORKAROUND))) {
- /* Apply a PIO specific workaround to the dma_reasons */
- pio_irq_workaround(dev, B43_MMIO_PIO1_BASE, 0);
- pio_irq_workaround(dev, B43_MMIO_PIO2_BASE, 1);
- pio_irq_workaround(dev, B43_MMIO_PIO3_BASE, 2);
- pio_irq_workaround(dev, B43_MMIO_PIO4_BASE, 3);
- }
-
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);
b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);
@@ -1551,54 +1557,73 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
return ret;
}
+static void do_release_fw(struct b43_firmware_file *fw)
+{
+ release_firmware(fw->data);
+ fw->data = NULL;
+ fw->filename = NULL;
+}
+
static void b43_release_firmware(struct b43_wldev *dev)
{
- release_firmware(dev->fw.ucode);
- dev->fw.ucode = NULL;
- release_firmware(dev->fw.pcm);
- dev->fw.pcm = NULL;
- release_firmware(dev->fw.initvals);
- dev->fw.initvals = NULL;
- release_firmware(dev->fw.initvals_band);
- dev->fw.initvals_band = NULL;
+ do_release_fw(&dev->fw.ucode);
+ do_release_fw(&dev->fw.pcm);
+ do_release_fw(&dev->fw.initvals);
+ do_release_fw(&dev->fw.initvals_band);
}
-static void b43_print_fw_helptext(struct b43_wl *wl)
+static void b43_print_fw_helptext(struct b43_wl *wl, bool error)
{
- b43err(wl, "You must go to "
+ const char *text;
+
+ text = "You must go to "
"http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "
- "and download the correct firmware (version 4).\n");
+ "and download the latest firmware (version 4).\n";
+ if (error)
+ b43err(wl, text);
+ else
+ b43warn(wl, text);
}
static int do_request_fw(struct b43_wldev *dev,
const char *name,
- const struct firmware **fw)
+ struct b43_firmware_file *fw)
{
char path[sizeof(modparam_fwpostfix) + 32];
+ const struct firmware *blob;
struct b43_fw_header *hdr;
u32 size;
int err;
- if (!name)
+ if (!name) {
+ /* Don't fetch anything. Free possibly cached firmware. */
+ do_release_fw(fw);
return 0;
+ }
+ if (fw->filename) {
+ if (strcmp(fw->filename, name) == 0)
+ return 0; /* Already have this fw. */
+ /* Free the cached firmware first. */
+ do_release_fw(fw);
+ }
snprintf(path, ARRAY_SIZE(path),
"b43%s/%s.fw",
modparam_fwpostfix, name);
- err = request_firmware(fw, path, dev->dev->dev);
+ err = request_firmware(&blob, path, dev->dev->dev);
if (err) {
b43err(dev->wl, "Firmware file \"%s\" not found "
"or load failed.\n", path);
return err;
}
- if ((*fw)->size < sizeof(struct b43_fw_header))
+ if (blob->size < sizeof(struct b43_fw_header))
goto err_format;
- hdr = (struct b43_fw_header *)((*fw)->data);
+ hdr = (struct b43_fw_header *)(blob->data);
switch (hdr->type) {
case B43_FW_TYPE_UCODE:
case B43_FW_TYPE_PCM:
size = be32_to_cpu(hdr->size);
- if (size != (*fw)->size - sizeof(struct b43_fw_header))
+ if (size != blob->size - sizeof(struct b43_fw_header))
goto err_format;
/* fallthrough */
case B43_FW_TYPE_IV:
@@ -1609,10 +1634,15 @@ static int do_request_fw(struct b43_wldev *dev,
goto err_format;
}
- return err;
+ fw->data = blob;
+ fw->filename = name;
+
+ return 0;
err_format:
b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);
+ release_firmware(blob);
+
return -EPROTO;
}
@@ -1624,90 +1654,101 @@ static int b43_request_firmware(struct b43_wldev *dev)
u32 tmshigh;
int err;
+ /* Get microcode */
tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
- if (!fw->ucode) {
+ if ((rev >= 5) && (rev <= 10))
+ filename = "ucode5";
+ else if ((rev >= 11) && (rev <= 12))
+ filename = "ucode11";
+ else if (rev >= 13)
+ filename = "ucode13";
+ else
+ goto err_no_ucode;
+ err = do_request_fw(dev, filename, &fw->ucode);
+ if (err)
+ goto err_load;
+
+ /* Get PCM code */
+ if ((rev >= 5) && (rev <= 10))
+ filename = "pcm5";
+ else if (rev >= 11)
+ filename = NULL;
+ else
+ goto err_no_pcm;
+ err = do_request_fw(dev, filename, &fw->pcm);
+ if (err)
+ goto err_load;
+
+ /* Get initvals */
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ if ((rev >= 5) && (rev <= 10)) {
+ if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
+ filename = "a0g1initvals5";
+ else
+ filename = "a0g0initvals5";
+ } else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_G:
if ((rev >= 5) && (rev <= 10))
- filename = "ucode5";
- else if ((rev >= 11) && (rev <= 12))
- filename = "ucode11";
+ filename = "b0g0initvals5";
else if (rev >= 13)
- filename = "ucode13";
+ filename = "lp0initvals13";
else
- goto err_no_ucode;
- err = do_request_fw(dev, filename, &fw->ucode);
- if (err)
- goto err_load;
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_N:
+ if ((rev >= 11) && (rev <= 12))
+ filename = "n0initvals11";
+ else
+ goto err_no_initvals;
+ break;
+ default:
+ goto err_no_initvals;
}
- if (!fw->pcm) {
+ err = do_request_fw(dev, filename, &fw->initvals);
+ if (err)
+ goto err_load;
+
+ /* Get bandswitch initvals */
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ if ((rev >= 5) && (rev <= 10)) {
+ if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY)
+ filename = "a0g1bsinitvals5";
+ else
+ filename = "a0g0bsinitvals5";
+ } else if (rev >= 11)
+ filename = NULL;
+ else
+ goto err_no_initvals;
+ break;
+ case B43_PHYTYPE_G:
if ((rev >= 5) && (rev <= 10))
- filename = "pcm5";
+ filename = "b0g0bsinitvals5";
else if (rev >= 11)
filename = NULL;
else
- goto err_no_pcm;
- err = do_request_fw(dev, filename, &fw->pcm);
- if (err)
- goto err_load;
- }
- if (!fw->initvals) {
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- if ((rev >= 5) && (rev <= 10)) {
- if (tmshigh & B43_TMSHIGH_GPHY)
- filename = "a0g1initvals5";
- else
- filename = "a0g0initvals5";
- } else
- goto err_no_initvals;
- break;
- case B43_PHYTYPE_G:
- if ((rev >= 5) && (rev <= 10))
- filename = "b0g0initvals5";
- else if (rev >= 13)
- filename = "lp0initvals13";
- else
- goto err_no_initvals;
- break;
- default:
goto err_no_initvals;
- }
- err = do_request_fw(dev, filename, &fw->initvals);
- if (err)
- goto err_load;
- }
- if (!fw->initvals_band) {
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- if ((rev >= 5) && (rev <= 10)) {
- if (tmshigh & B43_TMSHIGH_GPHY)
- filename = "a0g1bsinitvals5";
- else
- filename = "a0g0bsinitvals5";
- } else if (rev >= 11)
- filename = NULL;
- else
- goto err_no_initvals;
- break;
- case B43_PHYTYPE_G:
- if ((rev >= 5) && (rev <= 10))
- filename = "b0g0bsinitvals5";
- else if (rev >= 11)
- filename = NULL;
- else
- goto err_no_initvals;
- break;
- default:
+ break;
+ case B43_PHYTYPE_N:
+ if ((rev >= 11) && (rev <= 12))
+ filename = "n0bsinitvals11";
+ else
goto err_no_initvals;
- }
- err = do_request_fw(dev, filename, &fw->initvals_band);
- if (err)
- goto err_load;
+ break;
+ default:
+ goto err_no_initvals;
}
+ err = do_request_fw(dev, filename, &fw->initvals_band);
+ if (err)
+ goto err_load;
return 0;
err_load:
- b43_print_fw_helptext(dev->wl);
+ b43_print_fw_helptext(dev->wl, 1);
goto error;
err_no_ucode:
@@ -1737,22 +1778,33 @@ static int b43_upload_microcode(struct b43_wldev *dev)
const __be32 *data;
unsigned int i, len;
u16 fwrev, fwpatch, fwdate, fwtime;
- u32 tmp;
+ u32 tmp, macctl;
int err = 0;
+ /* Jump the microcode PSM to offset 0 */
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ B43_WARN_ON(macctl & B43_MACCTL_PSM_RUN);
+ macctl |= B43_MACCTL_PSM_JMP0;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
+ /* Zero out all microcode PSM registers and shared memory. */
+ for (i = 0; i < 64; i++)
+ b43_shm_write16(dev, B43_SHM_SCRATCH, i, 0);
+ for (i = 0; i < 4096; i += 2)
+ b43_shm_write16(dev, B43_SHM_SHARED, i, 0);
+
/* Upload Microcode. */
- data = (__be32 *) (dev->fw.ucode->data + hdr_len);
- len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
+ data = (__be32 *) (dev->fw.ucode.data->data + hdr_len);
+ len = (dev->fw.ucode.data->size - hdr_len) / sizeof(__be32);
b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);
for (i = 0; i < len; i++) {
b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));
udelay(10);
}
- if (dev->fw.pcm) {
+ if (dev->fw.pcm.data) {
/* Upload PCM data. */
- data = (__be32 *) (dev->fw.pcm->data + hdr_len);
- len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32);
+ data = (__be32 *) (dev->fw.pcm.data->data + hdr_len);
+ len = (dev->fw.pcm.data->size - hdr_len) / sizeof(__be32);
b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);
b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);
/* No need for autoinc bit in SHM_HW */
@@ -1764,9 +1816,12 @@ static int b43_upload_microcode(struct b43_wldev *dev)
}
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);
- b43_write32(dev, B43_MMIO_MACCTL,
- B43_MACCTL_PSM_RUN |
- B43_MACCTL_IHR_ENABLED | B43_MACCTL_INFRA);
+
+ /* Start the microcode PSM */
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ macctl &= ~B43_MACCTL_PSM_JMP0;
+ macctl |= B43_MACCTL_PSM_RUN;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Wait for the microcode to load and respond */
i = 0;
@@ -1775,13 +1830,17 @@ static int b43_upload_microcode(struct b43_wldev *dev)
if (tmp == B43_IRQ_MAC_SUSPENDED)
break;
i++;
- if (i >= 50) {
+ if (i >= 20) {
b43err(dev->wl, "Microcode not responding\n");
- b43_print_fw_helptext(dev->wl);
+ b43_print_fw_helptext(dev->wl, 1);
err = -ENODEV;
- goto out;
+ goto error;
+ }
+ msleep_interruptible(50);
+ if (signal_pending(current)) {
+ err = -EINTR;
+ goto error;
}
- udelay(10);
}
b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); /* dummy read */
@@ -1795,10 +1854,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "
"binary drivers older than version 4.x is unsupported. "
"You must upgrade your firmware files.\n");
- b43_print_fw_helptext(dev->wl);
- b43_write32(dev, B43_MMIO_MACCTL, 0);
+ b43_print_fw_helptext(dev->wl, 1);
err = -EOPNOTSUPP;
- goto out;
+ goto error;
}
b43dbg(dev->wl, "Loading firmware version %u.%u "
"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
@@ -1809,7 +1867,20 @@ static int b43_upload_microcode(struct b43_wldev *dev)
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
- out:
+ if (b43_is_old_txhdr_format(dev)) {
+ b43warn(dev->wl, "You are using an old firmware image. "
+ "Support for old firmware will be removed in July 2008.\n");
+ b43_print_fw_helptext(dev->wl, 0);
+ }
+
+ return 0;
+
+error:
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ macctl &= ~B43_MACCTL_PSM_RUN;
+ macctl |= B43_MACCTL_PSM_JMP0;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
+
return err;
}
@@ -1869,7 +1940,7 @@ static int b43_write_initvals(struct b43_wldev *dev,
err_format:
b43err(dev->wl, "Initial Values Firmware file-format error.\n");
- b43_print_fw_helptext(dev->wl);
+ b43_print_fw_helptext(dev->wl, 1);
return -EPROTO;
}
@@ -1883,19 +1954,19 @@ static int b43_upload_initvals(struct b43_wldev *dev)
size_t count;
int err;
- hdr = (const struct b43_fw_header *)(fw->initvals->data);
- ivals = (const struct b43_iv *)(fw->initvals->data + hdr_len);
+ hdr = (const struct b43_fw_header *)(fw->initvals.data->data);
+ ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len);
count = be32_to_cpu(hdr->size);
err = b43_write_initvals(dev, ivals, count,
- fw->initvals->size - hdr_len);
+ fw->initvals.data->size - hdr_len);
if (err)
goto out;
- if (fw->initvals_band) {
- hdr = (const struct b43_fw_header *)(fw->initvals_band->data);
- ivals = (const struct b43_iv *)(fw->initvals_band->data + hdr_len);
+ if (fw->initvals_band.data) {
+ hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data);
+ ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len);
count = be32_to_cpu(hdr->size);
err = b43_write_initvals(dev, ivals, count,
- fw->initvals_band->size - hdr_len);
+ fw->initvals_band.data->size - hdr_len);
if (err)
goto out;
}
@@ -1932,7 +2003,7 @@ static int b43_gpio_init(struct b43_wldev *dev)
mask |= 0x0180;
set |= 0x0180;
}
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) {
b43_write16(dev, B43_MMIO_GPIO_MASK,
b43_read16(dev, B43_MMIO_GPIO_MASK)
| 0x0200);
@@ -2102,6 +2173,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev)
switch (dev->phy.type) {
case B43_PHYTYPE_A:
case B43_PHYTYPE_G:
+ case B43_PHYTYPE_N:
b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1);
b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1);
@@ -2131,13 +2203,19 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
switch (antenna) {
case B43_ANTENNA0:
- ant |= B43_TX4_PHY_ANT0;
+ ant |= B43_TXH_PHY_ANT0;
break;
case B43_ANTENNA1:
- ant |= B43_TX4_PHY_ANT1;
+ ant |= B43_TXH_PHY_ANT1;
+ break;
+ case B43_ANTENNA2:
+ ant |= B43_TXH_PHY_ANT2;
+ break;
+ case B43_ANTENNA3:
+ ant |= B43_TXH_PHY_ANT3;
break;
case B43_ANTENNA_AUTO:
- ant |= B43_TX4_PHY_ANTLAST;
+ ant |= B43_TXH_PHY_ANT01AUTO;
break;
default:
B43_WARN_ON(1);
@@ -2147,15 +2225,15 @@ static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna)
/* For Beacons */
tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
- tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
+ tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, tmp);
/* For ACK/CTS */
tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL);
- tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
+ tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp);
/* For Probe Resposes */
tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL);
- tmp = (tmp & ~B43_TX4_PHY_ANT) | ant;
+ tmp = (tmp & ~B43_TXH_PHY_ANT) | ant;
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp);
}
@@ -2174,11 +2252,15 @@ static int b43_chip_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
int err, tmp;
- u32 value32;
+ u32 value32, macctl;
u16 value16;
- b43_write32(dev, B43_MMIO_MACCTL,
- B43_MACCTL_PSM_JMP0 | B43_MACCTL_IHR_ENABLED);
+ /* Initialize the MAC control */
+ macctl = B43_MACCTL_IHR_ENABLED | B43_MACCTL_SHM_ENABLED;
+ if (dev->phy.gmode)
+ macctl |= B43_MACCTL_GMODE;
+ macctl |= B43_MACCTL_INFRA;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
err = b43_request_firmware(dev);
if (err)
@@ -2223,14 +2305,6 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
| B43_MACCTL_INFRA);
- if (b43_using_pio(dev)) {
- b43_write32(dev, 0x0210, 0x00000100);
- b43_write32(dev, 0x0230, 0x00000100);
- b43_write32(dev, 0x0250, 0x00000100);
- b43_write32(dev, 0x0270, 0x00000100);
- b43_shm_write16(dev, B43_SHM_SHARED, 0x0034, 0x0000);
- }
-
/* Probe Response Timeout value */
/* FIXME: Default to 0, has to be set by ioctl probably... :-/ */
b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000);
@@ -2292,9 +2366,11 @@ static void b43_periodic_every60sec(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ if (phy->type != B43_PHYTYPE_G)
+ return;
if (!b43_has_hardware_pctl(phy))
b43_lo_g_ctl_mark_all_unused(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
b43_mac_suspend(dev);
b43_calc_nrssi_slope(dev);
if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) {
@@ -2346,6 +2422,9 @@ static void b43_periodic_every15sec(struct b43_wldev *dev)
}
b43_phy_xmitpower(dev); //FIXME: unless scanning?
//TODO for APHY (temperature?)
+
+ atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+ wmb();
}
static void do_periodic_work(struct b43_wldev *dev)
@@ -2403,32 +2482,42 @@ static void b43_periodic_tasks_setup(struct b43_wldev *dev)
queue_delayed_work(dev->wl->hw->workqueue, work, 0);
}
-/* Validate access to the chip (SHM) */
+/* Check if communication with the device works correctly. */
static int b43_validate_chipaccess(struct b43_wldev *dev)
{
- u32 value;
- u32 shm_backup;
+ u32 v, backup;
- shm_backup = b43_shm_read32(dev, B43_SHM_SHARED, 0);
- b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA);
- if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
- goto error;
+ backup = b43_shm_read32(dev, B43_SHM_SHARED, 0);
+
+ /* Check for read/write and endianness problems. */
b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55);
if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0x55AAAA55)
goto error;
- b43_shm_write32(dev, B43_SHM_SHARED, 0, shm_backup);
-
- value = b43_read32(dev, B43_MMIO_MACCTL);
- if ((value | B43_MACCTL_GMODE) !=
- (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED))
+ b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA);
+ if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA)
goto error;
- value = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
- if (value)
+ b43_shm_write32(dev, B43_SHM_SHARED, 0, backup);
+
+ if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) {
+ /* The 32bit register shadows the two 16bit registers
+ * with update sideeffects. Validate this. */
+ b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA);
+ b43_write32(dev, B43_MMIO_TSF_CFP_START, 0xCCCCBBBB);
+ if (b43_read16(dev, B43_MMIO_TSF_CFP_START_LOW) != 0xBBBB)
+ goto error;
+ if (b43_read16(dev, B43_MMIO_TSF_CFP_START_HIGH) != 0xCCCC)
+ goto error;
+ }
+ b43_write32(dev, B43_MMIO_TSF_CFP_START, 0);
+
+ v = b43_read32(dev, B43_MMIO_MACCTL);
+ v |= B43_MACCTL_GMODE;
+ if (v != (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED))
goto error;
return 0;
- error:
+error:
b43err(dev->wl, "Failed to validate the chipaccess\n");
return -ENODEV;
}
@@ -2491,40 +2580,35 @@ static int b43_rng_init(struct b43_wl *wl)
return err;
}
-static int b43_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
+static int b43_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
int err = -ENODEV;
- unsigned long flags;
if (unlikely(!dev))
goto out;
if (unlikely(b43_status(dev) < B43_STAT_STARTED))
goto out;
/* DMA-TX is done without a global lock. */
- if (b43_using_pio(dev)) {
- spin_lock_irqsave(&wl->irq_lock, flags);
- err = b43_pio_tx(dev, skb, ctl);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- } else
- err = b43_dma_tx(dev, skb, ctl);
- out:
+ err = b43_dma_tx(dev, skb, ctl);
+out:
if (unlikely(err))
return NETDEV_TX_BUSY;
return NETDEV_TX_OK;
}
-static int b43_conf_tx(struct ieee80211_hw *hw,
- int queue,
- const struct ieee80211_tx_queue_params *params)
+static int b43_op_conf_tx(struct ieee80211_hw *hw,
+ int queue,
+ const struct ieee80211_tx_queue_params *params)
{
return 0;
}
-static int b43_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
+static int b43_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -2535,19 +2619,16 @@ static int b43_get_tx_stats(struct ieee80211_hw *hw,
goto out;
spin_lock_irqsave(&wl->irq_lock, flags);
if (likely(b43_status(dev) >= B43_STAT_STARTED)) {
- if (b43_using_pio(dev))
- b43_pio_get_tx_stats(dev, stats);
- else
- b43_dma_get_tx_stats(dev, stats);
+ b43_dma_get_tx_stats(dev, stats);
err = 0;
}
spin_unlock_irqrestore(&wl->irq_lock, flags);
- out:
+out:
return err;
}
-static int b43_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int b43_op_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
unsigned long flags;
@@ -2686,8 +2767,36 @@ static int b43_switch_phymode(struct b43_wl *wl, unsigned int new_mode)
return err;
}
-static int b43_antenna_from_ieee80211(u8 antenna)
+/* Check if the use of the antenna that ieee80211 told us to
+ * use is possible. This will fall back to DEFAULT.
+ * "antenna_nr" is the antenna identifier we got from ieee80211. */
+u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+ u8 antenna_nr)
+{
+ u8 antenna_mask;
+
+ if (antenna_nr == 0) {
+ /* Zero means "use default antenna". That's always OK. */
+ return 0;
+ }
+
+ /* Get the mask of available antennas. */
+ if (dev->phy.gmode)
+ antenna_mask = dev->dev->bus->sprom.ant_available_bg;
+ else
+ antenna_mask = dev->dev->bus->sprom.ant_available_a;
+
+ if (!(antenna_mask & (1 << (antenna_nr - 1)))) {
+ /* This antenna is not available. Fall back to default. */
+ return 0;
+ }
+
+ return antenna_nr;
+}
+
+static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
{
+ antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
switch (antenna) {
case 0: /* default/diversity */
return B43_ANTENNA_DEFAULT;
@@ -2695,26 +2804,26 @@ static int b43_antenna_from_ieee80211(u8 antenna)
return B43_ANTENNA0;
case 2: /* Antenna 1 */
return B43_ANTENNA1;
+ case 3: /* Antenna 2 */
+ return B43_ANTENNA2;
+ case 4: /* Antenna 3 */
+ return B43_ANTENNA3;
default:
return B43_ANTENNA_DEFAULT;
}
}
-static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
struct b43_phy *phy;
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
- int antenna_tx;
- int antenna_rx;
+ int antenna;
int err = 0;
u32 savedirqs;
- antenna_tx = b43_antenna_from_ieee80211(conf->antenna_sel_tx);
- antenna_rx = b43_antenna_from_ieee80211(conf->antenna_sel_rx);
-
mutex_lock(&wl->mutex);
/* Switch the PHY mode (if necessary). */
@@ -2764,6 +2873,8 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
b43_short_slot_timing_disable(dev);
}
+ dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
if (conf->power_level != phy->power_level) {
@@ -2773,8 +2884,10 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
}
/* Antennas for RX and management frame TX. */
- b43_mgmtframe_txantenna(dev, antenna_tx);
- b43_set_rx_antenna(dev, antenna_rx);
+ antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
+ b43_mgmtframe_txantenna(dev, antenna);
+ antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
+ b43_set_rx_antenna(dev, antenna);
/* Update templates for AP mode. */
if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
@@ -2805,23 +2918,30 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
return err;
}
-static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev = wl->current_dev;
+ struct b43_wldev *dev;
unsigned long flags;
u8 algorithm;
u8 index;
- int err = -EINVAL;
+ int err;
DECLARE_MAC_BUF(mac);
if (modparam_nohwcrypt)
return -ENOSPC; /* User disabled HW-crypto */
- if (!dev)
- return -ENODEV;
+ mutex_lock(&wl->mutex);
+ spin_lock_irqsave(&wl->irq_lock, flags);
+
+ dev = wl->current_dev;
+ err = -ENODEV;
+ if (!dev || b43_status(dev) < B43_STAT_INITIALIZED)
+ goto out_unlock;
+
+ err = -EINVAL;
switch (key->alg) {
case ALG_WEP:
if (key->keylen == 5)
@@ -2837,20 +2957,11 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
break;
default:
B43_WARN_ON(1);
- goto out;
+ goto out_unlock;
}
-
index = (u8) (key->keyidx);
if (index > 3)
- goto out;
-
- mutex_lock(&wl->mutex);
- spin_lock_irqsave(&wl->irq_lock, flags);
-
- if (b43_status(dev) < B43_STAT_INITIALIZED) {
- err = -ENODEV;
goto out_unlock;
- }
switch (cmd) {
case SET_KEY:
@@ -2896,7 +3007,6 @@ static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
out_unlock:
spin_unlock_irqrestore(&wl->irq_lock, flags);
mutex_unlock(&wl->mutex);
-out:
if (!err) {
b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
"mac: %s\n",
@@ -2906,9 +3016,9 @@ out:
return err;
}
-static void b43_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed, unsigned int *fflags,
- int mc_count, struct dev_addr_list *mc_list)
+static void b43_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed, unsigned int *fflags,
+ int mc_count, struct dev_addr_list *mc_list)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -2943,8 +3053,9 @@ static void b43_configure_filter(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
-static int b43_config_interface(struct ieee80211_hw *hw,
- int if_id, struct ieee80211_if_conf *conf)
+static int b43_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -2954,7 +3065,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
return -ENODEV;
mutex_lock(&wl->mutex);
spin_lock_irqsave(&wl->irq_lock, flags);
- B43_WARN_ON(wl->if_id != if_id);
+ B43_WARN_ON(wl->vif != vif);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
@@ -2964,7 +3075,7 @@ static int b43_config_interface(struct ieee80211_hw *hw,
B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->beacon)
- b43_refresh_templates(dev, conf->beacon);
+ b43_update_templates(wl, conf->beacon);
}
b43_write_mac_bssid_templates(dev);
}
@@ -3067,9 +3178,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
case B43_PHYTYPE_G:
- if (phy_rev > 8)
+ if (phy_rev > 9)
unsupported = 1;
break;
+#ifdef CONFIG_B43_NPHY
+ case B43_PHYTYPE_N:
+ if (phy_rev > 1)
+ unsupported = 1;
+ break;
+#endif
default:
unsupported = 1;
};
@@ -3092,14 +3209,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
tmp = 0x5205017F;
} else {
b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH);
- tmp <<= 16;
+ tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID);
- tmp |= b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
+ tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16;
}
radio_manuf = (tmp & 0x00000FFF);
radio_ver = (tmp & 0x0FFFF000) >> 12;
radio_rev = (tmp & 0xF0000000) >> 28;
+ if (radio_manuf != 0x17F /* Broadcom */)
+ unsupported = 1;
switch (phy_type) {
case B43_PHYTYPE_A:
if (radio_ver != 0x2060)
@@ -3117,6 +3235,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
if (radio_ver != 0x2050)
unsupported = 1;
break;
+ case B43_PHYTYPE_N:
+ if (radio_ver != 0x2055)
+ unsupported = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -3149,9 +3271,6 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
- /* Flags */
- phy->locked = 0;
-
phy->aci_enable = 0;
phy->aci_wlan_automatic = 0;
phy->aci_hw_rssi = 0;
@@ -3178,17 +3297,22 @@ static void setup_struct_phy_for_init(struct b43_wldev *dev,
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- spin_lock_init(&phy->lock);
phy->interfmode = B43_INTERFMODE_NONE;
phy->channel = 0xFF;
phy->hardware_power_control = !!modparam_hwpctl;
+
+ /* PHY TX errors counter. */
+ atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT);
+
+ /* OFDM-table address caching. */
+ phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN;
}
static void setup_struct_wldev_for_init(struct b43_wldev *dev)
{
- /* Flags */
- dev->reg124_set_0x4 = 0;
+ dev->dfq_valid = 0;
+
/* Assume the radio is enabled. If it's not enabled, the state will
* immediately get fixed on the first periodic work run. */
dev->radio_hw_enable = 1;
@@ -3214,13 +3338,13 @@ static void b43_bluetooth_coext_enable(struct b43_wldev *dev)
struct ssb_sprom *sprom = &dev->dev->bus->sprom;
u32 hf;
- if (!(sprom->r1.boardflags_lo & B43_BFL_BTCOEXIST))
+ if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST))
return;
if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode)
return;
hf = b43_hf_read(dev);
- if (sprom->r1.boardflags_lo & B43_BFL_BTCMOD)
+ if (sprom->boardflags_lo & B43_BFL_BTCMOD)
hf |= B43_HF_BTCOEXALT;
else
hf |= B43_HF_BTCOEX;
@@ -3259,20 +3383,42 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
+/* Write the short and long frame retry limit values. */
+static void b43_set_retry_limits(struct b43_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
+{
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
+ short_retry);
+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
+ long_retry);
+}
+
/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43_wireless_core_exit(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
+ u32 macctl;
B43_WARN_ON(b43_status(dev) > B43_STAT_INITIALIZED);
if (b43_status(dev) != B43_STAT_INITIALIZED)
return;
b43_set_status(dev, B43_STAT_UNINIT);
+ /* Stop the microcode PSM. */
+ macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ macctl &= ~B43_MACCTL_PSM_RUN;
+ macctl |= B43_MACCTL_PSM_JMP0;
+ b43_write32(dev, B43_MMIO_MACCTL, macctl);
+
b43_leds_exit(dev);
b43_rng_exit(dev->wl);
- b43_pio_free(dev);
b43_dma_free(dev);
b43_chip_exit(dev);
b43_radio_turn_off(dev, 1);
@@ -3281,6 +3427,11 @@ static void b43_wireless_core_exit(struct b43_wldev *dev)
kfree(phy->tssi2dbm);
kfree(phy->lo_control);
phy->lo_control = NULL;
+ if (dev->wl->current_beacon) {
+ dev_kfree_skb_any(dev->wl->current_beacon);
+ dev->wl->current_beacon = NULL;
+ }
+
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(dev->dev->bus);
}
@@ -3335,7 +3486,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
hf |= B43_HF_SYMW;
if (phy->rev == 1)
hf |= B43_HF_GDCW;
- if (sprom->r1.boardflags_lo & B43_BFL_PACTRL)
+ if (sprom->boardflags_lo & B43_BFL_PACTRL)
hf |= B43_HF_OFDMPABOOST;
} else if (phy->type == B43_PHYTYPE_B) {
hf |= B43_HF_SYMW;
@@ -3344,15 +3495,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
}
b43_hf_write(dev, hf);
- /* Short/Long Retry Limit.
- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter.
- */
- tmp = limit_value(modparam_short_retry, 0, 0xF);
- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, tmp);
- tmp = limit_value(modparam_long_retry, 0, 0xF);
- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, tmp);
-
+ b43_set_retry_limits(dev, B43_DEFAULT_SHORT_RETRY_LIMIT,
+ B43_DEFAULT_LONG_RETRY_LIMIT);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2);
@@ -3373,17 +3517,10 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
/* Maximum Contention Window */
b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF);
- do {
- if (b43_using_pio(dev)) {
- err = b43_pio_init(dev);
- } else {
- err = b43_dma_init(dev);
- if (!err)
- b43_qos_init(dev);
- }
- } while (err == -EAGAIN);
+ err = b43_dma_init(dev);
if (err)
goto err_chip_exit;
+ b43_qos_init(dev);
//FIXME
#if 1
@@ -3421,8 +3558,8 @@ out:
return err;
}
-static int b43_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static int b43_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -3445,7 +3582,7 @@ static int b43_add_interface(struct ieee80211_hw *hw,
dev = wl->current_dev;
wl->operating = 1;
- wl->if_id = conf->if_id;
+ wl->vif = conf->vif;
wl->if_type = conf->type;
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
@@ -3461,8 +3598,8 @@ static int b43_add_interface(struct ieee80211_hw *hw,
return err;
}
-static void b43_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static void b43_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -3473,7 +3610,8 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
B43_WARN_ON(!wl->operating);
- B43_WARN_ON(wl->if_id != conf->if_id);
+ B43_WARN_ON(wl->vif != conf->vif);
+ wl->vif = NULL;
wl->operating = 0;
@@ -3486,7 +3624,7 @@ static void b43_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static int b43_start(struct ieee80211_hw *hw)
+static int b43_op_start(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -3521,7 +3659,7 @@ static int b43_start(struct ieee80211_hw *hw)
return err;
}
-static void b43_stop(struct ieee80211_hw *hw)
+static void b43_op_stop(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev = wl->current_dev;
@@ -3535,19 +3673,76 @@ static void b43_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
+static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry_limit, u32 long_retry_limit)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ b43_set_retry_limits(dev, short_retry_limit, long_retry_limit);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
+
+static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct sk_buff *beacon;
+ unsigned long flags;
+
+ /* We could modify the existing beacon and set the aid bit in
+ * the TIM field, but that would probably require resizing and
+ * moving of data within the beacon template.
+ * Simply request a new beacon and let mac80211 do the hard work. */
+ beacon = ieee80211_beacon_get(hw, wl->vif, NULL);
+ if (unlikely(!beacon))
+ return -ENOMEM;
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43_update_templates(wl, beacon);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ return 0;
+}
+
+static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *beacon,
+ struct ieee80211_tx_control *ctl)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43_update_templates(wl, beacon);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ return 0;
+}
+
static const struct ieee80211_ops b43_hw_ops = {
- .tx = b43_tx,
- .conf_tx = b43_conf_tx,
- .add_interface = b43_add_interface,
- .remove_interface = b43_remove_interface,
- .config = b43_dev_config,
- .config_interface = b43_config_interface,
- .configure_filter = b43_configure_filter,
- .set_key = b43_dev_set_key,
- .get_stats = b43_get_stats,
- .get_tx_stats = b43_get_tx_stats,
- .start = b43_start,
- .stop = b43_stop,
+ .tx = b43_op_tx,
+ .conf_tx = b43_op_conf_tx,
+ .add_interface = b43_op_add_interface,
+ .remove_interface = b43_op_remove_interface,
+ .config = b43_op_config,
+ .config_interface = b43_op_config_interface,
+ .configure_filter = b43_op_configure_filter,
+ .set_key = b43_op_set_key,
+ .get_stats = b43_op_get_stats,
+ .get_tx_stats = b43_op_get_tx_stats,
+ .start = b43_op_start,
+ .stop = b43_op_stop,
+ .set_retry_limit = b43_op_set_retry_limit,
+ .set_tim = b43_op_beacon_set_tim,
+ .beacon_update = b43_op_ibss_beacon_update,
};
/* Hard-reset the chip. Do not call this directly.
@@ -3592,72 +3787,30 @@ static void b43_chip_reset(struct work_struct *work)
}
static int b43_setup_modes(struct b43_wldev *dev,
- int have_aphy, int have_bphy, int have_gphy)
+ bool have_2ghz_phy, bool have_5ghz_phy)
{
struct ieee80211_hw *hw = dev->wl->hw;
struct ieee80211_hw_mode *mode;
struct b43_phy *phy = &dev->phy;
- int cnt = 0;
int err;
-/*FIXME: Don't tell ieee80211 about an A-PHY, because we currently don't support A-PHY. */
- have_aphy = 0;
-
- phy->possible_phymodes = 0;
- for (; 1; cnt++) {
- if (have_aphy) {
- B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
- mode = &phy->hwmodes[cnt];
-
- mode->mode = MODE_IEEE80211A;
- mode->num_channels = b43_a_chantable_size;
- mode->channels = b43_a_chantable;
- mode->num_rates = b43_a_ratetable_size;
- mode->rates = b43_a_ratetable;
- err = ieee80211_register_hwmode(hw, mode);
- if (err)
- return err;
-
- phy->possible_phymodes |= B43_PHYMODE_A;
- have_aphy = 0;
- continue;
- }
- if (have_bphy) {
- B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
- mode = &phy->hwmodes[cnt];
-
- mode->mode = MODE_IEEE80211B;
- mode->num_channels = b43_bg_chantable_size;
- mode->channels = b43_bg_chantable;
- mode->num_rates = b43_b_ratetable_size;
- mode->rates = b43_b_ratetable;
- err = ieee80211_register_hwmode(hw, mode);
- if (err)
- return err;
-
- phy->possible_phymodes |= B43_PHYMODE_B;
- have_bphy = 0;
- continue;
- }
- if (have_gphy) {
- B43_WARN_ON(cnt >= B43_MAX_PHYHWMODES);
- mode = &phy->hwmodes[cnt];
-
- mode->mode = MODE_IEEE80211G;
- mode->num_channels = b43_bg_chantable_size;
- mode->channels = b43_bg_chantable;
- mode->num_rates = b43_g_ratetable_size;
- mode->rates = b43_g_ratetable;
- err = ieee80211_register_hwmode(hw, mode);
- if (err)
- return err;
-
- phy->possible_phymodes |= B43_PHYMODE_G;
- have_gphy = 0;
- continue;
- }
- break;
- }
+ /* XXX: This function will go away soon, when mac80211
+ * band stuff is rewritten. So this is just a hack.
+ * For now we always claim GPHY mode, as there is no
+ * support for NPHY and APHY in the device, yet.
+ * This assumption is OK, as any B, N or A PHY will already
+ * have died a horrible sanity check death earlier. */
+
+ mode = &phy->hwmodes[0];
+ mode->mode = MODE_IEEE80211G;
+ mode->num_channels = b43_2ghz_chantable_size;
+ mode->channels = b43_2ghz_chantable;
+ mode->num_rates = b43_g_ratetable_size;
+ mode->rates = b43_g_ratetable;
+ err = ieee80211_register_hwmode(hw, mode);
+ if (err)
+ return err;
+ phy->possible_phymodes |= B43_PHYMODE_G;
return 0;
}
@@ -3675,7 +3828,7 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
struct ssb_bus *bus = dev->dev->bus;
struct pci_dev *pdev = bus->host_pci;
int err;
- int have_aphy = 0, have_bphy = 0, have_gphy = 0;
+ bool have_2ghz_phy = 0, have_5ghz_phy = 0;
u32 tmp;
/* Do NOT do any device initialization here.
@@ -3695,17 +3848,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
u32 tmshigh;
tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
- have_aphy = !!(tmshigh & B43_TMSHIGH_APHY);
- have_gphy = !!(tmshigh & B43_TMSHIGH_GPHY);
- if (!have_aphy && !have_gphy)
- have_bphy = 1;
- } else if (dev->dev->id.revision == 4) {
- have_gphy = 1;
- have_aphy = 1;
+ have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY);
+ have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY);
} else
- have_bphy = 1;
+ B43_WARN_ON(1);
- dev->phy.gmode = (have_gphy || have_bphy);
+ dev->phy.gmode = have_2ghz_phy;
tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
@@ -3717,31 +3865,34 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
(pdev->device != 0x4312 &&
pdev->device != 0x4319 && pdev->device != 0x4324)) {
/* No multiband support. */
- have_aphy = 0;
- have_bphy = 0;
- have_gphy = 0;
+ have_2ghz_phy = 0;
+ have_5ghz_phy = 0;
switch (dev->phy.type) {
case B43_PHYTYPE_A:
- have_aphy = 1;
- break;
- case B43_PHYTYPE_B:
- have_bphy = 1;
+ have_5ghz_phy = 1;
break;
case B43_PHYTYPE_G:
- have_gphy = 1;
+ case B43_PHYTYPE_N:
+ have_2ghz_phy = 1;
break;
default:
B43_WARN_ON(1);
}
}
- dev->phy.gmode = (have_gphy || have_bphy);
+ if (dev->phy.type == B43_PHYTYPE_A) {
+ /* FIXME */
+ b43err(wl, "IEEE 802.11a devices are unsupported\n");
+ err = -EOPNOTSUPP;
+ goto err_powerdown;
+ }
+ dev->phy.gmode = have_2ghz_phy;
tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0;
b43_wireless_core_reset(dev, tmp);
err = b43_validate_chipaccess(dev);
if (err)
goto err_powerdown;
- err = b43_setup_modes(dev, have_aphy, have_bphy, have_gphy);
+ err = b43_setup_modes(dev, have_2ghz_phy, have_5ghz_phy);
if (err)
goto err_powerdown;
@@ -3812,8 +3963,6 @@ static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl)
tasklet_init(&wldev->isr_tasklet,
(void (*)(unsigned long))b43_interrupt_tasklet,
(unsigned long)wldev);
- if (modparam_pio)
- wldev->__using_pio = 1;
INIT_LIST_HEAD(&wldev->list);
err = b43_wireless_core_attach(wldev);
@@ -3838,20 +3987,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus)
/* boardflags workarounds */
if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL &&
bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74)
- bus->sprom.r1.boardflags_lo |= B43_BFL_BTCOEXIST;
+ bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST;
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40)
- bus->sprom.r1.boardflags_lo |= B43_BFL_PACTRL;
-
- /* Handle case when gain is not set in sprom */
- if (bus->sprom.r1.antenna_gain_a == 0xFF)
- bus->sprom.r1.antenna_gain_a = 2;
- if (bus->sprom.r1.antenna_gain_bg == 0xFF)
- bus->sprom.r1.antenna_gain_bg = 2;
-
- /* Convert Antennagain values to Q5.2 */
- bus->sprom.r1.antenna_gain_a <<= 2;
- bus->sprom.r1.antenna_gain_bg <<= 2;
+ bus->sprom.boardflags_lo |= B43_BFL_PACTRL;
}
static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl)
@@ -3878,16 +4017,17 @@ static int b43_wireless_init(struct ssb_device *dev)
}
/* fill hw info */
- hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE |
+ IEEE80211_HW_RX_INCLUDES_FCS;
hw->max_signal = 100;
hw->max_rssi = -110;
hw->max_noise = -110;
hw->queues = 1; /* FIXME: hardware has more queues */
SET_IEEE80211_DEV(hw, dev->dev);
- if (is_valid_ether_addr(sprom->r1.et1mac))
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+ if (is_valid_ether_addr(sprom->et1mac))
+ SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
else
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+ SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
/* Get and initialize struct b43_wl */
wl = hw_to_b43_wl(hw);
@@ -3895,6 +4035,7 @@ static int b43_wireless_init(struct ssb_device *dev)
wl->hw = hw;
spin_lock_init(&wl->irq_lock);
spin_lock_init(&wl->leds_lock);
+ spin_lock_init(&wl->shm_lock);
mutex_init(&wl->mutex);
INIT_LIST_HEAD(&wl->devlist);
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 08e2e56e48f4..2d52d9de9305 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mb@bu3sch.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -84,6 +84,9 @@ static inline int b43_is_ofdm_rate(int rate)
return !b43_is_cck_rate(rate);
}
+u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
+ u8 antenna_nr);
+
void b43_tsf_read(struct b43_wldev *dev, u64 * tsf);
void b43_tsf_write(struct b43_wldev *dev, u64 tsf);
diff --git a/drivers/net/wireless/b43/nphy.c b/drivers/net/wireless/b43/nphy.c
new file mode 100644
index 000000000000..705131ef4bfa
--- /dev/null
+++ b/drivers/net/wireless/b43/nphy.c
@@ -0,0 +1,489 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n PHY support
+
+ Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include <linux/delay.h>
+#include <linux/types.h>
+
+#include "b43.h"
+#include "nphy.h"
+#include "tables_nphy.h"
+
+#include <linux/delay.h>
+
+
+void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
+{//TODO
+}
+
+void b43_nphy_xmitpower(struct b43_wldev *dev)
+{//TODO
+}
+
+static void b43_chantab_radio_upload(struct b43_wldev *dev,
+ const struct b43_nphy_channeltab_entry *e)
+{
+ b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref);
+ b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
+ b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
+ b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
+ b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
+ b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
+ b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
+ b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
+ b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
+ b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
+ b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
+ b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
+ b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
+ b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
+ b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
+ b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
+ b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
+ b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
+ b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
+ b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
+ b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
+ b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
+}
+
+static void b43_chantab_phy_upload(struct b43_wldev *dev,
+ const struct b43_nphy_channeltab_entry *e)
+{
+ b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
+ b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
+ b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
+ b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
+ b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
+ b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
+}
+
+static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
+{
+ //TODO
+}
+
+/* Tune the hardware to a new channel. Don't call this directly.
+ * Use b43_radio_selectchannel() */
+int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel)
+{
+ const struct b43_nphy_channeltab_entry *tabent;
+
+ tabent = b43_nphy_get_chantabent(dev, channel);
+ if (!tabent)
+ return -ESRCH;
+
+ //FIXME enable/disable band select upper20 in RXCTL
+ if (0 /*FIXME 5Ghz*/)
+ b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20);
+ else
+ b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50);
+ b43_chantab_radio_upload(dev, tabent);
+ udelay(50);
+ b43_radio_write16(dev, B2055_VCO_CAL10, 5);
+ b43_radio_write16(dev, B2055_VCO_CAL10, 45);
+ b43_radio_write16(dev, B2055_VCO_CAL10, 65);
+ udelay(300);
+ if (0 /*FIXME 5Ghz*/)
+ b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
+ else
+ b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
+ b43_chantab_phy_upload(dev, tabent);
+ b43_nphy_tx_power_fix(dev);
+
+ return 0;
+}
+
+static void b43_radio_init2055_pre(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_PORFORCE);
+ b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+ B43_NPHY_RFCTL_CMD_CHIP0PU |
+ B43_NPHY_RFCTL_CMD_OEPORFORCE);
+ b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
+ B43_NPHY_RFCTL_CMD_PORFORCE);
+}
+
+static void b43_radio_init2055_post(struct b43_wldev *dev)
+{
+ struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+ struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo);
+ int i;
+ u16 val;
+
+ b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
+ msleep(1);
+ if ((sprom->revision != 4) || !(sprom->boardflags_hi & 0x0002)) {
+ if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) ||
+ (binfo->type != 0x46D) ||
+ (binfo->rev < 0x41)) {
+ b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
+ b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
+ msleep(1);
+ }
+ }
+ b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C);
+ msleep(1);
+ b43_radio_write16(dev, B2055_CAL_MISC, 0x3C);
+ msleep(1);
+ b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
+ msleep(1);
+ b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
+ msleep(1);
+ b43_radio_set(dev, B2055_CAL_MISC, 0x1);
+ msleep(1);
+ b43_radio_set(dev, B2055_CAL_MISC, 0x40);
+ msleep(1);
+ for (i = 0; i < 100; i++) {
+ val = b43_radio_read16(dev, B2055_CAL_COUT2);
+ if (val & 0x80)
+ break;
+ udelay(10);
+ }
+ msleep(1);
+ b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
+ msleep(1);
+ b43_radio_selectchannel(dev, dev->phy.channel, 0);
+ b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9);
+ b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9);
+ b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
+ b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
+}
+
+/* Initialize a Broadcom 2055 N-radio */
+static void b43_radio_init2055(struct b43_wldev *dev)
+{
+ b43_radio_init2055_pre(dev);
+ if (b43_status(dev) < B43_STAT_INITIALIZED)
+ b2055_upload_inittab(dev, 0, 1);
+ else
+ b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
+ b43_radio_init2055_post(dev);
+}
+
+void b43_nphy_radio_turn_on(struct b43_wldev *dev)
+{
+ b43_radio_init2055(dev);
+}
+
+void b43_nphy_radio_turn_off(struct b43_wldev *dev)
+{
+ b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
+ ~B43_NPHY_RFCTL_CMD_EN);
+}
+
+#define ntab_upload(dev, offset, data) do { \
+ unsigned int i; \
+ for (i = 0; i < (offset##_SIZE); i++) \
+ b43_ntab_write(dev, (offset) + i, (data)[i]); \
+ } while (0)
+
+/* Upload the N-PHY tables. */
+static void b43_nphy_tables_init(struct b43_wldev *dev)
+{
+ /* Static tables */
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
+ ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
+ ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
+ ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
+ ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
+ ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
+ ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
+ ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
+ ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
+ ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
+ ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
+ ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
+ ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
+ ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
+
+ /* Volatile tables */
+ ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
+ ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
+ ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
+ ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
+}
+
+static void b43_nphy_workarounds(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ unsigned int i;
+
+ b43_phy_set(dev, B43_NPHY_IQFLIP,
+ B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
+ //FIXME the following condition is different in the specs.
+ if (1 /* FIXME band is 2.4GHz */) {
+ b43_phy_set(dev, B43_NPHY_CLASSCTL,
+ B43_NPHY_CLASSCTL_CCKEN);
+ } else {
+ b43_phy_mask(dev, B43_NPHY_CLASSCTL,
+ ~B43_NPHY_CLASSCTL_CCKEN);
+ }
+ b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
+ b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8);
+
+ /* Fixup some tables */
+ b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800);
+ b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800);
+
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
+ b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
+
+ //TODO set RF sequence
+
+ /* Set narrowband clip threshold */
+ b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66);
+ b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66);
+
+ /* Set wideband clip 2 threshold */
+ b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+ ~B43_NPHY_C1_CLIPWBTHRES_CLIP2,
+ 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+ ~B43_NPHY_C2_CLIPWBTHRES_CLIP2,
+ 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT);
+
+ /* Set Clip 2 detect */
+ b43_phy_set(dev, B43_NPHY_C1_CGAINI,
+ B43_NPHY_C1_CGAINI_CL2DETECT);
+ b43_phy_set(dev, B43_NPHY_C2_CGAINI,
+ B43_NPHY_C2_CGAINI_CL2DETECT);
+
+ if (0 /*FIXME*/) {
+ /* Set dwell lengths */
+ b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43);
+ b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43);
+ b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9);
+ b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9);
+
+ /* Set gain backoff */
+ b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
+ ~B43_NPHY_C1_CGAINI_GAINBKOFF,
+ 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
+ ~B43_NPHY_C2_CGAINI_GAINBKOFF,
+ 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT);
+
+ /* Set HPVGA2 index */
+ b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN,
+ ~B43_NPHY_C1_INITGAIN_HPVGA2,
+ 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN,
+ ~B43_NPHY_C2_INITGAIN_HPVGA2,
+ 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
+
+ //FIXME verify that the specs really mean to use autoinc here.
+ for (i = 0; i < 3; i++)
+ b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673);
+ }
+
+ /* Set minimum gain value */
+ b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN,
+ ~B43_NPHY_C1_MINGAIN,
+ 23 << B43_NPHY_C1_MINGAIN_SHIFT);
+ b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN,
+ ~B43_NPHY_C2_MINGAIN,
+ 23 << B43_NPHY_C2_MINGAIN_SHIFT);
+
+ if (phy->rev < 2) {
+ b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
+ ~B43_NPHY_SCRAM_SIGCTL_SCM);
+ }
+
+ /* Set phase track alpha and beta */
+ b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
+ b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
+ b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
+}
+
+static void b43_nphy_reset_cca(struct b43_wldev *dev)
+{
+ u16 bbcfg;
+
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC);
+ bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
+ b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA);
+ b43_phy_write(dev, B43_NPHY_BBCFG,
+ bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC);
+}
+
+enum b43_nphy_rf_sequence {
+ B43_RFSEQ_RX2TX,
+ B43_RFSEQ_TX2RX,
+ B43_RFSEQ_RESET2RX,
+ B43_RFSEQ_UPDATE_GAINH,
+ B43_RFSEQ_UPDATE_GAINL,
+ B43_RFSEQ_UPDATE_GAINU,
+};
+
+static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
+ enum b43_nphy_rf_sequence seq)
+{
+ static const u16 trigger[] = {
+ [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX,
+ [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX,
+ [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX,
+ [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH,
+ [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL,
+ [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU,
+ };
+ int i;
+
+ B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
+
+ b43_phy_set(dev, B43_NPHY_RFSEQMODE,
+ B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
+ b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
+ for (i = 0; i < 200; i++) {
+ if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
+ goto ok;
+ msleep(1);
+ }
+ b43err(dev->wl, "RF sequence status timeout\n");
+ok:
+ b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+ ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER));
+}
+
+static void b43_nphy_bphy_init(struct b43_wldev *dev)
+{
+ unsigned int i;
+ u16 val;
+
+ val = 0x1E1F;
+ for (i = 0; i < 14; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
+ val -= 0x202;
+ }
+ val = 0x3E3F;
+ for (i = 0; i < 16; i++) {
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val);
+ val -= 0x202;
+ }
+ b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
+}
+
+/* RSSI Calibration */
+static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type)
+{
+ //TODO
+}
+
+int b43_phy_initn(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ u16 tmp;
+
+ //TODO: Spectral management
+ b43_nphy_tables_init(dev);
+
+ /* Clear all overrides */
+ b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
+ b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
+ b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
+ ~(B43_NPHY_RFSEQMODE_CAOVER |
+ B43_NPHY_RFSEQMODE_TROVER));
+ b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
+
+ tmp = (phy->rev < 2) ? 64 : 59;
+ b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
+ ~B43_NPHY_BPHY_CTL3_SCALE,
+ tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
+
+ b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
+ b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
+
+ b43_phy_write(dev, B43_NPHY_TXREALFD, 184);
+ b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200);
+ b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80);
+ b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511);
+
+ //TODO MIMO-Config
+ //TODO Update TX/RX chain
+
+ if (phy->rev < 2) {
+ b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
+ b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
+ }
+ b43_nphy_workarounds(dev);
+ b43_nphy_reset_cca(dev);
+
+ ssb_write32(dev->dev, SSB_TMSLOW,
+ ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN);
+ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
+ b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
+
+ b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */
+ //TODO read core1/2 clip1 thres regs
+
+ if (1 /* FIXME Band is 2.4GHz */)
+ b43_nphy_bphy_init(dev);
+ //TODO disable TX power control
+ //TODO Fix the TX power settings
+ //TODO Init periodic calibration with reason 3
+ b43_nphy_rssi_cal(dev, 2);
+ b43_nphy_rssi_cal(dev, 0);
+ b43_nphy_rssi_cal(dev, 1);
+ //TODO get TX gain
+ //TODO init superswitch
+ //TODO calibrate LO
+ //TODO idle TSSI TX pctl
+ //TODO TX power control power setup
+ //TODO table writes
+ //TODO TX power control coefficients
+ //TODO enable TX power control
+ //TODO control antenna selection
+ //TODO init radar detection
+ //TODO reset channel if changed
+
+ b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
+ return 0;
+}
diff --git a/drivers/net/wireless/b43/nphy.h b/drivers/net/wireless/b43/nphy.h
new file mode 100644
index 000000000000..5d95118b8193
--- /dev/null
+++ b/drivers/net/wireless/b43/nphy.h
@@ -0,0 +1,932 @@
+#ifndef B43_NPHY_H_
+#define B43_NPHY_H_
+
+#include "phy.h"
+
+
+/* N-PHY registers. */
+
+#define B43_NPHY_BBCFG B43_PHY_N(0x001) /* BB config */
+#define B43_NPHY_BBCFG_RSTCCA 0x4000 /* Reset CCA */
+#define B43_NPHY_BBCFG_RSTRX 0x8000 /* Reset RX */
+#define B43_NPHY_CHANNEL B43_PHY_N(0x005) /* Channel */
+#define B43_NPHY_TXERR B43_PHY_N(0x007) /* TX error */
+#define B43_NPHY_BANDCTL B43_PHY_N(0x009) /* Band control */
+#define B43_NPHY_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */
+#define B43_NPHY_4WI_ADDR B43_PHY_N(0x00B) /* Four-wire bus address */
+#define B43_NPHY_4WI_DATAHI B43_PHY_N(0x00C) /* Four-wire bus data high */
+#define B43_NPHY_4WI_DATALO B43_PHY_N(0x00D) /* Four-wire bus data low */
+#define B43_NPHY_BIST_STAT0 B43_PHY_N(0x00E) /* Built-in self test status 0 */
+#define B43_NPHY_BIST_STAT1 B43_PHY_N(0x00F) /* Built-in self test status 1 */
+
+#define B43_NPHY_C1_DESPWR B43_PHY_N(0x018) /* Core 1 desired power */
+#define B43_NPHY_C1_CCK_DESPWR B43_PHY_N(0x019) /* Core 1 CCK desired power */
+#define B43_NPHY_C1_BCLIPBKOFF B43_PHY_N(0x01A) /* Core 1 barely clip backoff */
+#define B43_NPHY_C1_CCK_BCLIPBKOFF B43_PHY_N(0x01B) /* Core 1 CCK barely clip backoff */
+#define B43_NPHY_C1_CGAINI B43_PHY_N(0x01C) /* Core 1 compute gain info */
+#define B43_NPHY_C1_CGAINI_GAINBKOFF 0x001F /* Gain backoff */
+#define B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT 0
+#define B43_NPHY_C1_CGAINI_CLIPGBKOFF 0x03E0 /* Clip gain backoff */
+#define B43_NPHY_C1_CGAINI_CLIPGBKOFF_SHIFT 5
+#define B43_NPHY_C1_CGAINI_GAINSTEP 0x1C00 /* Gain step */
+#define B43_NPHY_C1_CGAINI_GAINSTEP_SHIFT 10
+#define B43_NPHY_C1_CGAINI_CL2DETECT 0x2000 /* Clip 2 detect mask */
+#define B43_NPHY_C1_CCK_CGAINI B43_PHY_N(0x01D) /* Core 1 CCK compute gain info */
+#define B43_NPHY_C1_CCK_CGAINI_GAINBKOFF 0x001F /* Gain backoff */
+#define B43_NPHY_C1_CCK_CGAINI_CLIPGBKOFF 0x01E0 /* CCK barely clip gain backoff */
+#define B43_NPHY_C1_MINMAX_GAIN B43_PHY_N(0x01E) /* Core 1 min/max gain */
+#define B43_NPHY_C1_MINGAIN 0x00FF /* Minimum gain */
+#define B43_NPHY_C1_MINGAIN_SHIFT 0
+#define B43_NPHY_C1_MAXGAIN 0xFF00 /* Maximum gain */
+#define B43_NPHY_C1_MAXGAIN_SHIFT 8
+#define B43_NPHY_C1_CCK_MINMAX_GAIN B43_PHY_N(0x01F) /* Core 1 CCK min/max gain */
+#define B43_NPHY_C1_CCK_MINGAIN 0x00FF /* Minimum gain */
+#define B43_NPHY_C1_CCK_MINGAIN_SHIFT 0
+#define B43_NPHY_C1_CCK_MAXGAIN 0xFF00 /* Maximum gain */
+#define B43_NPHY_C1_CCK_MAXGAIN_SHIFT 8
+#define B43_NPHY_C1_INITGAIN B43_PHY_N(0x020) /* Core 1 initial gain code */
+#define B43_NPHY_C1_INITGAIN_EXTLNA 0x0001 /* External LNA index */
+#define B43_NPHY_C1_INITGAIN_LNA 0x0006 /* LNA index */
+#define B43_NPHY_C1_INITGAIN_LNAIDX_SHIFT 1
+#define B43_NPHY_C1_INITGAIN_HPVGA1 0x0078 /* HPVGA1 index */
+#define B43_NPHY_C1_INITGAIN_HPVGA1_SHIFT 3
+#define B43_NPHY_C1_INITGAIN_HPVGA2 0x0F80 /* HPVGA2 index */
+#define B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT 7
+#define B43_NPHY_C1_INITGAIN_TRRX 0x1000 /* TR RX index */
+#define B43_NPHY_C1_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_C1_CLIP1_HIGAIN B43_PHY_N(0x021) /* Core 1 clip1 high gain code */
+#define B43_NPHY_C1_CLIP1_MEDGAIN B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */
+#define B43_NPHY_C1_CLIP1_LOGAIN B43_PHY_N(0x023) /* Core 1 clip1 low gain code */
+#define B43_NPHY_C1_CLIP2_GAIN B43_PHY_N(0x024) /* Core 1 clip2 gain code */
+#define B43_NPHY_C1_FILTERGAIN B43_PHY_N(0x025) /* Core 1 filter gain */
+#define B43_NPHY_C1_LPF_QHPF_BW B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */
+#define B43_NPHY_C1_CLIPWBTHRES B43_PHY_N(0x027) /* Core 1 clip wideband threshold */
+#define B43_NPHY_C1_CLIPWBTHRES_CLIP2 0x003F /* Clip 2 */
+#define B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT 0
+#define B43_NPHY_C1_CLIPWBTHRES_CLIP1 0x0FC0 /* Clip 1 */
+#define B43_NPHY_C1_CLIPWBTHRES_CLIP1_SHIFT 6
+#define B43_NPHY_C1_W1THRES B43_PHY_N(0x028) /* Core 1 W1 threshold */
+#define B43_NPHY_C1_EDTHRES B43_PHY_N(0x029) /* Core 1 ED threshold */
+#define B43_NPHY_C1_SMSIGTHRES B43_PHY_N(0x02A) /* Core 1 small sig threshold */
+#define B43_NPHY_C1_NBCLIPTHRES B43_PHY_N(0x02B) /* Core 1 NB clip threshold */
+#define B43_NPHY_C1_CLIP1THRES B43_PHY_N(0x02C) /* Core 1 clip1 threshold */
+#define B43_NPHY_C1_CLIP2THRES B43_PHY_N(0x02D) /* Core 1 clip2 threshold */
+
+#define B43_NPHY_C2_DESPWR B43_PHY_N(0x02E) /* Core 2 desired power */
+#define B43_NPHY_C2_CCK_DESPWR B43_PHY_N(0x02F) /* Core 2 CCK desired power */
+#define B43_NPHY_C2_BCLIPBKOFF B43_PHY_N(0x030) /* Core 2 barely clip backoff */
+#define B43_NPHY_C2_CCK_BCLIPBKOFF B43_PHY_N(0x031) /* Core 2 CCK barely clip backoff */
+#define B43_NPHY_C2_CGAINI B43_PHY_N(0x032) /* Core 2 compute gain info */
+#define B43_NPHY_C2_CGAINI_GAINBKOFF 0x001F /* Gain backoff */
+#define B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT 0
+#define B43_NPHY_C2_CGAINI_CLIPGBKOFF 0x03E0 /* Clip gain backoff */
+#define B43_NPHY_C2_CGAINI_CLIPGBKOFF_SHIFT 5
+#define B43_NPHY_C2_CGAINI_GAINSTEP 0x1C00 /* Gain step */
+#define B43_NPHY_C2_CGAINI_GAINSTEP_SHIFT 10
+#define B43_NPHY_C2_CGAINI_CL2DETECT 0x2000 /* Clip 2 detect mask */
+#define B43_NPHY_C2_CCK_CGAINI B43_PHY_N(0x033) /* Core 2 CCK compute gain info */
+#define B43_NPHY_C2_CCK_CGAINI_GAINBKOFF 0x001F /* Gain backoff */
+#define B43_NPHY_C2_CCK_CGAINI_CLIPGBKOFF 0x01E0 /* CCK barely clip gain backoff */
+#define B43_NPHY_C2_MINMAX_GAIN B43_PHY_N(0x034) /* Core 2 min/max gain */
+#define B43_NPHY_C2_MINGAIN 0x00FF /* Minimum gain */
+#define B43_NPHY_C2_MINGAIN_SHIFT 0
+#define B43_NPHY_C2_MAXGAIN 0xFF00 /* Maximum gain */
+#define B43_NPHY_C2_MAXGAIN_SHIFT 8
+#define B43_NPHY_C2_CCK_MINMAX_GAIN B43_PHY_N(0x035) /* Core 2 CCK min/max gain */
+#define B43_NPHY_C2_CCK_MINGAIN 0x00FF /* Minimum gain */
+#define B43_NPHY_C2_CCK_MINGAIN_SHIFT 0
+#define B43_NPHY_C2_CCK_MAXGAIN 0xFF00 /* Maximum gain */
+#define B43_NPHY_C2_CCK_MAXGAIN_SHIFT 8
+#define B43_NPHY_C2_INITGAIN B43_PHY_N(0x036) /* Core 2 initial gain code */
+#define B43_NPHY_C2_INITGAIN_EXTLNA 0x0001 /* External LNA index */
+#define B43_NPHY_C2_INITGAIN_LNA 0x0006 /* LNA index */
+#define B43_NPHY_C2_INITGAIN_LNAIDX_SHIFT 1
+#define B43_NPHY_C2_INITGAIN_HPVGA1 0x0078 /* HPVGA1 index */
+#define B43_NPHY_C2_INITGAIN_HPVGA1_SHIFT 3
+#define B43_NPHY_C2_INITGAIN_HPVGA2 0x0F80 /* HPVGA2 index */
+#define B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT 7
+#define B43_NPHY_C2_INITGAIN_TRRX 0x1000 /* TR RX index */
+#define B43_NPHY_C2_INITGAIN_TRTX 0x2000 /* TR TX index */
+#define B43_NPHY_C2_CLIP1_HIGAIN B43_PHY_N(0x037) /* Core 2 clip1 high gain code */
+#define B43_NPHY_C2_CLIP1_MEDGAIN B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */
+#define B43_NPHY_C2_CLIP1_LOGAIN B43_PHY_N(0x039) /* Core 2 clip1 low gain code */
+#define B43_NPHY_C2_CLIP2_GAIN B43_PHY_N(0x03A) /* Core 2 clip2 gain code */
+#define B43_NPHY_C2_FILTERGAIN B43_PHY_N(0x03B) /* Core 2 filter gain */
+#define B43_NPHY_C2_LPF_QHPF_BW B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */
+#define B43_NPHY_C2_CLIPWBTHRES B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */
+#define B43_NPHY_C2_CLIPWBTHRES_CLIP2 0x003F /* Clip 2 */
+#define B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT 0
+#define B43_NPHY_C2_CLIPWBTHRES_CLIP1 0x0FC0 /* Clip 1 */
+#define B43_NPHY_C2_CLIPWBTHRES_CLIP1_SHIFT 6
+#define B43_NPHY_C2_W1THRES B43_PHY_N(0x03E) /* Core 2 W1 threshold */
+#define B43_NPHY_C2_EDTHRES B43_PHY_N(0x03F) /* Core 2 ED threshold */
+#define B43_NPHY_C2_SMSIGTHRES B43_PHY_N(0x040) /* Core 2 small sig threshold */
+#define B43_NPHY_C2_NBCLIPTHRES B43_PHY_N(0x041) /* Core 2 NB clip threshold */
+#define B43_NPHY_C2_CLIP1THRES B43_PHY_N(0x042) /* Core 2 clip1 threshold */
+#define B43_NPHY_C2_CLIP2THRES B43_PHY_N(0x043) /* Core 2 clip2 threshold */
+
+#define B43_NPHY_CRS_THRES1 B43_PHY_N(0x044) /* CRS threshold 1 */
+#define B43_NPHY_CRS_THRES2 B43_PHY_N(0x045) /* CRS threshold 2 */
+#define B43_NPHY_CRS_THRES3 B43_PHY_N(0x046) /* CRS threshold 3 */
+#define B43_NPHY_CRSCTL B43_PHY_N(0x047) /* CRS control */
+#define B43_NPHY_DCFADDR B43_PHY_N(0x048) /* DC filter address */
+#define B43_NPHY_RXF20_NUM0 B43_PHY_N(0x049) /* RX filter 20 numerator 0 */
+#define B43_NPHY_RXF20_NUM1 B43_PHY_N(0x04A) /* RX filter 20 numerator 1 */
+#define B43_NPHY_RXF20_NUM2 B43_PHY_N(0x04B) /* RX filter 20 numerator 2 */
+#define B43_NPHY_RXF20_DENOM0 B43_PHY_N(0x04C) /* RX filter 20 denominator 0 */
+#define B43_NPHY_RXF20_DENOM1 B43_PHY_N(0x04D) /* RX filter 20 denominator 1 */
+#define B43_NPHY_RXF20_NUM10 B43_PHY_N(0x04E) /* RX filter 20 numerator 10 */
+#define B43_NPHY_RXF20_NUM11 B43_PHY_N(0x04F) /* RX filter 20 numerator 11 */
+#define B43_NPHY_RXF20_NUM12 B43_PHY_N(0x050) /* RX filter 20 numerator 12 */
+#define B43_NPHY_RXF20_DENOM10 B43_PHY_N(0x051) /* RX filter 20 denominator 10 */
+#define B43_NPHY_RXF20_DENOM11 B43_PHY_N(0x052) /* RX filter 20 denominator 11 */
+#define B43_NPHY_RXF40_NUM0 B43_PHY_N(0x053) /* RX filter 40 numerator 0 */
+#define B43_NPHY_RXF40_NUM1 B43_PHY_N(0x054) /* RX filter 40 numerator 1 */
+#define B43_NPHY_RXF40_NUM2 B43_PHY_N(0x055) /* RX filter 40 numerator 2 */
+#define B43_NPHY_RXF40_DENOM0 B43_PHY_N(0x056) /* RX filter 40 denominator 0 */
+#define B43_NPHY_RXF40_DENOM1 B43_PHY_N(0x057) /* RX filter 40 denominator 1 */
+#define B43_NPHY_RXF40_NUM10 B43_PHY_N(0x058) /* RX filter 40 numerator 10 */
+#define B43_NPHY_RXF40_NUM11 B43_PHY_N(0x059) /* RX filter 40 numerator 11 */
+#define B43_NPHY_RXF40_NUM12 B43_PHY_N(0x05A) /* RX filter 40 numerator 12 */
+#define B43_NPHY_RXF40_DENOM10 B43_PHY_N(0x05B) /* RX filter 40 denominator 10 */
+#define B43_NPHY_RXF40_DENOM11 B43_PHY_N(0x05C) /* RX filter 40 denominator 11 */
+#define B43_NPHY_PPROC_RSTLEN B43_PHY_N(0x060) /* Packet processing reset length */
+#define B43_NPHY_INITCARR_DLEN B43_PHY_N(0x061) /* Initial carrier detection length */
+#define B43_NPHY_CLIP1CARR_DLEN B43_PHY_N(0x062) /* Clip1 carrier detection length */
+#define B43_NPHY_CLIP2CARR_DLEN B43_PHY_N(0x063) /* Clip2 carrier detection length */
+#define B43_NPHY_INITGAIN_SLEN B43_PHY_N(0x064) /* Initial gain settle length */
+#define B43_NPHY_CLIP1GAIN_SLEN B43_PHY_N(0x065) /* Clip1 gain settle length */
+#define B43_NPHY_CLIP2GAIN_SLEN B43_PHY_N(0x066) /* Clip2 gain settle length */
+#define B43_NPHY_PACKGAIN_SLEN B43_PHY_N(0x067) /* Packet gain settle length */
+#define B43_NPHY_CARRSRC_TLEN B43_PHY_N(0x068) /* Carrier search timeout length */
+#define B43_NPHY_TISRC_TLEN B43_PHY_N(0x069) /* Timing search timeout length */
+#define B43_NPHY_ENDROP_TLEN B43_PHY_N(0x06A) /* Energy drop timeout length */
+#define B43_NPHY_CLIP1_NBDWELL_LEN B43_PHY_N(0x06B) /* Clip1 NB dwell length */
+#define B43_NPHY_CLIP2_NBDWELL_LEN B43_PHY_N(0x06C) /* Clip2 NB dwell length */
+#define B43_NPHY_W1CLIP1_DWELL_LEN B43_PHY_N(0x06D) /* W1 clip1 dwell length */
+#define B43_NPHY_W1CLIP2_DWELL_LEN B43_PHY_N(0x06E) /* W1 clip2 dwell length */
+#define B43_NPHY_W2CLIP1_DWELL_LEN B43_PHY_N(0x06F) /* W2 clip1 dwell length */
+#define B43_NPHY_PLOAD_CSENSE_EXTLEN B43_PHY_N(0x070) /* Payload carrier sense extension length */
+#define B43_NPHY_EDROP_CSENSE_EXTLEN B43_PHY_N(0x071) /* Energy drop carrier sense extension length */
+#define B43_NPHY_TABLE_ADDR B43_PHY_N(0x072) /* Table address */
+#define B43_NPHY_TABLE_DATALO B43_PHY_N(0x073) /* Table data low */
+#define B43_NPHY_TABLE_DATAHI B43_PHY_N(0x074) /* Table data high */
+#define B43_NPHY_WWISE_LENIDX B43_PHY_N(0x075) /* WWiSE length index */
+#define B43_NPHY_TGNSYNC_LENIDX B43_PHY_N(0x076) /* TGNsync length index */
+#define B43_NPHY_TXMACIF_HOLDOFF B43_PHY_N(0x077) /* TX MAC IF Hold off */
+#define B43_NPHY_RFCTL_CMD B43_PHY_N(0x078) /* RF control (command) */
+#define B43_NPHY_RFCTL_CMD_START 0x0001 /* Start sequence */
+#define B43_NPHY_RFCTL_CMD_RXTX 0x0002 /* RX/TX */
+#define B43_NPHY_RFCTL_CMD_CORESEL 0x0038 /* Core select */
+#define B43_NPHY_RFCTL_CMD_CORESEL_SHIFT 3
+#define B43_NPHY_RFCTL_CMD_PORFORCE 0x0040 /* POR force */
+#define B43_NPHY_RFCTL_CMD_OEPORFORCE 0x0080 /* OE POR force */
+#define B43_NPHY_RFCTL_CMD_RXEN 0x0100 /* RX enable */
+#define B43_NPHY_RFCTL_CMD_TXEN 0x0200 /* TX enable */
+#define B43_NPHY_RFCTL_CMD_CHIP0PU 0x0400 /* Chip0 PU */
+#define B43_NPHY_RFCTL_CMD_EN 0x0800 /* Radio enabled */
+#define B43_NPHY_RFCTL_CMD_SEQENCORE 0xF000 /* Seq en core */
+#define B43_NPHY_RFCTL_CMD_SEQENCORE_SHIFT 12
+#define B43_NPHY_RFCTL_RSSIO1 B43_PHY_N(0x07A) /* RF control (RSSI others 1) */
+#define B43_NPHY_RFCTL_RSSIO1_RXPD 0x0001 /* RX PD */
+#define B43_NPHY_RFCTL_RSSIO1_TXPD 0x0002 /* TX PD */
+#define B43_NPHY_RFCTL_RSSIO1_PAPD 0x0004 /* PA PD */
+#define B43_NPHY_RFCTL_RSSIO1_RSSICTL 0x0030 /* RSSI control */
+#define B43_NPHY_RFCTL_RSSIO1_LPFBW 0x00C0 /* LPF bandwidth */
+#define B43_NPHY_RFCTL_RSSIO1_HPFBWHI 0x0100 /* HPF bandwidth high */
+#define B43_NPHY_RFCTL_RSSIO1_HIQDISCO 0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG1 B43_PHY_N(0x07B) /* RF control (RX gain 1) */
+#define B43_NPHY_RFCTL_TXG1 B43_PHY_N(0x07C) /* RF control (TX gain 1) */
+#define B43_NPHY_RFCTL_RSSIO2 B43_PHY_N(0x07D) /* RF control (RSSI others 2) */
+#define B43_NPHY_RFCTL_RSSIO2_RXPD 0x0001 /* RX PD */
+#define B43_NPHY_RFCTL_RSSIO2_TXPD 0x0002 /* TX PD */
+#define B43_NPHY_RFCTL_RSSIO2_PAPD 0x0004 /* PA PD */
+#define B43_NPHY_RFCTL_RSSIO2_RSSICTL 0x0030 /* RSSI control */
+#define B43_NPHY_RFCTL_RSSIO2_LPFBW 0x00C0 /* LPF bandwidth */
+#define B43_NPHY_RFCTL_RSSIO2_HPFBWHI 0x0100 /* HPF bandwidth high */
+#define B43_NPHY_RFCTL_RSSIO2_HIQDISCO 0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG2 B43_PHY_N(0x07E) /* RF control (RX gain 2) */
+#define B43_NPHY_RFCTL_TXG2 B43_PHY_N(0x07F) /* RF control (TX gain 2) */
+#define B43_NPHY_RFCTL_RSSIO3 B43_PHY_N(0x080) /* RF control (RSSI others 3) */
+#define B43_NPHY_RFCTL_RSSIO3_RXPD 0x0001 /* RX PD */
+#define B43_NPHY_RFCTL_RSSIO3_TXPD 0x0002 /* TX PD */
+#define B43_NPHY_RFCTL_RSSIO3_PAPD 0x0004 /* PA PD */
+#define B43_NPHY_RFCTL_RSSIO3_RSSICTL 0x0030 /* RSSI control */
+#define B43_NPHY_RFCTL_RSSIO3_LPFBW 0x00C0 /* LPF bandwidth */
+#define B43_NPHY_RFCTL_RSSIO3_HPFBWHI 0x0100 /* HPF bandwidth high */
+#define B43_NPHY_RFCTL_RSSIO3_HIQDISCO 0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG3 B43_PHY_N(0x081) /* RF control (RX gain 3) */
+#define B43_NPHY_RFCTL_TXG3 B43_PHY_N(0x082) /* RF control (TX gain 3) */
+#define B43_NPHY_RFCTL_RSSIO4 B43_PHY_N(0x083) /* RF control (RSSI others 4) */
+#define B43_NPHY_RFCTL_RSSIO4_RXPD 0x0001 /* RX PD */
+#define B43_NPHY_RFCTL_RSSIO4_TXPD 0x0002 /* TX PD */
+#define B43_NPHY_RFCTL_RSSIO4_PAPD 0x0004 /* PA PD */
+#define B43_NPHY_RFCTL_RSSIO4_RSSICTL 0x0030 /* RSSI control */
+#define B43_NPHY_RFCTL_RSSIO4_LPFBW 0x00C0 /* LPF bandwidth */
+#define B43_NPHY_RFCTL_RSSIO4_HPFBWHI 0x0100 /* HPF bandwidth high */
+#define B43_NPHY_RFCTL_RSSIO4_HIQDISCO 0x0200 /* HIQ dis core */
+#define B43_NPHY_RFCTL_RXG4 B43_PHY_N(0x084) /* RF control (RX gain 4) */
+#define B43_NPHY_RFCTL_TXG4 B43_PHY_N(0x085) /* RF control (TX gain 4) */
+#define B43_NPHY_C1_TXIQ_COMP_OFF B43_PHY_N(0x087) /* Core 1 TX I/Q comp offset */
+#define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */
+#define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */
+#define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */
+#define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */
+#define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */
+#define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0
+#define B43_NPHY_SCRAM_SIGCTL_SCM 0x0080 /* Scram control mode */
+#define B43_NPHY_SCRAM_SIGCTL_SICE 0x0100 /* Scram index control enable */
+#define B43_NPHY_SCRAM_SIGCTL_START 0xFE00 /* Scram start bit */
+#define B43_NPHY_SCRAM_SIGCTL_START_SHIFT 9
+#define B43_NPHY_RFCTL_INTC1 B43_PHY_N(0x091) /* RF control (intc 1) */
+#define B43_NPHY_RFCTL_INTC2 B43_PHY_N(0x092) /* RF control (intc 2) */
+#define B43_NPHY_RFCTL_INTC3 B43_PHY_N(0x093) /* RF control (intc 3) */
+#define B43_NPHY_RFCTL_INTC4 B43_PHY_N(0x094) /* RF control (intc 4) */
+#define B43_NPHY_NRDTO_WWISE B43_PHY_N(0x095) /* # datatones WWiSE */
+#define B43_NPHY_NRDTO_TGNSYNC B43_PHY_N(0x096) /* # datatones TGNsync */
+#define B43_NPHY_SIGFMOD_WWISE B43_PHY_N(0x097) /* Signal field mod WWiSE */
+#define B43_NPHY_LEG_SIGFMOD_11N B43_PHY_N(0x098) /* Legacy signal field mod 11n */
+#define B43_NPHY_HT_SIGFMOD_11N B43_PHY_N(0x099) /* HT signal field mod 11n */
+#define B43_NPHY_C1_RXIQ_COMPA0 B43_PHY_N(0x09A) /* Core 1 RX I/Q comp A0 */
+#define B43_NPHY_C1_RXIQ_COMPB0 B43_PHY_N(0x09B) /* Core 1 RX I/Q comp B0 */
+#define B43_NPHY_C2_RXIQ_COMPA1 B43_PHY_N(0x09C) /* Core 2 RX I/Q comp A1 */
+#define B43_NPHY_C2_RXIQ_COMPB1 B43_PHY_N(0x09D) /* Core 2 RX I/Q comp B1 */
+#define B43_NPHY_RXCTL B43_PHY_N(0x0A0) /* RX control */
+#define B43_NPHY_RXCTL_BSELU20 0x0010 /* Band select upper 20 */
+#define B43_NPHY_RXCTL_RIFSEN 0x0080 /* RIFS enable */
+#define B43_NPHY_RFSEQMODE B43_PHY_N(0x0A1) /* RF seq mode */
+#define B43_NPHY_RFSEQMODE_CAOVER 0x0001 /* Core active override */
+#define B43_NPHY_RFSEQMODE_TROVER 0x0002 /* Trigger override */
+#define B43_NPHY_RFSEQCA B43_PHY_N(0x0A2) /* RF seq core active */
+#define B43_NPHY_RFSEQCA_TXEN 0x000F /* TX enable */
+#define B43_NPHY_RFSEQCA_TXEN_SHIFT 0
+#define B43_NPHY_RFSEQCA_RXEN 0x00F0 /* RX enable */
+#define B43_NPHY_RFSEQCA_RXEN_SHIFT 4
+#define B43_NPHY_RFSEQCA_TXDIS 0x0F00 /* TX disable */
+#define B43_NPHY_RFSEQCA_TXDIS_SHIFT 8
+#define B43_NPHY_RFSEQCA_RXDIS 0xF000 /* RX disable */
+#define B43_NPHY_RFSEQCA_RXDIS_SHIFT 12
+#define B43_NPHY_RFSEQTR B43_PHY_N(0x0A3) /* RF seq trigger */
+#define B43_NPHY_RFSEQTR_RX2TX 0x0001 /* RX2TX */
+#define B43_NPHY_RFSEQTR_TX2RX 0x0002 /* TX2RX */
+#define B43_NPHY_RFSEQTR_UPGH 0x0004 /* Update gain H */
+#define B43_NPHY_RFSEQTR_UPGL 0x0008 /* Update gain L */
+#define B43_NPHY_RFSEQTR_UPGU 0x0010 /* Update gain U */
+#define B43_NPHY_RFSEQTR_RST2RX 0x0020 /* Reset to RX */
+#define B43_NPHY_RFSEQST B43_PHY_N(0x0A4) /* RF seq status. Values same as trigger. */
+#define B43_NPHY_AFECTL_OVER B43_PHY_N(0x0A5) /* AFE control override */
+#define B43_NPHY_AFECTL_C1 B43_PHY_N(0x0A6) /* AFE control core 1 */
+#define B43_NPHY_AFECTL_C2 B43_PHY_N(0x0A7) /* AFE control core 2 */
+#define B43_NPHY_AFECTL_C3 B43_PHY_N(0x0A8) /* AFE control core 3 */
+#define B43_NPHY_AFECTL_C4 B43_PHY_N(0x0A9) /* AFE control core 4 */
+#define B43_NPHY_AFECTL_DACGAIN1 B43_PHY_N(0x0AA) /* AFE control DAC gain 1 */
+#define B43_NPHY_AFECTL_DACGAIN2 B43_PHY_N(0x0AB) /* AFE control DAC gain 2 */
+#define B43_NPHY_AFECTL_DACGAIN3 B43_PHY_N(0x0AC) /* AFE control DAC gain 3 */
+#define B43_NPHY_AFECTL_DACGAIN4 B43_PHY_N(0x0AD) /* AFE control DAC gain 4 */
+#define B43_NPHY_STR_ADDR1 B43_PHY_N(0x0AE) /* STR address 1 */
+#define B43_NPHY_STR_ADDR2 B43_PHY_N(0x0AF) /* STR address 2 */
+#define B43_NPHY_CLASSCTL B43_PHY_N(0x0B0) /* Classifier control */
+#define B43_NPHY_CLASSCTL_CCKEN 0x0001 /* CCK enable */
+#define B43_NPHY_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */
+#define B43_NPHY_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */
+#define B43_NPHY_IQFLIP B43_PHY_N(0x0B1) /* I/Q flip */
+#define B43_NPHY_IQFLIP_ADC1 0x0001 /* ADC1 */
+#define B43_NPHY_IQFLIP_ADC2 0x0010 /* ADC2 */
+#define B43_NPHY_SISO_SNR_THRES B43_PHY_N(0x0B2) /* SISO SNR threshold */
+#define B43_NPHY_SIGMA_N_MULT B43_PHY_N(0x0B3) /* Sigma N multiplier */
+#define B43_NPHY_TXMACDELAY B43_PHY_N(0x0B4) /* TX MAC delay */
+#define B43_NPHY_TXFRAMEDELAY B43_PHY_N(0x0B5) /* TX frame delay */
+#define B43_NPHY_MLPARM B43_PHY_N(0x0B6) /* ML parameters */
+#define B43_NPHY_MLCTL B43_PHY_N(0x0B7) /* ML control */
+#define B43_NPHY_WWISE_20NCYCDAT B43_PHY_N(0x0B8) /* WWiSE 20 N cyc data */
+#define B43_NPHY_WWISE_40NCYCDAT B43_PHY_N(0x0B9) /* WWiSE 40 N cyc data */
+#define B43_NPHY_TGNSYNC_20NCYCDAT B43_PHY_N(0x0BA) /* TGNsync 20 N cyc data */
+#define B43_NPHY_TGNSYNC_40NCYCDAT B43_PHY_N(0x0BB) /* TGNsync 40 N cyc data */
+#define B43_NPHY_INITSWIZP B43_PHY_N(0x0BC) /* Initial swizzle pattern */
+#define B43_NPHY_TXTAILCNT B43_PHY_N(0x0BD) /* TX tail count value */
+#define B43_NPHY_BPHY_CTL1 B43_PHY_N(0x0BE) /* B PHY control 1 */
+#define B43_NPHY_BPHY_CTL2 B43_PHY_N(0x0BF) /* B PHY control 2 */
+#define B43_NPHY_BPHY_CTL2_LUT 0x001F /* LUT index */
+#define B43_NPHY_BPHY_CTL2_LUT_SHIFT 0
+#define B43_NPHY_BPHY_CTL2_MACDEL 0x7FE0 /* MAC delay */
+#define B43_NPHY_BPHY_CTL2_MACDEL_SHIFT 5
+#define B43_NPHY_IQLOCAL_CMD B43_PHY_N(0x0C0) /* I/Q LO cal command */
+#define B43_NPHY_IQLOCAL_CMD_EN 0x8000
+#define B43_NPHY_IQLOCAL_CMDNNUM B43_PHY_N(0x0C1) /* I/Q LO cal command N num */
+#define B43_NPHY_IQLOCAL_CMDGCTL B43_PHY_N(0x0C2) /* I/Q LO cal command G control */
+#define B43_NPHY_SAMP_CMD B43_PHY_N(0x0C3) /* Sample command */
+#define B43_NPHY_SAMP_CMD_STOP 0x0002 /* Stop */
+#define B43_NPHY_SAMP_LOOPCNT B43_PHY_N(0x0C4) /* Sample loop count */
+#define B43_NPHY_SAMP_WAITCNT B43_PHY_N(0x0C5) /* Sample wait count */
+#define B43_NPHY_SAMP_DEPCNT B43_PHY_N(0x0C6) /* Sample depth count */
+#define B43_NPHY_SAMP_STAT B43_PHY_N(0x0C7) /* Sample status */
+#define B43_NPHY_GPIO_LOOEN B43_PHY_N(0x0C8) /* GPIO low out enable */
+#define B43_NPHY_GPIO_HIOEN B43_PHY_N(0x0C9) /* GPIO high out enable */
+#define B43_NPHY_GPIO_SEL B43_PHY_N(0x0CA) /* GPIO select */
+#define B43_NPHY_GPIO_CLKCTL B43_PHY_N(0x0CB) /* GPIO clock control */
+#define B43_NPHY_TXF_20CO_AS0 B43_PHY_N(0x0CC) /* TX filter 20 coeff A stage 0 */
+#define B43_NPHY_TXF_20CO_AS1 B43_PHY_N(0x0CD) /* TX filter 20 coeff A stage 1 */
+#define B43_NPHY_TXF_20CO_AS2 B43_PHY_N(0x0CE) /* TX filter 20 coeff A stage 2 */
+#define B43_NPHY_TXF_20CO_B32S0 B43_PHY_N(0x0CF) /* TX filter 20 coeff B32 stage 0 */
+#define B43_NPHY_TXF_20CO_B1S0 B43_PHY_N(0x0D0) /* TX filter 20 coeff B1 stage 0 */
+#define B43_NPHY_TXF_20CO_B32S1 B43_PHY_N(0x0D1) /* TX filter 20 coeff B32 stage 1 */
+#define B43_NPHY_TXF_20CO_B1S1 B43_PHY_N(0x0D2) /* TX filter 20 coeff B1 stage 1 */
+#define B43_NPHY_TXF_20CO_B32S2 B43_PHY_N(0x0D3) /* TX filter 20 coeff B32 stage 2 */
+#define B43_NPHY_TXF_20CO_B1S2 B43_PHY_N(0x0D4) /* TX filter 20 coeff B1 stage 2 */
+#define B43_NPHY_SIGFLDTOL B43_PHY_N(0x0D5) /* Signal fld tolerance */
+#define B43_NPHY_TXSERFLD B43_PHY_N(0x0D6) /* TX service field */
+#define B43_NPHY_AFESEQ_RX2TX_PUD B43_PHY_N(0x0D7) /* AFE seq RX2TX power up/down delay */
+#define B43_NPHY_AFESEQ_TX2RX_PUD B43_PHY_N(0x0D8) /* AFE seq TX2RX power up/down delay */
+#define B43_NPHY_TGNSYNC_SCRAMI0 B43_PHY_N(0x0D9) /* TGNsync scram init 0 */
+#define B43_NPHY_TGNSYNC_SCRAMI1 B43_PHY_N(0x0DA) /* TGNsync scram init 1 */
+#define B43_NPHY_INITSWIZPATTLEG B43_PHY_N(0x0DB) /* Initial swizzle pattern leg */
+#define B43_NPHY_BPHY_CTL3 B43_PHY_N(0x0DC) /* B PHY control 3 */
+#define B43_NPHY_BPHY_CTL3_SCALE 0x00FF /* Scale */
+#define B43_NPHY_BPHY_CTL3_SCALE_SHIFT 0
+#define B43_NPHY_BPHY_CTL3_FSC 0xFF00 /* Frame start count value */
+#define B43_NPHY_BPHY_CTL3_FSC_SHIFT 8
+#define B43_NPHY_BPHY_CTL4 B43_PHY_N(0x0DD) /* B PHY control 4 */
+#define B43_NPHY_C1_TXBBMULT B43_PHY_N(0x0DE) /* Core 1 TX BB multiplier */
+#define B43_NPHY_C2_TXBBMULT B43_PHY_N(0x0DF) /* Core 2 TX BB multiplier */
+#define B43_NPHY_TXF_40CO_AS0 B43_PHY_N(0x0E1) /* TX filter 40 coeff A stage 0 */
+#define B43_NPHY_TXF_40CO_AS1 B43_PHY_N(0x0E2) /* TX filter 40 coeff A stage 1 */
+#define B43_NPHY_TXF_40CO_AS2 B43_PHY_N(0x0E3) /* TX filter 40 coeff A stage 2 */
+#define B43_NPHY_TXF_40CO_B32S0 B43_PHY_N(0x0E4) /* TX filter 40 coeff B32 stage 0 */
+#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
+#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
+#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
+#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
+#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
+#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */
+#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */
+#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */
+#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */
+#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */
+#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */
+#define B43_NPHY_RADAR_BLNKCTL B43_PHY_N(0x0EE) /* Radar blank control */
+#define B43_NPHY_A0RADAR_FIFOCTL B43_PHY_N(0x0EF) /* Antenna 0 radar FIFO control */
+#define B43_NPHY_A1RADAR_FIFOCTL B43_PHY_N(0x0F0) /* Antenna 1 radar FIFO control */
+#define B43_NPHY_A0RADAR_FIFODAT B43_PHY_N(0x0F1) /* Antenna 0 radar FIFO data */
+#define B43_NPHY_A1RADAR_FIFODAT B43_PHY_N(0x0F2) /* Antenna 1 radar FIFO data */
+#define B43_NPHY_RADAR_THRES0 B43_PHY_N(0x0F3) /* Radar threshold 0 */
+#define B43_NPHY_RADAR_THRES1 B43_PHY_N(0x0F4) /* Radar threshold 1 */
+#define B43_NPHY_RADAR_THRES0R B43_PHY_N(0x0F5) /* Radar threshold 0R */
+#define B43_NPHY_RADAR_THRES1R B43_PHY_N(0x0F6) /* Radar threshold 1R */
+#define B43_NPHY_CSEN_20IN40_DLEN B43_PHY_N(0x0F7) /* Carrier sense 20 in 40 dwell length */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO1 B43_PHY_N(0x0F8) /* RF control LUT TRSW lower 1 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP1 B43_PHY_N(0x0F9) /* RF control LUT TRSW upper 1 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO2 B43_PHY_N(0x0FA) /* RF control LUT TRSW lower 2 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP2 B43_PHY_N(0x0FB) /* RF control LUT TRSW upper 2 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO3 B43_PHY_N(0x0FC) /* RF control LUT TRSW lower 3 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP3 B43_PHY_N(0x0FD) /* RF control LUT TRSW upper 3 */
+#define B43_NPHY_RFCTL_LUT_TRSW_LO4 B43_PHY_N(0x0FE) /* RF control LUT TRSW lower 4 */
+#define B43_NPHY_RFCTL_LUT_TRSW_UP4 B43_PHY_N(0x0FF) /* RF control LUT TRSW upper 4 */
+#define B43_NPHY_RFCTL_LUT_LNAPA1 B43_PHY_N(0x100) /* RF control LUT LNA PA 1 */
+#define B43_NPHY_RFCTL_LUT_LNAPA2 B43_PHY_N(0x101) /* RF control LUT LNA PA 2 */
+#define B43_NPHY_RFCTL_LUT_LNAPA3 B43_PHY_N(0x102) /* RF control LUT LNA PA 3 */
+#define B43_NPHY_RFCTL_LUT_LNAPA4 B43_PHY_N(0x103) /* RF control LUT LNA PA 4 */
+#define B43_NPHY_TGNSYNC_CRCM0 B43_PHY_N(0x104) /* TGNsync CRC mask 0 */
+#define B43_NPHY_TGNSYNC_CRCM1 B43_PHY_N(0x105) /* TGNsync CRC mask 1 */
+#define B43_NPHY_TGNSYNC_CRCM2 B43_PHY_N(0x106) /* TGNsync CRC mask 2 */
+#define B43_NPHY_TGNSYNC_CRCM3 B43_PHY_N(0x107) /* TGNsync CRC mask 3 */
+#define B43_NPHY_TGNSYNC_CRCM4 B43_PHY_N(0x108) /* TGNsync CRC mask 4 */
+#define B43_NPHY_CRCPOLY B43_PHY_N(0x109) /* CRC polynomial */
+#define B43_NPHY_SIGCNT B43_PHY_N(0x10A) /* # sig count */
+#define B43_NPHY_SIGSTARTBIT_CTL B43_PHY_N(0x10B) /* Sig start bit control */
+#define B43_NPHY_CRCPOLY_ORDER B43_PHY_N(0x10C) /* CRC polynomial order */
+#define B43_NPHY_RFCTL_CST0 B43_PHY_N(0x10D) /* RF control core swap table 0 */
+#define B43_NPHY_RFCTL_CST1 B43_PHY_N(0x10E) /* RF control core swap table 1 */
+#define B43_NPHY_RFCTL_CST2O B43_PHY_N(0x10F) /* RF control core swap table 2 + others */
+#define B43_NPHY_BPHY_CTL5 B43_PHY_N(0x111) /* B PHY control 5 */
+#define B43_NPHY_RFSEQ_LPFBW B43_PHY_N(0x112) /* RF seq LPF bandwidth */
+#define B43_NPHY_TSSIBIAS1 B43_PHY_N(0x114) /* TSSI bias val 1 */
+#define B43_NPHY_TSSIBIAS2 B43_PHY_N(0x115) /* TSSI bias val 2 */
+#define B43_NPHY_TSSIBIAS_BIAS 0x00FF /* Bias */
+#define B43_NPHY_TSSIBIAS_BIAS_SHIFT 0
+#define B43_NPHY_TSSIBIAS_VAL 0xFF00 /* Value */
+#define B43_NPHY_TSSIBIAS_VAL_SHIFT 8
+#define B43_NPHY_ESTPWR1 B43_PHY_N(0x118) /* Estimated power 1 */
+#define B43_NPHY_ESTPWR2 B43_PHY_N(0x119) /* Estimated power 2 */
+#define B43_NPHY_ESTPWR_PWR 0x00FF /* Estimated power */
+#define B43_NPHY_ESTPWR_PWR_SHIFT 0
+#define B43_NPHY_ESTPWR_VALID 0x0100 /* Estimated power valid */
+#define B43_NPHY_TSSI_MAXTXFDT B43_PHY_N(0x11C) /* TSSI max TX frame delay time */
+#define B43_NPHY_TSSI_MAXTXFDT_VAL 0x00FF /* max TX frame delay time */
+#define B43_NPHY_TSSI_MAXTXFDT_VAL_SHIFT 0
+#define B43_NPHY_TSSI_MAXTDT B43_PHY_N(0x11D) /* TSSI max TSSI delay time */
+#define B43_NPHY_TSSI_MAXTDT_VAL 0x00FF /* max TSSI delay time */
+#define B43_NPHY_TSSI_MAXTDT_VAL_SHIFT 0
+#define B43_NPHY_ITSSI1 B43_PHY_N(0x11E) /* TSSI idle 1 */
+#define B43_NPHY_ITSSI2 B43_PHY_N(0x11F) /* TSSI idle 2 */
+#define B43_NPHY_ITSSI_VAL 0x00FF /* Idle TSSI */
+#define B43_NPHY_ITSSI_VAL_SHIFT 0
+#define B43_NPHY_TSSIMODE B43_PHY_N(0x122) /* TSSI mode */
+#define B43_NPHY_TSSIMODE_EN 0x0001 /* TSSI enable */
+#define B43_NPHY_TSSIMODE_PDEN 0x0002 /* Power det enable */
+#define B43_NPHY_RXMACIFM B43_PHY_N(0x123) /* RX Macif mode */
+#define B43_NPHY_CRSIT_COCNT_LO B43_PHY_N(0x124) /* CRS idle time CRS-on count (low) */
+#define B43_NPHY_CRSIT_COCNT_HI B43_PHY_N(0x125) /* CRS idle time CRS-on count (high) */
+#define B43_NPHY_CRSIT_MTCNT_LO B43_PHY_N(0x126) /* CRS idle time measure time count (low) */
+#define B43_NPHY_CRSIT_MTCNT_HI B43_PHY_N(0x127) /* CRS idle time measure time count (high) */
+#define B43_NPHY_SAMTWC B43_PHY_N(0x128) /* Sample tail wait count */
+#define B43_NPHY_IQEST_CMD B43_PHY_N(0x129) /* I/Q estimate command */
+#define B43_NPHY_IQEST_CMD_START 0x0001 /* Start */
+#define B43_NPHY_IQEST_CMD_MODE 0x0002 /* Mode */
+#define B43_NPHY_IQEST_WT B43_PHY_N(0x12A) /* I/Q estimate wait time */
+#define B43_NPHY_IQEST_WT_VAL 0x00FF /* Wait time */
+#define B43_NPHY_IQEST_WT_VAL_SHIFT 0
+#define B43_NPHY_IQEST_SAMCNT B43_PHY_N(0x12B) /* I/Q estimate sample count */
+#define B43_NPHY_IQEST_IQACC_LO0 B43_PHY_N(0x12C) /* I/Q estimate I/Q acc lo 0 */
+#define B43_NPHY_IQEST_IQACC_HI0 B43_PHY_N(0x12D) /* I/Q estimate I/Q acc hi 0 */
+#define B43_NPHY_IQEST_IPACC_LO0 B43_PHY_N(0x12E) /* I/Q estimate I power acc lo 0 */
+#define B43_NPHY_IQEST_IPACC_HI0 B43_PHY_N(0x12F) /* I/Q estimate I power acc hi 0 */
+#define B43_NPHY_IQEST_QPACC_LO0 B43_PHY_N(0x130) /* I/Q estimate Q power acc lo 0 */
+#define B43_NPHY_IQEST_QPACC_HI0 B43_PHY_N(0x131) /* I/Q estimate Q power acc hi 0 */
+#define B43_NPHY_IQEST_IQACC_LO1 B43_PHY_N(0x134) /* I/Q estimate I/Q acc lo 1 */
+#define B43_NPHY_IQEST_IQACC_HI1 B43_PHY_N(0x135) /* I/Q estimate I/Q acc hi 1 */
+#define B43_NPHY_IQEST_IPACC_LO1 B43_PHY_N(0x136) /* I/Q estimate I power acc lo 1 */
+#define B43_NPHY_IQEST_IPACC_HI1 B43_PHY_N(0x137) /* I/Q estimate I power acc hi 1 */
+#define B43_NPHY_IQEST_QPACC_LO1 B43_PHY_N(0x138) /* I/Q estimate Q power acc lo 1 */
+#define B43_NPHY_IQEST_QPACC_HI1 B43_PHY_N(0x139) /* I/Q estimate Q power acc hi 1 */
+#define B43_NPHY_MIMO_CRSTXEXT B43_PHY_N(0x13A) /* MIMO PHY CRS TX extension */
+#define B43_NPHY_PWRDET1 B43_PHY_N(0x13B) /* Power det 1 */
+#define B43_NPHY_PWRDET2 B43_PHY_N(0x13C) /* Power det 2 */
+#define B43_NPHY_MAXRSSI_DTIME B43_PHY_N(0x13F) /* RSSI max RSSI delay time */
+#define B43_NPHY_PIL_DW0 B43_PHY_N(0x141) /* Pilot data weight 0 */
+#define B43_NPHY_PIL_DW1 B43_PHY_N(0x142) /* Pilot data weight 1 */
+#define B43_NPHY_PIL_DW2 B43_PHY_N(0x143) /* Pilot data weight 2 */
+#define B43_NPHY_PIL_DW_BPSK 0x000F /* BPSK */
+#define B43_NPHY_PIL_DW_BPSK_SHIFT 0
+#define B43_NPHY_PIL_DW_QPSK 0x00F0 /* QPSK */
+#define B43_NPHY_PIL_DW_QPSK_SHIFT 4
+#define B43_NPHY_PIL_DW_16QAM 0x0F00 /* 16-QAM */
+#define B43_NPHY_PIL_DW_16QAM_SHIFT 8
+#define B43_NPHY_PIL_DW_64QAM 0xF000 /* 64-QAM */
+#define B43_NPHY_PIL_DW_64QAM_SHIFT 12
+#define B43_NPHY_FMDEM_CFG B43_PHY_N(0x144) /* FM demodulation config */
+#define B43_NPHY_PHASETR_A0 B43_PHY_N(0x145) /* Phase track alpha 0 */
+#define B43_NPHY_PHASETR_A1 B43_PHY_N(0x146) /* Phase track alpha 1 */
+#define B43_NPHY_PHASETR_A2 B43_PHY_N(0x147) /* Phase track alpha 2 */
+#define B43_NPHY_PHASETR_B0 B43_PHY_N(0x148) /* Phase track beta 0 */
+#define B43_NPHY_PHASETR_B1 B43_PHY_N(0x149) /* Phase track beta 1 */
+#define B43_NPHY_PHASETR_B2 B43_PHY_N(0x14A) /* Phase track beta 2 */
+#define B43_NPHY_PHASETR_CHG0 B43_PHY_N(0x14B) /* Phase track change 0 */
+#define B43_NPHY_PHASETR_CHG1 B43_PHY_N(0x14C) /* Phase track change 1 */
+#define B43_NPHY_PHASETW_OFF B43_PHY_N(0x14D) /* Phase track offset */
+#define B43_NPHY_RFCTL_DBG B43_PHY_N(0x14E) /* RF control debug */
+#define B43_NPHY_CCK_SHIFTB_REF B43_PHY_N(0x150) /* CCK shiftbits reference var */
+#define B43_NPHY_OVER_DGAIN0 B43_PHY_N(0x152) /* Override digital gain 0 */
+#define B43_NPHY_OVER_DGAIN1 B43_PHY_N(0x153) /* Override digital gain 1 */
+#define B43_NPHY_OVER_DGAIN_FDGV 0x0007 /* Force digital gain value */
+#define B43_NPHY_OVER_DGAIN_FDGV_SHIFT 0
+#define B43_NPHY_OVER_DGAIN_FDGEN 0x0008 /* Force digital gain enable */
+#define B43_NPHY_OVER_DGAIN_CCKDGECV 0xFF00 /* CCK digital gain enable count value */
+#define B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT 8
+#define B43_NPHY_BIST_STAT4 B43_PHY_N(0x156) /* BIST status 4 */
+#define B43_NPHY_RADAR_MAL B43_PHY_N(0x157) /* Radar MA length */
+#define B43_NPHY_RADAR_SRCCTL B43_PHY_N(0x158) /* Radar search control */
+#define B43_NPHY_VLD_DTSIG B43_PHY_N(0x159) /* VLD data tones sig */
+#define B43_NPHY_VLD_DTDAT B43_PHY_N(0x15A) /* VLD data tones data */
+#define B43_NPHY_C1_BPHY_RXIQCA0 B43_PHY_N(0x15B) /* Core 1 B PHY RX I/Q comp A0 */
+#define B43_NPHY_C1_BPHY_RXIQCB0 B43_PHY_N(0x15C) /* Core 1 B PHY RX I/Q comp B0 */
+#define B43_NPHY_C2_BPHY_RXIQCA1 B43_PHY_N(0x15D) /* Core 2 B PHY RX I/Q comp A1 */
+#define B43_NPHY_C2_BPHY_RXIQCB1 B43_PHY_N(0x15E) /* Core 2 B PHY RX I/Q comp B1 */
+#define B43_NPHY_FREQGAIN0 B43_PHY_N(0x160) /* Frequency gain 0 */
+#define B43_NPHY_FREQGAIN1 B43_PHY_N(0x161) /* Frequency gain 1 */
+#define B43_NPHY_FREQGAIN2 B43_PHY_N(0x162) /* Frequency gain 2 */
+#define B43_NPHY_FREQGAIN3 B43_PHY_N(0x163) /* Frequency gain 3 */
+#define B43_NPHY_FREQGAIN4 B43_PHY_N(0x164) /* Frequency gain 4 */
+#define B43_NPHY_FREQGAIN5 B43_PHY_N(0x165) /* Frequency gain 5 */
+#define B43_NPHY_FREQGAIN6 B43_PHY_N(0x166) /* Frequency gain 6 */
+#define B43_NPHY_FREQGAIN7 B43_PHY_N(0x167) /* Frequency gain 7 */
+#define B43_NPHY_FREQGAIN_BYPASS B43_PHY_N(0x168) /* Frequency gain bypass */
+#define B43_NPHY_TRLOSS B43_PHY_N(0x169) /* TR loss value */
+#define B43_NPHY_C1_ADCCLIP B43_PHY_N(0x16A) /* Core 1 ADC clip */
+#define B43_NPHY_C2_ADCCLIP B43_PHY_N(0x16B) /* Core 2 ADC clip */
+#define B43_NPHY_LTRN_OFFGAIN B43_PHY_N(0x16F) /* LTRN offset gain */
+#define B43_NPHY_LTRN_OFF B43_PHY_N(0x170) /* LTRN offset */
+#define B43_NPHY_NRDATAT_WWISE20SIG B43_PHY_N(0x171) /* # data tones WWiSE 20 sig */
+#define B43_NPHY_NRDATAT_WWISE40SIG B43_PHY_N(0x172) /* # data tones WWiSE 40 sig */
+#define B43_NPHY_NRDATAT_TGNSYNC20SIG B43_PHY_N(0x173) /* # data tones TGNsync 20 sig */
+#define B43_NPHY_NRDATAT_TGNSYNC40SIG B43_PHY_N(0x174) /* # data tones TGNsync 40 sig */
+#define B43_NPHY_WWISE_CRCM0 B43_PHY_N(0x175) /* WWiSE CRC mask 0 */
+#define B43_NPHY_WWISE_CRCM1 B43_PHY_N(0x176) /* WWiSE CRC mask 1 */
+#define B43_NPHY_WWISE_CRCM2 B43_PHY_N(0x177) /* WWiSE CRC mask 2 */
+#define B43_NPHY_WWISE_CRCM3 B43_PHY_N(0x178) /* WWiSE CRC mask 3 */
+#define B43_NPHY_WWISE_CRCM4 B43_PHY_N(0x179) /* WWiSE CRC mask 4 */
+#define B43_NPHY_CHANEST_CDDSH B43_PHY_N(0x17A) /* Channel estimate CDD shift */
+#define B43_NPHY_HTAGC_WCNT B43_PHY_N(0x17B) /* HT ADC wait counters */
+#define B43_NPHY_SQPARM B43_PHY_N(0x17C) /* SQ params */
+#define B43_NPHY_MCSDUP6M B43_PHY_N(0x17D) /* MCS dup 6M */
+#define B43_NPHY_NDATAT_DUP40 B43_PHY_N(0x17E) /* # data tones dup 40 */
+#define B43_NPHY_DUP40_TGNSYNC_CYCD B43_PHY_N(0x17F) /* Dup40 TGNsync cycle data */
+#define B43_NPHY_DUP40_GFBL B43_PHY_N(0x180) /* Dup40 GF format BL address */
+#define B43_NPHY_DUP40_BL B43_PHY_N(0x181) /* Dup40 format BL address */
+#define B43_NPHY_LEGDUP_FTA B43_PHY_N(0x182) /* Legacy dup frm table address */
+#define B43_NPHY_PACPROC_DBG B43_PHY_N(0x183) /* Packet processing debug */
+#define B43_NPHY_PIL_CYC1 B43_PHY_N(0x184) /* Pilot cycle counter 1 */
+#define B43_NPHY_PIL_CYC2 B43_PHY_N(0x185) /* Pilot cycle counter 2 */
+#define B43_NPHY_TXF_20CO_S0A1 B43_PHY_N(0x186) /* TX filter 20 coeff stage 0 A1 */
+#define B43_NPHY_TXF_20CO_S0A2 B43_PHY_N(0x187) /* TX filter 20 coeff stage 0 A2 */
+#define B43_NPHY_TXF_20CO_S1A1 B43_PHY_N(0x188) /* TX filter 20 coeff stage 1 A1 */
+#define B43_NPHY_TXF_20CO_S1A2 B43_PHY_N(0x189) /* TX filter 20 coeff stage 1 A2 */
+#define B43_NPHY_TXF_20CO_S2A1 B43_PHY_N(0x18A) /* TX filter 20 coeff stage 2 A1 */
+#define B43_NPHY_TXF_20CO_S2A2 B43_PHY_N(0x18B) /* TX filter 20 coeff stage 2 A2 */
+#define B43_NPHY_TXF_20CO_S0B1 B43_PHY_N(0x18C) /* TX filter 20 coeff stage 0 B1 */
+#define B43_NPHY_TXF_20CO_S0B2 B43_PHY_N(0x18D) /* TX filter 20 coeff stage 0 B2 */
+#define B43_NPHY_TXF_20CO_S0B3 B43_PHY_N(0x18E) /* TX filter 20 coeff stage 0 B3 */
+#define B43_NPHY_TXF_20CO_S1B1 B43_PHY_N(0x18F) /* TX filter 20 coeff stage 1 B1 */
+#define B43_NPHY_TXF_20CO_S1B2 B43_PHY_N(0x190) /* TX filter 20 coeff stage 1 B2 */
+#define B43_NPHY_TXF_20CO_S1B3 B43_PHY_N(0x191) /* TX filter 20 coeff stage 1 B3 */
+#define B43_NPHY_TXF_20CO_S2B1 B43_PHY_N(0x192) /* TX filter 20 coeff stage 2 B1 */
+#define B43_NPHY_TXF_20CO_S2B2 B43_PHY_N(0x193) /* TX filter 20 coeff stage 2 B2 */
+#define B43_NPHY_TXF_20CO_S2B3 B43_PHY_N(0x194) /* TX filter 20 coeff stage 2 B3 */
+#define B43_NPHY_TXF_40CO_S0A1 B43_PHY_N(0x195) /* TX filter 40 coeff stage 0 A1 */
+#define B43_NPHY_TXF_40CO_S0A2 B43_PHY_N(0x196) /* TX filter 40 coeff stage 0 A2 */
+#define B43_NPHY_TXF_40CO_S1A1 B43_PHY_N(0x197) /* TX filter 40 coeff stage 1 A1 */
+#define B43_NPHY_TXF_40CO_S1A2 B43_PHY_N(0x198) /* TX filter 40 coeff stage 1 A2 */
+#define B43_NPHY_TXF_40CO_S2A1 B43_PHY_N(0x199) /* TX filter 40 coeff stage 2 A1 */
+#define B43_NPHY_TXF_40CO_S2A2 B43_PHY_N(0x19A) /* TX filter 40 coeff stage 2 A2 */
+#define B43_NPHY_TXF_40CO_S0B1 B43_PHY_N(0x19B) /* TX filter 40 coeff stage 0 B1 */
+#define B43_NPHY_TXF_40CO_S0B2 B43_PHY_N(0x19C) /* TX filter 40 coeff stage 0 B2 */
+#define B43_NPHY_TXF_40CO_S0B3 B43_PHY_N(0x19D) /* TX filter 40 coeff stage 0 B3 */
+#define B43_NPHY_TXF_40CO_S1B1 B43_PHY_N(0x19E) /* TX filter 40 coeff stage 1 B1 */
+#define B43_NPHY_TXF_40CO_S1B2 B43_PHY_N(0x19F) /* TX filter 40 coeff stage 1 B2 */
+#define B43_NPHY_TXF_40CO_S1B3 B43_PHY_N(0x1A0) /* TX filter 40 coeff stage 1 B3 */
+#define B43_NPHY_TXF_40CO_S2B1 B43_PHY_N(0x1A1) /* TX filter 40 coeff stage 2 B1 */
+#define B43_NPHY_TXF_40CO_S2B2 B43_PHY_N(0x1A2) /* TX filter 40 coeff stage 2 B2 */
+#define B43_NPHY_TXF_40CO_S2B3 B43_PHY_N(0x1A3) /* TX filter 40 coeff stage 2 B3 */
+#define B43_NPHY_RSSIMC_0I_RSSI_X B43_PHY_N(0x1A4) /* RSSI multiplication coefficient 0 I RSSI X */
+#define B43_NPHY_RSSIMC_0I_RSSI_Y B43_PHY_N(0x1A5) /* RSSI multiplication coefficient 0 I RSSI Y */
+#define B43_NPHY_RSSIMC_0I_RSSI_Z B43_PHY_N(0x1A6) /* RSSI multiplication coefficient 0 I RSSI Z */
+#define B43_NPHY_RSSIMC_0I_TBD B43_PHY_N(0x1A7) /* RSSI multiplication coefficient 0 I TBD */
+#define B43_NPHY_RSSIMC_0I_PWRDET B43_PHY_N(0x1A8) /* RSSI multiplication coefficient 0 I power det */
+#define B43_NPHY_RSSIMC_0I_TSSI B43_PHY_N(0x1A9) /* RSSI multiplication coefficient 0 I TSSI */
+#define B43_NPHY_RSSIMC_0Q_RSSI_X B43_PHY_N(0x1AA) /* RSSI multiplication coefficient 0 Q RSSI X */
+#define B43_NPHY_RSSIMC_0Q_RSSI_Y B43_PHY_N(0x1AB) /* RSSI multiplication coefficient 0 Q RSSI Y */
+#define B43_NPHY_RSSIMC_0Q_RSSI_Z B43_PHY_N(0x1AC) /* RSSI multiplication coefficient 0 Q RSSI Z */
+#define B43_NPHY_RSSIMC_0Q_TBD B43_PHY_N(0x1AD) /* RSSI multiplication coefficient 0 Q TBD */
+#define B43_NPHY_RSSIMC_0Q_PWRDET B43_PHY_N(0x1AE) /* RSSI multiplication coefficient 0 Q power det */
+#define B43_NPHY_RSSIMC_0Q_TSSI B43_PHY_N(0x1AF) /* RSSI multiplication coefficient 0 Q TSSI */
+#define B43_NPHY_RSSIMC_1I_RSSI_X B43_PHY_N(0x1B0) /* RSSI multiplication coefficient 1 I RSSI X */
+#define B43_NPHY_RSSIMC_1I_RSSI_Y B43_PHY_N(0x1B1) /* RSSI multiplication coefficient 1 I RSSI Y */
+#define B43_NPHY_RSSIMC_1I_RSSI_Z B43_PHY_N(0x1B2) /* RSSI multiplication coefficient 1 I RSSI Z */
+#define B43_NPHY_RSSIMC_1I_TBD B43_PHY_N(0x1B3) /* RSSI multiplication coefficient 1 I TBD */
+#define B43_NPHY_RSSIMC_1I_PWRDET B43_PHY_N(0x1B4) /* RSSI multiplication coefficient 1 I power det */
+#define B43_NPHY_RSSIMC_1I_TSSI B43_PHY_N(0x1B5) /* RSSI multiplication coefficient 1 I TSSI */
+#define B43_NPHY_RSSIMC_1Q_RSSI_X B43_PHY_N(0x1B6) /* RSSI multiplication coefficient 1 Q RSSI X */
+#define B43_NPHY_RSSIMC_1Q_RSSI_Y B43_PHY_N(0x1B7) /* RSSI multiplication coefficient 1 Q RSSI Y */
+#define B43_NPHY_RSSIMC_1Q_RSSI_Z B43_PHY_N(0x1B8) /* RSSI multiplication coefficient 1 Q RSSI Z */
+#define B43_NPHY_RSSIMC_1Q_TBD B43_PHY_N(0x1B9) /* RSSI multiplication coefficient 1 Q TBD */
+#define B43_NPHY_RSSIMC_1Q_PWRDET B43_PHY_N(0x1BA) /* RSSI multiplication coefficient 1 Q power det */
+#define B43_NPHY_RSSIMC_1Q_TSSI B43_PHY_N(0x1BB) /* RSSI multiplication coefficient 1 Q TSSI */
+#define B43_NPHY_SAMC_WCNT B43_PHY_N(0x1BC) /* Sample collect wait counter */
+#define B43_NPHY_PTHROUGH_CNT B43_PHY_N(0x1BD) /* Pass-through counter */
+#define B43_NPHY_LTRN_OFF_G20L B43_PHY_N(0x1C4) /* LTRN offset gain 20L */
+#define B43_NPHY_LTRN_OFF_20L B43_PHY_N(0x1C5) /* LTRN offset 20L */
+#define B43_NPHY_LTRN_OFF_G20U B43_PHY_N(0x1C6) /* LTRN offset gain 20U */
+#define B43_NPHY_LTRN_OFF_20U B43_PHY_N(0x1C7) /* LTRN offset 20U */
+#define B43_NPHY_DSSSCCK_GAINSL B43_PHY_N(0x1C8) /* DSSS/CCK gain settle length */
+#define B43_NPHY_GPIO_LOOUT B43_PHY_N(0x1C9) /* GPIO low out */
+#define B43_NPHY_GPIO_HIOUT B43_PHY_N(0x1CA) /* GPIO high out */
+#define B43_NPHY_CRS_CHECK B43_PHY_N(0x1CB) /* CRS check */
+#define B43_NPHY_ML_LOGSS_RAT B43_PHY_N(0x1CC) /* ML/logss ratio */
+#define B43_NPHY_DUPSCALE B43_PHY_N(0x1CD) /* Dup scale */
+#define B43_NPHY_BW1A B43_PHY_N(0x1CE) /* BW 1A */
+#define B43_NPHY_BW2 B43_PHY_N(0x1CF) /* BW 2 */
+#define B43_NPHY_BW3 B43_PHY_N(0x1D0) /* BW 3 */
+#define B43_NPHY_BW4 B43_PHY_N(0x1D1) /* BW 4 */
+#define B43_NPHY_BW5 B43_PHY_N(0x1D2) /* BW 5 */
+#define B43_NPHY_BW6 B43_PHY_N(0x1D3) /* BW 6 */
+#define B43_NPHY_COALEN0 B43_PHY_N(0x1D4) /* Coarse length 0 */
+#define B43_NPHY_COALEN1 B43_PHY_N(0x1D5) /* Coarse length 1 */
+#define B43_NPHY_CRSTHRES_1U B43_PHY_N(0x1D6) /* CRS threshold 1 U */
+#define B43_NPHY_CRSTHRES_2U B43_PHY_N(0x1D7) /* CRS threshold 2 U */
+#define B43_NPHY_CRSTHRES_3U B43_PHY_N(0x1D8) /* CRS threshold 3 U */
+#define B43_NPHY_CRSCTL_U B43_PHY_N(0x1D9) /* CRS control U */
+#define B43_NPHY_CRSTHRES_1L B43_PHY_N(0x1DA) /* CRS threshold 1 L */
+#define B43_NPHY_CRSTHRES_2L B43_PHY_N(0x1DB) /* CRS threshold 2 L */
+#define B43_NPHY_CRSTHRES_3L B43_PHY_N(0x1DC) /* CRS threshold 3 L */
+#define B43_NPHY_CRSCTL_L B43_PHY_N(0x1DD) /* CRS control L */
+#define B43_NPHY_STRA_1U B43_PHY_N(0x1DE) /* STR address 1 U */
+#define B43_NPHY_STRA_2U B43_PHY_N(0x1DF) /* STR address 2 U */
+#define B43_NPHY_STRA_1L B43_PHY_N(0x1E0) /* STR address 1 L */
+#define B43_NPHY_STRA_2L B43_PHY_N(0x1E1) /* STR address 2 L */
+#define B43_NPHY_CRSCHECK1 B43_PHY_N(0x1E2) /* CRS check 1 */
+#define B43_NPHY_CRSCHECK2 B43_PHY_N(0x1E3) /* CRS check 2 */
+#define B43_NPHY_CRSCHECK3 B43_PHY_N(0x1E4) /* CRS check 3 */
+#define B43_NPHY_JMPSTP0 B43_PHY_N(0x1E5) /* Jump step 0 */
+#define B43_NPHY_JMPSTP1 B43_PHY_N(0x1E6) /* Jump step 1 */
+#define B43_NPHY_TXPCTL_CMD B43_PHY_N(0x1E7) /* TX power control command */
+#define B43_NPHY_TXPCTL_CMD_INIT 0x007F /* Init */
+#define B43_NPHY_TXPCTL_CMD_INIT_SHIFT 0
+#define B43_NPHY_TXPCTL_CMD_COEFF 0x2000 /* Power control coefficients */
+#define B43_NPHY_TXPCTL_CMD_HWPCTLEN 0x4000 /* Hardware TX power control enable */
+#define B43_NPHY_TXPCTL_CMD_PCTLEN 0x8000 /* TX power control enable */
+#define B43_NPHY_TXPCTL_N B43_PHY_N(0x1E8) /* TX power control N num */
+#define B43_NPHY_TXPCTL_N_TSSID 0x00FF /* N TSSI delay */
+#define B43_NPHY_TXPCTL_N_TSSID_SHIFT 0
+#define B43_NPHY_TXPCTL_N_NPTIL2 0x0700 /* N PT integer log2 */
+#define B43_NPHY_TXPCTL_N_NPTIL2_SHIFT 8
+#define B43_NPHY_TXPCTL_ITSSI B43_PHY_N(0x1E9) /* TX power control idle TSSI */
+#define B43_NPHY_TXPCTL_ITSSI_0 0x003F /* Idle TSSI 0 */
+#define B43_NPHY_TXPCTL_ITSSI_0_SHIFT 0
+#define B43_NPHY_TXPCTL_ITSSI_1 0x3F00 /* Idle TSSI 1 */
+#define B43_NPHY_TXPCTL_ITSSI_1_SHIFT 8
+#define B43_NPHY_TXPCTL_ITSSI_BINF 0x8000 /* Raw TSSI offset bin format */
+#define B43_NPHY_TXPCTL_TPWR B43_PHY_N(0x1EA) /* TX power control target power */
+#define B43_NPHY_TXPCTL_TPWR_0 0x00FF /* Power 0 */
+#define B43_NPHY_TXPCTL_TPWR_0_SHIFT 0
+#define B43_NPHY_TXPCTL_TPWR_1 0xFF00 /* Power 1 */
+#define B43_NPHY_TXPCTL_TPWR_1_SHIFT 8
+#define B43_NPHY_TXPCTL_BIDX B43_PHY_N(0x1EB) /* TX power control base index */
+#define B43_NPHY_TXPCTL_BIDX_0 0x007F /* uC base index 0 */
+#define B43_NPHY_TXPCTL_BIDX_0_SHIFT 0
+#define B43_NPHY_TXPCTL_BIDX_1 0x7F00 /* uC base index 1 */
+#define B43_NPHY_TXPCTL_BIDX_1_SHIFT 8
+#define B43_NPHY_TXPCTL_BIDX_LOAD 0x8000 /* Load base index */
+#define B43_NPHY_TXPCTL_PIDX B43_PHY_N(0x1EC) /* TX power control power index */
+#define B43_NPHY_TXPCTL_PIDX_0 0x007F /* uC power index 0 */
+#define B43_NPHY_TXPCTL_PIDX_0_SHIFT 0
+#define B43_NPHY_TXPCTL_PIDX_1 0x7F00 /* uC power index 1 */
+#define B43_NPHY_TXPCTL_PIDX_1_SHIFT 8
+#define B43_NPHY_C1_TXPCTL_STAT B43_PHY_N(0x1ED) /* Core 1 TX power control status */
+#define B43_NPHY_C2_TXPCTL_STAT B43_PHY_N(0x1EE) /* Core 2 TX power control status */
+#define B43_NPHY_TXPCTL_STAT_EST 0x00FF /* Estimated power */
+#define B43_NPHY_TXPCTL_STAT_EST_SHIFT 0
+#define B43_NPHY_TXPCTL_STAT_BIDX 0x7F00 /* Base index */
+#define B43_NPHY_TXPCTL_STAT_BIDX_SHIFT 8
+#define B43_NPHY_TXPCTL_STAT_ESTVALID 0x8000 /* Estimated power valid */
+#define B43_NPHY_SMALLSGS_LEN B43_PHY_N(0x1EF) /* Small sig gain settle length */
+#define B43_NPHY_PHYSTAT_GAIN0 B43_PHY_N(0x1F0) /* PHY stats gain info 0 */
+#define B43_NPHY_PHYSTAT_GAIN1 B43_PHY_N(0x1F1) /* PHY stats gain info 1 */
+#define B43_NPHY_PHYSTAT_FREQEST B43_PHY_N(0x1F2) /* PHY stats frequency estimate */
+#define B43_NPHY_PHYSTAT_ADVRET B43_PHY_N(0x1F3) /* PHY stats ADV retard */
+#define B43_NPHY_PHYLB_MODE B43_PHY_N(0x1F4) /* PHY loopback mode */
+#define B43_NPHY_TONE_MIDX20_1 B43_PHY_N(0x1F5) /* Tone map index 20/1 */
+#define B43_NPHY_TONE_MIDX20_2 B43_PHY_N(0x1F6) /* Tone map index 20/2 */
+#define B43_NPHY_TONE_MIDX20_3 B43_PHY_N(0x1F7) /* Tone map index 20/3 */
+#define B43_NPHY_TONE_MIDX40_1 B43_PHY_N(0x1F8) /* Tone map index 40/1 */
+#define B43_NPHY_TONE_MIDX40_2 B43_PHY_N(0x1F9) /* Tone map index 40/2 */
+#define B43_NPHY_TONE_MIDX40_3 B43_PHY_N(0x1FA) /* Tone map index 40/3 */
+#define B43_NPHY_TONE_MIDX40_4 B43_PHY_N(0x1FB) /* Tone map index 40/4 */
+#define B43_NPHY_PILTONE_MIDX1 B43_PHY_N(0x1FC) /* Pilot tone map index 1 */
+#define B43_NPHY_PILTONE_MIDX2 B43_PHY_N(0x1FD) /* Pilot tone map index 2 */
+#define B43_NPHY_PILTONE_MIDX3 B43_PHY_N(0x1FE) /* Pilot tone map index 3 */
+#define B43_NPHY_TXRIFS_FRDEL B43_PHY_N(0x1FF) /* TX RIFS frame delay */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_40M B43_PHY_N(0x200) /* AFE seq rx2tx power up/down delay 40M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_40M B43_PHY_N(0x201) /* AFE seq tx2rx power up/down delay 40M */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_20M B43_PHY_N(0x202) /* AFE seq rx2tx power up/down delay 20M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_20M B43_PHY_N(0x203) /* AFE seq tx2rx power up/down delay 20M */
+#define B43_NPHY_RX_SIGCTL B43_PHY_N(0x204) /* RX signal control */
+#define B43_NPHY_RXPIL_CYCNT0 B43_PHY_N(0x205) /* RX pilot cycle counter 0 */
+#define B43_NPHY_RXPIL_CYCNT1 B43_PHY_N(0x206) /* RX pilot cycle counter 1 */
+#define B43_NPHY_RXPIL_CYCNT2 B43_PHY_N(0x207) /* RX pilot cycle counter 2 */
+#define B43_NPHY_AFESEQ_RX2TX_PUD_10M B43_PHY_N(0x208) /* AFE seq rx2tx power up/down delay 10M */
+#define B43_NPHY_AFESEQ_TX2RX_PUD_10M B43_PHY_N(0x209) /* AFE seq tx2rx power up/down delay 10M */
+#define B43_NPHY_DSSSCCK_CRSEXTL B43_PHY_N(0x20A) /* DSSS/CCK CRS extension length */
+#define B43_NPHY_ML_LOGSS_RATSLOPE B43_PHY_N(0x20B) /* ML/logss ratio slope */
+#define B43_NPHY_RIFS_SRCTL B43_PHY_N(0x20C) /* RIFS search timeout length */
+#define B43_NPHY_TXREALFD B43_PHY_N(0x20D) /* TX real frame delay */
+#define B43_NPHY_HPANT_SWTHRES B43_PHY_N(0x20E) /* High power antenna switch threshold */
+#define B43_NPHY_EDCRS_ASSTHRES0 B43_PHY_N(0x210) /* ED CRS assert threshold 0 */
+#define B43_NPHY_EDCRS_ASSTHRES1 B43_PHY_N(0x211) /* ED CRS assert threshold 1 */
+#define B43_NPHY_EDCRS_DEASSTHRES0 B43_PHY_N(0x212) /* ED CRS deassert threshold 0 */
+#define B43_NPHY_EDCRS_DEASSTHRES1 B43_PHY_N(0x213) /* ED CRS deassert threshold 1 */
+#define B43_NPHY_STR_WTIME20U B43_PHY_N(0x214) /* STR wait time 20U */
+#define B43_NPHY_STR_WTIME20L B43_PHY_N(0x215) /* STR wait time 20L */
+#define B43_NPHY_TONE_MIDX657M B43_PHY_N(0x216) /* Tone map index 657M */
+#define B43_NPHY_HTSIGTONES B43_PHY_N(0x217) /* HT signal tones */
+#define B43_NPHY_RSSI1 B43_PHY_N(0x219) /* RSSI value 1 */
+#define B43_NPHY_RSSI2 B43_PHY_N(0x21A) /* RSSI value 2 */
+#define B43_NPHY_CHAN_ESTHANG B43_PHY_N(0x21D) /* Channel estimate hang */
+#define B43_NPHY_FINERX2_CGC B43_PHY_N(0x221) /* Fine RX 2 clock gate control */
+#define B43_NPHY_FINERX2_CGC_DECGC 0x0008 /* Decode gated clocks */
+#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */
+#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */
+#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0
+
+
+
+/* Broadcom 2055 radio registers */
+
+#define B2055_GEN_SPARE 0x00 /* GEN spare */
+#define B2055_SP_PINPD 0x02 /* SP PIN PD */
+#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */
+#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */
+#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */
+#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */
+#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */
+#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */
+#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */
+#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */
+#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */
+#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */
+#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */
+#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */
+#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */
+#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */
+#define B2055_MASTER1 0x11 /* Master control 1 */
+#define B2055_MASTER2 0x12 /* Master control 2 */
+#define B2055_PD_LGEN 0x13 /* PD LGEN */
+#define B2055_PD_PLLTS 0x14 /* PD PLL TS */
+#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */
+#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */
+#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */
+#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */
+#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */
+#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */
+#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */
+#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */
+#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */
+#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */
+#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */
+#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */
+#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */
+#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */
+#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */
+#define B2055_CAL_MISC 0x24 /* CAL MISC */
+#define B2055_CAL_COUT 0x25 /* CAL Counter out */
+#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */
+#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */
+#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */
+#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */
+#define B2055_CAL_TS 0x2A /* CAL TS */
+#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */
+#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */
+#define B2055_PADDRV 0x2D /* PAD driver */
+#define B2055_XOCTL1 0x2E /* XO Control 1 */
+#define B2055_XOCTL2 0x2F /* XO Control 2 */
+#define B2055_XOREGUL 0x30 /* XO Regulator */
+#define B2055_XOMISC 0x31 /* XO misc */
+#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */
+#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */
+#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */
+#define B2055_PLL_REF 0x35 /* PLL reference */
+#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */
+#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */
+#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */
+#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */
+#define B2055_PLL_RCAL 0x3A /* PLL RCAL */
+#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */
+#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */
+#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */
+#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */
+#define B2055_RF_MMDSP 0x3F /* RF MMD spare */
+#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */
+#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */
+#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */
+#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */
+#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */
+#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */
+#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */
+#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */
+#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */
+#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */
+#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */
+#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */
+#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */
+#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */
+#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */
+#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */
+#define B2055_VCO_KVCO 0x50 /* VCO KVCO */
+#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */
+#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */
+#define B2055_VCO_REG 0x53 /* VCO Regulator */
+#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */
+#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */
+#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */
+#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */
+#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */
+#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */
+#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */
+#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */
+#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */
+#define B2055_LGEN_DIV 0x5D /* LGEN div */
+#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */
+#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */
+#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */
+#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */
+#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */
+#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */
+#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */
+#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */
+#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */
+#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */
+#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */
+#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */
+#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */
+#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */
+#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */
+#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */
+#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */
+#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */
+#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */
+#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */
+#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */
+#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */
+#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */
+#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */
+#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */
+#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */
+#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */
+#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */
+#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */
+#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */
+#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */
+#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */
+#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */
+#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */
+#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */
+#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */
+#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */
+#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */
+#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */
+#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */
+#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */
+#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */
+#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */
+#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */
+#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */
+#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */
+#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */
+#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */
+#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */
+#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */
+#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */
+#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */
+#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */
+#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */
+#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */
+#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */
+#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */
+#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */
+#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */
+#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */
+#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */
+#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */
+#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */
+#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */
+#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */
+#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */
+#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */
+#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */
+#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */
+#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */
+#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */
+#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */
+#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */
+#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */
+#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */
+#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */
+#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */
+#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */
+#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */
+#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */
+#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */
+#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */
+#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */
+#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */
+#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */
+#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */
+#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */
+#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */
+#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */
+#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */
+#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */
+#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */
+#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */
+#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */
+#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */
+#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */
+#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */
+#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */
+#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */
+#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */
+#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */
+#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */
+#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */
+#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */
+#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */
+#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */
+#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */
+#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */
+#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */
+#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */
+#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */
+
+
+
+struct b43_wldev;
+
+int b43_phy_initn(struct b43_wldev *dev);
+
+void b43_nphy_radio_turn_on(struct b43_wldev *dev);
+void b43_nphy_radio_turn_off(struct b43_wldev *dev);
+
+int b43_nphy_selectchannel(struct b43_wldev *dev, u8 channel);
+
+void b43_nphy_xmitpower(struct b43_wldev *dev);
+void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna);
+
+#endif /* B43_NPHY_H_ */
diff --git a/drivers/net/wireless/b43/phy.c b/drivers/net/wireless/b43/phy.c
index 7ff091e69f05..71507b260b6d 100644
--- a/drivers/net/wireless/b43/phy.c
+++ b/drivers/net/wireless/b43/phy.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005, 2006 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -31,9 +31,12 @@
#include "b43.h"
#include "phy.h"
+#include "nphy.h"
#include "main.h"
#include "tables.h"
#include "lo.h"
+#include "wa.h"
+
static const s8 b43_tssi2dbm_b_table[] = {
0x4D, 0x4C, 0x4B, 0x4A,
@@ -225,42 +228,30 @@ static void b43_shm_clear_tssi(struct b43_wldev *dev)
}
}
-void b43_raw_phy_lock(struct b43_wldev *dev)
+/* Lock the PHY registers against concurrent access from the microcode.
+ * This lock is nonrecursive. */
+void b43_phy_lock(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
-
- B43_WARN_ON(!irqs_disabled());
-
- /* We had a check for MACCTL==0 here, but I think that doesn't
- * make sense, as MACCTL is never 0 when this is called.
- * --mb */
- B43_WARN_ON(b43_read32(dev, B43_MMIO_MACCTL) == 0);
+#if B43_DEBUG
+ B43_WARN_ON(dev->phy.phy_locked);
+ dev->phy.phy_locked = 1;
+#endif
+ B43_WARN_ON(dev->dev->id.revision < 3);
- if (dev->dev->id.revision < 3) {
- b43_mac_suspend(dev);
- spin_lock(&phy->lock);
- } else {
- if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
- b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
- }
- phy->locked = 1;
+ if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ b43_power_saving_ctl_bits(dev, B43_PS_AWAKE);
}
-void b43_raw_phy_unlock(struct b43_wldev *dev)
+void b43_phy_unlock(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
+#if B43_DEBUG
+ B43_WARN_ON(!dev->phy.phy_locked);
+ dev->phy.phy_locked = 0;
+#endif
+ B43_WARN_ON(dev->dev->id.revision < 3);
- B43_WARN_ON(!irqs_disabled());
- if (dev->dev->id.revision < 3) {
- if (phy->locked) {
- spin_unlock(&phy->lock);
- b43_mac_enable(dev);
- }
- } else {
- if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
- b43_power_saving_ctl_bits(dev, 0);
- }
- phy->locked = 0;
+ if (!b43_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
+ b43_power_saving_ctl_bits(dev, 0);
}
/* Different PHYs require different register routing flags.
@@ -271,15 +262,30 @@ static inline u16 adjust_phyreg_for_phytype(struct b43_phy *phy,
{
if (phy->type == B43_PHYTYPE_A) {
/* OFDM registers are base-registers for the A-PHY. */
- offset &= ~B43_PHYROUTE_OFDM_GPHY;
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
+ offset &= ~B43_PHYROUTE;
+ offset |= B43_PHYROUTE_BASE;
+ }
}
- if (offset & B43_PHYROUTE_EXT_GPHY) {
+
+#if B43_DEBUG
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
/* Ext-G registers are only available on G-PHYs */
if (phy->type != B43_PHYTYPE_G) {
- b43dbg(dev->wl, "EXT-G PHY access at "
- "0x%04X on %u type PHY\n", offset, phy->type);
+ b43err(dev->wl, "Invalid EXT-G PHY access at "
+ "0x%04X on PHY type %u\n", offset, phy->type);
+ dump_stack();
}
}
+ if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) {
+ /* N-BMODE registers are only available on N-PHYs */
+ if (phy->type != B43_PHYTYPE_N) {
+ b43err(dev->wl, "Invalid N-BMODE PHY access at "
+ "0x%04X on PHY type %u\n", offset, phy->type);
+ dump_stack();
+ }
+ }
+#endif /* B43_DEBUG */
return offset;
}
@@ -299,11 +305,26 @@ void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val)
offset = adjust_phyreg_for_phytype(phy, offset, dev);
b43_write16(dev, B43_MMIO_PHY_CONTROL, offset);
- mmiowb();
b43_write16(dev, B43_MMIO_PHY_DATA, val);
}
-static void b43_radio_set_txpower_a(struct b43_wldev *dev, u16 txpower);
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+ b43_phy_write(dev, offset,
+ b43_phy_read(dev, offset) & mask);
+}
+
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+ b43_phy_write(dev, offset,
+ b43_phy_read(dev, offset) | set);
+}
+
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+ b43_phy_write(dev, offset,
+ (b43_phy_read(dev, offset) & mask) | set);
+}
/* Adjust the transmission power output (G-PHY) */
void b43_set_txpower_g(struct b43_wldev *dev,
@@ -763,366 +784,96 @@ static void b43_phy_init_pctl(struct b43_wldev *dev)
b43_shm_clear_tssi(dev);
}
-static void b43_phy_agcsetup(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
- u16 offset = 0x0000;
-
- if (phy->rev == 1)
- offset = 0x4C00;
-
- b43_ofdmtab_write16(dev, offset, 0, 0x00FE);
- b43_ofdmtab_write16(dev, offset, 1, 0x000D);
- b43_ofdmtab_write16(dev, offset, 2, 0x0013);
- b43_ofdmtab_write16(dev, offset, 3, 0x0019);
-
- if (phy->rev == 1) {
- b43_ofdmtab_write16(dev, 0x1800, 0, 0x2710);
- b43_ofdmtab_write16(dev, 0x1801, 0, 0x9B83);
- b43_ofdmtab_write16(dev, 0x1802, 0, 0x9B83);
- b43_ofdmtab_write16(dev, 0x1803, 0, 0x0F8D);
- b43_phy_write(dev, 0x0455, 0x0004);
- }
-
- b43_phy_write(dev, 0x04A5, (b43_phy_read(dev, 0x04A5)
- & 0x00FF) | 0x5700);
- b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A)
- & 0xFF80) | 0x000F);
- b43_phy_write(dev, 0x041A, (b43_phy_read(dev, 0x041A)
- & 0xC07F) | 0x2B80);
- b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C)
- & 0xF0FF) | 0x0300);
-
- b43_radio_write16(dev, 0x007A, b43_radio_read16(dev, 0x007A)
- | 0x0008);
-
- b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
- & 0xFFF0) | 0x0008);
- b43_phy_write(dev, 0x04A1, (b43_phy_read(dev, 0x04A1)
- & 0xF0FF) | 0x0600);
- b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
- & 0xF0FF) | 0x0700);
- b43_phy_write(dev, 0x04A0, (b43_phy_read(dev, 0x04A0)
- & 0xF0FF) | 0x0100);
-
- if (phy->rev == 1) {
- b43_phy_write(dev, 0x04A2, (b43_phy_read(dev, 0x04A2)
- & 0xFFF0) | 0x0007);
- }
-
- b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488)
- & 0xFF00) | 0x001C);
- b43_phy_write(dev, 0x0488, (b43_phy_read(dev, 0x0488)
- & 0xC0FF) | 0x0200);
- b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496)
- & 0xFF00) | 0x001C);
- b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489)
- & 0xFF00) | 0x0020);
- b43_phy_write(dev, 0x0489, (b43_phy_read(dev, 0x0489)
- & 0xC0FF) | 0x0200);
- b43_phy_write(dev, 0x0482, (b43_phy_read(dev, 0x0482)
- & 0xFF00) | 0x002E);
- b43_phy_write(dev, 0x0496, (b43_phy_read(dev, 0x0496)
- & 0x00FF) | 0x1A00);
- b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481)
- & 0xFF00) | 0x0028);
- b43_phy_write(dev, 0x0481, (b43_phy_read(dev, 0x0481)
- & 0x00FF) | 0x2C00);
-
- if (phy->rev == 1) {
- b43_phy_write(dev, 0x0430, 0x092B);
- b43_phy_write(dev, 0x041B, (b43_phy_read(dev, 0x041B)
- & 0xFFE1) | 0x0002);
- } else {
- b43_phy_write(dev, 0x041B, b43_phy_read(dev, 0x041B)
- & 0xFFE1);
- b43_phy_write(dev, 0x041F, 0x287A);
- b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420)
- & 0xFFF0) | 0x0004);
- }
-
- if (phy->rev >= 6) {
- b43_phy_write(dev, 0x0422, 0x287A);
- b43_phy_write(dev, 0x0420, (b43_phy_read(dev, 0x0420)
- & 0x0FFF) | 0x3000);
- }
-
- b43_phy_write(dev, 0x04A8, (b43_phy_read(dev, 0x04A8)
- & 0x8080) | 0x7874);
- b43_phy_write(dev, 0x048E, 0x1C00);
-
- offset = 0x0800;
- if (phy->rev == 1) {
- offset = 0x5400;
- b43_phy_write(dev, 0x04AB, (b43_phy_read(dev, 0x04AB)
- & 0xF0FF) | 0x0600);
- b43_phy_write(dev, 0x048B, 0x005E);
- b43_phy_write(dev, 0x048C, (b43_phy_read(dev, 0x048C)
- & 0xFF00) | 0x001E);
- b43_phy_write(dev, 0x048D, 0x0002);
- }
- b43_ofdmtab_write16(dev, offset, 0, 0x00);
- b43_ofdmtab_write16(dev, offset, 1, 0x07);
- b43_ofdmtab_write16(dev, offset, 2, 0x10);
- b43_ofdmtab_write16(dev, offset, 3, 0x1C);
-
- if (phy->rev >= 6) {
- b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426)
- & 0xFFFC);
- b43_phy_write(dev, 0x0426, b43_phy_read(dev, 0x0426)
- & 0xEFFF);
- }
-}
-
-static void b43_phy_setupg(struct b43_wldev *dev)
+static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable)
{
- struct ssb_bus *bus = dev->dev->bus;
- struct b43_phy *phy = &dev->phy;
- u16 i;
-
- B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if (phy->rev == 1) {
- b43_phy_write(dev, 0x0406, 0x4F19);
- b43_phy_write(dev, B43_PHY_G_CRS,
- (b43_phy_read(dev, B43_PHY_G_CRS) & 0xFC3F) |
- 0x0340);
- b43_phy_write(dev, 0x042C, 0x005A);
- b43_phy_write(dev, 0x0427, 0x001A);
-
- for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x5800, i,
- b43_tab_finefreqg[i]);
- for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg1[i]);
- for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x2000, i, b43_tab_rotor[i]);
- } else {
- /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */
- b43_nrssi_hw_write(dev, 0xBA98, (s16) 0x7654);
-
- if (phy->rev == 2) {
- b43_phy_write(dev, 0x04C0, 0x1861);
- b43_phy_write(dev, 0x04C1, 0x0271);
- } else if (phy->rev > 2) {
- b43_phy_write(dev, 0x04C0, 0x0098);
- b43_phy_write(dev, 0x04C1, 0x0070);
- b43_phy_write(dev, 0x04C9, 0x0080);
- }
- b43_phy_write(dev, 0x042B, b43_phy_read(dev, 0x042B) | 0x800);
-
- for (i = 0; i < 64; i++)
- b43_ofdmtab_write16(dev, 0x4000, i, i);
- for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noiseg2[i]);
- }
-
- if (phy->rev <= 2)
- for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1400, i,
- b43_tab_noisescaleg1[i]);
- else if ((phy->rev >= 7) && (b43_phy_read(dev, 0x0449) & 0x0200))
- for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1400, i,
- b43_tab_noisescaleg3[i]);
- else
- for (i = 0; i < B43_TAB_NOISESCALEG_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1400, i,
- b43_tab_noisescaleg2[i]);
-
- if (phy->rev == 2)
- for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x5000, i,
- b43_tab_sigmasqr1[i]);
- else if ((phy->rev > 2) && (phy->rev <= 8))
- for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x5000, i,
- b43_tab_sigmasqr2[i]);
-
- if (phy->rev == 1) {
- for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
- b43_ofdmtab_write32(dev, 0x2400, i, b43_tab_retard[i]);
- for (i = 4; i < 20; i++)
- b43_ofdmtab_write16(dev, 0x5400, i, 0x0020);
- b43_phy_agcsetup(dev);
-
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306) &&
- (bus->boardinfo.rev == 0x17))
- return;
-
- b43_ofdmtab_write16(dev, 0x5001, 0, 0x0002);
- b43_ofdmtab_write16(dev, 0x5002, 0, 0x0001);
- } else {
- for (i = 0; i < 0x20; i++)
- b43_ofdmtab_write16(dev, 0x1000, i, 0x0820);
- b43_phy_agcsetup(dev);
- b43_phy_read(dev, 0x0400); /* dummy read */
- b43_phy_write(dev, 0x0403, 0x1000);
- b43_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
- b43_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
-
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- (bus->boardinfo.type == SSB_BOARD_BU4306) &&
- (bus->boardinfo.rev == 0x17))
- return;
-
- b43_ofdmtab_write16(dev, 0x0401, 0, 0x0002);
- b43_ofdmtab_write16(dev, 0x0402, 0, 0x0001);
- }
-}
-
-/* Initialize the noisescaletable for APHY */
-static void b43_phy_init_noisescaletbl(struct b43_wldev *dev)
-{
- struct b43_phy *phy = &dev->phy;
int i;
- for (i = 0; i < 12; i++) {
- if (phy->rev == 2)
- b43_ofdmtab_write16(dev, 0x1400, i, 0x6767);
+ if (dev->phy.rev < 3) {
+ if (enable)
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8);
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, 0xFFF8);
+ }
else
- b43_ofdmtab_write16(dev, 0x1400, i, 0x2323);
- }
- if (phy->rev == 2)
- b43_ofdmtab_write16(dev, 0x1400, i, 0x6700);
- else
- b43_ofdmtab_write16(dev, 0x1400, i, 0x2300);
- for (i = 0; i < 11; i++) {
- if (phy->rev == 2)
- b43_ofdmtab_write16(dev, 0x1400, i, 0x6767);
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) {
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]);
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]);
+ }
+ } else {
+ if (enable)
+ for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++)
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, 0x0820);
else
- b43_ofdmtab_write16(dev, 0x1400, i, 0x2323);
+ for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++)
+ b43_ofdmtab_write16(dev,
+ B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]);
}
- if (phy->rev == 2)
- b43_ofdmtab_write16(dev, 0x1400, i, 0x0067);
- else
- b43_ofdmtab_write16(dev, 0x1400, i, 0x0023);
}
-static void b43_phy_setupa(struct b43_wldev *dev)
+static void b43_phy_ww(struct b43_wldev *dev)
{
- struct b43_phy *phy = &dev->phy;
- u16 i;
-
- B43_WARN_ON(phy->type != B43_PHYTYPE_A);
- switch (phy->rev) {
- case 2:
- b43_phy_write(dev, 0x008E, 0x3800);
- b43_phy_write(dev, 0x0035, 0x03FF);
- b43_phy_write(dev, 0x0036, 0x0400);
-
- b43_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
-
- b43_phy_write(dev, 0x001C, 0x0FF9);
- b43_phy_write(dev, 0x0020, b43_phy_read(dev, 0x0020) & 0xFF0F);
- b43_ofdmtab_write16(dev, 0x3C0C, 0, 0x07BF);
- b43_radio_write16(dev, 0x0002, 0x07BF);
-
- b43_phy_write(dev, 0x0024, 0x4680);
- b43_phy_write(dev, 0x0020, 0x0003);
- b43_phy_write(dev, 0x001D, 0x0F40);
- b43_phy_write(dev, 0x001F, 0x1C00);
-
- b43_phy_write(dev, 0x002A, (b43_phy_read(dev, 0x002A)
- & 0x00FF) | 0x0400);
- b43_phy_write(dev, 0x002B, b43_phy_read(dev, 0x002B)
- & 0xFBFF);
- b43_phy_write(dev, 0x008E, 0x58C1);
-
- b43_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
- b43_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
- b43_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
- b43_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
- b43_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
-
- b43_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
- b43_ofdmtab_write16(dev, 0x0000, 1, 0x0013);
- b43_ofdmtab_write16(dev, 0x0000, 2, 0x0013);
- b43_ofdmtab_write16(dev, 0x0000, 3, 0x0013);
- b43_ofdmtab_write16(dev, 0x0000, 4, 0x0015);
- b43_ofdmtab_write16(dev, 0x0000, 5, 0x0015);
- b43_ofdmtab_write16(dev, 0x0000, 6, 0x0019);
-
- b43_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
- b43_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
- b43_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
-
- for (i = 0; i < 16; i++)
- b43_ofdmtab_write16(dev, 0x4000, i, (0x8 + i) & 0x000F);
-
- b43_ofdmtab_write16(dev, 0x3003, 0, 0x1044);
- b43_ofdmtab_write16(dev, 0x3004, 0, 0x7201);
- b43_ofdmtab_write16(dev, 0x3006, 0, 0x0040);
- b43_ofdmtab_write16(dev, 0x3001, 0,
- (b43_ofdmtab_read16(dev, 0x3001, 0) &
- 0x0010) | 0x0008);
-
- for (i = 0; i < B43_TAB_FINEFREQA_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x5800, i,
- b43_tab_finefreqa[i]);
- for (i = 0; i < B43_TAB_NOISEA2_SIZE; i++)
- b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noisea2[i]);
- for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
- b43_ofdmtab_write32(dev, 0x2000, i, b43_tab_rotor[i]);
- b43_phy_init_noisescaletbl(dev);
- for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
- b43_ofdmtab_write32(dev, 0x2400, i, b43_tab_retard[i]);
- break;
- case 3:
- for (i = 0; i < 64; i++)
- b43_ofdmtab_write16(dev, 0x4000, i, i);
-
- b43_ofdmtab_write16(dev, 0x3807, 0, 0x0051);
-
- b43_phy_write(dev, 0x001C, 0x0FF9);
- b43_phy_write(dev, 0x0020, b43_phy_read(dev, 0x0020) & 0xFF0F);
- b43_radio_write16(dev, 0x0002, 0x07BF);
-
- b43_phy_write(dev, 0x0024, 0x4680);
- b43_phy_write(dev, 0x0020, 0x0003);
- b43_phy_write(dev, 0x001D, 0x0F40);
- b43_phy_write(dev, 0x001F, 0x1C00);
- b43_phy_write(dev, 0x002A, (b43_phy_read(dev, 0x002A)
- & 0x00FF) | 0x0400);
-
- b43_ofdmtab_write16(dev, 0x3000, 1,
- (b43_ofdmtab_read16(dev, 0x3000, 1)
- & 0x0010) | 0x0008);
- for (i = 0; i < B43_TAB_NOISEA3_SIZE; i++) {
- b43_ofdmtab_write16(dev, 0x1800, i, b43_tab_noisea3[i]);
- }
- b43_phy_init_noisescaletbl(dev);
- for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
- b43_ofdmtab_write16(dev, 0x5000, i,
- b43_tab_sigmasqr1[i]);
- }
-
- b43_phy_write(dev, 0x0003, 0x1808);
-
- b43_ofdmtab_write16(dev, 0x0803, 0, 0x000F);
- b43_ofdmtab_write16(dev, 0x0804, 0, 0x001F);
- b43_ofdmtab_write16(dev, 0x0805, 0, 0x002A);
- b43_ofdmtab_write16(dev, 0x0805, 0, 0x0030);
- b43_ofdmtab_write16(dev, 0x0807, 0, 0x003A);
-
- b43_ofdmtab_write16(dev, 0x0000, 0, 0x0013);
- b43_ofdmtab_write16(dev, 0x0001, 0, 0x0013);
- b43_ofdmtab_write16(dev, 0x0002, 0, 0x0013);
- b43_ofdmtab_write16(dev, 0x0003, 0, 0x0013);
- b43_ofdmtab_write16(dev, 0x0004, 0, 0x0015);
- b43_ofdmtab_write16(dev, 0x0005, 0, 0x0015);
- b43_ofdmtab_write16(dev, 0x0006, 0, 0x0019);
-
- b43_ofdmtab_write16(dev, 0x0404, 0, 0x0003);
- b43_ofdmtab_write16(dev, 0x0405, 0, 0x0003);
- b43_ofdmtab_write16(dev, 0x0406, 0, 0x0007);
+ u16 b, curr_s, best_s = 0xFFFF;
+ int i;
- b43_ofdmtab_write16(dev, 0x3C02, 0, 0x000F);
- b43_ofdmtab_write16(dev, 0x3C03, 0, 0x0014);
- break;
- default:
- B43_WARN_ON(1);
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) & ~B43_PHY_CRS0_EN);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ b43_phy_read(dev, B43_PHY_OFDM(0x1B)) | 0x1000);
+ b43_phy_write(dev, B43_PHY_OFDM(0x82),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & 0xF0FF) | 0x0300);
+ b43_radio_write16(dev, 0x0009,
+ b43_radio_read16(dev, 0x0009) | 0x0080);
+ b43_radio_write16(dev, 0x0012,
+ (b43_radio_read16(dev, 0x0012) & 0xFFFC) | 0x0002);
+ b43_wa_initgains(dev);
+ b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5);
+ b = b43_phy_read(dev, B43_PHY_PWRDOWN);
+ b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005);
+ b43_radio_write16(dev, 0x0004,
+ b43_radio_read16(dev, 0x0004) | 0x0004);
+ for (i = 0x10; i <= 0x20; i++) {
+ b43_radio_write16(dev, 0x0013, i);
+ curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF;
+ if (!curr_s) {
+ best_s = 0x0000;
+ break;
+ } else if (curr_s >= 0x0080)
+ curr_s = 0x0100 - curr_s;
+ if (curr_s < best_s)
+ best_s = curr_s;
}
+ b43_phy_write(dev, B43_PHY_PWRDOWN, b);
+ b43_radio_write16(dev, 0x0004,
+ b43_radio_read16(dev, 0x0004) & 0xFFFB);
+ b43_radio_write16(dev, 0x0013, best_s);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0);
+ b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF);
+ b43_phy_write(dev, B43_PHY_OFDM(0xBB),
+ (b43_phy_read(dev, B43_PHY_OFDM(0xBB)) & 0xF000) | 0x0053);
+ b43_phy_write(dev, B43_PHY_OFDM61,
+ (b43_phy_read(dev, B43_PHY_OFDM61 & 0xFE1F)) | 0x0120);
+ b43_phy_write(dev, B43_PHY_OFDM(0x13),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x13)) & 0x0FFF) | 0x3000);
+ b43_phy_write(dev, B43_PHY_OFDM(0x14),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x14)) & 0x0FFF) | 0x3000);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017);
+ for (i = 0; i < 6; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013);
+ b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030);
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
}
/* Initialize APHY. This is also called for the GPHY in some cases. */
@@ -1130,64 +881,54 @@ static void b43_phy_inita(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->dev->bus;
struct b43_phy *phy = &dev->phy;
- u16 tval;
might_sleep();
- if (phy->type == B43_PHYTYPE_A) {
- b43_phy_setupa(dev);
- } else {
- b43_phy_setupg(dev);
- if (phy->gmode &&
- (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL))
- b43_phy_write(dev, 0x046E, 0x03CF);
- return;
+ if (phy->rev >= 6) {
+ if (phy->type == B43_PHYTYPE_A)
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x1000);
+ if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+ b43_phy_write(dev, B43_PHY_ENCORE,
+ b43_phy_read(dev, B43_PHY_ENCORE) | 0x0010);
+ else
+ b43_phy_write(dev, B43_PHY_ENCORE,
+ b43_phy_read(dev, B43_PHY_ENCORE) & ~0x1010);
}
- b43_phy_write(dev, B43_PHY_A_CRS,
- (b43_phy_read(dev, B43_PHY_A_CRS) & 0xF83C) | 0x0340);
- b43_phy_write(dev, 0x0034, 0x0001);
+ b43_wa_all(dev);
- //TODO: RSSI AGC
- b43_phy_write(dev, B43_PHY_A_CRS,
- b43_phy_read(dev, B43_PHY_A_CRS) | (1 << 14));
- b43_radio_init2060(dev);
+ if (phy->type == B43_PHYTYPE_A) {
+ if (phy->gmode && (phy->rev < 3))
+ b43_phy_write(dev, 0x0034,
+ b43_phy_read(dev, 0x0034) | 0x0001);
+ b43_phy_rssiagc(dev, 0);
- if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
- ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
- (bus->boardinfo.type == SSB_BOARD_BU4309))) {
- if (phy->lofcal == 0xFFFF) {
- //TODO: LOF Cal
- b43_radio_set_tx_iq(dev);
- } else
- b43_radio_write16(dev, 0x001E, phy->lofcal);
- }
+ b43_phy_write(dev, B43_PHY_CRS0,
+ b43_phy_read(dev, B43_PHY_CRS0) | B43_PHY_CRS0_EN);
- b43_phy_write(dev, 0x007A, 0xF111);
+ b43_radio_init2060(dev);
- if (phy->cur_idle_tssi == 0) {
- b43_radio_write16(dev, 0x0019, 0x0000);
- b43_radio_write16(dev, 0x0017, 0x0020);
-
- tval = b43_ofdmtab_read16(dev, 0x3001, 0);
- if (phy->rev == 1) {
- b43_ofdmtab_write16(dev, 0x3001, 0,
- (b43_ofdmtab_read16(dev, 0x3001, 0)
- & 0xFF87)
- | 0x0058);
- } else {
- b43_ofdmtab_write16(dev, 0x3001, 0,
- (b43_ofdmtab_read16(dev, 0x3001, 0)
- & 0xFFC3)
- | 0x002C);
+ if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) &&
+ ((bus->boardinfo.type == SSB_BOARD_BU4306) ||
+ (bus->boardinfo.type == SSB_BOARD_BU4309))) {
+ ; //TODO: A PHY LO
}
- b43_dummy_transmission(dev);
- phy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_A_PCTL);
- b43_ofdmtab_write16(dev, 0x3001, 0, tval);
- b43_radio_set_txpower_a(dev, 0x0018);
+ if (phy->rev >= 3)
+ b43_phy_ww(dev);
+
+ hardware_pctl_init_aphy(dev);
+
+ //TODO: radar detection
+ }
+
+ if ((phy->type == B43_PHYTYPE_G) &&
+ (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) {
+ b43_phy_write(dev, B43_PHY_OFDM(0x6E),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x6E))
+ & 0xE000) | 0x3CF);
}
- b43_shm_clear_tssi(dev);
}
static void b43_phy_initb2(struct b43_wldev *dev)
@@ -1286,7 +1027,7 @@ static void b43_phy_initb4(struct b43_wldev *dev)
if (phy->radio_ver == 0x2050)
b43_phy_write(dev, 0x002A, 0x88C2);
b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt, phy->tx_control);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
b43_calc_nrssi_slope(dev);
b43_calc_nrssi_threshold(dev);
}
@@ -1433,7 +1174,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_radio_write16(dev, 0x5A, 0x88);
b43_radio_write16(dev, 0x5B, 0x6B);
b43_radio_write16(dev, 0x5C, 0x0F);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_ALTIQ) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) {
b43_radio_write16(dev, 0x5D, 0xFA);
b43_radio_write16(dev, 0x5E, 0xD8);
} else {
@@ -1525,7 +1266,7 @@ static void b43_phy_initb6(struct b43_wldev *dev)
b43_phy_write(dev, 0x0062, 0x0007);
b43_radio_init2050(dev);
b43_lo_g_measure(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI) {
b43_calc_nrssi_slope(dev);
b43_calc_nrssi_threshold(dev);
}
@@ -1552,14 +1293,14 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER);
backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL);
}
- backup_phy[6] = b43_phy_read(dev, B43_PHY_BASE(0x5A));
- backup_phy[7] = b43_phy_read(dev, B43_PHY_BASE(0x59));
- backup_phy[8] = b43_phy_read(dev, B43_PHY_BASE(0x58));
- backup_phy[9] = b43_phy_read(dev, B43_PHY_BASE(0x0A));
- backup_phy[10] = b43_phy_read(dev, B43_PHY_BASE(0x03));
+ backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A));
+ backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59));
+ backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58));
+ backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A));
+ backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03));
backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK);
backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL);
- backup_phy[13] = b43_phy_read(dev, B43_PHY_BASE(0x2B));
+ backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B));
backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL);
backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
backup_bband = phy->bbatt.att;
@@ -1601,12 +1342,12 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
(b43_phy_read(dev, B43_PHY_RFOVERVAL)
& 0xFFCF) | 0x10);
- b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0780);
- b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
- b43_phy_write(dev, B43_PHY_BASE(0x0A),
- b43_phy_read(dev, B43_PHY_BASE(0x0A)) | 0x2000);
+ b43_phy_write(dev, B43_PHY_CCK(0x0A),
+ b43_phy_read(dev, B43_PHY_CCK(0x0A)) | 0x2000);
if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */
b43_phy_write(dev, B43_PHY_ANALOGOVER,
b43_phy_read(dev, B43_PHY_ANALOGOVER) | 0x0004);
@@ -1614,8 +1355,8 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_read(dev,
B43_PHY_ANALOGOVERVAL) & 0xFFFB);
}
- b43_phy_write(dev, B43_PHY_BASE(0x03),
- (b43_phy_read(dev, B43_PHY_BASE(0x03))
+ b43_phy_write(dev, B43_PHY_CCK(0x03),
+ (b43_phy_read(dev, B43_PHY_CCK(0x03))
& 0xFF9F) | 0x40);
if (phy->radio_rev == 8) {
@@ -1633,11 +1374,11 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020);
b43_phy_write(dev, B43_PHY_LO_CTL, 0);
- b43_phy_write(dev, B43_PHY_BASE(0x2B),
- (b43_phy_read(dev, B43_PHY_BASE(0x2B))
+ b43_phy_write(dev, B43_PHY_CCK(0x2B),
+ (b43_phy_read(dev, B43_PHY_CCK(0x2B))
& 0xFFC0) | 0x01);
- b43_phy_write(dev, B43_PHY_BASE(0x2B),
- (b43_phy_read(dev, B43_PHY_BASE(0x2B))
+ b43_phy_write(dev, B43_PHY_CCK(0x2B),
+ (b43_phy_read(dev, B43_PHY_CCK(0x2B))
& 0xC0FF) | 0x800);
b43_phy_write(dev, B43_PHY_RFOVER,
@@ -1645,7 +1386,7 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_RFOVERVAL,
b43_phy_read(dev, B43_PHY_RFOVERVAL) & 0xCFFF);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_EXTLNA) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43_phy_write(dev, B43_PHY_RFOVER,
b43_phy_read(dev, B43_PHY_RFOVER)
@@ -1708,14 +1449,14 @@ static void b43_calc_loopback_gain(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]);
b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]);
}
- b43_phy_write(dev, B43_PHY_BASE(0x5A), backup_phy[6]);
- b43_phy_write(dev, B43_PHY_BASE(0x59), backup_phy[7]);
- b43_phy_write(dev, B43_PHY_BASE(0x58), backup_phy[8]);
- b43_phy_write(dev, B43_PHY_BASE(0x0A), backup_phy[9]);
- b43_phy_write(dev, B43_PHY_BASE(0x03), backup_phy[10]);
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]);
+ b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]);
+ b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]);
b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]);
b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]);
- b43_phy_write(dev, B43_PHY_BASE(0x2B), backup_phy[13]);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]);
b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]);
b43_phy_set_baseband_attenuation(dev, backup_bband);
@@ -1807,26 +1548,26 @@ static void b43_phy_initg(struct b43_wldev *dev)
| phy->lo_control->tx_bias);
}
if (phy->rev >= 6) {
- b43_phy_write(dev, B43_PHY_BASE(0x36),
- (b43_phy_read(dev, B43_PHY_BASE(0x36))
+ b43_phy_write(dev, B43_PHY_CCK(0x36),
+ (b43_phy_read(dev, B43_PHY_CCK(0x36))
& 0x0FFF) | (phy->lo_control->
tx_bias << 12));
}
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL)
- b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x8075);
+ if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075);
else
- b43_phy_write(dev, B43_PHY_BASE(0x2E), 0x807F);
+ b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F);
if (phy->rev < 2)
- b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x101);
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101);
else
- b43_phy_write(dev, B43_PHY_BASE(0x2F), 0x202);
+ b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202);
}
if (phy->gmode || phy->rev >= 2) {
b43_lo_g_adjust(dev);
b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078);
}
- if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
+ if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -1995,7 +1736,6 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
int rfatt_delta, bbatt_delta;
int rfatt, bbatt;
u8 tx_control;
- unsigned long phylock_flags;
tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x0058);
v0 = (s8) (tmp & 0x00FF);
@@ -2036,16 +1776,15 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
estimated_pwr =
b43_phy_estimate_power_out(dev, average);
- max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
- if ((dev->dev->bus->sprom.r1.
- boardflags_lo & B43_BFL_PACTRL)
- && (phy->type == B43_PHYTYPE_G))
+ max_pwr = dev->dev->bus->sprom.maxpwr_bg;
+ if ((dev->dev->bus->sprom.boardflags_lo
+ & B43_BFL_PACTRL) && (phy->type == B43_PHYTYPE_G))
max_pwr -= 0x3;
if (unlikely(max_pwr <= 0)) {
b43warn(dev->wl,
"Invalid max-TX-power value in SPROM.\n");
max_pwr = 60; /* fake it */
- dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
+ dev->dev->bus->sprom.maxpwr_bg = max_pwr;
}
/*TODO:
@@ -2103,7 +1842,7 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
B43_TXCTL_TXMIX;
rfatt += 2;
bbatt += 2;
- } else if (dev->dev->bus->sprom.r1.
+ } else if (dev->dev->bus->sprom.
boardflags_lo &
B43_BFL_PACTRL) {
bbatt += 4 * (rfatt - 2);
@@ -2127,15 +1866,18 @@ void b43_phy_xmitpower(struct b43_wldev *dev)
phy->bbatt.att = bbatt;
/* Adjust the hardware */
- b43_phy_lock(dev, phylock_flags);
+ b43_phy_lock(dev);
b43_radio_lock(dev);
b43_set_txpower_g(dev, &phy->bbatt, &phy->rfatt,
phy->tx_control);
b43_lo_g_ctl_mark_cur_used(dev);
b43_radio_unlock(dev);
- b43_phy_unlock(dev, phylock_flags);
+ b43_phy_unlock(dev);
break;
}
+ case B43_PHYTYPE_N:
+ b43_nphy_xmitpower(dev);
+ break;
default:
B43_WARN_ON(1);
}
@@ -2179,13 +1921,13 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
s8 *dyn_tssi2dbm;
if (phy->type == B43_PHYTYPE_A) {
- pab0 = (s16) (dev->dev->bus->sprom.r1.pa1b0);
- pab1 = (s16) (dev->dev->bus->sprom.r1.pa1b1);
- pab2 = (s16) (dev->dev->bus->sprom.r1.pa1b2);
+ pab0 = (s16) (dev->dev->bus->sprom.pa1b0);
+ pab1 = (s16) (dev->dev->bus->sprom.pa1b1);
+ pab2 = (s16) (dev->dev->bus->sprom.pa1b2);
} else {
- pab0 = (s16) (dev->dev->bus->sprom.r1.pa0b0);
- pab1 = (s16) (dev->dev->bus->sprom.r1.pa0b1);
- pab2 = (s16) (dev->dev->bus->sprom.r1.pa0b2);
+ pab0 = (s16) (dev->dev->bus->sprom.pa0b0);
+ pab1 = (s16) (dev->dev->bus->sprom.pa0b1);
+ pab2 = (s16) (dev->dev->bus->sprom.pa0b2);
}
if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
@@ -2198,17 +1940,17 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
if (phy->type == B43_PHYTYPE_A) {
- if ((s8) dev->dev->bus->sprom.r1.itssi_a != 0 &&
- (s8) dev->dev->bus->sprom.r1.itssi_a != -1)
+ if ((s8) dev->dev->bus->sprom.itssi_a != 0 &&
+ (s8) dev->dev->bus->sprom.itssi_a != -1)
phy->tgt_idle_tssi =
- (s8) (dev->dev->bus->sprom.r1.itssi_a);
+ (s8) (dev->dev->bus->sprom.itssi_a);
else
phy->tgt_idle_tssi = 62;
} else {
- if ((s8) dev->dev->bus->sprom.r1.itssi_bg != 0 &&
- (s8) dev->dev->bus->sprom.r1.itssi_bg != -1)
+ if ((s8) dev->dev->bus->sprom.itssi_bg != 0 &&
+ (s8) dev->dev->bus->sprom.itssi_bg != -1)
phy->tgt_idle_tssi =
- (s8) (dev->dev->bus->sprom.r1.itssi_bg);
+ (s8) (dev->dev->bus->sprom.itssi_bg);
else
phy->tgt_idle_tssi = 62;
}
@@ -2255,41 +1997,44 @@ int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev)
int b43_phy_init(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
- int err = -ENODEV;
+ bool unsupported = 0;
+ int err = 0;
switch (phy->type) {
case B43_PHYTYPE_A:
- if (phy->rev == 2 || phy->rev == 3) {
+ if (phy->rev == 2 || phy->rev == 3)
b43_phy_inita(dev);
- err = 0;
- }
+ else
+ unsupported = 1;
break;
case B43_PHYTYPE_B:
switch (phy->rev) {
case 2:
b43_phy_initb2(dev);
- err = 0;
break;
case 4:
b43_phy_initb4(dev);
- err = 0;
break;
case 5:
b43_phy_initb5(dev);
- err = 0;
break;
case 6:
b43_phy_initb6(dev);
- err = 0;
break;
+ default:
+ unsupported = 1;
}
break;
case B43_PHYTYPE_G:
b43_phy_initg(dev);
- err = 0;
break;
+ case B43_PHYTYPE_N:
+ err = b43_phy_initn(dev);
+ break;
+ default:
+ unsupported = 1;
}
- if (err)
+ if (unsupported)
b43err(dev->wl, "Unknown PHYTYPE found\n");
return err;
@@ -2392,6 +2137,9 @@ void b43_set_rx_antenna(struct b43_wldev *dev, int antenna)
<< B43_PHY_BBANDCFG_RXANT_SHIFT;
b43_phy_write(dev, B43_PHY_CCKBBANDCFG, tmp);
break;
+ case B43_PHYTYPE_N:
+ b43_nphy_set_rxantenna(dev, antenna);
+ break;
default:
B43_WARN_ON(1);
}
@@ -2421,6 +2169,7 @@ void b43_radio_lock(struct b43_wldev *dev)
u32 macctl;
macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ B43_WARN_ON(macctl & B43_MACCTL_RADIOLOCK);
macctl |= B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
/* Commit the write and wait for the device
@@ -2437,6 +2186,7 @@ void b43_radio_unlock(struct b43_wldev *dev)
b43_read16(dev, B43_MMIO_PHY_VER);
/* unlock */
macctl = b43_read32(dev, B43_MMIO_MACCTL);
+ B43_WARN_ON(!(macctl & B43_MACCTL_RADIOLOCK));
macctl &= ~B43_MACCTL_RADIOLOCK;
b43_write32(dev, B43_MMIO_MACCTL, macctl);
}
@@ -2445,9 +2195,12 @@ u16 b43_radio_read16(struct b43_wldev *dev, u16 offset)
{
struct b43_phy *phy = &dev->phy;
+ /* Offset 1 is a 32-bit register. */
+ B43_WARN_ON(offset == 1);
+
switch (phy->type) {
case B43_PHYTYPE_A:
- offset |= 0x0040;
+ offset |= 0x40;
break;
case B43_PHYTYPE_B:
if (phy->radio_ver == 0x2053) {
@@ -2463,6 +2216,14 @@ u16 b43_radio_read16(struct b43_wldev *dev, u16 offset)
case B43_PHYTYPE_G:
offset |= 0x80;
break;
+ case B43_PHYTYPE_N:
+ offset |= 0x100;
+ break;
+ case B43_PHYTYPE_LP:
+ /* No adjustment required. */
+ break;
+ default:
+ B43_WARN_ON(1);
}
b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
@@ -2471,11 +2232,31 @@ u16 b43_radio_read16(struct b43_wldev *dev, u16 offset)
void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val)
{
+ /* Offset 1 is a 32-bit register. */
+ B43_WARN_ON(offset == 1);
+
b43_write16(dev, B43_MMIO_RADIO_CONTROL, offset);
- mmiowb();
b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, val);
}
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask)
+{
+ b43_radio_write16(dev, offset,
+ b43_radio_read16(dev, offset) & mask);
+}
+
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set)
+{
+ b43_radio_write16(dev, offset,
+ b43_radio_read16(dev, offset) | set);
+}
+
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
+{
+ b43_radio_write16(dev, offset,
+ (b43_radio_read16(dev, offset) & mask) | set);
+}
+
static void b43_set_all_gains(struct b43_wldev *dev,
s16 first, s16 second, s16 third)
{
@@ -2605,12 +2386,11 @@ u8 b43_radio_aci_scan(struct b43_wldev * dev)
u8 ret[13];
unsigned int channel = phy->channel;
unsigned int i, j, start, end;
- unsigned long phylock_flags;
if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0)))
return 0;
- b43_phy_lock(dev, phylock_flags);
+ b43_phy_lock(dev);
b43_radio_lock(dev);
b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) & 0xFFFC);
b43_phy_write(dev, B43_PHY_G_CRS,
@@ -2639,7 +2419,7 @@ u8 b43_radio_aci_scan(struct b43_wldev * dev)
ret[j] = 1;
}
b43_radio_unlock(dev);
- b43_phy_unlock(dev, phylock_flags);
+ b43_phy_unlock(dev);
return ret[channel - 1];
}
@@ -3114,7 +2894,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev)
if (phy->radio_ver != 0x2050)
return;
if (!
- (dev->dev->bus->sprom.r1.
+ (dev->dev->bus->sprom.
boardflags_lo & B43_BFL_RSSI))
return;
@@ -3145,7 +2925,7 @@ void b43_calc_nrssi_threshold(struct b43_wldev *dev)
}
case B43_PHYTYPE_G:
if (!phy->gmode ||
- !(dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_RSSI)) {
+ !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) {
tmp16 = b43_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
tmp16 -= 0x40;
@@ -3667,7 +3447,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
}
if ((phy->rev < 7) ||
- !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+ !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
if (phy_register == B43_PHY_RFOVER) {
return 0x1B3;
} else if (phy_register == B43_PHY_RFOVERVAL) {
@@ -3707,7 +3487,7 @@ static u16 radio2050_rfover_val(struct b43_wldev *dev,
}
} else {
if ((phy->rev < 7) ||
- !(sprom->r1.boardflags_lo & B43_BFL_EXTLNA)) {
+ !(sprom->boardflags_lo & B43_BFL_EXTLNA)) {
if (phy_register == B43_PHY_RFOVER) {
return 0x1B3;
} else if (phy_register == B43_PHY_RFOVERVAL) {
@@ -3757,10 +3537,10 @@ struct init2050_saved_values {
u16 radio_52;
/* PHY registers */
u16 phy_pgactl;
- u16 phy_base_5A;
- u16 phy_base_59;
- u16 phy_base_58;
- u16 phy_base_30;
+ u16 phy_cck_5A;
+ u16 phy_cck_59;
+ u16 phy_cck_58;
+ u16 phy_cck_30;
u16 phy_rfover;
u16 phy_rfoverval;
u16 phy_analogover;
@@ -3788,15 +3568,15 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
sav.radio_51 = b43_radio_read16(dev, 0x51);
sav.radio_52 = b43_radio_read16(dev, 0x52);
sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL);
- sav.phy_base_5A = b43_phy_read(dev, B43_PHY_BASE(0x5A));
- sav.phy_base_59 = b43_phy_read(dev, B43_PHY_BASE(0x59));
- sav.phy_base_58 = b43_phy_read(dev, B43_PHY_BASE(0x58));
+ sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A));
+ sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59));
+ sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58));
if (phy->type == B43_PHYTYPE_B) {
- sav.phy_base_30 = b43_phy_read(dev, B43_PHY_BASE(0x30));
+ sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30));
sav.reg_3EC = b43_read16(dev, 0x3EC);
- b43_phy_write(dev, B43_PHY_BASE(0x30), 0xFF);
+ b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF);
b43_write16(dev, 0x3EC, 0x3F3F);
} else if (phy->gmode || phy->rev >= 2) {
sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER);
@@ -3847,8 +3627,8 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_write16(dev, 0x03E6, 0x0122);
} else {
if (phy->analog >= 2) {
- b43_phy_write(dev, B43_PHY_BASE(0x03),
- (b43_phy_read(dev, B43_PHY_BASE(0x03))
+ b43_phy_write(dev, B43_PHY_CCK(0x03),
+ (b43_phy_read(dev, B43_PHY_CCK(0x03))
& 0xFFBF) | 0x40);
}
b43_write16(dev, B43_MMIO_CHANNEL_EXT,
@@ -3865,7 +3645,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
LPD(0, 1, 1)));
}
b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF);
- b43_phy_write(dev, B43_PHY_BASE(0x2B), 0x1403);
+ b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403);
if (phy->gmode || phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_RFOVERVAL,
radio2050_rfover_val(dev, B43_PHY_RFOVERVAL,
@@ -3881,12 +3661,12 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_radio_write16(dev, 0x43, (b43_radio_read16(dev, 0x43)
& 0xFFF0) | 0x0009);
}
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
for (i = 0; i < 16; i++) {
- b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0480);
- b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
if (phy->gmode || phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_RFOVERVAL,
radio2050_rfover_val(dev,
@@ -3912,7 +3692,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
udelay(20);
tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
if (phy->gmode || phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_RFOVERVAL,
radio2050_rfover_val(dev,
@@ -3923,7 +3703,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
}
udelay(10);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
tmp1++;
tmp1 >>= 9;
@@ -3932,9 +3712,9 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_radio_write16(dev, 0x78, radio78);
udelay(10);
for (j = 0; j < 16; j++) {
- b43_phy_write(dev, B43_PHY_BASE(0x5A), 0x0D80);
- b43_phy_write(dev, B43_PHY_BASE(0x59), 0xC810);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0x000D);
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D);
if (phy->gmode || phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_RFOVERVAL,
radio2050_rfover_val(dev,
@@ -3963,7 +3743,7 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0);
udelay(10);
tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE);
- b43_phy_write(dev, B43_PHY_BASE(0x58), 0);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), 0);
if (phy->gmode || phy->rev >= 2) {
b43_phy_write(dev, B43_PHY_RFOVERVAL,
radio2050_rfover_val(dev,
@@ -3984,16 +3764,16 @@ u16 b43_radio_init2050(struct b43_wldev *dev)
b43_radio_write16(dev, 0x51, sav.radio_51);
b43_radio_write16(dev, 0x52, sav.radio_52);
b43_radio_write16(dev, 0x43, sav.radio_43);
- b43_phy_write(dev, B43_PHY_BASE(0x5A), sav.phy_base_5A);
- b43_phy_write(dev, B43_PHY_BASE(0x59), sav.phy_base_59);
- b43_phy_write(dev, B43_PHY_BASE(0x58), sav.phy_base_58);
+ b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A);
+ b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59);
+ b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58);
b43_write16(dev, 0x3E6, sav.reg_3E6);
if (phy->analog != 0)
b43_write16(dev, 0x3F4, sav.reg_3F4);
b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl);
b43_synth_pu_workaround(dev, phy->channel);
if (phy->type == B43_PHYTYPE_B) {
- b43_phy_write(dev, B43_PHY_BASE(0x30), sav.phy_base_30);
+ b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30);
b43_write16(dev, 0x3EC, sav.reg_3EC);
} else if (phy->gmode) {
b43_write16(dev, B43_MMIO_PHY_RADIO,
@@ -4103,7 +3883,8 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
struct b43_phy *phy = &dev->phy;
u16 r8, tmp;
u16 freq;
- u16 channelcookie;
+ u16 channelcookie, savedcookie;
+ int err = 0;
if (channel == 0xFF) {
switch (phy->type) {
@@ -4114,6 +3895,10 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
case B43_PHYTYPE_G:
channel = B43_DEFAULT_CHANNEL_BG;
break;
+ case B43_PHYTYPE_N:
+ //FIXME check if we are on 2.4GHz or 5GHz and set a default channel.
+ channel = 1;
+ break;
default:
B43_WARN_ON(1);
}
@@ -4123,13 +3908,18 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
* firmware from sending ghost packets.
*/
channelcookie = channel;
- if (phy->type == B43_PHYTYPE_A)
+ if (0 /*FIXME on 5Ghz */)
channelcookie |= 0x100;
+ //FIXME set 40Mhz flag if required
+ savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN);
b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie);
- if (phy->type == B43_PHYTYPE_A) {
- if (channel > 200)
- return -EINVAL;
+ switch (phy->type) {
+ case B43_PHYTYPE_A:
+ if (channel > 200) {
+ err = -EINVAL;
+ goto out;
+ }
freq = channel2freq_a(channel);
r8 = b43_radio_read16(dev, 0x0008);
@@ -4176,9 +3966,12 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
b43_radio_set_tx_iq(dev);
//TODO: TSSI2dbm workaround
b43_phy_xmitpower(dev); //FIXME correct?
- } else {
- if ((channel < 1) || (channel > 14))
- return -EINVAL;
+ break;
+ case B43_PHYTYPE_G:
+ if ((channel < 1) || (channel > 14)) {
+ err = -EINVAL;
+ goto out;
+ }
if (synthetic_pu_workaround)
b43_synth_pu_workaround(dev, channel);
@@ -4186,7 +3979,7 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel));
if (channel == 14) {
- if (dev->dev->bus->sprom.r1.country_code ==
+ if (dev->dev->bus->sprom.country_code ==
SSB_SPROM1CCODE_JAPAN)
b43_hf_write(dev,
b43_hf_read(dev) & ~B43_HF_ACPR);
@@ -4201,110 +3994,25 @@ int b43_radio_selectchannel(struct b43_wldev *dev,
b43_read16(dev, B43_MMIO_CHANNEL_EXT)
& 0xF7BF);
}
+ break;
+ case B43_PHYTYPE_N:
+ err = b43_nphy_selectchannel(dev, channel);
+ if (err)
+ goto out;
+ break;
+ default:
+ B43_WARN_ON(1);
}
phy->channel = channel;
/* Wait for the radio to tune to the channel and stabilize. */
msleep(8);
-
- return 0;
-}
-
-/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */
-static u16 b43_get_txgain_base_band(u16 txpower)
-{
- u16 ret;
-
- B43_WARN_ON(txpower > 63);
-
- if (txpower >= 54)
- ret = 2;
- else if (txpower >= 49)
- ret = 4;
- else if (txpower >= 44)
- ret = 5;
- else
- ret = 6;
-
- return ret;
-}
-
-/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */
-static u16 b43_get_txgain_freq_power_amp(u16 txpower)
-{
- u16 ret;
-
- B43_WARN_ON(txpower > 63);
-
- if (txpower >= 32)
- ret = 0;
- else if (txpower >= 25)
- ret = 1;
- else if (txpower >= 20)
- ret = 2;
- else if (txpower >= 12)
- ret = 3;
- else
- ret = 4;
-
- return ret;
-}
-
-/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */
-static u16 b43_get_txgain_dac(u16 txpower)
-{
- u16 ret;
-
- B43_WARN_ON(txpower > 63);
-
- if (txpower >= 54)
- ret = txpower - 53;
- else if (txpower >= 49)
- ret = txpower - 42;
- else if (txpower >= 44)
- ret = txpower - 37;
- else if (txpower >= 32)
- ret = txpower - 32;
- else if (txpower >= 25)
- ret = txpower - 20;
- else if (txpower >= 20)
- ret = txpower - 13;
- else if (txpower >= 12)
- ret = txpower - 8;
- else
- ret = txpower;
-
- return ret;
-}
-
-static void b43_radio_set_txpower_a(struct b43_wldev *dev, u16 txpower)
-{
- struct b43_phy *phy = &dev->phy;
- u16 pamp, base, dac, t;
-
- txpower = limit_value(txpower, 0, 63);
-
- pamp = b43_get_txgain_freq_power_amp(txpower);
- pamp <<= 5;
- pamp &= 0x00E0;
- b43_phy_write(dev, 0x0019, pamp);
-
- base = b43_get_txgain_base_band(txpower);
- base &= 0x000F;
- b43_phy_write(dev, 0x0017, base | 0x0020);
-
- t = b43_ofdmtab_read16(dev, 0x3000, 1);
- t &= 0x0007;
-
- dac = b43_get_txgain_dac(txpower);
- dac <<= 3;
- dac |= t;
-
- b43_ofdmtab_write16(dev, 0x3000, 1, dac);
-
- phy->txpwr_offset = txpower;
-
- //TODO: FuncPlaceholder (Adjust BB loft cancel)
+out:
+ if (err) {
+ b43_shm_write16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_CHAN, savedcookie);
+ }
+ return err;
}
void b43_radio_turn_on(struct b43_wldev *dev)
@@ -4344,6 +4052,9 @@ void b43_radio_turn_on(struct b43_wldev *dev)
err |= b43_radio_selectchannel(dev, channel, 0);
B43_WARN_ON(err);
break;
+ case B43_PHYTYPE_N:
+ b43_nphy_radio_turn_on(dev);
+ break;
default:
B43_WARN_ON(1);
}
@@ -4357,13 +4068,17 @@ void b43_radio_turn_off(struct b43_wldev *dev, bool force)
if (!phy->radio_on && !force)
return;
- if (phy->type == B43_PHYTYPE_A) {
+ switch (phy->type) {
+ case B43_PHYTYPE_N:
+ b43_nphy_radio_turn_off(dev);
+ break;
+ case B43_PHYTYPE_A:
b43_radio_write16(dev, 0x0004, 0x00FF);
b43_radio_write16(dev, 0x0005, 0x00FB);
b43_phy_write(dev, 0x0010, b43_phy_read(dev, 0x0010) | 0x0008);
b43_phy_write(dev, 0x0011, b43_phy_read(dev, 0x0011) | 0x0008);
- }
- if (phy->type == B43_PHYTYPE_G && dev->dev->id.revision >= 5) {
+ break;
+ case B43_PHYTYPE_G: {
u16 rfover, rfoverval;
rfover = b43_phy_read(dev, B43_PHY_RFOVER);
@@ -4375,7 +4090,10 @@ void b43_radio_turn_off(struct b43_wldev *dev, bool force)
}
b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C);
b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73);
- } else
- b43_phy_write(dev, 0x0015, 0xAA00);
+ break;
+ }
+ default:
+ B43_WARN_ON(1);
+ }
phy->radio_on = 0;
}
diff --git a/drivers/net/wireless/b43/phy.h b/drivers/net/wireless/b43/phy.h
index c64d74504fc0..6d165d822175 100644
--- a/drivers/net/wireless/b43/phy.h
+++ b/drivers/net/wireless/b43/phy.h
@@ -9,14 +9,21 @@ struct b43_phy;
/*** PHY Registers ***/
/* Routing */
-#define B43_PHYROUTE_OFDM_GPHY 0x400
-#define B43_PHYROUTE_EXT_GPHY 0x800
-
-/* Base registers. */
-#define B43_PHY_BASE(reg) (reg)
-/* OFDM (A) registers of a G-PHY */
+#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */
+#define B43_PHYROUTE_BASE 0x0000 /* Base registers */
+#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */
+#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */
+#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */
+
+/* CCK (B-PHY) registers. */
+#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE)
+/* N-PHY registers. */
+#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE)
+/* N-PHY BMODE registers. */
+#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE)
+/* OFDM (A-PHY) registers. */
#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY)
-/* Extended G-PHY registers */
+/* Extended G-PHY registers. */
#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY)
/* OFDM (A) PHY Registers */
@@ -25,10 +32,13 @@ struct b43_phy;
#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */
#define B43_PHY_BBANDCFG_RXANT_SHIFT 7
#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */
-#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 */
+#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */
#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */
+#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */
#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */
#define B43_PHY_CRS0 B43_PHY_OFDM(0x29)
+#define B43_PHY_CRS0_EN 0x4000
+#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30)
#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */
#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */
#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */
@@ -37,6 +47,7 @@ struct b43_phy;
#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */
#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */
#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */
+#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */
#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */
#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */
#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */
@@ -44,6 +55,9 @@ struct b43_phy;
#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */
#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */
#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */
+#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */
+#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B)
+#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */
#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */
#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */
#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */
@@ -54,33 +68,35 @@ struct b43_phy;
#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2)
#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3)
#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4)
+#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */
+#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */
#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */
#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9)
#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA)
#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB)
#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */
#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */
-#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (rev 1 only) */
-#define B43_PHY_CRSTHRES2_R1 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (rev 1 only) */
+#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */
+#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */
#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */
#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */
#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */
/* CCK (B) PHY Registers */
-#define B43_PHY_VERSION_CCK B43_PHY_BASE(0x00) /* Versioning register for B-PHY */
-#define B43_PHY_CCKBBANDCFG B43_PHY_BASE(0x01) /* Contains antenna 0/1 control bit */
-#define B43_PHY_PGACTL B43_PHY_BASE(0x15) /* PGA control */
+#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */
+#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */
+#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */
#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */
#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */
#define B43_PHY_PGACTL_UNKNOWN 0xEFA0
-#define B43_PHY_FBCTL1 B43_PHY_BASE(0x18) /* Frequency bandwidth control 1 */
-#define B43_PHY_ITSSI B43_PHY_BASE(0x29) /* Idle TSSI */
-#define B43_PHY_LO_LEAKAGE B43_PHY_BASE(0x2D) /* Measured LO leakage */
-#define B43_PHY_ENERGY B43_PHY_BASE(0x33) /* Energy */
-#define B43_PHY_SYNCCTL B43_PHY_BASE(0x35)
-#define B43_PHY_FBCTL2 B43_PHY_BASE(0x38) /* Frequency bandwidth control 2 */
-#define B43_PHY_DACCTL B43_PHY_BASE(0x60) /* DAC control */
-#define B43_PHY_RCCALOVER B43_PHY_BASE(0x78) /* RC calibration override */
+#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */
+#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */
+#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */
+#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */
+#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35)
+#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */
+#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */
+#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */
/* Extended G-PHY Registers */
#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */
@@ -125,13 +141,14 @@ struct b43_phy;
#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7)
#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12)
#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13)
-//TODO
+#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename
+#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename
#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12)
#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0)
-//TODO
+#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename
#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0)
-#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO rename
-#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 1)
+#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove!
+#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0)
#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0)
#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4)
#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0)
@@ -163,6 +180,8 @@ enum {
B43_ANTENNA1, /* Antenna 0 */
B43_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */
B43_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */
+ B43_ANTENNA2,
+ B43_ANTENNA3 = 8,
B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0,
B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO,
@@ -182,21 +201,21 @@ enum {
#define B43_PHYVER_TYPE_SHIFT 8
#define B43_PHYVER_VERSION 0x00FF
-void b43_raw_phy_lock(struct b43_wldev *dev);
-#define b43_phy_lock(dev, flags) \
- do { \
- local_irq_save(flags); \
- b43_raw_phy_lock(dev); \
- } while (0)
-void b43_raw_phy_unlock(struct b43_wldev *dev);
-#define b43_phy_unlock(dev, flags) \
- do { \
- b43_raw_phy_unlock(dev); \
- local_irq_restore(flags); \
- } while (0)
+void b43_phy_lock(struct b43_wldev *dev);
+void b43_phy_unlock(struct b43_wldev *dev);
+
+/* Read a value from a PHY register */
u16 b43_phy_read(struct b43_wldev *dev, u16 offset);
+/* Write a value to a PHY register */
void b43_phy_write(struct b43_wldev *dev, u16 offset, u16 val);
+/* Mask a PHY register with a mask */
+void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+/* OR a PHY register with a bitmap */
+void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set);
+/* Mask and OR a PHY register with a mask and bitmap */
+void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
int b43_phy_init_tssi2dbm_table(struct b43_wldev *dev);
@@ -260,8 +279,18 @@ extern const u8 b43_radio_channel_codes_bg[];
void b43_radio_lock(struct b43_wldev *dev);
void b43_radio_unlock(struct b43_wldev *dev);
+
+/* Read a value from a 16bit radio register */
u16 b43_radio_read16(struct b43_wldev *dev, u16 offset);
+/* Write a value to a 16bit radio register */
void b43_radio_write16(struct b43_wldev *dev, u16 offset, u16 val);
+/* Mask a 16bit radio register with a mask */
+void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask);
+/* OR a 16bit radio register with a bitmap */
+void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set);
+/* Mask and OR a PHY register with a mask and bitmap */
+void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set);
+
u16 b43_radio_init2050(struct b43_wldev *dev);
void b43_radio_init2060(struct b43_wldev *dev);
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
deleted file mode 100644
index 67752a28eb9c..000000000000
--- a/drivers/net/wireless/b43/pio.c
+++ /dev/null
@@ -1,652 +0,0 @@
-/*
-
- Broadcom B43 wireless driver
-
- PIO Transmission
-
- Copyright (c) 2005 Michael Buesch <mb@bu3sch.de>
-
- 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; see the file COPYING. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
- Boston, MA 02110-1301, USA.
-
-*/
-
-#include "b43.h"
-#include "pio.h"
-#include "main.h"
-#include "xmit.h"
-
-#include <linux/delay.h>
-
-static void tx_start(struct b43_pioqueue *queue)
-{
- b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_INIT);
-}
-
-static void tx_octet(struct b43_pioqueue *queue, u8 octet)
-{
- if (queue->need_workarounds) {
- b43_pio_write(queue, B43_PIO_TXDATA, octet);
- b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_WRITELO);
- } else {
- b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_WRITELO);
- b43_pio_write(queue, B43_PIO_TXDATA, octet);
- }
-}
-
-static u16 tx_get_next_word(const u8 * txhdr,
- const u8 * packet,
- size_t txhdr_size, unsigned int *pos)
-{
- const u8 *source;
- unsigned int i = *pos;
- u16 ret;
-
- if (i < txhdr_size) {
- source = txhdr;
- } else {
- source = packet;
- i -= txhdr_size;
- }
- ret = le16_to_cpu(*((__le16 *)(source + i)));
- *pos += 2;
-
- return ret;
-}
-
-static void tx_data(struct b43_pioqueue *queue,
- u8 * txhdr, const u8 * packet, unsigned int octets)
-{
- u16 data;
- unsigned int i = 0;
-
- if (queue->need_workarounds) {
- data = tx_get_next_word(txhdr, packet,
- sizeof(struct b43_txhdr_fw4), &i);
- b43_pio_write(queue, B43_PIO_TXDATA, data);
- }
- b43_pio_write(queue, B43_PIO_TXCTL,
- B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI);
- while (i < octets - 1) {
- data = tx_get_next_word(txhdr, packet,
- sizeof(struct b43_txhdr_fw4), &i);
- b43_pio_write(queue, B43_PIO_TXDATA, data);
- }
- if (octets % 2)
- tx_octet(queue,
- packet[octets - sizeof(struct b43_txhdr_fw4) - 1]);
-}
-
-static void tx_complete(struct b43_pioqueue *queue, struct sk_buff *skb)
-{
- if (queue->need_workarounds) {
- b43_pio_write(queue, B43_PIO_TXDATA, skb->data[skb->len - 1]);
- b43_pio_write(queue, B43_PIO_TXCTL,
- B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_COMPLETE);
- } else {
- b43_pio_write(queue, B43_PIO_TXCTL, B43_PIO_TXCTL_COMPLETE);
- }
-}
-
-static u16 generate_cookie(struct b43_pioqueue *queue,
- struct b43_pio_txpacket *packet)
-{
- u16 cookie = 0x0000;
- u16 packetindex;
-
- /* We use the upper 4 bits for the PIO
- * controller ID and the lower 12 bits
- * for the packet index (in the cache).
- */
- switch (queue->mmio_base) {
- case B43_MMIO_PIO1_BASE:
- break;
- case B43_MMIO_PIO2_BASE:
- cookie = 0x1000;
- break;
- case B43_MMIO_PIO3_BASE:
- cookie = 0x2000;
- break;
- case B43_MMIO_PIO4_BASE:
- cookie = 0x3000;
- break;
- default:
- B43_WARN_ON(1);
- }
- packetindex = packet->index;
- B43_WARN_ON(packetindex & ~0x0FFF);
- cookie |= (u16) packetindex;
-
- return cookie;
-}
-
-static
-struct b43_pioqueue *parse_cookie(struct b43_wldev *dev,
- u16 cookie, struct b43_pio_txpacket **packet)
-{
- struct b43_pio *pio = &dev->pio;
- struct b43_pioqueue *queue = NULL;
- int packetindex;
-
- switch (cookie & 0xF000) {
- case 0x0000:
- queue = pio->queue0;
- break;
- case 0x1000:
- queue = pio->queue1;
- break;
- case 0x2000:
- queue = pio->queue2;
- break;
- case 0x3000:
- queue = pio->queue3;
- break;
- default:
- B43_WARN_ON(1);
- }
- packetindex = (cookie & 0x0FFF);
- B43_WARN_ON(!(packetindex >= 0 && packetindex < B43_PIO_MAXTXPACKETS));
- *packet = &(queue->tx_packets_cache[packetindex]);
-
- return queue;
-}
-
-union txhdr_union {
- struct b43_txhdr_fw4 txhdr_fw4;
-};
-
-static void pio_tx_write_fragment(struct b43_pioqueue *queue,
- struct sk_buff *skb,
- struct b43_pio_txpacket *packet,
- size_t txhdr_size)
-{
- union txhdr_union txhdr_data;
- u8 *txhdr = NULL;
- unsigned int octets;
-
- txhdr = (u8 *) (&txhdr_data.txhdr_fw4);
-
- B43_WARN_ON(skb_shinfo(skb)->nr_frags);
- b43_generate_txhdr(queue->dev,
- txhdr, skb->data, skb->len,
- &packet->txstat.control,
- generate_cookie(queue, packet));
-
- tx_start(queue);
- octets = skb->len + txhdr_size;
- if (queue->need_workarounds)
- octets--;
- tx_data(queue, txhdr, (u8 *) skb->data, octets);
- tx_complete(queue, skb);
-}
-
-static void free_txpacket(struct b43_pio_txpacket *packet)
-{
- struct b43_pioqueue *queue = packet->queue;
-
- if (packet->skb)
- dev_kfree_skb_any(packet->skb);
- list_move(&packet->list, &queue->txfree);
- queue->nr_txfree++;
-}
-
-static int pio_tx_packet(struct b43_pio_txpacket *packet)
-{
- struct b43_pioqueue *queue = packet->queue;
- struct sk_buff *skb = packet->skb;
- u16 octets;
-
- octets = (u16) skb->len + sizeof(struct b43_txhdr_fw4);
- if (queue->tx_devq_size < octets) {
- b43warn(queue->dev->wl, "PIO queue too small. "
- "Dropping packet.\n");
- /* Drop it silently (return success) */
- free_txpacket(packet);
- return 0;
- }
- B43_WARN_ON(queue->tx_devq_packets > B43_PIO_MAXTXDEVQPACKETS);
- B43_WARN_ON(queue->tx_devq_used > queue->tx_devq_size);
- /* Check if there is sufficient free space on the device
- * TX queue. If not, return and let the TX tasklet
- * retry later.
- */
- if (queue->tx_devq_packets == B43_PIO_MAXTXDEVQPACKETS)
- return -EBUSY;
- if (queue->tx_devq_used + octets > queue->tx_devq_size)
- return -EBUSY;
- /* Now poke the device. */
- pio_tx_write_fragment(queue, skb, packet, sizeof(struct b43_txhdr_fw4));
-
- /* Account for the packet size.
- * (We must not overflow the device TX queue)
- */
- queue->tx_devq_packets++;
- queue->tx_devq_used += octets;
-
- /* Transmission started, everything ok, move the
- * packet to the txrunning list.
- */
- list_move_tail(&packet->list, &queue->txrunning);
-
- return 0;
-}
-
-static void tx_tasklet(unsigned long d)
-{
- struct b43_pioqueue *queue = (struct b43_pioqueue *)d;
- struct b43_wldev *dev = queue->dev;
- unsigned long flags;
- struct b43_pio_txpacket *packet, *tmp_packet;
- int err;
- u16 txctl;
-
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- if (queue->tx_frozen)
- goto out_unlock;
- txctl = b43_pio_read(queue, B43_PIO_TXCTL);
- if (txctl & B43_PIO_TXCTL_SUSPEND)
- goto out_unlock;
-
- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) {
- /* Try to transmit the packet. This can fail, if
- * the device queue is full. In case of failure, the
- * packet is left in the txqueue.
- * If transmission succeed, the packet is moved to txrunning.
- * If it is impossible to transmit the packet, it
- * is dropped.
- */
- err = pio_tx_packet(packet);
- if (err)
- break;
- }
- out_unlock:
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
-}
-
-static void setup_txqueues(struct b43_pioqueue *queue)
-{
- struct b43_pio_txpacket *packet;
- int i;
-
- queue->nr_txfree = B43_PIO_MAXTXPACKETS;
- for (i = 0; i < B43_PIO_MAXTXPACKETS; i++) {
- packet = &(queue->tx_packets_cache[i]);
-
- packet->queue = queue;
- INIT_LIST_HEAD(&packet->list);
- packet->index = i;
-
- list_add(&packet->list, &queue->txfree);
- }
-}
-
-static
-struct b43_pioqueue *b43_setup_pioqueue(struct b43_wldev *dev,
- u16 pio_mmio_base)
-{
- struct b43_pioqueue *queue;
- u16 qsize;
-
- queue = kzalloc(sizeof(*queue), GFP_KERNEL);
- if (!queue)
- goto out;
-
- queue->dev = dev;
- queue->mmio_base = pio_mmio_base;
- queue->need_workarounds = (dev->dev->id.revision < 3);
-
- INIT_LIST_HEAD(&queue->txfree);
- INIT_LIST_HEAD(&queue->txqueue);
- INIT_LIST_HEAD(&queue->txrunning);
- tasklet_init(&queue->txtask, tx_tasklet, (unsigned long)queue);
-
- b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
- & ~B43_MACCTL_BE);
-
- qsize = b43_read16(dev, queue->mmio_base + B43_PIO_TXQBUFSIZE);
- if (qsize == 0) {
- b43err(dev->wl, "This card does not support PIO "
- "operation mode. Please use DMA mode "
- "(module parameter pio=0).\n");
- goto err_freequeue;
- }
- if (qsize <= B43_PIO_TXQADJUST) {
- b43err(dev->wl, "PIO tx device-queue too small (%u)\n", qsize);
- goto err_freequeue;
- }
- qsize -= B43_PIO_TXQADJUST;
- queue->tx_devq_size = qsize;
-
- setup_txqueues(queue);
-
- out:
- return queue;
-
- err_freequeue:
- kfree(queue);
- queue = NULL;
- goto out;
-}
-
-static void cancel_transfers(struct b43_pioqueue *queue)
-{
- struct b43_pio_txpacket *packet, *tmp_packet;
-
- tasklet_disable(&queue->txtask);
-
- list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list)
- free_txpacket(packet);
- list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list)
- free_txpacket(packet);
-}
-
-static void b43_destroy_pioqueue(struct b43_pioqueue *queue)
-{
- if (!queue)
- return;
-
- cancel_transfers(queue);
- kfree(queue);
-}
-
-void b43_pio_free(struct b43_wldev *dev)
-{
- struct b43_pio *pio;
-
- if (!b43_using_pio(dev))
- return;
- pio = &dev->pio;
-
- b43_destroy_pioqueue(pio->queue3);
- pio->queue3 = NULL;
- b43_destroy_pioqueue(pio->queue2);
- pio->queue2 = NULL;
- b43_destroy_pioqueue(pio->queue1);
- pio->queue1 = NULL;
- b43_destroy_pioqueue(pio->queue0);
- pio->queue0 = NULL;
-}
-
-int b43_pio_init(struct b43_wldev *dev)
-{
- struct b43_pio *pio = &dev->pio;
- struct b43_pioqueue *queue;
- int err = -ENOMEM;
-
- queue = b43_setup_pioqueue(dev, B43_MMIO_PIO1_BASE);
- if (!queue)
- goto out;
- pio->queue0 = queue;
-
- queue = b43_setup_pioqueue(dev, B43_MMIO_PIO2_BASE);
- if (!queue)
- goto err_destroy0;
- pio->queue1 = queue;
-
- queue = b43_setup_pioqueue(dev, B43_MMIO_PIO3_BASE);
- if (!queue)
- goto err_destroy1;
- pio->queue2 = queue;
-
- queue = b43_setup_pioqueue(dev, B43_MMIO_PIO4_BASE);
- if (!queue)
- goto err_destroy2;
- pio->queue3 = queue;
-
- if (dev->dev->id.revision < 3)
- dev->irq_savedstate |= B43_IRQ_PIO_WORKAROUND;
-
- b43dbg(dev->wl, "PIO initialized\n");
- err = 0;
- out:
- return err;
-
- err_destroy2:
- b43_destroy_pioqueue(pio->queue2);
- pio->queue2 = NULL;
- err_destroy1:
- b43_destroy_pioqueue(pio->queue1);
- pio->queue1 = NULL;
- err_destroy0:
- b43_destroy_pioqueue(pio->queue0);
- pio->queue0 = NULL;
- goto out;
-}
-
-int b43_pio_tx(struct b43_wldev *dev,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-{
- struct b43_pioqueue *queue = dev->pio.queue1;
- struct b43_pio_txpacket *packet;
-
- B43_WARN_ON(queue->tx_suspended);
- B43_WARN_ON(list_empty(&queue->txfree));
-
- packet = list_entry(queue->txfree.next, struct b43_pio_txpacket, list);
- packet->skb = skb;
-
- memset(&packet->txstat, 0, sizeof(packet->txstat));
- memcpy(&packet->txstat.control, ctl, sizeof(*ctl));
-
- list_move_tail(&packet->list, &queue->txqueue);
- queue->nr_txfree--;
- queue->nr_tx_packets++;
- B43_WARN_ON(queue->nr_txfree >= B43_PIO_MAXTXPACKETS);
-
- tasklet_schedule(&queue->txtask);
-
- return 0;
-}
-
-void b43_pio_handle_txstatus(struct b43_wldev *dev,
- const struct b43_txstatus *status)
-{
- struct b43_pioqueue *queue;
- struct b43_pio_txpacket *packet;
-
- queue = parse_cookie(dev, status->cookie, &packet);
- if (B43_WARN_ON(!queue))
- return;
-
- queue->tx_devq_packets--;
- queue->tx_devq_used -=
- (packet->skb->len + sizeof(struct b43_txhdr_fw4));
-
- if (status->acked) {
- packet->txstat.flags |= IEEE80211_TX_STATUS_ACK;
- } else {
- if (!(packet->txstat.control.flags & IEEE80211_TXCTL_NO_ACK))
- packet->txstat.excessive_retries = 1;
- }
- if (status->frame_count == 0) {
- /* The frame was not transmitted at all. */
- packet->txstat.retry_count = 0;
- } else
- packet->txstat.retry_count = status->frame_count - 1;
- ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb,
- &(packet->txstat));
- packet->skb = NULL;
-
- free_txpacket(packet);
- /* If there are packets on the txqueue, poke the tasklet
- * to transmit them.
- */
- if (!list_empty(&queue->txqueue))
- tasklet_schedule(&queue->txtask);
-}
-
-void b43_pio_get_tx_stats(struct b43_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
- struct b43_pio *pio = &dev->pio;
- struct b43_pioqueue *queue;
- struct ieee80211_tx_queue_stats_data *data;
-
- queue = pio->queue1;
- data = &(stats->data[0]);
- data->len = B43_PIO_MAXTXPACKETS - queue->nr_txfree;
- data->limit = B43_PIO_MAXTXPACKETS;
- data->count = queue->nr_tx_packets;
-}
-
-static void pio_rx_error(struct b43_pioqueue *queue,
- int clear_buffers, const char *error)
-{
- int i;
-
- b43err(queue->dev->wl, "PIO RX error: %s\n", error);
- b43_pio_write(queue, B43_PIO_RXCTL, B43_PIO_RXCTL_READY);
- if (clear_buffers) {
- B43_WARN_ON(queue->mmio_base != B43_MMIO_PIO1_BASE);
- for (i = 0; i < 15; i++) {
- /* Dummy read. */
- b43_pio_read(queue, B43_PIO_RXDATA);
- }
- }
-}
-
-void b43_pio_rx(struct b43_pioqueue *queue)
-{
- __le16 preamble[21] = { 0 };
- struct b43_rxhdr_fw4 *rxhdr;
- u16 tmp, len;
- u32 macstat;
- int i, preamble_readwords;
- struct sk_buff *skb;
-
- tmp = b43_pio_read(queue, B43_PIO_RXCTL);
- if (!(tmp & B43_PIO_RXCTL_DATAAVAILABLE))
- return;
- b43_pio_write(queue, B43_PIO_RXCTL, B43_PIO_RXCTL_DATAAVAILABLE);
-
- for (i = 0; i < 10; i++) {
- tmp = b43_pio_read(queue, B43_PIO_RXCTL);
- if (tmp & B43_PIO_RXCTL_READY)
- goto data_ready;
- udelay(10);
- }
- b43dbg(queue->dev->wl, "PIO RX timed out\n");
- return;
-data_ready:
-
- len = b43_pio_read(queue, B43_PIO_RXDATA);
- if (unlikely(len > 0x700)) {
- pio_rx_error(queue, 0, "len > 0x700");
- return;
- }
- if (unlikely(len == 0 && queue->mmio_base != B43_MMIO_PIO4_BASE)) {
- pio_rx_error(queue, 0, "len == 0");
- return;
- }
- preamble[0] = cpu_to_le16(len);
- if (queue->mmio_base == B43_MMIO_PIO4_BASE)
- preamble_readwords = 14 / sizeof(u16);
- else
- preamble_readwords = 18 / sizeof(u16);
- for (i = 0; i < preamble_readwords; i++) {
- tmp = b43_pio_read(queue, B43_PIO_RXDATA);
- preamble[i + 1] = cpu_to_le16(tmp);
- }
- rxhdr = (struct b43_rxhdr_fw4 *)preamble;
- macstat = le32_to_cpu(rxhdr->mac_status);
- if (macstat & B43_RX_MAC_FCSERR) {
- pio_rx_error(queue,
- (queue->mmio_base == B43_MMIO_PIO1_BASE),
- "Frame FCS error");
- return;
- }
- if (queue->mmio_base == B43_MMIO_PIO4_BASE) {
- /* We received an xmit status. */
- struct b43_hwtxstatus *hw;
-
- hw = (struct b43_hwtxstatus *)(preamble + 1);
- b43_handle_hwtxstatus(queue->dev, hw);
-
- return;
- }
-
- skb = dev_alloc_skb(len);
- if (unlikely(!skb)) {
- pio_rx_error(queue, 1, "OOM");
- return;
- }
- skb_put(skb, len);
- for (i = 0; i < len - 1; i += 2) {
- tmp = b43_pio_read(queue, B43_PIO_RXDATA);
- *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
- }
- if (len % 2) {
- tmp = b43_pio_read(queue, B43_PIO_RXDATA);
- skb->data[len - 1] = (tmp & 0x00FF);
-/* The specs say the following is required, but
- * it is wrong and corrupts the PLCP. If we don't do
- * this, the PLCP seems to be correct. So ifdef it out for now.
- */
-#if 0
- if (rxflags2 & B43_RXHDR_FLAGS2_TYPE2FRAME)
- skb->data[2] = (tmp & 0xFF00) >> 8;
- else
- skb->data[0] = (tmp & 0xFF00) >> 8;
-#endif
- }
- b43_rx(queue->dev, skb, rxhdr);
-}
-
-void b43_pio_tx_suspend(struct b43_pioqueue *queue)
-{
- b43_power_saving_ctl_bits(queue->dev, B43_PS_AWAKE);
- b43_pio_write(queue, B43_PIO_TXCTL, b43_pio_read(queue, B43_PIO_TXCTL)
- | B43_PIO_TXCTL_SUSPEND);
-}
-
-void b43_pio_tx_resume(struct b43_pioqueue *queue)
-{
- b43_pio_write(queue, B43_PIO_TXCTL, b43_pio_read(queue, B43_PIO_TXCTL)
- & ~B43_PIO_TXCTL_SUSPEND);
- b43_power_saving_ctl_bits(queue->dev, 0);
- tasklet_schedule(&queue->txtask);
-}
-
-void b43_pio_freeze_txqueues(struct b43_wldev *dev)
-{
- struct b43_pio *pio;
-
- B43_WARN_ON(!b43_using_pio(dev));
- pio = &dev->pio;
- pio->queue0->tx_frozen = 1;
- pio->queue1->tx_frozen = 1;
- pio->queue2->tx_frozen = 1;
- pio->queue3->tx_frozen = 1;
-}
-
-void b43_pio_thaw_txqueues(struct b43_wldev *dev)
-{
- struct b43_pio *pio;
-
- B43_WARN_ON(!b43_using_pio(dev));
- pio = &dev->pio;
- pio->queue0->tx_frozen = 0;
- pio->queue1->tx_frozen = 0;
- pio->queue2->tx_frozen = 0;
- pio->queue3->tx_frozen = 0;
- if (!list_empty(&pio->queue0->txqueue))
- tasklet_schedule(&pio->queue0->txtask);
- if (!list_empty(&pio->queue1->txqueue))
- tasklet_schedule(&pio->queue1->txtask);
- if (!list_empty(&pio->queue2->txqueue))
- tasklet_schedule(&pio->queue2->txtask);
- if (!list_empty(&pio->queue3->txqueue))
- tasklet_schedule(&pio->queue3->txtask);
-}
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h
deleted file mode 100644
index 3488f2447bbf..000000000000
--- a/drivers/net/wireless/b43/pio.h
+++ /dev/null
@@ -1,153 +0,0 @@
-#ifndef B43_PIO_H_
-#define B43_PIO_H_
-
-#include "b43.h"
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/list.h>
-#include <linux/skbuff.h>
-
-#define B43_PIO_TXCTL 0x00
-#define B43_PIO_TXDATA 0x02
-#define B43_PIO_TXQBUFSIZE 0x04
-#define B43_PIO_RXCTL 0x08
-#define B43_PIO_RXDATA 0x0A
-
-#define B43_PIO_TXCTL_WRITELO (1 << 0)
-#define B43_PIO_TXCTL_WRITEHI (1 << 1)
-#define B43_PIO_TXCTL_COMPLETE (1 << 2)
-#define B43_PIO_TXCTL_INIT (1 << 3)
-#define B43_PIO_TXCTL_SUSPEND (1 << 7)
-
-#define B43_PIO_RXCTL_DATAAVAILABLE (1 << 0)
-#define B43_PIO_RXCTL_READY (1 << 1)
-
-/* PIO constants */
-#define B43_PIO_MAXTXDEVQPACKETS 31
-#define B43_PIO_TXQADJUST 80
-
-/* PIO tuning knobs */
-#define B43_PIO_MAXTXPACKETS 256
-
-#ifdef CONFIG_B43_PIO
-
-struct b43_pioqueue;
-struct b43_xmitstatus;
-
-struct b43_pio_txpacket {
- struct b43_pioqueue *queue;
- struct sk_buff *skb;
- struct ieee80211_tx_status txstat;
- struct list_head list;
- u16 index; /* Index in the tx_packets_cache */
-};
-
-struct b43_pioqueue {
- struct b43_wldev *dev;
- u16 mmio_base;
-
- bool tx_suspended;
- bool tx_frozen;
- bool need_workarounds; /* Workarounds needed for core.rev < 3 */
-
- /* Adjusted size of the device internal TX buffer. */
- u16 tx_devq_size;
- /* Used octets of the device internal TX buffer. */
- u16 tx_devq_used;
- /* Used packet slots in the device internal TX buffer. */
- u8 tx_devq_packets;
- /* Packets from the txfree list can
- * be taken on incoming TX requests.
- */
- struct list_head txfree;
- unsigned int nr_txfree;
- /* Packets on the txqueue are queued,
- * but not completely written to the chip, yet.
- */
- struct list_head txqueue;
- /* Packets on the txrunning queue are completely
- * posted to the device. We are waiting for the txstatus.
- */
- struct list_head txrunning;
- /* Total number or packets sent.
- * (This counter can obviously wrap).
- */
- unsigned int nr_tx_packets;
- struct tasklet_struct txtask;
- struct b43_pio_txpacket tx_packets_cache[B43_PIO_MAXTXPACKETS];
-};
-
-static inline u16 b43_pio_read(struct b43_pioqueue *queue, u16 offset)
-{
- return b43_read16(queue->dev, queue->mmio_base + offset);
-}
-
-static inline
- void b43_pio_write(struct b43_pioqueue *queue, u16 offset, u16 value)
-{
- b43_write16(queue->dev, queue->mmio_base + offset, value);
- mmiowb();
-}
-
-int b43_pio_init(struct b43_wldev *dev);
-void b43_pio_free(struct b43_wldev *dev);
-
-int b43_pio_tx(struct b43_wldev *dev,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl);
-void b43_pio_handle_txstatus(struct b43_wldev *dev,
- const struct b43_txstatus *status);
-void b43_pio_get_tx_stats(struct b43_wldev *dev,
- struct ieee80211_tx_queue_stats *stats);
-void b43_pio_rx(struct b43_pioqueue *queue);
-
-/* Suspend TX queue in hardware. */
-void b43_pio_tx_suspend(struct b43_pioqueue *queue);
-void b43_pio_tx_resume(struct b43_pioqueue *queue);
-/* Suspend (freeze) the TX tasklet (software level). */
-void b43_pio_freeze_txqueues(struct b43_wldev *dev);
-void b43_pio_thaw_txqueues(struct b43_wldev *dev);
-
-#else /* CONFIG_B43_PIO */
-
-static inline int b43_pio_init(struct b43_wldev *dev)
-{
- return 0;
-}
-static inline void b43_pio_free(struct b43_wldev *dev)
-{
-}
-static inline
- int b43_pio_tx(struct b43_wldev *dev,
- struct sk_buff *skb, struct ieee80211_tx_control *ctl)
-{
- return 0;
-}
-static inline
- void b43_pio_handle_txstatus(struct b43_wldev *dev,
- const struct b43_txstatus *status)
-{
-}
-static inline
- void b43_pio_get_tx_stats(struct b43_wldev *dev,
- struct ieee80211_tx_queue_stats *stats)
-{
-}
-static inline void b43_pio_rx(struct b43_pioqueue *queue)
-{
-}
-static inline void b43_pio_tx_suspend(struct b43_pioqueue *queue)
-{
-}
-static inline void b43_pio_tx_resume(struct b43_pioqueue *queue)
-{
-}
-static inline void b43_pio_freeze_txqueues(struct b43_wldev *dev)
-{
-}
-static inline void b43_pio_thaw_txqueues(struct b43_wldev *dev)
-{
-}
-
-#endif /* CONFIG_B43_PIO */
-#endif /* B43_PIO_H_ */
diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c
index 15a87183a572..3f5ea06bf13c 100644
--- a/drivers/net/wireless/b43/tables.c
+++ b/drivers/net/wireless/b43/tables.c
@@ -3,7 +3,7 @@
Broadcom B43 wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2006, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -229,7 +229,7 @@ const u16 b43_tab_noisea2[] = {
};
const u16 b43_tab_noisea3[] = {
- 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
+ 0x5E5E, 0x5E5E, 0x5E5E, 0x3F48,
0x4C4C, 0x4C4C, 0x4C4C, 0x2D36,
};
@@ -243,6 +243,26 @@ const u16 b43_tab_noiseg2[] = {
0x0000, 0x0000, 0x0000, 0x0000,
};
+const u16 b43_tab_noisescalea2[] = {
+ 0x6767, 0x6767, 0x6767, 0x6767, /* 0 */
+ 0x6767, 0x6767, 0x6767, 0x6767,
+ 0x6767, 0x6767, 0x6767, 0x6767,
+ 0x6767, 0x6700, 0x6767, 0x6767,
+ 0x6767, 0x6767, 0x6767, 0x6767, /* 16 */
+ 0x6767, 0x6767, 0x6767, 0x6767,
+ 0x6767, 0x6767, 0x0067,
+};
+
+const u16 b43_tab_noisescalea3[] = {
+ 0x2323, 0x2323, 0x2323, 0x2323, /* 0 */
+ 0x2323, 0x2323, 0x2323, 0x2323,
+ 0x2323, 0x2323, 0x2323, 0x2323,
+ 0x2323, 0x2300, 0x2323, 0x2323,
+ 0x2323, 0x2323, 0x2323, 0x2323, /* 16 */
+ 0x2323, 0x2323, 0x2323, 0x2323,
+ 0x2323, 0x2323, 0x0023,
+};
+
const u16 b43_tab_noisescaleg1[] = {
0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */
0x2F2D, 0x2A2A, 0x2527, 0x1F21,
@@ -254,7 +274,7 @@ const u16 b43_tab_noisescaleg1[] = {
};
const u16 b43_tab_noisescaleg2[] = {
- 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */
+ 0xD8DD, 0xCBD4, 0xBCC0, 0xB6B7, /* 0 */
0xB2B0, 0xADAD, 0xA7A9, 0x9FA1,
0x969B, 0x9195, 0x8F8F, 0x8A8A,
0x8A8A, 0x8A00, 0x8A8A, 0x8F8A,
@@ -307,6 +327,28 @@ const u16 b43_tab_sigmasqr2[] = {
0x00DE,
};
+const u16 b43_tab_rssiagc1[] = {
+ 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, /* 0 */
+ 0xFFF8, 0xFFF9, 0xFFFC, 0xFFFE,
+ 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+ 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8,
+};
+
+const u16 b43_tab_rssiagc2[] = {
+ 0x0820, 0x0820, 0x0920, 0x0C38, /* 0 */
+ 0x0820, 0x0820, 0x0820, 0x0820,
+ 0x0820, 0x0820, 0x0920, 0x0A38,
+ 0x0820, 0x0820, 0x0820, 0x0820,
+ 0x0820, 0x0820, 0x0920, 0x0A38, /* 16 */
+ 0x0820, 0x0820, 0x0820, 0x0820,
+ 0x0820, 0x0820, 0x0920, 0x0A38,
+ 0x0820, 0x0820, 0x0820, 0x0820,
+ 0x0820, 0x0820, 0x0920, 0x0A38, /* 32 */
+ 0x0820, 0x0820, 0x0820, 0x0820,
+ 0x0820, 0x0820, 0x0920, 0x0A38,
+ 0x0820, 0x0820, 0x0820, 0x0820,
+};
+
static inline void assert_sizes(void)
{
BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor));
@@ -317,36 +359,73 @@ static inline void assert_sizes(void)
BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3));
BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1));
BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2));
- BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+ BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+ ARRAY_SIZE(b43_tab_noisescalea2));
+ BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
+ ARRAY_SIZE(b43_tab_noisescalea3));
+ BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg1));
- BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+ BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg2));
- BUILD_BUG_ON(B43_TAB_NOISESCALEG_SIZE !=
+ BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE !=
ARRAY_SIZE(b43_tab_noisescaleg3));
BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1));
BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2));
+ BUILD_BUG_ON(B43_TAB_RSSIAGC1_SIZE != ARRAY_SIZE(b43_tab_rssiagc1));
+ BUILD_BUG_ON(B43_TAB_RSSIAGC2_SIZE != ARRAY_SIZE(b43_tab_rssiagc2));
}
u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset)
{
- assert_sizes();
+ struct b43_phy *phy = &dev->phy;
+ u16 addr;
+
+ addr = table + offset;
+ if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+ (addr - 1 != phy->ofdmtab_addr)) {
+ /* The hardware has a different address in memory. Update it. */
+ b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+ phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+ }
+ phy->ofdmtab_addr = addr;
- b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
return b43_phy_read(dev, B43_PHY_OTABLEI);
+
+ /* Some compiletime assertions... */
+ assert_sizes();
}
void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table,
u16 offset, u16 value)
{
- b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+ struct b43_phy *phy = &dev->phy;
+ u16 addr;
+
+ addr = table + offset;
+ if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+ (addr - 1 != phy->ofdmtab_addr)) {
+ /* The hardware has a different address in memory. Update it. */
+ b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+ phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+ }
+ phy->ofdmtab_addr = addr;
b43_phy_write(dev, B43_PHY_OTABLEI, value);
}
u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
{
+ struct b43_phy *phy = &dev->phy;
u32 ret;
+ u16 addr;
- b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+ addr = table + offset;
+ if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) ||
+ (addr - 1 != phy->ofdmtab_addr)) {
+ /* The hardware has a different address in memory. Update it. */
+ b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+ phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ;
+ }
+ phy->ofdmtab_addr = addr;
ret = b43_phy_read(dev, B43_PHY_OTABLEQ);
ret <<= 16;
ret |= b43_phy_read(dev, B43_PHY_OTABLEI);
@@ -357,7 +436,18 @@ u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset)
void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table,
u16 offset, u32 value)
{
- b43_phy_write(dev, B43_PHY_OTABLECTL, table + offset);
+ struct b43_phy *phy = &dev->phy;
+ u16 addr;
+
+ addr = table + offset;
+ if ((phy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) ||
+ (addr - 1 != phy->ofdmtab_addr)) {
+ /* The hardware has a different address in memory. Update it. */
+ b43_phy_write(dev, B43_PHY_OTABLECTL, addr);
+ phy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE;
+ }
+ phy->ofdmtab_addr = addr;
+
b43_phy_write(dev, B43_PHY_OTABLEI, value);
b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16));
}
diff --git a/drivers/net/wireless/b43/tables.h b/drivers/net/wireless/b43/tables.h
index 64635d7b518c..80e73c7cbac5 100644
--- a/drivers/net/wireless/b43/tables.h
+++ b/drivers/net/wireless/b43/tables.h
@@ -1,9 +1,9 @@
#ifndef B43_TABLES_H_
#define B43_TABLES_H_
-#define B43_TAB_ROTOR_SIZE 53
+#define B43_TAB_ROTOR_SIZE 53
extern const u32 b43_tab_rotor[];
-#define B43_TAB_RETARD_SIZE 53
+#define B43_TAB_RETARD_SIZE 53
extern const u32 b43_tab_retard[];
#define B43_TAB_FINEFREQA_SIZE 256
extern const u16 b43_tab_finefreqa[];
@@ -17,12 +17,18 @@ extern const u16 b43_tab_noisea3[];
extern const u16 b43_tab_noiseg1[];
#define B43_TAB_NOISEG2_SIZE 8
extern const u16 b43_tab_noiseg2[];
-#define B43_TAB_NOISESCALEG_SIZE 27
+#define B43_TAB_NOISESCALE_SIZE 27
+extern const u16 b43_tab_noisescalea2[];
+extern const u16 b43_tab_noisescalea3[];
extern const u16 b43_tab_noisescaleg1[];
extern const u16 b43_tab_noisescaleg2[];
extern const u16 b43_tab_noisescaleg3[];
#define B43_TAB_SIGMASQR_SIZE 53
extern const u16 b43_tab_sigmasqr1[];
extern const u16 b43_tab_sigmasqr2[];
+#define B43_TAB_RSSIAGC1_SIZE 16
+extern const u16 b43_tab_rssiagc1[];
+#define B43_TAB_RSSIAGC2_SIZE 48
+extern const u16 b43_tab_rssiagc2[];
#endif /* B43_TABLES_H_ */
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
new file mode 100644
index 000000000000..2aa57551786a
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -0,0 +1,2476 @@
+/*
+
+ Broadcom B43 wireless driver
+ IEEE 802.11n PHY and radio device data tables
+
+ Copyright (c) 2008 Michael Buesch <mb@bu3sch.de>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "tables_nphy.h"
+#include "phy.h"
+#include "nphy.h"
+
+
+struct b2055_inittab_entry {
+ /* Value to write if we use the 5GHz band. */
+ u16 ghz5;
+ /* Value to write if we use the 2.4GHz band. */
+ u16 ghz2;
+ /* Flags */
+ u8 flags;
+#define B2055_INITTAB_ENTRY_OK 0x01
+#define B2055_INITTAB_UPLOAD 0x02
+};
+#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD
+#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK
+
+static const struct b2055_inittab_entry b2055_inittab [] = {
+ [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+ [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, },
+ [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+ [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+ [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, },
+ [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, },
+ [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+ [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+ [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, },
+ [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, },
+ [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, },
+ [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, },
+ [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, },
+ [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, },
+ [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, },
+ [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+ [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, },
+ [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+ [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, },
+ [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, },
+ [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, },
+ [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, },
+ [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, },
+ [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, },
+ [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, },
+ [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, },
+ [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, },
+ [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+ [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, },
+ [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, },
+ [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, },
+ [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, },
+ [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, },
+ [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, },
+ [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, },
+ [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, },
+ [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, },
+ [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+ [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+ [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+ [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+ [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+ [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+ [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+ [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+ [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+ [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+ [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+ [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+ [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+ [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+ [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, },
+ [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, },
+ [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, },
+ [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, },
+ [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, },
+ [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, },
+ [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, },
+ [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, },
+ [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, },
+ [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, },
+ [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, },
+ [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, },
+ [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, },
+ [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, },
+ [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, },
+ [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, },
+ [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
+ [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, },
+ [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, },
+ [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, },
+ [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, },
+ [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, },
+ [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, },
+ [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, },
+ [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, },
+ [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, },
+ [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, },
+ [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, },
+ [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, },
+ [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, },
+ [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, },
+ [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, },
+ [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, },
+ [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
+ [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, },
+ [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+ [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+};
+
+
+void b2055_upload_inittab(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag)
+{
+ const struct b2055_inittab_entry *e;
+ unsigned int i;
+ u16 value;
+
+ for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
+ e = &(b2055_inittab[i]);
+ if (!(e->flags & B2055_INITTAB_ENTRY_OK))
+ continue;
+ if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) {
+ if (ghz5)
+ value = e->ghz5;
+ else
+ value = e->ghz2;
+ b43_radio_write16(dev, i, value);
+ }
+ }
+}
+
+
+#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \
+ r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \
+ .radio_pll_ref = r0, \
+ .radio_rf_pllmod0 = r1, \
+ .radio_rf_pllmod1 = r2, \
+ .radio_vco_captail = r3, \
+ .radio_vco_cal1 = r4, \
+ .radio_vco_cal2 = r5, \
+ .radio_pll_lfc1 = r6, \
+ .radio_pll_lfr1 = r7, \
+ .radio_pll_lfc2 = r8, \
+ .radio_lgbuf_cenbuf = r9, \
+ .radio_lgen_tune1 = r10, \
+ .radio_lgen_tune2 = r11, \
+ .radio_c1_lgbuf_atune = r12, \
+ .radio_c1_lgbuf_gtune = r13, \
+ .radio_c1_rx_rfr1 = r14, \
+ .radio_c1_tx_pgapadtn = r15, \
+ .radio_c1_tx_mxbgtrim = r16, \
+ .radio_c2_lgbuf_atune = r17, \
+ .radio_c2_lgbuf_gtune = r18, \
+ .radio_c2_rx_rfr1 = r19, \
+ .radio_c2_tx_pgapadtn = r20, \
+ .radio_c2_tx_mxbgtrim = r21
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5) \
+ .phy_bw1a = r0, \
+ .phy_bw2 = r1, \
+ .phy_bw3 = r2, \
+ .phy_bw4 = r3, \
+ .phy_bw5 = r4, \
+ .phy_bw6 = r5
+
+static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = {
+ { .channel = 184,
+ .freq = 4920, /* MHz */
+ .unk2 = 3280,
+ RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602),
+ },
+ { .channel = 186,
+ .freq = 4930, /* MHz */
+ .unk2 = 3287,
+ RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502),
+ },
+ { .channel = 188,
+ .freq = 4940, /* MHz */
+ .unk2 = 3293,
+ RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402),
+ },
+ { .channel = 190,
+ .freq = 4950, /* MHz */
+ .unk2 = 3300,
+ RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302),
+ },
+ { .channel = 192,
+ .freq = 4960, /* MHz */
+ .unk2 = 3307,
+ RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202),
+ },
+ { .channel = 194,
+ .freq = 4970, /* MHz */
+ .unk2 = 3313,
+ RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102),
+ },
+ { .channel = 196,
+ .freq = 4980, /* MHz */
+ .unk2 = 3320,
+ RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02),
+ },
+ { .channel = 198,
+ .freq = 4990, /* MHz */
+ .unk2 = 3327,
+ RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02),
+ },
+ { .channel = 200,
+ .freq = 5000, /* MHz */
+ .unk2 = 3333,
+ RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02),
+ },
+ { .channel = 202,
+ .freq = 5010, /* MHz */
+ .unk2 = 3340,
+ RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02),
+ },
+ { .channel = 204,
+ .freq = 5020, /* MHz */
+ .unk2 = 3347,
+ RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02),
+ },
+ { .channel = 206,
+ .freq = 5030, /* MHz */
+ .unk2 = 3353,
+ RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02),
+ },
+ { .channel = 208,
+ .freq = 5040, /* MHz */
+ .unk2 = 3360,
+ RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902),
+ },
+ { .channel = 210,
+ .freq = 5050, /* MHz */
+ .unk2 = 3367,
+ RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F,
+ 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F),
+ PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802),
+ },
+ { .channel = 212,
+ .freq = 5060, /* MHz */
+ .unk2 = 3373,
+ RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+ 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+ PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702),
+ },
+ { .channel = 214,
+ .freq = 5070, /* MHz */
+ .unk2 = 3380,
+ RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F,
+ 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E),
+ PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602),
+ },
+ { .channel = 216,
+ .freq = 5080, /* MHz */
+ .unk2 = 3387,
+ RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+ PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502),
+ },
+ { .channel = 218,
+ .freq = 5090, /* MHz */
+ .unk2 = 3393,
+ RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D),
+ PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402),
+ },
+ { .channel = 220,
+ .freq = 5100, /* MHz */
+ .unk2 = 3400,
+ RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+ PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302),
+ },
+ { .channel = 222,
+ .freq = 5110, /* MHz */
+ .unk2 = 3407,
+ RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F,
+ 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D),
+ PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202),
+ },
+ { .channel = 224,
+ .freq = 5120, /* MHz */
+ .unk2 = 3413,
+ RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+ 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+ PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102),
+ },
+ { .channel = 226,
+ .freq = 5130, /* MHz */
+ .unk2 = 3420,
+ RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F,
+ 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C),
+ PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002),
+ },
+ { .channel = 228,
+ .freq = 5140, /* MHz */
+ .unk2 = 3427,
+ RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E,
+ 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B),
+ PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01),
+ },
+ { .channel = 32,
+ .freq = 5160, /* MHz */
+ .unk2 = 3440,
+ RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+ 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+ PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01),
+ },
+ { .channel = 34,
+ .freq = 5170, /* MHz */
+ .unk2 = 3447,
+ RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D,
+ 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A),
+ PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01),
+ },
+ { .channel = 36,
+ .freq = 5180, /* MHz */
+ .unk2 = 3453,
+ RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+ 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+ PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01),
+ },
+ { .channel = 38,
+ .freq = 5190, /* MHz */
+ .unk2 = 3460,
+ RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+ 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C,
+ 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89),
+ PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01),
+ },
+ { .channel = 40,
+ .freq = 5200, /* MHz */
+ .unk2 = 3467,
+ RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+ 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+ PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901),
+ },
+ { .channel = 42,
+ .freq = 5210, /* MHz */
+ .unk2 = 3473,
+ RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B,
+ 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89),
+ PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801),
+ },
+ { .channel = 44,
+ .freq = 5220, /* MHz */
+ .unk2 = 3480,
+ RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+ 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+ PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701),
+ },
+ { .channel = 46,
+ .freq = 5230, /* MHz */
+ .unk2 = 3487,
+ RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+ 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A,
+ 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88),
+ PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601),
+ },
+ { .channel = 48,
+ .freq = 5240, /* MHz */
+ .unk2 = 3493,
+ RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+ 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+ PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501),
+ },
+ { .channel = 50,
+ .freq = 5250, /* MHz */
+ .unk2 = 3500,
+ RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A,
+ 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87),
+ PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401),
+ },
+ { .channel = 52,
+ .freq = 5260, /* MHz */
+ .unk2 = 3507,
+ RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+ 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+ PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301),
+ },
+ { .channel = 54,
+ .freq = 5270, /* MHz */
+ .unk2 = 3513,
+ RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+ 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09,
+ 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87),
+ PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201),
+ },
+ { .channel = 56,
+ .freq = 5280, /* MHz */
+ .unk2 = 3520,
+ RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+ 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+ PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101),
+ },
+ { .channel = 58,
+ .freq = 5290, /* MHz */
+ .unk2 = 3527,
+ RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08,
+ 0x86, 0x99, 0x00, 0x08, 0x08, 0x86),
+ PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001),
+ },
+ { .channel = 60,
+ .freq = 5300, /* MHz */
+ .unk2 = 3533,
+ RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+ 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+ PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001),
+ },
+ { .channel = 62,
+ .freq = 5310, /* MHz */
+ .unk2 = 3540,
+ RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+ 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07,
+ 0x85, 0x99, 0x00, 0x08, 0x07, 0x85),
+ PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01),
+ },
+ { .channel = 64,
+ .freq = 5320, /* MHz */
+ .unk2 = 3547,
+ RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+ 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+ PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01),
+ },
+ { .channel = 66,
+ .freq = 5330, /* MHz */
+ .unk2 = 3553,
+ RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07,
+ 0x84, 0x88, 0x00, 0x07, 0x07, 0x84),
+ PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01),
+ },
+ { .channel = 68,
+ .freq = 5340, /* MHz */
+ .unk2 = 3560,
+ RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+ 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+ PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01),
+ },
+ { .channel = 70,
+ .freq = 5350, /* MHz */
+ .unk2 = 3567,
+ RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+ 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06,
+ 0x84, 0x88, 0x00, 0x07, 0x06, 0x84),
+ PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01),
+ },
+ { .channel = 72,
+ .freq = 5360, /* MHz */
+ .unk2 = 3573,
+ RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+ 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+ PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01),
+ },
+ { .channel = 74,
+ .freq = 5370, /* MHz */
+ .unk2 = 3580,
+ RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05,
+ 0x83, 0x77, 0x00, 0x06, 0x05, 0x83),
+ PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901),
+ },
+ { .channel = 76,
+ .freq = 5380, /* MHz */
+ .unk2 = 3587,
+ RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+ 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+ PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801),
+ },
+ { .channel = 78,
+ .freq = 5390, /* MHz */
+ .unk2 = 3593,
+ RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+ 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04,
+ 0x82, 0x77, 0x00, 0x06, 0x04, 0x82),
+ PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701),
+ },
+ { .channel = 80,
+ .freq = 5400, /* MHz */
+ .unk2 = 3600,
+ RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+ 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+ PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601),
+ },
+ { .channel = 82,
+ .freq = 5410, /* MHz */
+ .unk2 = 3607,
+ RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04,
+ 0x81, 0x66, 0x00, 0x05, 0x04, 0x81),
+ PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501),
+ },
+ { .channel = 84,
+ .freq = 5420, /* MHz */
+ .unk2 = 3613,
+ RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+ 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+ PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501),
+ },
+ { .channel = 86,
+ .freq = 5430, /* MHz */
+ .unk2 = 3620,
+ RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+ 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03,
+ 0x80, 0x66, 0x00, 0x05, 0x03, 0x80),
+ PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401),
+ },
+ { .channel = 88,
+ .freq = 5440, /* MHz */
+ .unk2 = 3627,
+ RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+ 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+ PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301),
+ },
+ { .channel = 90,
+ .freq = 5450, /* MHz */
+ .unk2 = 3633,
+ RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02,
+ 0x80, 0x55, 0x00, 0x04, 0x02, 0x80),
+ PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201),
+ },
+ { .channel = 92,
+ .freq = 5460, /* MHz */
+ .unk2 = 3640,
+ RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+ 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+ PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101),
+ },
+ { .channel = 94,
+ .freq = 5470, /* MHz */
+ .unk2 = 3647,
+ RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+ 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01,
+ 0x80, 0x55, 0x00, 0x04, 0x01, 0x80),
+ PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001),
+ },
+ { .channel = 96,
+ .freq = 5480, /* MHz */
+ .unk2 = 3653,
+ RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01),
+ },
+ { .channel = 98,
+ .freq = 5490, /* MHz */
+ .unk2 = 3660,
+ RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01),
+ },
+ { .channel = 100,
+ .freq = 5500, /* MHz */
+ .unk2 = 3667,
+ RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01),
+ },
+ { .channel = 102,
+ .freq = 5510, /* MHz */
+ .unk2 = 3673,
+ RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+ 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00,
+ 0x80, 0x44, 0x00, 0x03, 0x00, 0x80),
+ PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01),
+ },
+ { .channel = 104,
+ .freq = 5520, /* MHz */
+ .unk2 = 3680,
+ RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01),
+ },
+ { .channel = 106,
+ .freq = 5530, /* MHz */
+ .unk2 = 3687,
+ RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01),
+ },
+ { .channel = 108,
+ .freq = 5540, /* MHz */
+ .unk2 = 3693,
+ RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01),
+ },
+ { .channel = 110,
+ .freq = 5550, /* MHz */
+ .unk2 = 3700,
+ RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+ 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+ 0x80, 0x33, 0x00, 0x02, 0x00, 0x80),
+ PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901),
+ },
+ { .channel = 112,
+ .freq = 5560, /* MHz */
+ .unk2 = 3707,
+ RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801),
+ },
+ { .channel = 114,
+ .freq = 5570, /* MHz */
+ .unk2 = 3713,
+ RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701),
+ },
+ { .channel = 116,
+ .freq = 5580, /* MHz */
+ .unk2 = 3720,
+ RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701),
+ },
+ { .channel = 118,
+ .freq = 5590, /* MHz */
+ .unk2 = 3727,
+ RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+ 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00,
+ 0x80, 0x22, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601),
+ },
+ { .channel = 120,
+ .freq = 5600, /* MHz */
+ .unk2 = 3733,
+ RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+ 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501),
+ },
+ { .channel = 122,
+ .freq = 5610, /* MHz */
+ .unk2 = 3740,
+ RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00,
+ 0x80, 0x11, 0x00, 0x01, 0x00, 0x80),
+ PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401),
+ },
+ { .channel = 124,
+ .freq = 5620, /* MHz */
+ .unk2 = 3747,
+ RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301),
+ },
+ { .channel = 126,
+ .freq = 5630, /* MHz */
+ .unk2 = 3753,
+ RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+ 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
+ 0x80, 0x11, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201),
+ },
+ { .channel = 128,
+ .freq = 5640, /* MHz */
+ .unk2 = 3760,
+ RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201),
+ },
+ { .channel = 130,
+ .freq = 5650, /* MHz */
+ .unk2 = 3767,
+ RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101),
+ },
+ { .channel = 132,
+ .freq = 5660, /* MHz */
+ .unk2 = 3773,
+ RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001),
+ },
+ { .channel = 134,
+ .freq = 5670, /* MHz */
+ .unk2 = 3780,
+ RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01),
+ },
+ { .channel = 136,
+ .freq = 5680, /* MHz */
+ .unk2 = 3787,
+ RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01),
+ },
+ { .channel = 138,
+ .freq = 5690, /* MHz */
+ .unk2 = 3793,
+ RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01),
+ },
+ { .channel = 140,
+ .freq = 5700, /* MHz */
+ .unk2 = 3800,
+ RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01),
+ },
+ { .channel = 142,
+ .freq = 5710, /* MHz */
+ .unk2 = 3807,
+ RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01),
+ },
+ { .channel = 144,
+ .freq = 5720, /* MHz */
+ .unk2 = 3813,
+ RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01),
+ },
+ { .channel = 145,
+ .freq = 5725, /* MHz */
+ .unk2 = 3817,
+ RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01),
+ },
+ { .channel = 146,
+ .freq = 5730, /* MHz */
+ .unk2 = 3820,
+ RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01),
+ },
+ { .channel = 147,
+ .freq = 5735, /* MHz */
+ .unk2 = 3823,
+ RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01),
+ },
+ { .channel = 148,
+ .freq = 5740, /* MHz */
+ .unk2 = 3827,
+ RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901),
+ },
+ { .channel = 149,
+ .freq = 5745, /* MHz */
+ .unk2 = 3830,
+ RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901),
+ },
+ { .channel = 150,
+ .freq = 5750, /* MHz */
+ .unk2 = 3833,
+ RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901),
+ },
+ { .channel = 151,
+ .freq = 5755, /* MHz */
+ .unk2 = 3837,
+ RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801),
+ },
+ { .channel = 152,
+ .freq = 5760, /* MHz */
+ .unk2 = 3840,
+ RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801),
+ },
+ { .channel = 153,
+ .freq = 5765, /* MHz */
+ .unk2 = 3843,
+ RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801),
+ },
+ { .channel = 154,
+ .freq = 5770, /* MHz */
+ .unk2 = 3847,
+ RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701),
+ },
+ { .channel = 155,
+ .freq = 5775, /* MHz */
+ .unk2 = 3850,
+ RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701),
+ },
+ { .channel = 156,
+ .freq = 5780, /* MHz */
+ .unk2 = 3853,
+ RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601),
+ },
+ { .channel = 157,
+ .freq = 5785, /* MHz */
+ .unk2 = 3857,
+ RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601),
+ },
+ { .channel = 158,
+ .freq = 5790, /* MHz */
+ .unk2 = 3860,
+ RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601),
+ },
+ { .channel = 159,
+ .freq = 5795, /* MHz */
+ .unk2 = 3863,
+ RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501),
+ },
+ { .channel = 160,
+ .freq = 5800, /* MHz */
+ .unk2 = 3867,
+ RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501),
+ },
+ { .channel = 161,
+ .freq = 5805, /* MHz */
+ .unk2 = 3870,
+ RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401),
+ },
+ { .channel = 162,
+ .freq = 5810, /* MHz */
+ .unk2 = 3873,
+ RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401),
+ },
+ { .channel = 163,
+ .freq = 5815, /* MHz */
+ .unk2 = 3877,
+ RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401),
+ },
+ { .channel = 164,
+ .freq = 5820, /* MHz */
+ .unk2 = 3880,
+ RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301),
+ },
+ { .channel = 165,
+ .freq = 5825, /* MHz */
+ .unk2 = 3883,
+ RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301),
+ },
+ { .channel = 166,
+ .freq = 5830, /* MHz */
+ .unk2 = 3887,
+ RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201),
+ },
+ { .channel = 168,
+ .freq = 5840, /* MHz */
+ .unk2 = 3893,
+ RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201),
+ },
+ { .channel = 170,
+ .freq = 5850, /* MHz */
+ .unk2 = 3900,
+ RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101),
+ },
+ { .channel = 172,
+ .freq = 5860, /* MHz */
+ .unk2 = 3907,
+ RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001),
+ },
+ { .channel = 174,
+ .freq = 5870, /* MHz */
+ .unk2 = 3913,
+ RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01),
+ },
+ { .channel = 176,
+ .freq = 5880, /* MHz */
+ .unk2 = 3920,
+ RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01),
+ },
+ { .channel = 178,
+ .freq = 5890, /* MHz */
+ .unk2 = 3927,
+ RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01),
+ },
+ { .channel = 180,
+ .freq = 5900, /* MHz */
+ .unk2 = 3933,
+ RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01),
+ },
+ { .channel = 182,
+ .freq = 5910, /* MHz */
+ .unk2 = 3940,
+ RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x80),
+ PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01),
+ },
+ { .channel = 1,
+ .freq = 2412, /* MHz */
+ .unk2 = 3216,
+ RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C,
+ 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80),
+ PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304),
+ },
+ { .channel = 2,
+ .freq = 2417, /* MHz */
+ .unk2 = 3223,
+ RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80),
+ PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104),
+ },
+ { .channel = 3,
+ .freq = 2422, /* MHz */
+ .unk2 = 3229,
+ RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+ PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04),
+ },
+ { .channel = 4,
+ .freq = 2427, /* MHz */
+ .unk2 = 3236,
+ RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A,
+ 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80),
+ PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04),
+ },
+ { .channel = 5,
+ .freq = 2432, /* MHz */
+ .unk2 = 3243,
+ RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09,
+ 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80),
+ PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04),
+ },
+ { .channel = 6,
+ .freq = 2437, /* MHz */
+ .unk2 = 3249,
+ RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08,
+ 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80),
+ PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804),
+ },
+ { .channel = 7,
+ .freq = 2442, /* MHz */
+ .unk2 = 3256,
+ RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07,
+ 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80),
+ PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604),
+ },
+ { .channel = 8,
+ .freq = 2447, /* MHz */
+ .unk2 = 3263,
+ RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06,
+ 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80),
+ PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404),
+ },
+ { .channel = 9,
+ .freq = 2452, /* MHz */
+ .unk2 = 3269,
+ RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06,
+ 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80),
+ PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104),
+ },
+ { .channel = 10,
+ .freq = 2457, /* MHz */
+ .unk2 = 3276,
+ RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05,
+ 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80),
+ PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04),
+ },
+ { .channel = 11,
+ .freq = 2462, /* MHz */
+ .unk2 = 3283,
+ RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04,
+ 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80),
+ PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04),
+ },
+ { .channel = 12,
+ .freq = 2467, /* MHz */
+ .unk2 = 3289,
+ RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03,
+ 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80),
+ PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04),
+ },
+ { .channel = 13,
+ .freq = 2472, /* MHz */
+ .unk2 = 3296,
+ RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03,
+ 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80),
+ PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904),
+ },
+ { .channel = 14,
+ .freq = 2484, /* MHz */
+ .unk2 = 3312,
+ RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+ 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01,
+ 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80),
+ PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404),
+ },
+};
+
+const struct b43_nphy_channeltab_entry *
+b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel)
+{
+ const struct b43_nphy_channeltab_entry *e;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) {
+ e = &(b43_nphy_channeltab[i]);
+ if (e->channel == channel)
+ return e;
+ }
+
+ return NULL;
+}
+
+
+const u8 b43_ntab_adjustpower0[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
+ 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
+ 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
+ 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
+ 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B,
+ 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D,
+ 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
+};
+
+const u8 b43_ntab_adjustpower1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03,
+ 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
+ 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07,
+ 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B,
+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
+ 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
+ 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
+ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
+ 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
+ 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
+ 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
+ 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B,
+ 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D,
+ 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F,
+};
+
+const u16 b43_ntab_bdi[] = {
+ 0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2,
+};
+
+const u32 b43_ntab_channelest[] = {
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x44444444, 0x44444444, 0x44444444, 0x44444444,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+ 0x10101010, 0x10101010, 0x10101010, 0x10101010,
+};
+
+const u8 b43_ntab_estimatepowerlt0[] = {
+ 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
+ 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+ 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
+ 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+ 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29,
+ 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
+ 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19,
+ 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+};
+
+const u8 b43_ntab_estimatepowerlt1[] = {
+ 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49,
+ 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41,
+ 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39,
+ 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31,
+ 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29,
+ 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21,
+ 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19,
+ 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11,
+};
+
+const u8 b43_ntab_framelookup[] = {
+ 0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
+ 0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E,
+ 0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A,
+ 0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A,
+};
+
+const u32 b43_ntab_framestruct[] = {
+ 0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+ 0x09804506, 0x00100030, 0x09804507, 0x00100030,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028,
+ 0x0980450E, 0x00100038, 0x0980450F, 0x00100038,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000A04, 0x00100000, 0x11008A05, 0x00100020,
+ 0x1980C506, 0x00100030, 0x21810506, 0x00100030,
+ 0x21810506, 0x00100030, 0x01800504, 0x00100030,
+ 0x11808505, 0x00100030, 0x29814507, 0x01100030,
+ 0x00000A04, 0x00100000, 0x11008A05, 0x00100020,
+ 0x21810506, 0x00100030, 0x21810506, 0x00100030,
+ 0x29814507, 0x01100030, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+ 0x1980C50E, 0x00100038, 0x2181050E, 0x00100038,
+ 0x2181050E, 0x00100038, 0x0180050C, 0x00100038,
+ 0x1180850D, 0x00100038, 0x2981450F, 0x01100038,
+ 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+ 0x2181050E, 0x00100038, 0x2181050E, 0x00100038,
+ 0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+ 0x1980C506, 0x00100030, 0x1980C506, 0x00100030,
+ 0x11808504, 0x00100030, 0x3981CA05, 0x00100030,
+ 0x29814507, 0x01100030, 0x00000000, 0x00000000,
+ 0x10008A04, 0x00100000, 0x3981CA05, 0x00100030,
+ 0x1980C506, 0x00100030, 0x29814507, 0x01100030,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028,
+ 0x1980C50E, 0x00100038, 0x1980C50E, 0x00100038,
+ 0x1180850C, 0x00100038, 0x3981CA0D, 0x00100038,
+ 0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+ 0x10008A0C, 0x00100008, 0x3981CA0D, 0x00100038,
+ 0x1980C50E, 0x00100038, 0x2981450F, 0x01100038,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x40021404, 0x00100000, 0x02001405, 0x00100040,
+ 0x0B004A06, 0x01900060, 0x13008A06, 0x01900060,
+ 0x13008A06, 0x01900060, 0x43020A04, 0x00100060,
+ 0x1B00CA05, 0x00100060, 0x23010A07, 0x01500060,
+ 0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+ 0x13008A06, 0x01900060, 0x13008A06, 0x01900060,
+ 0x23010A07, 0x01500060, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x00100010, 0x0200140D, 0x00100050,
+ 0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070,
+ 0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070,
+ 0x1B00CA0D, 0x00100070, 0x23010A0F, 0x01500070,
+ 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+ 0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070,
+ 0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x50029404, 0x00100000, 0x32019405, 0x00100040,
+ 0x0B004A06, 0x01900060, 0x0B004A06, 0x01900060,
+ 0x5B02CA04, 0x00100060, 0x3B01D405, 0x00100060,
+ 0x23010A07, 0x01500060, 0x00000000, 0x00000000,
+ 0x5802D404, 0x00100000, 0x3B01D405, 0x00100060,
+ 0x0B004A06, 0x01900060, 0x23010A07, 0x01500060,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x5002940C, 0x00100010, 0x3201940D, 0x00100050,
+ 0x0B004A0E, 0x01900070, 0x0B004A0E, 0x01900070,
+ 0x5B02CA0C, 0x00100070, 0x3B01D40D, 0x00100070,
+ 0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+ 0x5802D40C, 0x00100010, 0x3B01D40D, 0x00100070,
+ 0x0B004A0E, 0x01900070, 0x23010A0F, 0x01500070,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x40021404, 0x000F4800, 0x62031405, 0x00100040,
+ 0x53028A06, 0x01900060, 0x53028A07, 0x01900060,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x000F4810, 0x6203140D, 0x00100050,
+ 0x53028A0E, 0x01900070, 0x53028A0F, 0x01900070,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+ 0x1980C50E, 0x00100038, 0x2181050E, 0x00100038,
+ 0x2181050E, 0x00100038, 0x0180050C, 0x00100038,
+ 0x1180850D, 0x00100038, 0x1181850D, 0x00100038,
+ 0x2981450F, 0x01100038, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028,
+ 0x2181050E, 0x00100038, 0x2181050E, 0x00100038,
+ 0x1181850D, 0x00100038, 0x2981450F, 0x01100038,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x08004A04, 0x00100000, 0x01000A05, 0x00100020,
+ 0x0180C506, 0x00100030, 0x0180C506, 0x00100030,
+ 0x2180C50C, 0x00100030, 0x49820A0D, 0x0016A130,
+ 0x41824A0D, 0x0016A130, 0x2981450F, 0x01100030,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x2000CA0C, 0x00100000, 0x49820A0D, 0x0016A130,
+ 0x1980C50E, 0x00100030, 0x41824A0D, 0x0016A130,
+ 0x2981450F, 0x01100030, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x00100010, 0x0200140D, 0x00100050,
+ 0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070,
+ 0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070,
+ 0x1B00CA0D, 0x00100070, 0x1B014A0D, 0x00100070,
+ 0x23010A0F, 0x01500070, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+ 0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070,
+ 0x1B014A0D, 0x00100070, 0x23010A0F, 0x01500070,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x50029404, 0x00100000, 0x32019405, 0x00100040,
+ 0x03004A06, 0x01900060, 0x03004A06, 0x01900060,
+ 0x6B030A0C, 0x00100060, 0x4B02140D, 0x0016A160,
+ 0x4302540D, 0x0016A160, 0x23010A0F, 0x01500060,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x6B03140C, 0x00100060, 0x4B02140D, 0x0016A160,
+ 0x0B004A0E, 0x01900060, 0x4302540D, 0x0016A160,
+ 0x23010A0F, 0x01500060, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+ 0x53028A06, 0x01900060, 0x5B02CA06, 0x01900060,
+ 0x5B02CA06, 0x01900060, 0x43020A04, 0x00100060,
+ 0x1B00CA05, 0x00100060, 0x53028A07, 0x0190C060,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+ 0x53028A0E, 0x01900070, 0x5B02CA0E, 0x01900070,
+ 0x5B02CA0E, 0x01900070, 0x43020A0C, 0x00100070,
+ 0x1B00CA0D, 0x00100070, 0x53028A0F, 0x0190C070,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x40021404, 0x00100000, 0x1A00D405, 0x00100040,
+ 0x5B02CA06, 0x01900060, 0x5B02CA06, 0x01900060,
+ 0x53028A07, 0x0190C060, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050,
+ 0x5B02CA0E, 0x01900070, 0x5B02CA0E, 0x01900070,
+ 0x53028A0F, 0x0190C070, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32 b43_ntab_gainctl0[] = {
+ 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
+ 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
+ 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
+ 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38,
+ 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336,
+ 0x006B0435, 0x006A0535, 0x00690634, 0x00680734,
+ 0x00670833, 0x00660933, 0x00650A32, 0x00640B32,
+ 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30,
+ 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E,
+ 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C,
+ 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A,
+ 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28,
+ 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326,
+ 0x004B0425, 0x004A0525, 0x00490624, 0x00480724,
+ 0x00470823, 0x00460923, 0x00450A22, 0x00440B22,
+ 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20,
+ 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E,
+ 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C,
+ 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A,
+ 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18,
+ 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316,
+ 0x002B0415, 0x002A0515, 0x00290614, 0x00280714,
+ 0x00270813, 0x00260913, 0x00250A12, 0x00240B12,
+ 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10,
+ 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E,
+ 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C,
+ 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A,
+ 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08,
+ 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306,
+ 0x000B0405, 0x000A0505, 0x00090604, 0x00080704,
+ 0x00070803, 0x00060903, 0x00050A02, 0x00040B02,
+ 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
+};
+
+const u32 b43_ntab_gainctl1[] = {
+ 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E,
+ 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C,
+ 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A,
+ 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38,
+ 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336,
+ 0x006B0435, 0x006A0535, 0x00690634, 0x00680734,
+ 0x00670833, 0x00660933, 0x00650A32, 0x00640B32,
+ 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30,
+ 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E,
+ 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C,
+ 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A,
+ 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28,
+ 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326,
+ 0x004B0425, 0x004A0525, 0x00490624, 0x00480724,
+ 0x00470823, 0x00460923, 0x00450A22, 0x00440B22,
+ 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20,
+ 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E,
+ 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C,
+ 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A,
+ 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18,
+ 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316,
+ 0x002B0415, 0x002A0515, 0x00290614, 0x00280714,
+ 0x00270813, 0x00260913, 0x00250A12, 0x00240B12,
+ 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10,
+ 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E,
+ 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C,
+ 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A,
+ 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08,
+ 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306,
+ 0x000B0405, 0x000A0505, 0x00090604, 0x00080704,
+ 0x00070803, 0x00060903, 0x00050A02, 0x00040B02,
+ 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00,
+};
+
+const u32 b43_ntab_intlevel[] = {
+ 0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46,
+ 0x00C1188D, 0x080024D2, 0x00000070,
+};
+
+const u32 b43_ntab_iqlt0[] = {
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+};
+
+const u32 b43_ntab_iqlt1[] = {
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+ 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F,
+};
+
+const u16 b43_ntab_loftlt0[] = {
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103,
+};
+
+const u16 b43_ntab_loftlt1[] = {
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103,
+ 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101,
+ 0x0002, 0x0103,
+};
+
+const u8 b43_ntab_mcs[] = {
+ 0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C,
+ 0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C,
+ 0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C,
+ 0xC0, 0xC8, 0xCA, 0xD0, 0xD2, 0xD9, 0xDA, 0xDC,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x04, 0x08, 0x09, 0x0A, 0x0C,
+ 0x10, 0x11, 0x12, 0x14, 0x18, 0x19, 0x1A, 0x1C,
+ 0x20, 0x21, 0x22, 0x24, 0x40, 0x41, 0x42, 0x44,
+ 0x48, 0x49, 0x4A, 0x4C, 0x50, 0x51, 0x52, 0x54,
+ 0x58, 0x59, 0x5A, 0x5C, 0x60, 0x61, 0x62, 0x64,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+const u32 b43_ntab_noisevar10[] = {
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+};
+
+const u32 b43_ntab_noisevar11[] = {
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+ 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D,
+};
+
+const u16 b43_ntab_pilot[] = {
+ 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08,
+ 0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5,
+ 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82,
+ 0xFFA0, 0xFF28, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
+ 0xFF82, 0xFFA0, 0xFF28, 0xFF0A, 0xFFFF, 0xFFFF,
+ 0xFFFF, 0xFFFF, 0xF83F, 0xFA1F, 0xFA97, 0xFAB5,
+ 0xF2BD, 0xF0BF, 0xFFFF, 0xFFFF, 0xF017, 0xF815,
+ 0xF215, 0xF095, 0xF035, 0xF01D, 0xFFFF, 0xFFFF,
+ 0xFF08, 0xFF02, 0xFF80, 0xFF20, 0xFF08, 0xFF02,
+ 0xFF80, 0xFF20, 0xF01F, 0xF817, 0xFA15, 0xF295,
+ 0xF0B5, 0xF03D, 0xFFFF, 0xFFFF, 0xF82A, 0xFA0A,
+ 0xFA82, 0xFAA0, 0xF2A8, 0xF0AA, 0xFFFF, 0xFFFF,
+ 0xF002, 0xF800, 0xF200, 0xF080, 0xF020, 0xF008,
+ 0xFFFF, 0xFFFF, 0xF00A, 0xF802, 0xFA00, 0xF280,
+ 0xF0A0, 0xF028, 0xFFFF, 0xFFFF,
+};
+
+const u32 b43_ntab_pilotlt[] = {
+ 0x76540123, 0x62407351, 0x76543201, 0x76540213,
+ 0x76540123, 0x76430521,
+};
+
+const u32 b43_ntab_tdi20a0[] = {
+ 0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0,
+ 0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D,
+ 0x00020301, 0x00030504, 0x00040708, 0x0005090B,
+ 0x00064B8E, 0x00095291, 0x000A5494, 0x000B9718,
+ 0x000C9927, 0x000D9B2A, 0x000EDD2E, 0x000FDF31,
+ 0x000101B4, 0x000243B7, 0x000345BB, 0x000447BE,
+ 0x00058982, 0x00068C05, 0x00099309, 0x000A950C,
+ 0x000BD78F, 0x000CD992, 0x000DDB96, 0x000F1D99,
+ 0x00005FA8, 0x0001422C, 0x0002842F, 0x00038632,
+ 0x00048835, 0x0005CA38, 0x0006CCBC, 0x0009D3BF,
+ 0x000B1603, 0x000C1806, 0x000D1A0A, 0x000E1C0D,
+ 0x000F5E10, 0x00008093, 0x00018297, 0x0002C49A,
+ 0x0003C680, 0x0004C880, 0x00060B00, 0x00070D00,
+ 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32 b43_ntab_tdi20a1[] = {
+ 0x00014B26, 0x00028D29, 0x000393AD, 0x00049630,
+ 0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D,
+ 0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B,
+ 0x0000488E, 0x00018B91, 0x0002D214, 0x0003D418,
+ 0x0004D6A7, 0x000618AA, 0x00071AAE, 0x0009DCB1,
+ 0x000B1EB4, 0x000C0137, 0x000D033B, 0x000E053E,
+ 0x000F4702, 0x00008905, 0x00020C09, 0x0003128C,
+ 0x0004148F, 0x00051712, 0x00065916, 0x00091B19,
+ 0x000A1D28, 0x000B5F2C, 0x000C41AF, 0x000D43B2,
+ 0x000E85B5, 0x000F87B8, 0x0000C9BC, 0x00024CBF,
+ 0x00035303, 0x00045506, 0x0005978A, 0x0006998D,
+ 0x00095B90, 0x000A5D93, 0x000B9F97, 0x000C821A,
+ 0x000D8400, 0x000EC600, 0x000FC800, 0x00010A00,
+ 0x00000000, 0x00000000, 0x00000000,
+};
+
+const u32 b43_ntab_tdi40a0[] = {
+ 0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2,
+ 0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C,
+ 0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2,
+ 0x00056447, 0x00072DD0, 0x0008B6DA, 0x000A02E3,
+ 0x000B8C6C, 0x000D15F6, 0x0011E484, 0x0013AE0D,
+ 0x00153717, 0x00168320, 0x00180CA9, 0x00199633,
+ 0x001B6548, 0x001CEED1, 0x001EB7DB, 0x0000C3E4,
+ 0x00024D6D, 0x000416F7, 0x0005A585, 0x00076F0F,
+ 0x0008F818, 0x000A4421, 0x000BCDAB, 0x000D9734,
+ 0x00122649, 0x0013EFD2, 0x001578DC, 0x0016C4E5,
+ 0x00184E6E, 0x001A17F8, 0x001BA686, 0x001D3010,
+ 0x001EF999, 0x00010522, 0x00028EAC, 0x00045835,
+ 0x0005E74A, 0x0007B0D3, 0x00093A5D, 0x000A85E6,
+ 0x000C0F6F, 0x000DD8F9, 0x00126787, 0x00143111,
+ 0x0015BA9A, 0x00170623, 0x00188FAD, 0x001A5936,
+ 0x001BE84B, 0x001DB1D4, 0x001F3B5E, 0x000146E7,
+ 0x00031070, 0x000499FA, 0x00062888, 0x0007F212,
+ 0x00097B9B, 0x000AC7A4, 0x000C50AE, 0x000E1A37,
+ 0x0012A94C, 0x001472D5, 0x0015FC5F, 0x00174868,
+ 0x0018D171, 0x001A9AFB, 0x001C2989, 0x001DF313,
+ 0x001F7C9C, 0x000188A5, 0x000351AF, 0x0004DB38,
+ 0x0006AA4D, 0x000833D7, 0x0009BD60, 0x000B0969,
+ 0x000C9273, 0x000E5BFC, 0x00132A8A, 0x0014B414,
+ 0x00163D9D, 0x001789A6, 0x001912B0, 0x001ADC39,
+ 0x001C6BCE, 0x001E34D8, 0x001FBE61, 0x0001CA6A,
+ 0x00039374, 0x00051CFD, 0x0006EC0B, 0x00087515,
+ 0x0009FE9E, 0x000B4AA7, 0x000CD3B1, 0x000E9D3A,
+ 0x00000000, 0x00000000,
+};
+
+const u32 b43_ntab_tdi40a1[] = {
+ 0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD,
+ 0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07,
+ 0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D,
+ 0x00155C37, 0x0016EACB, 0x00187454, 0x001A3DDE,
+ 0x001B89E7, 0x001D12F0, 0x001F1CFA, 0x00016B88,
+ 0x00033492, 0x0004BE1B, 0x00060A24, 0x0007D32E,
+ 0x00095D38, 0x000AEC4C, 0x000C7555, 0x000E3EDF,
+ 0x00124AE8, 0x001413F1, 0x0015A37B, 0x00172C89,
+ 0x0018B593, 0x001A419C, 0x001BCB25, 0x001D942F,
+ 0x001F63B9, 0x0001AD4D, 0x00037657, 0x0004C260,
+ 0x00068BE9, 0x000814F3, 0x0009A47C, 0x000B2D8A,
+ 0x000CB694, 0x000E429D, 0x00128C26, 0x001455B0,
+ 0x0015E4BA, 0x00176E4E, 0x0018F758, 0x001A8361,
+ 0x001C0CEA, 0x001DD674, 0x001FA57D, 0x0001EE8B,
+ 0x0003B795, 0x0005039E, 0x0006CD27, 0x000856B1,
+ 0x0009E5C6, 0x000B6F4F, 0x000CF859, 0x000E8462,
+ 0x00130DEB, 0x00149775, 0x00162603, 0x0017AF8C,
+ 0x00193896, 0x001AC49F, 0x001C4E28, 0x001E17B2,
+ 0x0000A6C7, 0x00023050, 0x0003F9DA, 0x00054563,
+ 0x00070EEC, 0x00089876, 0x000A2704, 0x000BB08D,
+ 0x000D3A17, 0x001185A0, 0x00134F29, 0x0014D8B3,
+ 0x001667C8, 0x0017F151, 0x00197ADB, 0x001B0664,
+ 0x001C8FED, 0x001E5977, 0x0000E805, 0x0002718F,
+ 0x00043B18, 0x000586A1, 0x0007502B, 0x0008D9B4,
+ 0x000A68C9, 0x000BF252, 0x000DBBDC, 0x0011C7E5,
+ 0x001390EE, 0x00151A78, 0x0016A906, 0x00183290,
+ 0x0019BC19, 0x001B4822, 0x001CD12C, 0x001E9AB5,
+ 0x00000000, 0x00000000,
+};
+
+const u32 b43_ntab_tdtrn[] = {
+ 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6,
+ 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68,
+ 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52,
+ 0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050,
+ 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6,
+ 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68,
+ 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52,
+ 0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050,
+ 0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246,
+ 0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C,
+ 0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61,
+ 0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D,
+ 0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246,
+ 0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C,
+ 0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61,
+ 0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D,
+ 0xFA58FA58, 0xF895043B, 0xFF4C09C0, 0xFBC6FFA8,
+ 0xFB84F384, 0x0798F6F9, 0x05760122, 0x058409F6,
+ 0x0B500000, 0x05B7F542, 0x08860432, 0x06DDFEE7,
+ 0xFB84F384, 0xF9D90664, 0xF7E8025C, 0x00FFF7BD,
+ 0x05A805A8, 0xF7BD00FF, 0x025CF7E8, 0x0664F9D9,
+ 0xF384FB84, 0xFEE706DD, 0x04320886, 0xF54205B7,
+ 0x00000B50, 0x09F60584, 0x01220576, 0xF6F90798,
+ 0xF384FB84, 0xFFA8FBC6, 0x09C0FF4C, 0x043BF895,
+ 0x02D402D4, 0x07DE0270, 0xFC96079C, 0xF90AFE94,
+ 0xFE00FF2C, 0x02D4065D, 0x092A0096, 0x0014FBB8,
+ 0xFD2CFD2C, 0x076AFB3C, 0x0096F752, 0xF991FD87,
+ 0xFB2C0200, 0xFEB8F960, 0x08E0FC96, 0x049802A8,
+ 0xFD2CFD2C, 0x02A80498, 0xFC9608E0, 0xF960FEB8,
+ 0x0200FB2C, 0xFD87F991, 0xF7520096, 0xFB3C076A,
+ 0xFD2CFD2C, 0xFBB80014, 0x0096092A, 0x065D02D4,
+ 0xFF2CFE00, 0xFE94F90A, 0x079CFC96, 0x027007DE,
+ 0x02D402D4, 0x027007DE, 0x079CFC96, 0xFE94F90A,
+ 0xFF2CFE00, 0x065D02D4, 0x0096092A, 0xFBB80014,
+ 0xFD2CFD2C, 0xFB3C076A, 0xF7520096, 0xFD87F991,
+ 0x0200FB2C, 0xF960FEB8, 0xFC9608E0, 0x02A80498,
+ 0xFD2CFD2C, 0x049802A8, 0x08E0FC96, 0xFEB8F960,
+ 0xFB2C0200, 0xF991FD87, 0x0096F752, 0x076AFB3C,
+ 0xFD2CFD2C, 0x0014FBB8, 0x092A0096, 0x02D4065D,
+ 0xFE00FF2C, 0xF90AFE94, 0xFC96079C, 0x07DE0270,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D,
+ 0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF,
+ 0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8,
+ 0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7,
+ 0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3,
+ 0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841,
+ 0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608,
+ 0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759,
+ 0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D,
+ 0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF,
+ 0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8,
+ 0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7,
+ 0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3,
+ 0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841,
+ 0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608,
+ 0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759,
+ 0x061C061C, 0xFF30009D, 0xFFB21141, 0xFD87FB54,
+ 0xF65DFE59, 0x02EEF99E, 0x0166F03C, 0xFFF809B6,
+ 0x000008A4, 0x000AF42B, 0x00EFF577, 0xFA840BF2,
+ 0xFC02FF51, 0x08260F67, 0xFFF0036F, 0x0842F9C3,
+ 0x00000000, 0x063DF7BE, 0xFC910010, 0xF099F7DA,
+ 0x00AF03FE, 0xF40E057C, 0x0A89FF11, 0x0BD5FFF6,
+ 0xF75C0000, 0xF64A0008, 0x0FC4FE9A, 0x0662FD12,
+ 0x01A709A3, 0x04AC0279, 0xEEBF004E, 0xFF6300D0,
+ 0xF9E4F9E4, 0x00D0FF63, 0x004EEEBF, 0x027904AC,
+ 0x09A301A7, 0xFD120662, 0xFE9A0FC4, 0x0008F64A,
+ 0x0000F75C, 0xFFF60BD5, 0xFF110A89, 0x057CF40E,
+ 0x03FE00AF, 0xF7DAF099, 0x0010FC91, 0xF7BE063D,
+ 0x00000000, 0xF9C30842, 0x036FFFF0, 0x0F670826,
+ 0xFF51FC02, 0x0BF2FA84, 0xF57700EF, 0xF42B000A,
+ 0x08A40000, 0x09B6FFF8, 0xF03C0166, 0xF99E02EE,
+ 0xFE59F65D, 0xFB54FD87, 0x1141FFB2, 0x009DFF30,
+ 0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59,
+ 0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766,
+ 0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986,
+ 0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB,
+ 0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7,
+ 0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A,
+ 0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A,
+ 0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705,
+ 0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59,
+ 0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766,
+ 0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986,
+ 0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB,
+ 0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7,
+ 0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A,
+ 0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A,
+ 0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705,
+ 0xFA58FA58, 0xF8F0FE00, 0x0448073D, 0xFDC9FE46,
+ 0xF9910258, 0x089D0407, 0xFD5CF71A, 0x02AFFDE0,
+ 0x083E0496, 0xFF5A0740, 0xFF7AFD97, 0x00FE01F1,
+ 0x0009082E, 0xFA94FF75, 0xFECDF8EA, 0xFFB0F693,
+ 0xFD2CFA58, 0x0433FF16, 0xFBA405DD, 0xFA610341,
+ 0x06A606CB, 0x0039FD2D, 0x0677FA97, 0x01FA05E0,
+ 0xF896003E, 0x075A068B, 0x012CFC3E, 0xFA23F98D,
+ 0xFC7CFD43, 0xFF90FC0D, 0x01C10982, 0x00C601D6,
+ 0xFD2CFD2C, 0x01D600C6, 0x098201C1, 0xFC0DFF90,
+ 0xFD43FC7C, 0xF98DFA23, 0xFC3E012C, 0x068B075A,
+ 0x003EF896, 0x05E001FA, 0xFA970677, 0xFD2D0039,
+ 0x06CB06A6, 0x0341FA61, 0x05DDFBA4, 0xFF160433,
+ 0xFA58FD2C, 0xF693FFB0, 0xF8EAFECD, 0xFF75FA94,
+ 0x082E0009, 0x01F100FE, 0xFD97FF7A, 0x0740FF5A,
+ 0x0496083E, 0xFDE002AF, 0xF71AFD5C, 0x0407089D,
+ 0x0258F991, 0xFE46FDC9, 0x073D0448, 0xFE00F8F0,
+ 0xFD2CFD2C, 0xFCE00500, 0xFC09FDDC, 0xFE680157,
+ 0x04C70571, 0xFC3AFF21, 0xFCD70228, 0x056D0277,
+ 0x0200FE00, 0x0022F927, 0xFE3C032B, 0xFC44FF3C,
+ 0x03E9FBDB, 0x04570313, 0x04C9FF5C, 0x000D03B8,
+ 0xFA580000, 0xFBE900D2, 0xF9D0FE0B, 0x0125FDF9,
+ 0x042501BF, 0x0328FA2B, 0xFFA902F0, 0xFA250157,
+ 0x0200FE00, 0x03740438, 0xFF0405FD, 0x030CFE52,
+ 0x0037FB39, 0xFF6904C5, 0x04F8FD23, 0xFD31FC1B,
+ 0xFD2CFD2C, 0xFC1BFD31, 0xFD2304F8, 0x04C5FF69,
+ 0xFB390037, 0xFE52030C, 0x05FDFF04, 0x04380374,
+ 0xFE000200, 0x0157FA25, 0x02F0FFA9, 0xFA2B0328,
+ 0x01BF0425, 0xFDF90125, 0xFE0BF9D0, 0x00D2FBE9,
+ 0x0000FA58, 0x03B8000D, 0xFF5C04C9, 0x03130457,
+ 0xFBDB03E9, 0xFF3CFC44, 0x032BFE3C, 0xF9270022,
+ 0xFE000200, 0x0277056D, 0x0228FCD7, 0xFF21FC3A,
+ 0x057104C7, 0x0157FE68, 0xFDDCFC09, 0x0500FCE0,
+ 0xFD2CFD2C, 0x0500FCE0, 0xFDDCFC09, 0x0157FE68,
+ 0x057104C7, 0xFF21FC3A, 0x0228FCD7, 0x0277056D,
+ 0xFE000200, 0xF9270022, 0x032BFE3C, 0xFF3CFC44,
+ 0xFBDB03E9, 0x03130457, 0xFF5C04C9, 0x03B8000D,
+ 0x0000FA58, 0x00D2FBE9, 0xFE0BF9D0, 0xFDF90125,
+ 0x01BF0425, 0xFA2B0328, 0x02F0FFA9, 0x0157FA25,
+ 0xFE000200, 0x04380374, 0x05FDFF04, 0xFE52030C,
+ 0xFB390037, 0x04C5FF69, 0xFD2304F8, 0xFC1BFD31,
+ 0xFD2CFD2C, 0xFD31FC1B, 0x04F8FD23, 0xFF6904C5,
+ 0x0037FB39, 0x030CFE52, 0xFF0405FD, 0x03740438,
+ 0x0200FE00, 0xFA250157, 0xFFA902F0, 0x0328FA2B,
+ 0x042501BF, 0x0125FDF9, 0xF9D0FE0B, 0xFBE900D2,
+ 0xFA580000, 0x000D03B8, 0x04C9FF5C, 0x04570313,
+ 0x03E9FBDB, 0xFC44FF3C, 0xFE3C032B, 0x0022F927,
+ 0x0200FE00, 0x056D0277, 0xFCD70228, 0xFC3AFF21,
+ 0x04C70571, 0xFE680157, 0xFC09FDDC, 0xFCE00500,
+ 0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E,
+ 0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C,
+ 0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926,
+ 0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942,
+ 0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382,
+ 0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4,
+ 0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA,
+ 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE,
+ 0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E,
+ 0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C,
+ 0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926,
+ 0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942,
+ 0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382,
+ 0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4,
+ 0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA,
+ 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE,
+};
+
+const u32 b43_ntab_tmap[] = {
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0xF1111110, 0x11111111, 0x11F11111, 0x00000111,
+ 0x11000000, 0x1111F111, 0x11111111, 0x111111F1,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x000AA888,
+ 0x88880000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+ 0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+ 0xA2222220, 0x22222222, 0x22C22222, 0x00000222,
+ 0x22000000, 0x2222A222, 0x22222222, 0x222222A2,
+ 0xF1111110, 0x11111111, 0x11F11111, 0x00011111,
+ 0x11110000, 0x1111F111, 0x11111111, 0x111111F1,
+ 0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00088AAA,
+ 0xAAAA0000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+ 0xAAA8AAA0, 0x8AAA8AAA, 0xAA8A8A8A, 0x000AAA88,
+ 0x8AAA0000, 0xAAA8A888, 0x8AA88A8A, 0x8A88A888,
+ 0x08080A00, 0x0A08080A, 0x080A0A08, 0x00080808,
+ 0x080A0000, 0x080A0808, 0x080A0808, 0x0A0A0A08,
+ 0xA0A0A0A0, 0x80A0A080, 0x8080A0A0, 0x00008080,
+ 0x80A00000, 0x80A080A0, 0xA080A0A0, 0x8080A0A0,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x99999000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+ 0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888,
+ 0x22000000, 0x2222B222, 0x22222222, 0x222222B2,
+ 0xB2222220, 0x22222222, 0x22D22222, 0x00000222,
+ 0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+ 0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+ 0x33000000, 0x3333B333, 0x33333333, 0x333333B3,
+ 0xB3333330, 0x33333333, 0x33D33333, 0x00000333,
+ 0x22000000, 0x2222A222, 0x22222222, 0x222222A2,
+ 0xA2222220, 0x22222222, 0x22C22222, 0x00000222,
+ 0x99B99B00, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+ 0x9B99BB99, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888,
+ 0x22222200, 0x2222F222, 0x22222222, 0x222222F2,
+ 0x22222222, 0x22222222, 0x22F22222, 0x00000222,
+ 0x11000000, 0x1111F111, 0x11111111, 0x11111111,
+ 0xF1111111, 0x11111111, 0x11F11111, 0x01111111,
+ 0xBB9BB900, 0xB9B9BB99, 0xB99BBBBB, 0xBBBB9B9B,
+ 0xB9BB99BB, 0xB99999B9, 0xB9B9B99B, 0x00000BBB,
+ 0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+ 0xA8AA88AA, 0xA88888A8, 0xA8A8A88A, 0x0A888AAA,
+ 0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A,
+ 0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00000AAA,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0xBBBBBB00, 0x999BBBBB, 0x9BB99B9B, 0xB9B9B9BB,
+ 0xB9B99BBB, 0xB9B9B9BB, 0xB9BB9B99, 0x00000999,
+ 0x8A000000, 0xAA88A888, 0xA88888AA, 0xA88A8A88,
+ 0xA88AA88A, 0x88A8AAAA, 0xA8AA8AAA, 0x0888A88A,
+ 0x0B0B0B00, 0x090B0B0B, 0x0B090B0B, 0x0909090B,
+ 0x09090B0B, 0x09090B0B, 0x09090B09, 0x00000909,
+ 0x0A000000, 0x0A080808, 0x080A080A, 0x080A0A08,
+ 0x080A080A, 0x0808080A, 0x0A0A0A08, 0x0808080A,
+ 0xB0B0B000, 0x9090B0B0, 0x90B09090, 0xB0B0B090,
+ 0xB0B090B0, 0x90B0B0B0, 0xB0B09090, 0x00000090,
+ 0x80000000, 0xA080A080, 0xA08080A0, 0xA0808080,
+ 0xA080A080, 0x80A0A0A0, 0xA0A080A0, 0x00A0A0A0,
+ 0x22000000, 0x2222F222, 0x22222222, 0x222222F2,
+ 0xF2222220, 0x22222222, 0x22F22222, 0x00000222,
+ 0x11000000, 0x1111F111, 0x11111111, 0x111111F1,
+ 0xF1111110, 0x11111111, 0x11F11111, 0x00000111,
+ 0x33000000, 0x3333F333, 0x33333333, 0x333333F3,
+ 0xF3333330, 0x33333333, 0x33F33333, 0x00000333,
+ 0x22000000, 0x2222F222, 0x22222222, 0x222222F2,
+ 0xF2222220, 0x22222222, 0x22F22222, 0x00000222,
+ 0x99000000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9,
+ 0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x88888000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888,
+ 0x88A88A00, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888,
+ 0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+ 0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+ 0x11000000, 0x1111A111, 0x11111111, 0x111111A1,
+ 0xA1111110, 0x11111111, 0x11C11111, 0x00000111,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8,
+ 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static inline void assert_ntab_array_sizes(void)
+{
+#undef check
+#define check(table, size) \
+ BUILD_BUG_ON(ARRAY_SIZE(b43_ntab_##table) != B43_NTAB_##size##_SIZE)
+
+ check(adjustpower0, C0_ADJPLT);
+ check(adjustpower1, C1_ADJPLT);
+ check(bdi, BDI);
+ check(channelest, CHANEST);
+ check(estimatepowerlt0, C0_ESTPLT);
+ check(estimatepowerlt1, C1_ESTPLT);
+ check(framelookup, FRAMELT);
+ check(framestruct, FRAMESTRUCT);
+ check(gainctl0, C0_GAINCTL);
+ check(gainctl1, C1_GAINCTL);
+ check(intlevel, INTLEVEL);
+ check(iqlt0, C0_IQLT);
+ check(iqlt1, C1_IQLT);
+ check(loftlt0, C0_LOFEEDTH);
+ check(loftlt1, C1_LOFEEDTH);
+ check(mcs, MCS);
+ check(noisevar10, NOISEVAR10);
+ check(noisevar11, NOISEVAR11);
+ check(pilot, PILOT);
+ check(pilotlt, PILOTLT);
+ check(tdi20a0, TDI20A0);
+ check(tdi20a1, TDI20A1);
+ check(tdi40a0, TDI40A0);
+ check(tdi40a1, TDI40A1);
+ check(tdtrn, TDTRN);
+ check(tmap, TMAP);
+
+#undef check
+}
+
+void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value)
+{
+ u32 type;
+
+ type = offset & B43_NTAB_TYPEMASK;
+ offset &= 0xFFFF;
+
+ switch (type) {
+ case B43_NTAB_8BIT:
+ B43_WARN_ON(value & ~0xFF);
+ b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+ break;
+ case B43_NTAB_16BIT:
+ B43_WARN_ON(value & ~0xFFFF);
+ b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value);
+ break;
+ case B43_NTAB_32BIT:
+ b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset);
+ b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16);
+ b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value & 0xFFFF);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+
+ return;
+
+ /* Some compiletime assertions... */
+ assert_ntab_array_sizes();
+}
diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h
new file mode 100644
index 000000000000..4d498b053ec7
--- /dev/null
+++ b/drivers/net/wireless/b43/tables_nphy.h
@@ -0,0 +1,159 @@
+#ifndef B43_TABLES_NPHY_H_
+#define B43_TABLES_NPHY_H_
+
+#include <linux/types.h>
+
+
+struct b43_nphy_channeltab_entry {
+ /* The channel number */
+ u8 channel;
+ /* Radio register values on channelswitch */
+ u8 radio_pll_ref;
+ u8 radio_rf_pllmod0;
+ u8 radio_rf_pllmod1;
+ u8 radio_vco_captail;
+ u8 radio_vco_cal1;
+ u8 radio_vco_cal2;
+ u8 radio_pll_lfc1;
+ u8 radio_pll_lfr1;
+ u8 radio_pll_lfc2;
+ u8 radio_lgbuf_cenbuf;
+ u8 radio_lgen_tune1;
+ u8 radio_lgen_tune2;
+ u8 radio_c1_lgbuf_atune;
+ u8 radio_c1_lgbuf_gtune;
+ u8 radio_c1_rx_rfr1;
+ u8 radio_c1_tx_pgapadtn;
+ u8 radio_c1_tx_mxbgtrim;
+ u8 radio_c2_lgbuf_atune;
+ u8 radio_c2_lgbuf_gtune;
+ u8 radio_c2_rx_rfr1;
+ u8 radio_c2_tx_pgapadtn;
+ u8 radio_c2_tx_mxbgtrim;
+ /* PHY register values on channelswitch */
+ u16 phy_bw1a;
+ u16 phy_bw2;
+ u16 phy_bw3;
+ u16 phy_bw4;
+ u16 phy_bw5;
+ u16 phy_bw6;
+ /* The channel frequency in MHz */
+ u16 freq;
+ /* An unknown value */
+ u16 unk2;
+};
+
+
+struct b43_wldev;
+
+/* Upload the default register value table.
+ * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz
+ * table is uploaded. If "ignore_uploadflag" is true, we upload any value
+ * and ignore the "UPLOAD" flag. */
+void b2055_upload_inittab(struct b43_wldev *dev,
+ bool ghz5, bool ignore_uploadflag);
+
+
+/* Get the NPHY Channel Switch Table entry for a channel number.
+ * Returns NULL on failure to find an entry. */
+const struct b43_nphy_channeltab_entry *
+b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel);
+
+
+/* The N-PHY tables. */
+
+#define B43_NTAB_TYPEMASK 0xF0000000
+#define B43_NTAB_8BIT 0x10000000
+#define B43_NTAB_16BIT 0x20000000
+#define B43_NTAB_32BIT 0x30000000
+#define B43_NTAB8(table, offset) (((table) << 10) | (offset) | B43_NTAB_8BIT)
+#define B43_NTAB16(table, offset) (((table) << 10) | (offset) | B43_NTAB_16BIT)
+#define B43_NTAB32(table, offset) (((table) << 10) | (offset) | B43_NTAB_32BIT)
+
+/* Static N-PHY tables */
+#define B43_NTAB_FRAMESTRUCT B43_NTAB32(0x0A, 0x000) /* Frame Struct Table */
+#define B43_NTAB_FRAMESTRUCT_SIZE 832
+#define B43_NTAB_FRAMELT B43_NTAB8 (0x18, 0x000) /* Frame Lookup Table */
+#define B43_NTAB_FRAMELT_SIZE 32
+#define B43_NTAB_TMAP B43_NTAB32(0x0C, 0x000) /* T Map Table */
+#define B43_NTAB_TMAP_SIZE 448
+#define B43_NTAB_TDTRN B43_NTAB32(0x0E, 0x000) /* TDTRN Table */
+#define B43_NTAB_TDTRN_SIZE 704
+#define B43_NTAB_INTLEVEL B43_NTAB32(0x0D, 0x000) /* Int Level Table */
+#define B43_NTAB_INTLEVEL_SIZE 7
+#define B43_NTAB_PILOT B43_NTAB16(0x0B, 0x000) /* Pilot Table */
+#define B43_NTAB_PILOT_SIZE 88
+#define B43_NTAB_PILOTLT B43_NTAB32(0x14, 0x000) /* Pilot Lookup Table */
+#define B43_NTAB_PILOTLT_SIZE 6
+#define B43_NTAB_TDI20A0 B43_NTAB32(0x13, 0x080) /* TDI Table 20 Antenna 0 */
+#define B43_NTAB_TDI20A0_SIZE 55
+#define B43_NTAB_TDI20A1 B43_NTAB32(0x13, 0x100) /* TDI Table 20 Antenna 1 */
+#define B43_NTAB_TDI20A1_SIZE 55
+#define B43_NTAB_TDI40A0 B43_NTAB32(0x13, 0x280) /* TDI Table 40 Antenna 0 */
+#define B43_NTAB_TDI40A0_SIZE 110
+#define B43_NTAB_TDI40A1 B43_NTAB32(0x13, 0x300) /* TDI Table 40 Antenna 1 */
+#define B43_NTAB_TDI40A1_SIZE 110
+#define B43_NTAB_BDI B43_NTAB16(0x15, 0x000) /* BDI Table */
+#define B43_NTAB_BDI_SIZE 6
+#define B43_NTAB_CHANEST B43_NTAB32(0x16, 0x000) /* Channel Estimate Table */
+#define B43_NTAB_CHANEST_SIZE 96
+#define B43_NTAB_MCS B43_NTAB8 (0x12, 0x000) /* MCS Table */
+#define B43_NTAB_MCS_SIZE 128
+
+/* Volatile N-PHY tables */
+#define B43_NTAB_NOISEVAR10 B43_NTAB32(0x10, 0x000) /* Noise Var Table 10 */
+#define B43_NTAB_NOISEVAR10_SIZE 256
+#define B43_NTAB_NOISEVAR11 B43_NTAB32(0x10, 0x080) /* Noise Var Table 11 */
+#define B43_NTAB_NOISEVAR11_SIZE 256
+#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */
+#define B43_NTAB_C0_ESTPLT_SIZE 64
+#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ESTPLT_SIZE 64
+#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */
+#define B43_NTAB_C0_ADJPLT_SIZE 128
+#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */
+#define B43_NTAB_C1_ADJPLT_SIZE 128
+#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */
+#define B43_NTAB_C0_GAINCTL_SIZE 128
+#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */
+#define B43_NTAB_C1_GAINCTL_SIZE 128
+#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */
+#define B43_NTAB_C0_IQLT_SIZE 128
+#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */
+#define B43_NTAB_C1_IQLT_SIZE 128
+#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */
+#define B43_NTAB_C0_LOFEEDTH_SIZE 128
+#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
+#define B43_NTAB_C1_LOFEEDTH_SIZE 128
+
+void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value);
+
+extern const u8 b43_ntab_adjustpower0[];
+extern const u8 b43_ntab_adjustpower1[];
+extern const u16 b43_ntab_bdi[];
+extern const u32 b43_ntab_channelest[];
+extern const u8 b43_ntab_estimatepowerlt0[];
+extern const u8 b43_ntab_estimatepowerlt1[];
+extern const u8 b43_ntab_framelookup[];
+extern const u32 b43_ntab_framestruct[];
+extern const u32 b43_ntab_gainctl0[];
+extern const u32 b43_ntab_gainctl1[];
+extern const u32 b43_ntab_intlevel[];
+extern const u32 b43_ntab_iqlt0[];
+extern const u32 b43_ntab_iqlt1[];
+extern const u16 b43_ntab_loftlt0[];
+extern const u16 b43_ntab_loftlt1[];
+extern const u8 b43_ntab_mcs[];
+extern const u32 b43_ntab_noisevar10[];
+extern const u32 b43_ntab_noisevar11[];
+extern const u16 b43_ntab_pilot[];
+extern const u32 b43_ntab_pilotlt[];
+extern const u32 b43_ntab_tdi20a0[];
+extern const u32 b43_ntab_tdi20a1[];
+extern const u32 b43_ntab_tdi40a0[];
+extern const u32 b43_ntab_tdi40a1[];
+extern const u32 b43_ntab_tdtrn[];
+extern const u32 b43_ntab_tmap[];
+
+
+#endif /* B43_TABLES_NPHY_H_ */
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c
new file mode 100644
index 000000000000..e632125cb772
--- /dev/null
+++ b/drivers/net/wireless/b43/wa.c
@@ -0,0 +1,674 @@
+/*
+
+ Broadcom B43 wireless driver
+
+ PHY workarounds.
+
+ Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
+ Copyright (c) 2005-2007 Michael Buesch <mbuesch@freenet.de>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "b43.h"
+#include "main.h"
+#include "tables.h"
+#include "phy.h"
+#include "wa.h"
+
+static void b43_wa_papd(struct b43_wldev *dev)
+{
+ u16 backup;
+
+ backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0);
+ b43_dummy_transmission(dev);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup);
+}
+
+static void b43_wa_auxclipthr(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x3800);
+}
+
+static void b43_wa_afcdac(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, 0x0035, 0x03FF);
+ b43_phy_write(dev, 0x0036, 0x0400);
+}
+
+static void b43_wa_txdc_offset(struct b43_wldev *dev)
+{
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 0, 0x0051);
+}
+
+void b43_wa_initgains(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9);
+ b43_phy_write(dev, B43_PHY_LPFGAINCTL,
+ b43_phy_read(dev, B43_PHY_LPFGAINCTL) & 0xFF0F);
+ if (phy->rev <= 2)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF);
+ b43_radio_write16(dev, 0x0002, 0x1FBF);
+
+ b43_phy_write(dev, 0x0024, 0x4680);
+ b43_phy_write(dev, 0x0020, 0x0003);
+ b43_phy_write(dev, 0x001D, 0x0F40);
+ b43_phy_write(dev, 0x001F, 0x1C00);
+ if (phy->rev <= 3)
+ b43_phy_write(dev, 0x002A,
+ (b43_phy_read(dev, 0x002A) & 0x00FF) | 0x0400);
+ else if (phy->rev == 5) {
+ b43_phy_write(dev, 0x002A,
+ (b43_phy_read(dev, 0x002A) & 0x00FF) | 0x1A00);
+ b43_phy_write(dev, 0x00CC, 0x2121);
+ }
+ if (phy->rev >= 3)
+ b43_phy_write(dev, 0x00BA, 0x3ED5);
+}
+
+static void b43_wa_divider(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, 0x002B, b43_phy_read(dev, 0x002B) & ~0x0100);
+ b43_phy_write(dev, 0x008E, 0x58C1);
+}
+
+static void b43_wa_gt(struct b43_wldev *dev) /* Gain table. */
+{
+ if (dev->phy.rev <= 2) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 0, 15);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 1, 31);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 2, 42);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 3, 48);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 4, 58);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 0, 3);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 1, 3);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 2, 7);
+ } else {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25);
+ }
+}
+
+static void b43_wa_rssi_lt(struct b43_wldev *dev) /* RSSI lookup table */
+{
+ int i;
+
+ if (0 /* FIXME: For APHY.rev=2 this might be needed */) {
+ for (i = 0; i < 8; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i + 8);
+ for (i = 8; i < 16; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i - 8);
+ } else {
+ for (i = 0; i < 64; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i);
+ }
+}
+
+static void b43_wa_analog(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+ u16 ofdmrev;
+
+ ofdmrev = b43_phy_read(dev, B43_PHY_VERSION_OFDM) & B43_PHYVER_VERSION;
+ if (ofdmrev > 2) {
+ if (phy->type == B43_PHYTYPE_A)
+ b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1808);
+ else
+ b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1000);
+ } else {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 3, 0x1044);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 4, 0x7201);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 6, 0x0040);
+ }
+}
+
+static void b43_wa_dac(struct b43_wldev *dev)
+{
+ if (dev->phy.analog == 1)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1,
+ (b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0034) | 0x0008);
+ else
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1,
+ (b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0078) | 0x0010);
+}
+
+static void b43_wa_fft(struct b43_wldev *dev) /* Fine frequency table */
+{
+ int i;
+
+ if (dev->phy.type == B43_PHYTYPE_A)
+ for (i = 0; i < B43_TAB_FINEFREQA_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqa[i]);
+ else
+ for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqg[i]);
+}
+
+static void b43_wa_nft(struct b43_wldev *dev) /* Noise figure table */
+{
+ struct b43_phy *phy = &dev->phy;
+ int i;
+
+ if (phy->type == B43_PHYTYPE_A) {
+ if (phy->rev == 2)
+ for (i = 0; i < B43_TAB_NOISEA2_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea2[i]);
+ else
+ for (i = 0; i < B43_TAB_NOISEA3_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea3[i]);
+ } else {
+ if (phy->rev == 1)
+ for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg1[i]);
+ else
+ for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg2[i]);
+ }
+}
+
+static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
+{
+ int i;
+
+ for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
+ b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
+}
+
+static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
+{
+ struct b43_phy *phy = &dev->phy;
+ int i;
+
+ if (phy->type == B43_PHYTYPE_A) {
+ if (phy->rev <= 1)
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, 0);
+ else if (phy->rev == 2)
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescalea2[i]);
+ else if (phy->rev == 3)
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescalea3[i]);
+ else
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescaleg3[i]);
+ } else {
+ if (phy->rev >= 6) {
+ if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescaleg3[i]);
+ else
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescaleg2[i]);
+ } else {
+ for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE,
+ i, b43_tab_noisescaleg1[i]);
+ }
+ }
+}
+
+static void b43_wa_art(struct b43_wldev *dev) /* ADV retard table */
+{
+ int i;
+
+ for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
+ b43_ofdmtab_write32(dev, B43_OFDMTAB_ADVRETARD,
+ i, b43_tab_retard[i]);
+}
+
+static void b43_wa_txlna_gain(struct b43_wldev *dev)
+{
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 13, 0x0000);
+}
+
+static void b43_wa_crs_reset(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, 0x002C, 0x0064);
+}
+
+static void b43_wa_2060txlna_gain(struct b43_wldev *dev)
+{
+ b43_hf_write(dev, b43_hf_read(dev) |
+ B43_HF_2060W);
+}
+
+static void b43_wa_lms(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, 0x0055,
+ (b43_phy_read(dev, 0x0055) & 0xFFC0) | 0x0004);
+}
+
+static void b43_wa_mixedsignal(struct b43_wldev *dev)
+{
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1, 3);
+}
+
+static void b43_wa_msst(struct b43_wldev *dev) /* Min sigma square table */
+{
+ struct b43_phy *phy = &dev->phy;
+ int i;
+ const u16 *tab;
+
+ if (phy->type == B43_PHYTYPE_A) {
+ tab = b43_tab_sigmasqr1;
+ } else if (phy->type == B43_PHYTYPE_G) {
+ tab = b43_tab_sigmasqr2;
+ } else {
+ B43_WARN_ON(1);
+ return;
+ }
+
+ for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_MINSIGSQ,
+ i, tab[i]);
+ }
+}
+
+static void b43_wa_iqadc(struct b43_wldev *dev)
+{
+ if (dev->phy.analog == 4)
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 0,
+ b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 0) & ~0xF000);
+}
+
+static void b43_wa_crs_ed(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (phy->rev == 1) {
+ b43_phy_write(dev, B43_PHY_CRSTHRES1_R1, 0x4F19);
+ } else if (phy->rev == 2) {
+ b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861);
+ b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271);
+ b43_phy_write(dev, B43_PHY_ANTDWELL,
+ b43_phy_read(dev, B43_PHY_ANTDWELL)
+ | 0x0800);
+ } else {
+ b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098);
+ b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070);
+ b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080);
+ b43_phy_write(dev, B43_PHY_ANTDWELL,
+ b43_phy_read(dev, B43_PHY_ANTDWELL)
+ | 0x0800);
+ }
+}
+
+static void b43_wa_crs_thr(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, B43_PHY_CRS0,
+ (b43_phy_read(dev, B43_PHY_CRS0) & ~0x03C0) | 0xD000);
+}
+
+static void b43_wa_crs_blank(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, B43_PHY_OFDM(0x2C), 0x005A);
+}
+
+static void b43_wa_cck_shiftbits(struct b43_wldev *dev)
+{
+ b43_phy_write(dev, B43_PHY_CCKSHIFTBITS, 0x0026);
+}
+
+static void b43_wa_wrssi_offset(struct b43_wldev *dev)
+{
+ int i;
+
+ if (dev->phy.rev == 1) {
+ for (i = 0; i < 16; i++) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI_R1,
+ i, 0x0020);
+ }
+ } else {
+ for (i = 0; i < 32; i++) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI,
+ i, 0x0820);
+ }
+ }
+}
+
+static void b43_wa_txpuoff_rxpuon(struct b43_wldev *dev)
+{
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 2, 15);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 3, 20);
+}
+
+static void b43_wa_altagc(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (phy->rev == 1) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 254);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 1, 13);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 2, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 3, 25);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 0, 0x2710);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 1, 0x9B83);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 2, 0x9B83);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 3, 0x0F8D);
+ b43_phy_write(dev, B43_PHY_LMS, 4);
+ } else {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0, 254);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 1, 13);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 2, 19);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
+ }
+
+ b43_phy_write(dev, B43_PHY_CCKSHIFTBITS_WA,
+ (b43_phy_read(dev, B43_PHY_CCKSHIFTBITS_WA) & ~0xFF00) | 0x5700);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1A),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x1A)) & ~0x007F) | 0x000F);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1A),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x1A)) & ~0x3F80) | 0x2B80);
+ b43_phy_write(dev, B43_PHY_ANTWRSETT,
+ (b43_phy_read(dev, B43_PHY_ANTWRSETT) & 0xF0FF) | 0x0300);
+ b43_radio_write16(dev, 0x7A,
+ b43_radio_read16(dev, 0x7A) | 0x0008);
+ b43_phy_write(dev, B43_PHY_N1P1GAIN,
+ (b43_phy_read(dev, B43_PHY_N1P1GAIN) & ~0x000F) | 0x0008);
+ b43_phy_write(dev, B43_PHY_P1P2GAIN,
+ (b43_phy_read(dev, B43_PHY_P1P2GAIN) & ~0x0F00) | 0x0600);
+ b43_phy_write(dev, B43_PHY_N1N2GAIN,
+ (b43_phy_read(dev, B43_PHY_N1N2GAIN) & ~0x0F00) | 0x0700);
+ b43_phy_write(dev, B43_PHY_N1P1GAIN,
+ (b43_phy_read(dev, B43_PHY_N1P1GAIN) & ~0x0F00) | 0x0100);
+ if (phy->rev == 1) {
+ b43_phy_write(dev, B43_PHY_N1N2GAIN,
+ (b43_phy_read(dev, B43_PHY_N1N2GAIN)
+ & ~0x000F) | 0x0007);
+ }
+ b43_phy_write(dev, B43_PHY_OFDM(0x88),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x88)) & ~0x00FF) | 0x001C);
+ b43_phy_write(dev, B43_PHY_OFDM(0x88),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x88)) & ~0x3F00) | 0x0200);
+ b43_phy_write(dev, B43_PHY_OFDM(0x96),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x96)) & ~0x00FF) | 0x001C);
+ b43_phy_write(dev, B43_PHY_OFDM(0x89),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x89)) & ~0x00FF) | 0x0020);
+ b43_phy_write(dev, B43_PHY_OFDM(0x89),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x89)) & ~0x3F00) | 0x0200);
+ b43_phy_write(dev, B43_PHY_OFDM(0x82),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x82)) & ~0x00FF) | 0x002E);
+ b43_phy_write(dev, B43_PHY_OFDM(0x96),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x96)) & ~0xFF00) | 0x1A00);
+ b43_phy_write(dev, B43_PHY_OFDM(0x81),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x81)) & ~0x00FF) | 0x0028);
+ b43_phy_write(dev, B43_PHY_OFDM(0x81),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x81)) & ~0xFF00) | 0x2C00);
+ if (phy->rev == 1) {
+ b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ (b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x001E) | 0x0002);
+ } else {
+ b43_phy_write(dev, B43_PHY_OFDM(0x1B),
+ b43_phy_read(dev, B43_PHY_OFDM(0x1B)) & ~0x001E);
+ b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A);
+ b43_phy_write(dev, B43_PHY_LPFGAINCTL,
+ (b43_phy_read(dev, B43_PHY_LPFGAINCTL) & ~0x000F) | 0x0004);
+ if (phy->rev >= 6) {
+ b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
+ b43_phy_write(dev, B43_PHY_LPFGAINCTL,
+ (b43_phy_read(dev, B43_PHY_LPFGAINCTL) & ~0xF000) | 0x3000);
+ }
+ }
+ b43_phy_write(dev, B43_PHY_DIVSRCHIDX,
+ (b43_phy_read(dev, B43_PHY_DIVSRCHIDX) & 0x8080) | 0x7874);
+ b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00);
+ if (phy->rev == 1) {
+ b43_phy_write(dev, B43_PHY_DIVP1P2GAIN,
+ (b43_phy_read(dev, B43_PHY_DIVP1P2GAIN) & ~0x0F00) | 0x0600);
+ b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E);
+ b43_phy_write(dev, B43_PHY_ANTWRSETT,
+ (b43_phy_read(dev, B43_PHY_ANTWRSETT) & ~0x00FF) | 0x001E);
+ b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 2, 16);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 3, 28);
+ } else {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 0, 0);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 1, 7);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 2, 16);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28);
+ }
+ if (phy->rev >= 6) {
+ b43_phy_write(dev, B43_PHY_OFDM(0x26),
+ b43_phy_read(dev, B43_PHY_OFDM(0x26)) & ~0x0003);
+ b43_phy_write(dev, B43_PHY_OFDM(0x26),
+ b43_phy_read(dev, B43_PHY_OFDM(0x26)) & ~0x1000);
+ }
+ b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */
+}
+
+static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */
+{
+ b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0xC480);
+}
+
+static void b43_wa_cpll_nonpilot(struct b43_wldev *dev)
+{
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 0, 0);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 1, 0);
+}
+
+static void b43_wa_rssi_adc(struct b43_wldev *dev)
+{
+ if (dev->phy.analog == 4)
+ b43_phy_write(dev, 0x00DC, 0x7454);
+}
+
+static void b43_wa_boards_a(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+
+ if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM &&
+ bus->boardinfo.type == SSB_BOARD_BU4306 &&
+ bus->boardinfo.rev < 0x30) {
+ b43_phy_write(dev, 0x0010, 0xE000);
+ b43_phy_write(dev, 0x0013, 0x0140);
+ b43_phy_write(dev, 0x0014, 0x0280);
+ } else {
+ if (bus->boardinfo.type == SSB_BOARD_MP4318 &&
+ bus->boardinfo.rev < 0x20) {
+ b43_phy_write(dev, 0x0013, 0x0210);
+ b43_phy_write(dev, 0x0014, 0x0840);
+ } else {
+ b43_phy_write(dev, 0x0013, 0x0140);
+ b43_phy_write(dev, 0x0014, 0x0280);
+ }
+ if (dev->phy.rev <= 4)
+ b43_phy_write(dev, 0x0010, 0xE000);
+ else
+ b43_phy_write(dev, 0x0010, 0x2000);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 1, 0x0039);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 7, 0x0040);
+ }
+}
+
+static void b43_wa_boards_g(struct b43_wldev *dev)
+{
+ struct ssb_bus *bus = dev->dev->bus;
+ struct b43_phy *phy = &dev->phy;
+
+ if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM ||
+ bus->boardinfo.type != SSB_BOARD_BU4306 ||
+ bus->boardinfo.rev != 0x17) {
+ if (phy->rev < 2) {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
+ } else {
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
+ if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
+ (phy->rev >= 7)) {
+ b43_phy_write(dev, B43_PHY_EXTG(0x11),
+ b43_phy_read(dev, B43_PHY_EXTG(0x11)) & 0xF7FF);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0023, 0x0000);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0000, 0x0000);
+ b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0003, 0x0002);
+ }
+ }
+ }
+ if (bus->sprom.boardflags_lo & B43_BFL_FEM) {
+ b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
+ b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
+ }
+}
+
+void b43_wa_all(struct b43_wldev *dev)
+{
+ struct b43_phy *phy = &dev->phy;
+
+ if (phy->type == B43_PHYTYPE_A) {
+ switch (phy->rev) {
+ case 2:
+ b43_wa_papd(dev);
+ b43_wa_auxclipthr(dev);
+ b43_wa_afcdac(dev);
+ b43_wa_txdc_offset(dev);
+ b43_wa_initgains(dev);
+ b43_wa_divider(dev);
+ b43_wa_gt(dev);
+ b43_wa_rssi_lt(dev);
+ b43_wa_analog(dev);
+ b43_wa_dac(dev);
+ b43_wa_fft(dev);
+ b43_wa_nft(dev);
+ b43_wa_rt(dev);
+ b43_wa_nst(dev);
+ b43_wa_art(dev);
+ b43_wa_txlna_gain(dev);
+ b43_wa_crs_reset(dev);
+ b43_wa_2060txlna_gain(dev);
+ b43_wa_lms(dev);
+ break;
+ case 3:
+ b43_wa_papd(dev);
+ b43_wa_mixedsignal(dev);
+ b43_wa_rssi_lt(dev);
+ b43_wa_txdc_offset(dev);
+ b43_wa_initgains(dev);
+ b43_wa_dac(dev);
+ b43_wa_nft(dev);
+ b43_wa_nst(dev);
+ b43_wa_msst(dev);
+ b43_wa_analog(dev);
+ b43_wa_gt(dev);
+ b43_wa_txpuoff_rxpuon(dev);
+ b43_wa_txlna_gain(dev);
+ break;
+ case 5:
+ b43_wa_iqadc(dev);
+ case 6:
+ b43_wa_papd(dev);
+ b43_wa_rssi_lt(dev);
+ b43_wa_txdc_offset(dev);
+ b43_wa_initgains(dev);
+ b43_wa_dac(dev);
+ b43_wa_nft(dev);
+ b43_wa_nst(dev);
+ b43_wa_msst(dev);
+ b43_wa_analog(dev);
+ b43_wa_gt(dev);
+ b43_wa_txpuoff_rxpuon(dev);
+ b43_wa_txlna_gain(dev);
+ break;
+ case 7:
+ b43_wa_iqadc(dev);
+ b43_wa_papd(dev);
+ b43_wa_rssi_lt(dev);
+ b43_wa_txdc_offset(dev);
+ b43_wa_initgains(dev);
+ b43_wa_dac(dev);
+ b43_wa_nft(dev);
+ b43_wa_nst(dev);
+ b43_wa_msst(dev);
+ b43_wa_analog(dev);
+ b43_wa_gt(dev);
+ b43_wa_txpuoff_rxpuon(dev);
+ b43_wa_txlna_gain(dev);
+ b43_wa_rssi_adc(dev);
+ default:
+ B43_WARN_ON(1);
+ }
+ b43_wa_boards_a(dev);
+ } else if (phy->type == B43_PHYTYPE_G) {
+ switch (phy->rev) {
+ case 1://XXX review rev1
+ b43_wa_crs_ed(dev);
+ b43_wa_crs_thr(dev);
+ b43_wa_crs_blank(dev);
+ b43_wa_cck_shiftbits(dev);
+ b43_wa_fft(dev);
+ b43_wa_nft(dev);
+ b43_wa_rt(dev);
+ b43_wa_nst(dev);
+ b43_wa_art(dev);
+ b43_wa_wrssi_offset(dev);
+ b43_wa_altagc(dev);
+ break;
+ case 2:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ b43_wa_tr_ltov(dev);
+ b43_wa_crs_ed(dev);
+ b43_wa_rssi_lt(dev);
+ b43_wa_nft(dev);
+ b43_wa_nst(dev);
+ b43_wa_msst(dev);
+ b43_wa_wrssi_offset(dev);
+ b43_wa_altagc(dev);
+ b43_wa_analog(dev);
+ b43_wa_txpuoff_rxpuon(dev);
+ break;
+ default:
+ B43_WARN_ON(1);
+ }
+ b43_wa_boards_g(dev);
+ } else { /* No N PHY support so far */
+ B43_WARN_ON(1);
+ }
+
+ b43_wa_cpll_nonpilot(dev);
+}
diff --git a/drivers/net/wireless/b43/wa.h b/drivers/net/wireless/b43/wa.h
new file mode 100644
index 000000000000..e163c5e56e81
--- /dev/null
+++ b/drivers/net/wireless/b43/wa.h
@@ -0,0 +1,7 @@
+#ifndef B43_WA_H_
+#define B43_WA_H_
+
+void b43_wa_initgains(struct b43_wldev *dev);
+void b43_wa_all(struct b43_wldev *dev);
+
+#endif /* B43_WA_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 3307ba1856b1..3fc53e8b4416 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -5,7 +5,7 @@
Transmission (TX/RX) related functions.
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
- Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -30,7 +30,7 @@
#include "xmit.h"
#include "phy.h"
#include "dma.h"
-#include "pio.h"
+
/* Extract the bitrate out of a CCK PLCP header. */
static u8 b43_plcp_get_bitrate_cck(struct b43_plcp_hdr6 *plcp)
@@ -177,13 +177,15 @@ static u8 b43_calc_fallback_rate(u8 bitrate)
return 0;
}
-static void generate_txhdr_fw4(struct b43_wldev *dev,
- struct b43_txhdr_fw4 *txhdr,
- const unsigned char *fragment_data,
- unsigned int fragment_len,
- const struct ieee80211_tx_control *txctl,
- u16 cookie)
+/* Generate a TX data header. */
+void b43_generate_txhdr(struct b43_wldev *dev,
+ u8 *_txhdr,
+ const unsigned char *fragment_data,
+ unsigned int fragment_len,
+ const struct ieee80211_tx_control *txctl,
+ u16 cookie)
{
+ struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
const struct b43_phy *phy = &dev->phy;
const struct ieee80211_hdr *wlhdr =
(const struct ieee80211_hdr *)fragment_data;
@@ -221,7 +223,7 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
} else {
int fbrate_base100kbps = B43_RATE_TO_BASE100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_len,
fbrate_base100kbps);
}
@@ -241,23 +243,30 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
plcp_fragment_len += txctl->icv_len;
key_idx = b43_kidx_to_fw(dev, key_idx);
- mac_ctl |= (key_idx << B43_TX4_MAC_KEYIDX_SHIFT) &
- B43_TX4_MAC_KEYIDX;
- mac_ctl |= (key->algorithm << B43_TX4_MAC_KEYALG_SHIFT) &
- B43_TX4_MAC_KEYALG;
+ mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) &
+ B43_TXH_MAC_KEYIDX;
+ mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) &
+ B43_TXH_MAC_KEYALG;
wlhdr_len = ieee80211_get_hdrlen(fctl);
iv_len = min((size_t) txctl->iv_len,
ARRAY_SIZE(txhdr->iv));
memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len);
}
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp),
- plcp_fragment_len, rate);
+ if (b43_is_old_txhdr_format(dev)) {
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp),
+ plcp_fragment_len, rate);
+ } else {
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp),
+ plcp_fragment_len, rate);
+ }
b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb),
plcp_fragment_len, rate_fb);
/* Extra Frame Types */
if (rate_fb_ofdm)
- extra_ft |= B43_TX4_EFT_FBOFDM;
+ extra_ft |= B43_TXH_EFT_FB_OFDM;
+ else
+ extra_ft |= B43_TXH_EFT_FB_CCK;
/* Set channel radio code. Note that the micrcode ORs 0x100 to
* this value before comparing it to the value in SHM, if this
@@ -267,18 +276,27 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
/* PHY TX Control word */
if (rate_ofdm)
- phy_ctl |= B43_TX4_PHY_OFDM;
+ phy_ctl |= B43_TXH_PHY_ENC_OFDM;
+ else
+ phy_ctl |= B43_TXH_PHY_ENC_CCK;
if (dev->short_preamble)
- phy_ctl |= B43_TX4_PHY_SHORTPRMBL;
- switch (txctl->antenna_sel_tx) {
- case 0:
- phy_ctl |= B43_TX4_PHY_ANTLAST;
+ phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
+
+ switch (b43_ieee80211_antenna_sanitize(dev, txctl->antenna_sel_tx)) {
+ case 0: /* Default */
+ phy_ctl |= B43_TXH_PHY_ANT01AUTO;
+ break;
+ case 1: /* Antenna 0 */
+ phy_ctl |= B43_TXH_PHY_ANT0;
break;
- case 1:
- phy_ctl |= B43_TX4_PHY_ANT0;
+ case 2: /* Antenna 1 */
+ phy_ctl |= B43_TXH_PHY_ANT1;
break;
- case 2:
- phy_ctl |= B43_TX4_PHY_ANT1;
+ case 3: /* Antenna 2 */
+ phy_ctl |= B43_TXH_PHY_ANT2;
+ break;
+ case 4: /* Antenna 3 */
+ phy_ctl |= B43_TXH_PHY_ANT3;
break;
default:
B43_WARN_ON(1);
@@ -286,14 +304,16 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
/* MAC control */
if (!(txctl->flags & IEEE80211_TXCTL_NO_ACK))
- mac_ctl |= B43_TX4_MAC_ACK;
+ mac_ctl |= B43_TXH_MAC_ACK;
if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
- mac_ctl |= B43_TX4_MAC_HWSEQ;
+ mac_ctl |= B43_TXH_MAC_HWSEQ;
if (txctl->flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
- mac_ctl |= B43_TX4_MAC_STMSDU;
+ mac_ctl |= B43_TXH_MAC_STMSDU;
if (phy->type == B43_PHYTYPE_A)
- mac_ctl |= B43_TX4_MAC_5GHZ;
+ mac_ctl |= B43_TXH_MAC_5GHZ;
+ if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
+ mac_ctl |= B43_TXH_MAC_LONGFRAME;
/* Generate the RTS or CTS-to-self frame */
if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
@@ -302,6 +322,7 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
struct ieee80211_hdr *hdr;
int rts_rate, rts_rate_fb;
int rts_rate_ofdm, rts_rate_fb_ofdm;
+ struct b43_plcp_hdr6 *plcp;
rts_rate = txctl->rts_cts_rate;
rts_rate_ofdm = b43_is_ofdm_rate(rts_rate);
@@ -309,59 +330,84 @@ static void generate_txhdr_fw4(struct b43_wldev *dev,
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
- ieee80211_ctstoself_get(dev->wl->hw, dev->wl->if_id,
+ struct ieee80211_cts *cts;
+
+ if (b43_is_old_txhdr_format(dev)) {
+ cts = (struct ieee80211_cts *)
+ (txhdr->old_format.rts_frame);
+ } else {
+ cts = (struct ieee80211_cts *)
+ (txhdr->new_format.rts_frame);
+ }
+ ieee80211_ctstoself_get(dev->wl->hw, txctl->vif,
fragment_data, fragment_len,
- txctl,
- (struct ieee80211_cts *)(txhdr->
- rts_frame));
- mac_ctl |= B43_TX4_MAC_SENDCTS;
+ txctl, cts);
+ mac_ctl |= B43_TXH_MAC_SENDCTS;
len = sizeof(struct ieee80211_cts);
} else {
- ieee80211_rts_get(dev->wl->hw, dev->wl->if_id,
- fragment_data, fragment_len, txctl,
- (struct ieee80211_rts *)(txhdr->
- rts_frame));
- mac_ctl |= B43_TX4_MAC_SENDRTS;
+ struct ieee80211_rts *rts;
+
+ if (b43_is_old_txhdr_format(dev)) {
+ rts = (struct ieee80211_rts *)
+ (txhdr->old_format.rts_frame);
+ } else {
+ rts = (struct ieee80211_rts *)
+ (txhdr->new_format.rts_frame);
+ }
+ ieee80211_rts_get(dev->wl->hw, txctl->vif,
+ fragment_data, fragment_len,
+ txctl, rts);
+ mac_ctl |= B43_TXH_MAC_SENDRTS;
len = sizeof(struct ieee80211_rts);
}
len += FCS_LEN;
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->
- rts_plcp), len,
- rts_rate);
- b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->
- rts_plcp_fb),
+
+ /* Generate the PLCP headers for the RTS/CTS frame */
+ if (b43_is_old_txhdr_format(dev))
+ plcp = &txhdr->old_format.rts_plcp;
+ else
+ plcp = &txhdr->new_format.rts_plcp;
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
+ len, rts_rate);
+ plcp = &txhdr->rts_plcp_fb;
+ b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp,
len, rts_rate_fb);
- hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
+
+ if (b43_is_old_txhdr_format(dev)) {
+ hdr = (struct ieee80211_hdr *)
+ (&txhdr->old_format.rts_frame);
+ } else {
+ hdr = (struct ieee80211_hdr *)
+ (&txhdr->new_format.rts_frame);
+ }
txhdr->rts_dur_fb = hdr->duration_id;
+
if (rts_rate_ofdm) {
- extra_ft |= B43_TX4_EFT_RTSOFDM;
+ extra_ft |= B43_TXH_EFT_RTS_OFDM;
txhdr->phy_rate_rts =
b43_plcp_get_ratecode_ofdm(rts_rate);
- } else
+ } else {
+ extra_ft |= B43_TXH_EFT_RTS_CCK;
txhdr->phy_rate_rts =
b43_plcp_get_ratecode_cck(rts_rate);
+ }
if (rts_rate_fb_ofdm)
- extra_ft |= B43_TX4_EFT_RTSFBOFDM;
- mac_ctl |= B43_TX4_MAC_LONGFRAME;
+ extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
+ else
+ extra_ft |= B43_TXH_EFT_RTSFB_CCK;
}
/* Magic cookie */
- txhdr->cookie = cpu_to_le16(cookie);
+ if (b43_is_old_txhdr_format(dev))
+ txhdr->old_format.cookie = cpu_to_le16(cookie);
+ else
+ txhdr->new_format.cookie = cpu_to_le16(cookie);
/* Apply the bitfields */
txhdr->mac_ctl = cpu_to_le32(mac_ctl);
txhdr->phy_ctl = cpu_to_le16(phy_ctl);
txhdr->extra_ft = extra_ft;
-}
-void b43_generate_txhdr(struct b43_wldev *dev,
- u8 * txhdr,
- const unsigned char *fragment_data,
- unsigned int fragment_len,
- const struct ieee80211_tx_control *txctl, u16 cookie)
-{
- generate_txhdr_fw4(dev, (struct b43_txhdr_fw4 *)txhdr,
- fragment_data, fragment_len, txctl, cookie);
}
static s8 b43_rssi_postprocess(struct b43_wldev *dev,
@@ -384,7 +430,7 @@ static s8 b43_rssi_postprocess(struct b43_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->dev->bus->sprom.r1.
+ if (dev->dev->bus->sprom.
boardflags_lo & B43_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
@@ -488,7 +534,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
wlhdr = (struct ieee80211_hdr *)(skb->data);
fctl = le16_to_cpu(wlhdr->frame_control);
- skb_trim(skb, skb->len - FCS_LEN);
if (macstat & B43_RX_MAC_DEC) {
unsigned int keyidx;
@@ -525,7 +570,24 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
else
status.rate = b43_plcp_get_bitrate_cck(plcp);
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
- status.mactime = mactime;
+
+ /*
+ * If monitors are present get full 64-bit timestamp. This
+ * code assumes we get to process the packet within 16 bits
+ * of timestamp, i.e. about 65 milliseconds after the PHY
+ * received the first symbol.
+ */
+ if (dev->wl->radiotap_enabled) {
+ u16 low_mactime_now;
+
+ b43_tsf_read(dev, &status.mactime);
+ low_mactime_now = status.mactime;
+ status.mactime = status.mactime & ~0xFFFFULL;
+ status.mactime += mactime;
+ if (low_mactime_now <= mactime)
+ status.mactime -= 0x10000;
+ status.flag |= RX_FLAG_TSFT;
+ }
chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
switch (chanstat & B43_RX_CHAN_PHYTYPE) {
@@ -586,10 +648,7 @@ void b43_handle_txstatus(struct b43_wldev *dev,
dev->wl->ieee_stats.dot11RTSSuccessCount++;
}
- if (b43_using_pio(dev))
- b43_pio_handle_txstatus(dev, status);
- else
- b43_dma_handle_txstatus(dev, status);
+ b43_dma_handle_txstatus(dev, status);
}
/* Handle TX status report as received through DMA/PIO queues */
@@ -618,19 +677,13 @@ void b43_handle_hwtxstatus(struct b43_wldev *dev,
/* Stop any TX operation on the device (suspend the hardware queues) */
void b43_tx_suspend(struct b43_wldev *dev)
{
- if (b43_using_pio(dev))
- b43_pio_freeze_txqueues(dev);
- else
- b43_dma_tx_suspend(dev);
+ b43_dma_tx_suspend(dev);
}
/* Resume any TX operation on the device (resume the hardware queues) */
void b43_tx_resume(struct b43_wldev *dev)
{
- if (b43_using_pio(dev))
- b43_pio_thaw_txqueues(dev);
- else
- b43_dma_tx_resume(dev);
+ b43_dma_tx_resume(dev);
}
#if 0
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 6dc079382f7f..ca2a2ab8654c 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -19,68 +19,160 @@ _b43_declare_plcp_hdr(6);
#undef _b43_declare_plcp_hdr
/* TX header for v4 firmware */
-struct b43_txhdr_fw4 {
- __le32 mac_ctl; /* MAC TX control */
- __le16 mac_frame_ctl; /* Copy of the FrameControl field */
+struct b43_txhdr {
+ __le32 mac_ctl; /* MAC TX control */
+ __le16 mac_frame_ctl; /* Copy of the FrameControl field */
__le16 tx_fes_time_norm; /* TX FES Time Normal */
- __le16 phy_ctl; /* PHY TX control */
- __le16 phy_ctl_0; /* Unused */
- __le16 phy_ctl_1; /* Unused */
- __le16 phy_ctl_rts_0; /* Unused */
- __le16 phy_ctl_rts_1; /* Unused */
- __u8 phy_rate; /* PHY rate */
- __u8 phy_rate_rts; /* PHY rate for RTS/CTS */
- __u8 extra_ft; /* Extra Frame Types */
- __u8 chan_radio_code; /* Channel Radio Code */
- __u8 iv[16]; /* Encryption IV */
- __u8 tx_receiver[6]; /* TX Frame Receiver address */
- __le16 tx_fes_time_fb; /* TX FES Time Fallback */
- struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP */
- __le16 rts_dur_fb; /* RTS fallback duration */
- struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP */
- __le16 dur_fb; /* Fallback duration */
- __le16 mm_dur_time; /* Unused */
- __le16 mm_dur_time_fb; /* Unused */
- __le32 time_stamp; /* Timestamp */
- PAD_BYTES(2);
- __le16 cookie; /* TX frame cookie */
- __le16 tx_status; /* TX status */
- struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP */
- __u8 rts_frame[16]; /* The RTS frame (if used) */
- PAD_BYTES(2);
- struct b43_plcp_hdr6 plcp; /* Main PLCP */
+ __le16 phy_ctl; /* PHY TX control */
+ __le16 phy_ctl1; /* PHY TX control word 1 */
+ __le16 phy_ctl1_fb; /* PHY TX control word 1 for fallback rates */
+ __le16 phy_ctl1_rts; /* PHY TX control word 1 RTS */
+ __le16 phy_ctl1_rts_fb; /* PHY TX control word 1 RTS for fallback rates */
+ __u8 phy_rate; /* PHY rate */
+ __u8 phy_rate_rts; /* PHY rate for RTS/CTS */
+ __u8 extra_ft; /* Extra Frame Types */
+ __u8 chan_radio_code; /* Channel Radio Code */
+ __u8 iv[16]; /* Encryption IV */
+ __u8 tx_receiver[6]; /* TX Frame Receiver address */
+ __le16 tx_fes_time_fb; /* TX FES Time Fallback */
+ struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP header */
+ __le16 rts_dur_fb; /* RTS fallback duration */
+ struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP header */
+ __le16 dur_fb; /* Fallback duration */
+ __le16 mimo_modelen; /* MIMO mode length */
+ __le16 mimo_ratelen_fb; /* MIMO fallback rate length */
+ __le32 timeout; /* Timeout */
+
+ union {
+ /* The new r410 format. */
+ struct {
+ __le16 mimo_antenna; /* MIMO antenna select */
+ __le16 preload_size; /* Preload size */
+ PAD_BYTES(2);
+ __le16 cookie; /* TX frame cookie */
+ __le16 tx_status; /* TX status */
+ struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
+ __u8 rts_frame[16]; /* The RTS frame (if used) */
+ PAD_BYTES(2);
+ struct b43_plcp_hdr6 plcp; /* Main PLCP header */
+ } new_format __attribute__ ((__packed__));
+
+ /* The old r351 format. */
+ struct {
+ PAD_BYTES(2);
+ __le16 cookie; /* TX frame cookie */
+ __le16 tx_status; /* TX status */
+ struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */
+ __u8 rts_frame[16]; /* The RTS frame (if used) */
+ PAD_BYTES(2);
+ struct b43_plcp_hdr6 plcp; /* Main PLCP header */
+ } old_format __attribute__ ((__packed__));
+
+ } __attribute__ ((__packed__));
} __attribute__ ((__packed__));
/* MAC TX control */
-#define B43_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */
-#define B43_TX4_MAC_KEYIDX_SHIFT 20
-#define B43_TX4_MAC_KEYALG 0x00070000 /* Security key algorithm */
-#define B43_TX4_MAC_KEYALG_SHIFT 16
-#define B43_TX4_MAC_LIFETIME 0x00001000
-#define B43_TX4_MAC_FRAMEBURST 0x00000800
-#define B43_TX4_MAC_SENDCTS 0x00000400
-#define B43_TX4_MAC_AMPDU 0x00000300
-#define B43_TX4_MAC_AMPDU_SHIFT 8
-#define B43_TX4_MAC_5GHZ 0x00000080
-#define B43_TX4_MAC_IGNPMQ 0x00000020
-#define B43_TX4_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */
-#define B43_TX4_MAC_STMSDU 0x00000008 /* Start MSDU */
-#define B43_TX4_MAC_SENDRTS 0x00000004
-#define B43_TX4_MAC_LONGFRAME 0x00000002
-#define B43_TX4_MAC_ACK 0x00000001
+#define B43_TXH_MAC_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */
+#define B43_TXH_MAC_KEYIDX 0x0FF00000 /* Security key index */
+#define B43_TXH_MAC_KEYIDX_SHIFT 20
+#define B43_TXH_MAC_KEYALG 0x00070000 /* Security key algorithm */
+#define B43_TXH_MAC_KEYALG_SHIFT 16
+#define B43_TXH_MAC_AMIC 0x00008000 /* AMIC */
+#define B43_TXH_MAC_RIFS 0x00004000 /* Use RIFS */
+#define B43_TXH_MAC_LIFETIME 0x00002000 /* Lifetime */
+#define B43_TXH_MAC_FRAMEBURST 0x00001000 /* Frameburst */
+#define B43_TXH_MAC_SENDCTS 0x00000800 /* Send CTS-to-self */
+#define B43_TXH_MAC_AMPDU 0x00000600 /* AMPDU status */
+#define B43_TXH_MAC_AMPDU_MPDU 0x00000000 /* Regular MPDU, not an AMPDU */
+#define B43_TXH_MAC_AMPDU_FIRST 0x00000200 /* First MPDU or AMPDU */
+#define B43_TXH_MAC_AMPDU_INTER 0x00000400 /* Intermediate MPDU or AMPDU */
+#define B43_TXH_MAC_AMPDU_LAST 0x00000600 /* Last (or only) MPDU of AMPDU */
+#define B43_TXH_MAC_40MHZ 0x00000100 /* Use 40 MHz bandwidth */
+#define B43_TXH_MAC_5GHZ 0x00000080 /* 5GHz band */
+#define B43_TXH_MAC_DFCS 0x00000040 /* DFCS */
+#define B43_TXH_MAC_IGNPMQ 0x00000020 /* Ignore PMQ */
+#define B43_TXH_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */
+#define B43_TXH_MAC_STMSDU 0x00000008 /* Start MSDU */
+#define B43_TXH_MAC_SENDRTS 0x00000004 /* Send RTS */
+#define B43_TXH_MAC_LONGFRAME 0x00000002 /* Long frame */
+#define B43_TXH_MAC_ACK 0x00000001 /* Immediate ACK */
/* Extra Frame Types */
-#define B43_TX4_EFT_FBOFDM 0x0001 /* Data frame fallback rate type */
-#define B43_TX4_EFT_RTSOFDM 0x0004 /* RTS/CTS rate type */
-#define B43_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */
+#define B43_TXH_EFT_FB 0x03 /* Data frame fallback encoding */
+#define B43_TXH_EFT_FB_CCK 0x00 /* CCK */
+#define B43_TXH_EFT_FB_OFDM 0x01 /* OFDM */
+#define B43_TXH_EFT_FB_EWC 0x02 /* EWC */
+#define B43_TXH_EFT_FB_N 0x03 /* N */
+#define B43_TXH_EFT_RTS 0x0C /* RTS/CTS encoding */
+#define B43_TXH_EFT_RTS_CCK 0x00 /* CCK */
+#define B43_TXH_EFT_RTS_OFDM 0x04 /* OFDM */
+#define B43_TXH_EFT_RTS_EWC 0x08 /* EWC */
+#define B43_TXH_EFT_RTS_N 0x0C /* N */
+#define B43_TXH_EFT_RTSFB 0x30 /* RTS/CTS fallback encoding */
+#define B43_TXH_EFT_RTSFB_CCK 0x00 /* CCK */
+#define B43_TXH_EFT_RTSFB_OFDM 0x10 /* OFDM */
+#define B43_TXH_EFT_RTSFB_EWC 0x20 /* EWC */
+#define B43_TXH_EFT_RTSFB_N 0x30 /* N */
/* PHY TX control word */
-#define B43_TX4_PHY_OFDM 0x0001 /* Data frame rate type */
-#define B43_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
-#define B43_TX4_PHY_ANT 0x03C0 /* Antenna selection */
-#define B43_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */
-#define B43_TX4_PHY_ANT1 0x0100 /* Use antenna 1 */
-#define B43_TX4_PHY_ANTLAST 0x0300 /* Use last used antenna */
+#define B43_TXH_PHY_ENC 0x0003 /* Data frame encoding */
+#define B43_TXH_PHY_ENC_CCK 0x0000 /* CCK */
+#define B43_TXH_PHY_ENC_OFDM 0x0001 /* OFDM */
+#define B43_TXH_PHY_ENC_EWC 0x0002 /* EWC */
+#define B43_TXH_PHY_ENC_N 0x0003 /* N */
+#define B43_TXH_PHY_SHORTPRMBL 0x0010 /* Use short preamble */
+#define B43_TXH_PHY_ANT 0x03C0 /* Antenna selection */
+#define B43_TXH_PHY_ANT0 0x0000 /* Use antenna 0 */
+#define B43_TXH_PHY_ANT1 0x0040 /* Use antenna 1 */
+#define B43_TXH_PHY_ANT01AUTO 0x00C0 /* Use antenna 0/1 auto */
+#define B43_TXH_PHY_ANT2 0x0100 /* Use antenna 2 */
+#define B43_TXH_PHY_ANT3 0x0200 /* Use antenna 3 */
+#define B43_TXH_PHY_TXPWR 0xFC00 /* TX power */
+#define B43_TXH_PHY_TXPWR_SHIFT 10
+
+/* PHY TX control word 1 */
+#define B43_TXH_PHY1_BW 0x0007 /* Bandwidth */
+#define B43_TXH_PHY1_BW_10 0x0000 /* 10 MHz */
+#define B43_TXH_PHY1_BW_10U 0x0001 /* 10 MHz upper */
+#define B43_TXH_PHY1_BW_20 0x0002 /* 20 MHz */
+#define B43_TXH_PHY1_BW_20U 0x0003 /* 20 MHz upper */
+#define B43_TXH_PHY1_BW_40 0x0004 /* 40 MHz */
+#define B43_TXH_PHY1_BW_40DUP 0x0005 /* 50 MHz duplicate */
+#define B43_TXH_PHY1_MODE 0x0038 /* Mode */
+#define B43_TXH_PHY1_MODE_SISO 0x0000 /* SISO */
+#define B43_TXH_PHY1_MODE_CDD 0x0008 /* CDD */
+#define B43_TXH_PHY1_MODE_STBC 0x0010 /* STBC */
+#define B43_TXH_PHY1_MODE_SDM 0x0018 /* SDM */
+#define B43_TXH_PHY1_CRATE 0x0700 /* Coding rate */
+#define B43_TXH_PHY1_CRATE_1_2 0x0000 /* 1/2 */
+#define B43_TXH_PHY1_CRATE_2_3 0x0100 /* 2/3 */
+#define B43_TXH_PHY1_CRATE_3_4 0x0200 /* 3/4 */
+#define B43_TXH_PHY1_CRATE_4_5 0x0300 /* 4/5 */
+#define B43_TXH_PHY1_CRATE_5_6 0x0400 /* 5/6 */
+#define B43_TXH_PHY1_CRATE_7_8 0x0600 /* 7/8 */
+#define B43_TXH_PHY1_MODUL 0x3800 /* Modulation scheme */
+#define B43_TXH_PHY1_MODUL_BPSK 0x0000 /* BPSK */
+#define B43_TXH_PHY1_MODUL_QPSK 0x0800 /* QPSK */
+#define B43_TXH_PHY1_MODUL_QAM16 0x1000 /* QAM16 */
+#define B43_TXH_PHY1_MODUL_QAM64 0x1800 /* QAM64 */
+#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */
+
+
+/* r351 firmware compatibility stuff. */
+static inline
+bool b43_is_old_txhdr_format(struct b43_wldev *dev)
+{
+ return (dev->fw.rev <= 351);
+}
+
+static inline
+size_t b43_txhdr_size(struct b43_wldev *dev)
+{
+ if (b43_is_old_txhdr_format(dev))
+ return 100 + sizeof(struct b43_plcp_hdr6);
+ return 104 + sizeof(struct b43_plcp_hdr6);
+}
+
void b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr,
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 7e23ec23fc98..6745579ba96d 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -34,6 +34,22 @@ config B43LEGACY_PCICORE_AUTOSELECT
select SSB_DRIVER_PCICORE
default y
+# LED support
+# This config option automatically enables b43legacy LEDS support,
+# if it's possible.
+config B43LEGACY_LEDS
+ bool
+ depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY)
+ default y
+
+# RFKILL support
+# This config option automatically enables b43legacy RFKILL support,
+# if it's possible.
+config B43LEGACY_RFKILL
+ bool
+ depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
+ default y
+
config B43LEGACY_DEBUG
bool "Broadcom 43xx-legacy debugging"
depends on B43LEGACY
diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile
index ec3a2482bbad..80cdb73bd140 100644
--- a/drivers/net/wireless/b43legacy/Makefile
+++ b/drivers/net/wireless/b43legacy/Makefile
@@ -1,14 +1,19 @@
-obj-$(CONFIG_B43LEGACY) += b43legacy.o
-b43legacy-obj-$(CONFIG_B43LEGACY_DEBUG) += debugfs.o
+# b43legacy core
+b43legacy-y += main.o
+b43legacy-y += ilt.o
+b43legacy-y += phy.o
+b43legacy-y += radio.o
+b43legacy-y += sysfs.o
+b43legacy-y += xmit.o
+# b43 RFKILL button support
+b43legacy-$(CONFIG_B43LEGACY_RFKILL) += rfkill.o
+# b43legacy LED support
+b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o
+# b43legacy debugging
+b43legacy-$(CONFIG_B43LEGACY_DEBUG) += debugfs.o
+# b43legacy DMA and PIO
+b43legacy-$(CONFIG_B43LEGACY_DMA) += dma.o
+b43legacy-$(CONFIG_B43LEGACY_PIO) += pio.o
-b43legacy-obj-$(CONFIG_B43LEGACY_DMA) += dma.o
-b43legacy-obj-$(CONFIG_B43LEGACY_PIO) += pio.o
+obj-$(CONFIG_B43LEGACY) += b43legacy.o
-b43legacy-objs := main.o \
- ilt.o \
- leds.o \
- phy.o \
- radio.o \
- sysfs.o \
- xmit.o \
- $(b43legacy-obj-y)
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index afe145cec067..93419adb925e 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -19,6 +19,7 @@
#include "debugfs.h"
#include "leds.h"
+#include "rfkill.h"
#include "phy.h"
@@ -275,6 +276,8 @@
#define B43legacy_DEFAULT_SHORT_RETRY_LIMIT 7
#define B43legacy_DEFAULT_LONG_RETRY_LIMIT 4
+#define B43legacy_PHY_TX_BADNESS_LIMIT 1000
+
/* Max size of a security key */
#define B43legacy_SEC_KEYSIZE 16
/* Security algorithms. */
@@ -412,7 +415,6 @@ struct b43legacy_phy {
u8 calibrated:1;
u8 radio_rev; /* Radio revision */
- bool locked; /* Only used in b43legacy_phy_{un}lock() */
bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */
/* ACI (adjacent channel interference) flags. */
@@ -455,11 +457,6 @@ struct b43legacy_phy {
s16 lna_gain; /* LNA */
s16 pga_gain; /* PGA */
- /* PHY lock for core.rev < 3
- * This lock is only used by b43legacy_phy_{un}lock()
- */
- spinlock_t lock;
-
/* Desired TX power level (in dBm). This is set by the user and
* adjusted in b43legacy_phy_xmitpower(). */
u8 power_level;
@@ -483,9 +480,6 @@ struct b43legacy_phy {
u16 txpwr_offset;
};
-#ifdef CONFIG_B43LEGACY_DEBUG
- bool manual_txpower_control; /* Manual TX-power control enabled? */
-#endif
/* Current Interference Mitigation mode */
int interfmode;
/* Stack of saved values from the Interference Mitigation code.
@@ -510,6 +504,16 @@ struct b43legacy_phy {
u16 lofcal;
u16 initval;
+
+ /* PHY TX errors counter. */
+ atomic_t txerr_cnt;
+
+#if B43legacy_DEBUG
+ /* Manual TX-power control enabled? */
+ bool manual_txpower_control;
+ /* PHY registers locked by b43legacy_phy_lock()? */
+ bool phy_locked;
+#endif /* B43legacy_DEBUG */
};
/* Data structures for DMA transmission, per 80211 core. */
@@ -571,10 +575,7 @@ struct b43legacy_wl {
* at a time. General information about this interface follows.
*/
- /* Opaque ID of the operating interface from the ieee80211
- * subsystem. Do not modify.
- */
- int if_id;
+ struct ieee80211_vif *vif;
/* MAC address (can be NULL). */
u8 mac_addr[ETH_ALEN];
/* Current BSSID (can be NULL). */
@@ -592,9 +593,14 @@ struct b43legacy_wl {
u8 rng_initialized;
char rng_name[30 + 1];
+ /* The RF-kill button */
+ struct b43legacy_rfkill rfkill;
+
/* List of all wireless devices on this chip */
struct list_head devlist;
u8 nr_devs;
+
+ bool radiotap_enabled;
};
/* Pointers to the firmware data and meta information about it. */
@@ -663,8 +669,11 @@ struct b43legacy_wldev {
/* Various statistics about the physical device. */
struct b43legacy_stats stats;
-#define B43legacy_NR_LEDS 4
- struct b43legacy_led leds[B43legacy_NR_LEDS];
+ /* The device LEDs. */
+ struct b43legacy_led led_tx;
+ struct b43legacy_led led_rx;
+ struct b43legacy_led led_assoc;
+ struct b43legacy_led led_radio;
/* Reason code of the last interrupt. */
u32 irq_reason;
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 619b4534ef09..03ce0821a60e 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -209,7 +209,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
struct b43legacy_wldev *dev;
struct b43legacy_debugfs_fops *dfops;
struct b43legacy_dfs_file *dfile;
- ssize_t ret = 0;
+ ssize_t uninitialized_var(ret);
char *buf;
const size_t bufsize = 1024 * 128;
const size_t buforder = get_order(bufsize);
diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c
index 247fc780ffdb..a849078aea69 100644
--- a/drivers/net/wireless/b43legacy/ilt.c
+++ b/drivers/net/wireless/b43legacy/ilt.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c
index a584ea810502..cacb786d9713 100644
--- a/drivers/net/wireless/b43legacy/leds.c
+++ b/drivers/net/wireless/b43legacy/leds.c
@@ -1,13 +1,13 @@
/*
- Broadcom B43legacy wireless driver
+ Broadcom B43 wireless driver
+ LED control
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
- Michael Buesch <mb@bu3sch.de>
- Danny van Dyk <kugelfang@gentoo.org>
- Andreas Jaggi <andreas.jaggi@waterwave.ch>
- Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
+ Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
+ Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
+ Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
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
@@ -26,273 +26,216 @@
*/
-#include "leds.h"
#include "b43legacy.h"
-#include "main.h"
-
-static void b43legacy_led_changestate(struct b43legacy_led *led)
-{
- struct b43legacy_wldev *dev = led->dev;
- const int index = led->index;
- u16 ledctl;
+#include "leds.h"
- B43legacy_WARN_ON(!(index >= 0 && index < B43legacy_NR_LEDS));
- B43legacy_WARN_ON(!led->blink_interval);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- ledctl ^= (1 << index);
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
-}
-static void b43legacy_led_blink(unsigned long d)
+static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
+ bool activelow)
{
- struct b43legacy_led *led = (struct b43legacy_led *)d;
- struct b43legacy_wldev *dev = led->dev;
+ struct b43legacy_wl *wl = dev->wl;
unsigned long flags;
+ u16 ctl;
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- if (led->blink_interval) {
- b43legacy_led_changestate(led);
- mod_timer(&led->blink_timer, jiffies + led->blink_interval);
- }
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
+ spin_lock_irqsave(&wl->leds_lock, flags);
+ ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+ if (activelow)
+ ctl &= ~(1 << led_index);
+ else
+ ctl |= (1 << led_index);
+ b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+ spin_unlock_irqrestore(&wl->leds_lock, flags);
}
-static void b43legacy_led_blink_start(struct b43legacy_led *led,
- unsigned long interval)
+static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
+ bool activelow)
{
- if (led->blink_interval)
- return;
- led->blink_interval = interval;
- b43legacy_led_changestate(led);
- led->blink_timer.expires = jiffies + interval;
- add_timer(&led->blink_timer);
+ struct b43legacy_wl *wl = dev->wl;
+ unsigned long flags;
+ u16 ctl;
+
+ spin_lock_irqsave(&wl->leds_lock, flags);
+ ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
+ if (activelow)
+ ctl |= (1 << led_index);
+ else
+ ctl &= ~(1 << led_index);
+ b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
+ spin_unlock_irqrestore(&wl->leds_lock, flags);
}
-static void b43legacy_led_blink_stop(struct b43legacy_led *led, int sync)
+/* Callback from the LED subsystem. */
+static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
+ enum led_brightness brightness)
{
+ struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
+ led_dev);
struct b43legacy_wldev *dev = led->dev;
- const int index = led->index;
- u16 ledctl;
+ bool radio_enabled;
- if (!led->blink_interval)
- return;
- if (unlikely(sync))
- del_timer_sync(&led->blink_timer);
- else
- del_timer(&led->blink_timer);
- led->blink_interval = 0;
+ /* Checking the radio-enabled status here is slightly racy,
+ * but we want to avoid the locking overhead and we don't care
+ * whether the LED has the wrong state for a second. */
+ radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
- /* Make sure the LED is turned off. */
- B43legacy_WARN_ON(!(index >= 0 && index < B43legacy_NR_LEDS));
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- if (led->activelow)
- ledctl |= (1 << index);
+ if (brightness == LED_OFF || !radio_enabled)
+ b43legacy_led_turn_off(dev, led->index, led->activelow);
else
- ledctl &= ~(1 << index);
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
+ b43legacy_led_turn_on(dev, led->index, led->activelow);
}
-static void b43legacy_led_init_hardcoded(struct b43legacy_wldev *dev,
- struct b43legacy_led *led,
- int led_index)
+static int b43legacy_register_led(struct b43legacy_wldev *dev,
+ struct b43legacy_led *led,
+ const char *name, char *default_trigger,
+ u8 led_index, bool activelow)
{
- struct ssb_bus *bus = dev->dev->bus;
+ int err;
+
+ b43legacy_led_turn_off(dev, led_index, activelow);
+ if (led->dev)
+ return -EEXIST;
+ if (!default_trigger)
+ return -EINVAL;
+ led->dev = dev;
+ led->index = led_index;
+ led->activelow = activelow;
+ strncpy(led->name, name, sizeof(led->name));
+
+ led->led_dev.name = led->name;
+ led->led_dev.default_trigger = default_trigger;
+ led->led_dev.brightness_set = b43legacy_led_brightness_set;
+
+ err = led_classdev_register(dev->dev->dev, &led->led_dev);
+ if (err) {
+ b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
+ led->dev = NULL;
+ return err;
+ }
+ return 0;
+}
- /* This function is called, if the behaviour (and activelow)
- * information for a LED is missing in the SPROM.
- * We hardcode the behaviour values for various devices here.
- * Note that the B43legacy_LED_TEST_XXX behaviour values can
- * be used to figure out which led is mapped to which index.
- */
+static void b43legacy_unregister_led(struct b43legacy_led *led)
+{
+ if (!led->dev)
+ return;
+ led_classdev_unregister(&led->led_dev);
+ b43legacy_led_turn_off(led->dev, led->index, led->activelow);
+ led->dev = NULL;
+}
+
+static void b43legacy_map_led(struct b43legacy_wldev *dev,
+ u8 led_index,
+ enum b43legacy_led_behaviour behaviour,
+ bool activelow)
+{
+ struct ieee80211_hw *hw = dev->wl->hw;
+ char name[B43legacy_LED_MAX_NAME_LEN + 1];
- switch (led_index) {
- case 0:
- led->behaviour = B43legacy_LED_ACTIVITY;
- led->activelow = 1;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
- led->behaviour = B43legacy_LED_RADIO_ALL;
+ /* Map the b43 specific LED behaviour value to the
+ * generic LED triggers. */
+ switch (behaviour) {
+ case B43legacy_LED_INACTIVE:
break;
- case 1:
- led->behaviour = B43legacy_LED_RADIO_B;
- if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
- led->behaviour = B43legacy_LED_ASSOC;
+ case B43legacy_LED_OFF:
+ b43legacy_led_turn_off(dev, led_index, activelow);
break;
- case 2:
- led->behaviour = B43legacy_LED_RADIO_A;
+ case B43legacy_LED_ON:
+ b43legacy_led_turn_on(dev, led_index, activelow);
break;
- case 3:
- led->behaviour = B43legacy_LED_OFF;
+ case B43legacy_LED_ACTIVITY:
+ case B43legacy_LED_TRANSFER:
+ case B43legacy_LED_APTRANSFER:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:tx", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_tx, name,
+ ieee80211_get_tx_led_name(hw),
+ led_index, activelow);
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:rx", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_rx, name,
+ ieee80211_get_rx_led_name(hw),
+ led_index, activelow);
+ break;
+ case B43legacy_LED_RADIO_ALL:
+ case B43legacy_LED_RADIO_A:
+ case B43legacy_LED_RADIO_B:
+ case B43legacy_LED_MODE_BG:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:radio", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_radio, name,
+ b43legacy_rfkill_led_name(dev),
+ led_index, activelow);
+ /* Sync the RF-kill LED state with the switch state. */
+ if (dev->radio_hw_enable)
+ b43legacy_led_turn_on(dev, led_index, activelow);
+ break;
+ case B43legacy_LED_WEIRD:
+ case B43legacy_LED_ASSOC:
+ snprintf(name, sizeof(name),
+ "b43legacy-%s:assoc", wiphy_name(hw->wiphy));
+ b43legacy_register_led(dev, &dev->led_assoc, name,
+ ieee80211_get_assoc_led_name(hw),
+ led_index, activelow);
break;
default:
- B43legacy_BUG_ON(1);
+ b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
+ behaviour);
+ break;
}
}
-int b43legacy_leds_init(struct b43legacy_wldev *dev)
+void b43legacy_leds_init(struct b43legacy_wldev *dev)
{
- struct b43legacy_led *led;
+ struct ssb_bus *bus = dev->dev->bus;
u8 sprom[4];
int i;
-
- sprom[0] = dev->dev->bus->sprom.r1.gpio0;
- sprom[1] = dev->dev->bus->sprom.r1.gpio1;
- sprom[2] = dev->dev->bus->sprom.r1.gpio2;
- sprom[3] = dev->dev->bus->sprom.r1.gpio3;
-
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- led->index = i;
- led->dev = dev;
- setup_timer(&led->blink_timer,
- b43legacy_led_blink,
- (unsigned long)led);
-
- if (sprom[i] == 0xFF)
- b43legacy_led_init_hardcoded(dev, led, i);
- else {
- led->behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
- led->activelow = !!(sprom[i] &
- B43legacy_LED_ACTIVELOW);
+ enum b43legacy_led_behaviour behaviour;
+ bool activelow;
+
+ sprom[0] = bus->sprom.gpio0;
+ sprom[1] = bus->sprom.gpio1;
+ sprom[2] = bus->sprom.gpio2;
+ sprom[3] = bus->sprom.gpio3;
+
+ for (i = 0; i < 4; i++) {
+ if (sprom[i] == 0xFF) {
+ /* There is no LED information in the SPROM
+ * for this LED. Hardcode it here. */
+ activelow = 0;
+ switch (i) {
+ case 0:
+ behaviour = B43legacy_LED_ACTIVITY;
+ activelow = 1;
+ if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
+ behaviour = B43legacy_LED_RADIO_ALL;
+ break;
+ case 1:
+ behaviour = B43legacy_LED_RADIO_B;
+ if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
+ behaviour = B43legacy_LED_ASSOC;
+ break;
+ case 2:
+ behaviour = B43legacy_LED_RADIO_A;
+ break;
+ case 3:
+ behaviour = B43legacy_LED_OFF;
+ break;
+ default:
+ B43legacy_WARN_ON(1);
+ return;
+ }
+ } else {
+ behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
+ activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
}
+ b43legacy_map_led(dev, i, behaviour, activelow);
}
-
- return 0;
}
void b43legacy_leds_exit(struct b43legacy_wldev *dev)
{
- struct b43legacy_led *led;
- int i;
-
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- b43legacy_led_blink_stop(led, 1);
- }
- b43legacy_leds_switch_all(dev, 0);
-}
-
-void b43legacy_leds_update(struct b43legacy_wldev *dev, int activity)
-{
- struct b43legacy_led *led;
- struct b43legacy_phy *phy = &dev->phy;
- const int transferring = (jiffies - dev->stats.last_tx)
- < B43legacy_LED_XFER_THRES;
- int i;
- int turn_on;
- unsigned long interval = 0;
- u16 ledctl;
- unsigned long flags;
- bool radio_enabled = (phy->radio_on && dev->radio_hw_enable);
-
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
-
- turn_on = 0;
- switch (led->behaviour) {
- case B43legacy_LED_INACTIVE:
- continue;
- case B43legacy_LED_OFF:
- break;
- case B43legacy_LED_ON:
- turn_on = 1;
- break;
- case B43legacy_LED_ACTIVITY:
- turn_on = activity;
- break;
- case B43legacy_LED_RADIO_ALL:
- turn_on = radio_enabled;
- break;
- case B43legacy_LED_RADIO_A:
- break;
- case B43legacy_LED_RADIO_B:
- turn_on = radio_enabled;
- break;
- case B43legacy_LED_MODE_BG:
- if (phy->type == B43legacy_PHYTYPE_G && radio_enabled)
- turn_on = 1;
- break;
- case B43legacy_LED_TRANSFER:
- if (transferring)
- b43legacy_led_blink_start(led,
- B43legacy_LEDBLINK_MEDIUM);
- else
- b43legacy_led_blink_stop(led, 0);
- continue;
- case B43legacy_LED_APTRANSFER:
- if (b43legacy_is_mode(dev->wl,
- IEEE80211_IF_TYPE_AP)) {
- if (transferring) {
- interval = B43legacy_LEDBLINK_FAST;
- turn_on = 1;
- }
- } else {
- turn_on = 1;
- if (transferring)
- interval = B43legacy_LEDBLINK_FAST;
- else
- turn_on = 0;
- }
- if (turn_on)
- b43legacy_led_blink_start(led, interval);
- else
- b43legacy_led_blink_stop(led, 0);
- continue;
- case B43legacy_LED_WEIRD:
- break;
- case B43legacy_LED_ASSOC:
- turn_on = 1;
-#ifdef CONFIG_B43LEGACY_DEBUG
- case B43legacy_LED_TEST_BLINKSLOW:
- b43legacy_led_blink_start(led, B43legacy_LEDBLINK_SLOW);
- continue;
- case B43legacy_LED_TEST_BLINKMEDIUM:
- b43legacy_led_blink_start(led,
- B43legacy_LEDBLINK_MEDIUM);
- continue;
- case B43legacy_LED_TEST_BLINKFAST:
- b43legacy_led_blink_start(led, B43legacy_LEDBLINK_FAST);
- continue;
-#endif /* CONFIG_B43LEGACY_DEBUG */
- default:
- B43legacy_BUG_ON(1);
- };
-
- if (led->activelow)
- turn_on = !turn_on;
- if (turn_on)
- ledctl |= (1 << i);
- else
- ledctl &= ~(1 << i);
- }
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
-}
-
-void b43legacy_leds_switch_all(struct b43legacy_wldev *dev, int on)
-{
- struct b43legacy_led *led;
- u16 ledctl;
- int i;
- int bit_on;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->wl->leds_lock, flags);
- ledctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
- for (i = 0; i < B43legacy_NR_LEDS; i++) {
- led = &(dev->leds[i]);
- if (led->behaviour == B43legacy_LED_INACTIVE)
- continue;
- if (on)
- bit_on = led->activelow ? 0 : 1;
- else
- bit_on = led->activelow ? 1 : 0;
- if (bit_on)
- ledctl |= (1 << i);
- else
- ledctl &= ~(1 << i);
- }
- b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ledctl);
- spin_unlock_irqrestore(&dev->wl->leds_lock, flags);
+ b43legacy_unregister_led(&dev->led_tx);
+ b43legacy_unregister_led(&dev->led_rx);
+ b43legacy_unregister_led(&dev->led_assoc);
+ b43legacy_unregister_led(&dev->led_radio);
}
diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h
index b989f503e684..82167a90088f 100644
--- a/drivers/net/wireless/b43legacy/leds.h
+++ b/drivers/net/wireless/b43legacy/leds.h
@@ -1,30 +1,33 @@
#ifndef B43legacy_LEDS_H_
#define B43legacy_LEDS_H_
+struct b43legacy_wldev;
+
+#ifdef CONFIG_B43LEGACY_LEDS
+
#include <linux/types.h>
-#include <linux/timer.h>
+#include <linux/leds.h>
+#define B43legacy_LED_MAX_NAME_LEN 31
+
struct b43legacy_led {
- u8 behaviour;
- bool activelow;
- /* Index in the "leds" array in b43legacy_wldev */
- u8 index;
struct b43legacy_wldev *dev;
- struct timer_list blink_timer;
- unsigned long blink_interval;
+ /* The LED class device */
+ struct led_classdev led_dev;
+ /* The index number of the LED. */
+ u8 index;
+ /* If activelow is true, the LED is ON if the
+ * bit is switched off. */
+ bool activelow;
+ /* The unique name string for this LED device. */
+ char name[B43legacy_LED_MAX_NAME_LEN + 1];
};
-/* Delay between state changes when blinking in jiffies */
-#define B43legacy_LEDBLINK_SLOW (HZ / 1)
-#define B43legacy_LEDBLINK_MEDIUM (HZ / 4)
-#define B43legacy_LEDBLINK_FAST (HZ / 8)
-
-#define B43legacy_LED_XFER_THRES (HZ / 100)
-
#define B43legacy_LED_BEHAVIOUR 0x7F
#define B43legacy_LED_ACTIVELOW 0x80
-enum { /* LED behaviour values */
+/* LED behaviour values */
+enum b43legacy_led_behaviour {
B43legacy_LED_OFF,
B43legacy_LED_ON,
B43legacy_LED_ACTIVITY,
@@ -37,20 +40,24 @@ enum { /* LED behaviour values */
B43legacy_LED_WEIRD,
B43legacy_LED_ASSOC,
B43legacy_LED_INACTIVE,
-
- /* Behaviour values for testing.
- * With these values it is easier to figure out
- * the real behaviour of leds, in case the SPROM
- * is missing information.
- */
- B43legacy_LED_TEST_BLINKSLOW,
- B43legacy_LED_TEST_BLINKMEDIUM,
- B43legacy_LED_TEST_BLINKFAST,
};
-int b43legacy_leds_init(struct b43legacy_wldev *dev);
+void b43legacy_leds_init(struct b43legacy_wldev *dev);
void b43legacy_leds_exit(struct b43legacy_wldev *dev);
-void b43legacy_leds_update(struct b43legacy_wldev *dev, int activity);
-void b43legacy_leds_switch_all(struct b43legacy_wldev *dev, int on);
+
+#else /* CONFIG_B43EGACY_LEDS */
+/* LED support disabled */
+
+struct b43legacy_led {
+ /* empty */
+};
+
+static inline void b43legacy_leds_init(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_leds_exit(struct b43legacy_wldev *dev)
+{
+}
+#endif /* CONFIG_B43LEGACY_LEDS */
#endif /* B43legacy_LEDS_H_ */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 32d5e1785bda..4ed4243feeaa 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -3,7 +3,7 @@
* Broadcom B43legacy wireless driver
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
- * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ * Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
* Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -75,18 +75,6 @@ module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames"
" Preemption");
-static int modparam_short_retry = B43legacy_DEFAULT_SHORT_RETRY_LIMIT;
-module_param_named(short_retry, modparam_short_retry, int, 0444);
-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
-
-static int modparam_long_retry = B43legacy_DEFAULT_LONG_RETRY_LIMIT;
-module_param_named(long_retry, modparam_long_retry, int, 0444);
-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-
-static int modparam_noleds;
-module_param_named(noleds, modparam_noleds, int, 0444);
-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
-
static char modparam_fwpostfix[16];
module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
@@ -988,7 +976,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
plcp.data = 0;
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
size,
B43legacy_RATE_TO_100KBPS(rate));
/* Write PLCP in two parts and timing for packet transfer */
@@ -1054,7 +1042,7 @@ static u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
*dest_size,
B43legacy_RATE_TO_100KBPS(rate));
hdr->duration_id = dur;
@@ -1217,7 +1205,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
u32 merged_dma_reason = 0;
int i;
- int activity = 0;
unsigned long flags;
spin_lock_irqsave(&dev->wl->irq_lock, flags);
@@ -1234,8 +1221,15 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
if (unlikely(reason & B43legacy_IRQ_MAC_TXERR))
b43legacyerr(dev->wl, "MAC transmission error\n");
- if (unlikely(reason & B43legacy_IRQ_PHY_TXERR))
+ if (unlikely(reason & B43legacy_IRQ_PHY_TXERR)) {
b43legacyerr(dev->wl, "PHY transmission error\n");
+ rmb();
+ if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+ b43legacyerr(dev->wl, "Too many PHY TX errors, "
+ "restarting the controller\n");
+ b43legacy_controller_restart(dev, "PHY TX errors");
+ }
+ }
if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK |
B43legacy_DMAIRQ_NONFATALMASK))) {
@@ -1281,7 +1275,6 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
b43legacy_pio_rx(dev->pio.queue0);
else
b43legacy_dma_rx(dev->dma.rx_ring0);
- /* We intentionally don't set "activity" to 1, here. */
}
B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE);
@@ -1290,20 +1283,13 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
b43legacy_pio_rx(dev->pio.queue3);
else
b43legacy_dma_rx(dev->dma.rx_ring3);
- activity = 1;
}
B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE);
- if (reason & B43legacy_IRQ_TX_OK) {
+ if (reason & B43legacy_IRQ_TX_OK)
handle_irq_transmit_status(dev);
- activity = 1;
- /* TODO: In AP mode, this also causes sending of powersave
- responses. */
- }
- if (!modparam_noleds)
- b43legacy_leds_update(dev, activity);
b43legacy_interrupt_enable(dev, dev->irq_savedstate);
mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
@@ -1755,7 +1741,6 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
B43legacy_MMIO_STATUS_BITFIELD)
& 0xFFFF3FFF);
- b43legacy_leds_switch_all(dev, 0);
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
@@ -1767,7 +1752,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
mask |= 0x0060;
set |= 0x0060;
}
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) {
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
@@ -1811,6 +1796,7 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
{
dev->mac_suspended--;
B43legacy_WARN_ON(dev->mac_suspended < 0);
+ B43legacy_WARN_ON(irqs_disabled());
if (dev->mac_suspended == 0) {
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
b43legacy_read32(dev,
@@ -1822,6 +1808,11 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
b43legacy_power_saving_ctl_bits(dev, -1, -1);
+
+ /* Re-enable IRQs. */
+ spin_lock_irq(&dev->wl->irq_lock);
+ b43legacy_interrupt_enable(dev, dev->irq_savedstate);
+ spin_unlock_irq(&dev->wl->irq_lock);
}
}
@@ -1831,20 +1822,31 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
int i;
u32 tmp;
+ might_sleep();
+ B43legacy_WARN_ON(irqs_disabled());
B43legacy_WARN_ON(dev->mac_suspended < 0);
+
if (dev->mac_suspended == 0) {
+ /* Mask IRQs before suspending MAC. Otherwise
+ * the MAC stays busy and won't suspend. */
+ spin_lock_irq(&dev->wl->irq_lock);
+ tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+ spin_unlock_irq(&dev->wl->irq_lock);
+ b43legacy_synchronize_irq(dev);
+ dev->irq_savedstate = tmp;
+
b43legacy_power_saving_ctl_bits(dev, -1, 1);
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
b43legacy_read32(dev,
B43legacy_MMIO_STATUS_BITFIELD)
& ~B43legacy_SBF_MAC_ENABLED);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
- for (i = 10000; i; i--) {
+ for (i = 40; i; i--) {
tmp = b43legacy_read32(dev,
B43legacy_MMIO_GEN_IRQ_REASON);
if (tmp & B43legacy_IRQ_MAC_SUSPENDED)
goto out;
- udelay(1);
+ msleep(1);
}
b43legacyerr(dev->wl, "MAC suspend failed\n");
}
@@ -1989,27 +1991,10 @@ static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev,
B43legacy_SHM_SH_PRPHYCTL, tmp);
}
-/* Returns TRUE, if the radio is enabled in hardware. */
-static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
-{
- if (dev->phy.rev >= 3) {
- if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
- & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
- return 1;
- } else {
- if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
- & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
- return 1;
- }
- return 0;
-}
-
/* This is the opposite of b43legacy_chip_init() */
static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
{
- b43legacy_radio_turn_off(dev);
- if (!modparam_noleds)
- b43legacy_leds_exit(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_gpio_cleanup(dev);
/* firmware is released later */
}
@@ -2039,9 +2024,10 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
err = b43legacy_gpio_init(dev);
if (err)
goto out; /* firmware is released later */
+
err = b43legacy_upload_initvals(dev);
if (err)
- goto err_gpio_cleanup;
+ goto err_gpio_clean;
b43legacy_radio_turn_on(dev);
b43legacy_write16(dev, 0x03E6, 0x0000);
@@ -2113,14 +2099,17 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
+ /* PHY TX errors counter. */
+ atomic_set(&phy->txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+
B43legacy_WARN_ON(err != 0);
b43legacydbg(dev->wl, "Chip initialized\n");
out:
return err;
err_radio_off:
- b43legacy_radio_turn_off(dev);
-err_gpio_cleanup:
+ b43legacy_radio_turn_off(dev, 1);
+err_gpio_clean:
b43legacy_gpio_cleanup(dev);
goto out;
}
@@ -2140,7 +2129,7 @@ static void b43legacy_periodic_every120sec(struct b43legacy_wldev *dev)
static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_lo_mark_all_unused(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
b43legacy_mac_suspend(dev);
b43legacy_calc_nrssi_slope(dev);
b43legacy_mac_enable(dev);
@@ -2156,20 +2145,9 @@ static void b43legacy_periodic_every30sec(struct b43legacy_wldev *dev)
static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
-}
-
-static void b43legacy_periodic_every1sec(struct b43legacy_wldev *dev)
-{
- bool radio_hw_enable;
- /* check if radio hardware enabled status changed */
- radio_hw_enable = b43legacy_is_hw_radio_enabled(dev);
- if (unlikely(dev->radio_hw_enable != radio_hw_enable)) {
- dev->radio_hw_enable = radio_hw_enable;
- b43legacyinfo(dev->wl, "Radio hardware status changed to %s\n",
- (radio_hw_enable) ? "enabled" : "disabled");
- b43legacy_leds_update(dev, 0);
- }
+ atomic_set(&dev->phy.txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+ wmb();
}
static void do_periodic_work(struct b43legacy_wldev *dev)
@@ -2177,94 +2155,45 @@ static void do_periodic_work(struct b43legacy_wldev *dev)
unsigned int state;
state = dev->periodic_state;
- if (state % 120 == 0)
+ if (state % 8 == 0)
b43legacy_periodic_every120sec(dev);
- if (state % 60 == 0)
+ if (state % 4 == 0)
b43legacy_periodic_every60sec(dev);
- if (state % 30 == 0)
+ if (state % 2 == 0)
b43legacy_periodic_every30sec(dev);
- if (state % 15 == 0)
- b43legacy_periodic_every15sec(dev);
- b43legacy_periodic_every1sec(dev);
+ b43legacy_periodic_every15sec(dev);
}
-/* Estimate a "Badness" value based on the periodic work
- * state-machine state. "Badness" is worse (bigger), if the
- * periodic work will take longer.
+/* Periodic work locking policy:
+ * The whole periodic work handler is protected by
+ * wl->mutex. If another lock is needed somewhere in the
+ * pwork callchain, it's aquired in-place, where it's needed.
*/
-static int estimate_periodic_work_badness(unsigned int state)
-{
- int badness = 0;
-
- if (state % 120 == 0) /* every 120 sec */
- badness += 10;
- if (state % 60 == 0) /* every 60 sec */
- badness += 5;
- if (state % 30 == 0) /* every 30 sec */
- badness += 1;
- if (state % 15 == 0) /* every 15 sec */
- badness += 1;
-
-#define BADNESS_LIMIT 4
- return badness;
-}
-
static void b43legacy_periodic_work_handler(struct work_struct *work)
{
- struct b43legacy_wldev *dev =
- container_of(work, struct b43legacy_wldev,
- periodic_work.work);
- unsigned long flags;
+ struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev,
+ periodic_work.work);
+ struct b43legacy_wl *wl = dev->wl;
unsigned long delay;
- u32 savedirqs = 0;
- int badness;
- mutex_lock(&dev->wl->mutex);
+ mutex_lock(&wl->mutex);
if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED))
goto out;
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP))
goto out_requeue;
- badness = estimate_periodic_work_badness(dev->periodic_state);
- if (badness > BADNESS_LIMIT) {
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- /* Suspend TX as we don't want to transmit packets while
- * we recalibrate the hardware. */
- b43legacy_tx_suspend(dev);
- savedirqs = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- /* Periodic work will take a long time, so we want it to
- * be preemtible and release the spinlock. */
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
-
- do_periodic_work(dev);
+ do_periodic_work(dev);
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
- b43legacy_interrupt_enable(dev, savedirqs);
- b43legacy_tx_resume(dev);
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- } else {
- /* Take the global driver lock. This will lock any operation. */
- spin_lock_irqsave(&dev->wl->irq_lock, flags);
-
- do_periodic_work(dev);
-
- mmiowb();
- spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
- }
dev->periodic_state++;
out_requeue:
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
- delay = round_jiffies_relative(HZ);
- queue_delayed_work(dev->wl->hw->workqueue,
- &dev->periodic_work, delay);
+ delay = round_jiffies_relative(HZ * 15);
+ queue_delayed_work(wl->hw->workqueue, &dev->periodic_work, delay);
out:
- mutex_unlock(&dev->wl->mutex);
+ mutex_unlock(&wl->mutex);
}
static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev)
@@ -2366,9 +2295,9 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
return err;
}
-static int b43legacy_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+static int b43legacy_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2392,15 +2321,15 @@ out:
return NETDEV_TX_OK;
}
-static int b43legacy_conf_tx(struct ieee80211_hw *hw,
- int queue,
- const struct ieee80211_tx_queue_params *params)
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ int queue,
+ const struct ieee80211_tx_queue_params *params)
{
return 0;
}
-static int b43legacy_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
+static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2422,8 +2351,8 @@ out:
return err;
}
-static int b43legacy_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
@@ -2572,8 +2501,8 @@ static int b43legacy_antenna_from_ieee80211(u8 antenna)
}
}
-static int b43legacy_dev_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -2634,6 +2563,8 @@ static int b43legacy_dev_config(struct ieee80211_hw *hw,
b43legacy_short_slot_timing_disable(dev);
}
+ dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
if (conf->power_level != phy->power_level) {
@@ -2660,7 +2591,7 @@ static int b43legacy_dev_config(struct ieee80211_hw *hw,
" physically off. Press the"
" button to turn it on.\n");
} else {
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 0);
b43legacyinfo(dev->wl, "Radio turned off by"
" software\n");
}
@@ -2676,37 +2607,11 @@ out_unlock_mutex:
return err;
}
-static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- const u8 *local_addr, const u8 *addr,
- struct ieee80211_key_conf *key)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- unsigned long flags;
- int err = -EOPNOTSUPP;
- DECLARE_MAC_BUF(mac);
-
- if (!dev)
- return -ENODEV;
- mutex_lock(&wl->mutex);
- spin_lock_irqsave(&wl->irq_lock, flags);
-
- if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
- err = -ENODEV;
- }
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- mutex_unlock(&wl->mutex);
- b43legacydbg(wl, "Using software based encryption for "
- "mac: %s\n", print_mac(mac, addr));
- return err;
-}
-
-static void b43legacy_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed,
- unsigned int *fflags,
- int mc_count,
- struct dev_addr_list *mc_list)
+static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed,
+ unsigned int *fflags,
+ int mc_count,
+ struct dev_addr_list *mc_list)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2741,9 +2646,9 @@ static void b43legacy_configure_filter(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
-static int b43legacy_config_interface(struct ieee80211_hw *hw,
- int if_id,
- struct ieee80211_if_conf *conf)
+static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -2753,7 +2658,7 @@ static int b43legacy_config_interface(struct ieee80211_hw *hw,
return -ENODEV;
mutex_lock(&wl->mutex);
spin_lock_irqsave(&wl->irq_lock, flags);
- B43legacy_WARN_ON(wl->if_id != if_id);
+ B43legacy_WARN_ON(wl->vif != vif);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
@@ -2942,8 +2847,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
- /* Flags */
- phy->locked = 0;
/* Assume the radio is enabled. If it's not enabled, the state will
* immediately get fixed on the first periodic work run. */
dev->radio_hw_enable = 1;
@@ -2976,7 +2879,6 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- spin_lock_init(&phy->lock);
phy->interfmode = B43legacy_INTERFMODE_NONE;
phy->channel = 0xFF;
}
@@ -3029,6 +2931,20 @@ static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
+{
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+}
+
/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
@@ -3047,11 +2963,12 @@ static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
cancel_work_sync(&dev->restart_work);
mutex_lock(&wl->mutex);
+ b43legacy_leds_exit(dev);
b43legacy_rng_exit(dev->wl);
b43legacy_pio_free(dev);
b43legacy_dma_free(dev);
b43legacy_chip_exit(dev);
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_switch_analog(dev, 0);
if (phy->dyn_tssi_tbl)
kfree(phy->tssi2dbm);
@@ -3093,7 +3010,6 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
/* Flags */
phy->calibrated = 0;
- phy->locked = 0;
if (phy->_lo_pairs)
memset(phy->_lo_pairs, 0,
@@ -3153,7 +3069,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
hf |= B43legacy_HF_SYMW;
if (phy->rev == 1)
hf |= B43legacy_HF_GDCW;
- if (sprom->r1.boardflags_lo & B43legacy_BFL_PACTRL)
+ if (sprom->boardflags_lo & B43legacy_BFL_PACTRL)
hf |= B43legacy_HF_OFDMPABOOST;
} else if (phy->type == B43legacy_PHYTYPE_B) {
hf |= B43legacy_HF_SYMW;
@@ -3162,16 +3078,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
}
b43legacy_hf_write(dev, hf);
- /* Short/Long Retry Limit.
- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter.
- */
- tmp = limit_value(modparam_short_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0006, tmp);
- tmp = limit_value(modparam_long_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0007, tmp);
+ b43legacy_set_retry_limits(dev,
+ B43legacy_DEFAULT_SHORT_RETRY_LIMIT,
+ B43legacy_DEFAULT_LONG_RETRY_LIMIT);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
0x0044, 3);
@@ -3223,6 +3132,7 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
+ b43legacy_leds_init(dev);
out:
return err;
@@ -3239,8 +3149,8 @@ err_kfree_lo_control:
return err;
}
-static int b43legacy_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
@@ -3263,7 +3173,7 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
dev = wl->current_dev;
wl->operating = 1;
- wl->if_id = conf->if_id;
+ wl->vif = conf->vif;
wl->if_type = conf->type;
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
@@ -3279,8 +3189,8 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
return err;
}
-static void b43legacy_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
@@ -3291,7 +3201,8 @@ static void b43legacy_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(!wl->operating);
- B43legacy_WARN_ON(wl->if_id != conf->if_id);
+ B43legacy_WARN_ON(wl->vif != conf->vif);
+ wl->vif = NULL;
wl->operating = 0;
@@ -3304,13 +3215,17 @@ static void b43legacy_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static int b43legacy_start(struct ieee80211_hw *hw)
+static int b43legacy_op_start(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
int did_init = 0;
int err = 0;
+ /* First register RFkill.
+ * LEDs that are registered later depend on it. */
+ b43legacy_rfkill_init(dev);
+
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
@@ -3335,11 +3250,13 @@ out_mutex_unlock:
return err;
}
-static void b43legacy_stop(struct ieee80211_hw *hw)
+static void b43legacy_op_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
+ b43legacy_rfkill_exit(dev);
+
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
b43legacy_wireless_core_stop(dev);
@@ -3347,20 +3264,41 @@ static void b43legacy_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
+static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry_limit,
+ u32 long_retry_limit)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev ||
+ (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
static const struct ieee80211_ops b43legacy_hw_ops = {
- .tx = b43legacy_tx,
- .conf_tx = b43legacy_conf_tx,
- .add_interface = b43legacy_add_interface,
- .remove_interface = b43legacy_remove_interface,
- .config = b43legacy_dev_config,
- .config_interface = b43legacy_config_interface,
- .set_key = b43legacy_dev_set_key,
- .configure_filter = b43legacy_configure_filter,
- .get_stats = b43legacy_get_stats,
- .get_tx_stats = b43legacy_get_tx_stats,
- .start = b43legacy_start,
- .stop = b43legacy_stop,
+ .tx = b43legacy_op_tx,
+ .conf_tx = b43legacy_op_conf_tx,
+ .add_interface = b43legacy_op_add_interface,
+ .remove_interface = b43legacy_op_remove_interface,
+ .config = b43legacy_op_dev_config,
+ .config_interface = b43legacy_op_config_interface,
+ .configure_filter = b43legacy_op_configure_filter,
+ .get_stats = b43legacy_op_get_stats,
+ .get_tx_stats = b43legacy_op_get_tx_stats,
+ .start = b43legacy_op_start,
+ .stop = b43legacy_op_stop,
+ .set_retry_limit = b43legacy_op_set_retry_limit,
};
/* Hard-reset the chip. Do not call this directly.
@@ -3498,18 +3436,13 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
else
have_bphy = 1;
- /* Initialize LEDs structs. */
- err = b43legacy_leds_init(dev);
- if (err)
- goto err_powerdown;
-
dev->phy.gmode = (have_gphy || have_bphy);
tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
err = b43legacy_phy_versioning(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Check if this device supports multiband. */
if (!pdev ||
(pdev->device != 0x4312 &&
@@ -3535,17 +3468,17 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
err = b43legacy_validate_chipaccess(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
err = b43legacy_setup_modes(dev, have_bphy, have_gphy);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Now set some default "current_dev" */
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43legacy_chip_reset);
- b43legacy_radio_turn_off(dev);
+ b43legacy_radio_turn_off(dev, 1);
b43legacy_switch_analog(dev, 0);
ssb_device_disable(dev->dev, 0);
ssb_bus_may_powerdown(bus);
@@ -3553,8 +3486,6 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
out:
return err;
-err_leds_exit:
- b43legacy_leds_exit(dev);
err_powerdown:
ssb_bus_may_powerdown(bus);
return err;
@@ -3637,12 +3568,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus)
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E &&
bus->boardinfo.rev > 0x40)
- bus->sprom.r1.boardflags_lo |= B43legacy_BFL_PACTRL;
-
- /* Convert Antennagain values to Q5.2 */
- if (bus->sprom.r1.antenna_gain_bg == 0xFF)
- bus->sprom.r1.antenna_gain_bg = 2; /* if unset, use 2 dBm */
- bus->sprom.r1.antenna_gain_bg <<= 2;
+ bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
}
static void b43legacy_wireless_exit(struct ssb_device *dev,
@@ -3677,10 +3603,10 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
hw->max_noise = -110;
hw->queues = 1; /* FIXME: hardware has more queues */
SET_IEEE80211_DEV(hw, dev->dev);
- if (is_valid_ether_addr(sprom->r1.et1mac))
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+ if (is_valid_ether_addr(sprom->et1mac))
+ SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
else
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+ SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
/* Get and initialize struct b43legacy_wl */
wl = hw_to_b43legacy_wl(hw);
diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h
index 68435c50d8e0..1f0e2e379b02 100644
--- a/drivers/net/wireless/b43legacy/main.h
+++ b/drivers/net/wireless/b43legacy/main.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 491e518e4aeb..c16febbdbf5d 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -91,40 +91,36 @@ void b43legacy_voluntary_preempt(void)
#endif /* CONFIG_PREEMPT */
}
-void b43legacy_raw_phy_lock(struct b43legacy_wldev *dev)
+/* Lock the PHY registers against concurrent access from the microcode.
+ * This lock is nonrecursive. */
+void b43legacy_phy_lock(struct b43legacy_wldev *dev)
{
- struct b43legacy_phy *phy = &dev->phy;
+#if B43legacy_DEBUG
+ B43legacy_WARN_ON(dev->phy.phy_locked);
+ dev->phy.phy_locked = 1;
+#endif
- B43legacy_WARN_ON(!irqs_disabled());
- if (b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD) == 0) {
- phy->locked = 0;
- return;
- }
if (dev->dev->id.revision < 3) {
b43legacy_mac_suspend(dev);
- spin_lock(&phy->lock);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, 1);
}
- phy->locked = 1;
}
-void b43legacy_raw_phy_unlock(struct b43legacy_wldev *dev)
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev)
{
- struct b43legacy_phy *phy = &dev->phy;
+#if B43legacy_DEBUG
+ B43legacy_WARN_ON(!dev->phy.phy_locked);
+ dev->phy.phy_locked = 0;
+#endif
- B43legacy_WARN_ON(!irqs_disabled());
if (dev->dev->id.revision < 3) {
- if (phy->locked) {
- spin_unlock(&phy->lock);
- b43legacy_mac_enable(dev);
- }
+ b43legacy_mac_enable(dev);
} else {
if (!b43legacy_is_mode(dev->wl, IEEE80211_IF_TYPE_AP))
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
- phy->locked = 0;
}
u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset)
@@ -441,7 +437,7 @@ static void b43legacy_phy_inita(struct b43legacy_wldev *dev)
might_sleep();
b43legacy_phy_setupg(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL)
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL)
b43legacy_phy_write(dev, 0x046E, 0x03CF);
}
@@ -543,7 +539,7 @@ static void b43legacy_phy_initb4(struct b43legacy_wldev *dev)
if (phy->radio_ver == 0x2050)
b43legacy_phy_write(dev, 0x002A, 0x88C2);
b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
b43legacy_calc_nrssi_slope(dev);
b43legacy_calc_nrssi_threshold(dev);
}
@@ -699,7 +695,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_radio_write16(dev, 0x005A, 0x0088);
b43legacy_radio_write16(dev, 0x005B, 0x006B);
b43legacy_radio_write16(dev, 0x005C, 0x000F);
- if (dev->dev->bus->sprom.r1.boardflags_lo & 0x8000) {
+ if (dev->dev->bus->sprom.boardflags_lo & 0x8000) {
b43legacy_radio_write16(dev, 0x005D, 0x00FA);
b43legacy_radio_write16(dev, 0x005E, 0x00D8);
} else {
@@ -797,7 +793,7 @@ static void b43legacy_phy_initb6(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0062, 0x0007);
b43legacy_radio_init2050(dev);
b43legacy_phy_lo_g_measure(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo &
+ if (dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI) {
b43legacy_calc_nrssi_slope(dev);
b43legacy_calc_nrssi_threshold(dev);
@@ -921,7 +917,7 @@ static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev)
b43legacy_phy_read(dev, 0x0811) | 0x0100);
b43legacy_phy_write(dev, 0x0812,
b43legacy_phy_read(dev, 0x0812) & 0xCFFF);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_EXTLNA) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) {
if (phy->rev >= 7) {
b43legacy_phy_write(dev, 0x0811,
b43legacy_phy_read(dev, 0x0811)
@@ -1072,7 +1068,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0036,
(b43legacy_phy_read(dev, 0x0036)
& 0x0FFF) | (phy->txctl2 << 12));
- if (dev->dev->bus->sprom.r1.boardflags_lo &
+ if (dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_PACTRL)
b43legacy_phy_write(dev, 0x002E, 0x8075);
else
@@ -1087,7 +1083,7 @@ static void b43legacy_phy_initg(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x080F, 0x8078);
}
- if (!(dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI)) {
+ if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) {
/* The specs state to update the NRSSI LT with
* the value 0x7FFFFFFF here. I think that is some weird
* compiler optimization in the original driver.
@@ -1789,7 +1785,6 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
s16 baseband_att_delta;
s16 radio_attenuation;
s16 baseband_attenuation;
- unsigned long phylock_flags;
if (phy->savedpctlreg == 0xFFFF)
return;
@@ -1838,9 +1833,9 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
estimated_pwr = b43legacy_phy_estimate_power_out(dev, average);
- max_pwr = dev->dev->bus->sprom.r1.maxpwr_bg;
+ max_pwr = dev->dev->bus->sprom.maxpwr_bg;
- if ((dev->dev->bus->sprom.r1.boardflags_lo
+ if ((dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_PACTRL) &&
(phy->type == B43legacy_PHYTYPE_G))
max_pwr -= 0x3;
@@ -1848,7 +1843,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM."
"\n");
max_pwr = 74; /* fake it */
- dev->dev->bus->sprom.r1.maxpwr_bg = max_pwr;
+ dev->dev->bus->sprom.maxpwr_bg = max_pwr;
}
/* Use regulatory information to get the maximum power.
@@ -1858,7 +1853,8 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
* and 1.5 dBm (a safety factor??). The result is in Q5.2 format
* which accounts for the factor of 4 */
#define REG_MAX_PWR 20
- max_pwr = min(REG_MAX_PWR * 4 - dev->dev->bus->sprom.r1.antenna_gain_bg
+ max_pwr = min(REG_MAX_PWR * 4
+ - dev->dev->bus->sprom.antenna_gain.ghz24.a0
- 0x6, max_pwr);
/* find the desired power in Q5.2 - power_level is in dBm
@@ -1918,7 +1914,7 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
txpower = 3;
radio_attenuation += 2;
baseband_attenuation += 2;
- } else if (dev->dev->bus->sprom.r1.boardflags_lo
+ } else if (dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_PACTRL) {
baseband_attenuation += 4 *
(radio_attenuation - 2);
@@ -1943,13 +1939,13 @@ void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev)
phy->bbatt = baseband_attenuation;
/* Adjust the hardware */
- b43legacy_phy_lock(dev, phylock_flags);
+ b43legacy_phy_lock(dev);
b43legacy_radio_lock(dev);
b43legacy_radio_set_txpower_bg(dev, baseband_attenuation,
radio_attenuation, txpower);
b43legacy_phy_lo_mark_current_used(dev);
b43legacy_radio_unlock(dev);
- b43legacy_phy_unlock(dev, phylock_flags);
+ b43legacy_phy_unlock(dev);
}
static inline
@@ -2000,9 +1996,9 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B ||
phy->type == B43legacy_PHYTYPE_G));
- pab0 = (s16)(dev->dev->bus->sprom.r1.pa0b0);
- pab1 = (s16)(dev->dev->bus->sprom.r1.pa0b1);
- pab2 = (s16)(dev->dev->bus->sprom.r1.pa0b2);
+ pab0 = (s16)(dev->dev->bus->sprom.pa0b0);
+ pab1 = (s16)(dev->dev->bus->sprom.pa0b1);
+ pab2 = (s16)(dev->dev->bus->sprom.pa0b2);
if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) {
phy->idle_tssi = 0x34;
@@ -2013,9 +2009,10 @@ int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev)
if (pab0 != 0 && pab1 != 0 && pab2 != 0 &&
pab0 != -1 && pab1 != -1 && pab2 != -1) {
/* The pabX values are set in SPROM. Use them. */
- if ((s8)dev->dev->bus->sprom.r1.itssi_bg != 0 &&
- (s8)dev->dev->bus->sprom.r1.itssi_bg != -1)
- phy->idle_tssi = (s8)(dev->dev->bus->sprom.r1.itssi_bg);
+ if ((s8)dev->dev->bus->sprom.itssi_bg != 0 &&
+ (s8)dev->dev->bus->sprom.itssi_bg != -1)
+ phy->idle_tssi = (s8)(dev->dev->bus->sprom.
+ itssi_bg);
else
phy->idle_tssi = 62;
dyn_tssi2dbm = kmalloc(64, GFP_KERNEL);
diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h
index f11b4271714c..ecbe409f9a94 100644
--- a/drivers/net/wireless/b43legacy/phy.h
+++ b/drivers/net/wireless/b43legacy/phy.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -171,18 +171,8 @@ void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt);
struct b43legacy_wldev;
-void b43legacy_raw_phy_lock(struct b43legacy_wldev *dev);
-#define b43legacy_phy_lock(bcm, flags) \
- do { \
- local_irq_save(flags); \
- b43legacy_raw_phy_lock(bcm); \
- } while (0)
-void b43legacy_raw_phy_unlock(struct b43legacy_wldev *dev);
-#define b43legacy_phy_unlock(bcm, flags) \
- do { \
- b43legacy_raw_phy_unlock(bcm); \
- local_irq_restore(flags); \
- } while (0)
+void b43legacy_phy_lock(struct b43legacy_wldev *dev);
+void b43legacy_phy_unlock(struct b43legacy_wldev *dev);
/* Card uses the loopback gain stuff */
#define has_loopback_gain(phy) \
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c
index a361dee664af..318a270cf9b4 100644
--- a/drivers/net/wireless/b43legacy/radio.c
+++ b/drivers/net/wireless/b43legacy/radio.c
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -92,6 +92,7 @@ void b43legacy_radio_lock(struct b43legacy_wldev *dev)
u32 status;
status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ B43legacy_WARN_ON(status & B43legacy_SBF_RADIOREG_LOCK);
status |= B43legacy_SBF_RADIOREG_LOCK;
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
mmiowb();
@@ -104,6 +105,7 @@ void b43legacy_radio_unlock(struct b43legacy_wldev *dev)
b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */
status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ B43legacy_WARN_ON(!(status & B43legacy_SBF_RADIOREG_LOCK));
status &= ~B43legacy_SBF_RADIOREG_LOCK;
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
mmiowb();
@@ -284,12 +286,11 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
unsigned int j;
unsigned int start;
unsigned int end;
- unsigned long phylock_flags;
if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0)))
return 0;
- b43legacy_phy_lock(dev, phylock_flags);
+ b43legacy_phy_lock(dev);
b43legacy_radio_lock(dev);
b43legacy_phy_write(dev, 0x0802,
b43legacy_phy_read(dev, 0x0802) & 0xFFFC);
@@ -323,7 +324,7 @@ u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev)
ret[j] = 1;
}
b43legacy_radio_unlock(dev);
- b43legacy_phy_unlock(dev, phylock_flags);
+ b43legacy_phy_unlock(dev);
return ret[channel - 1];
}
@@ -827,7 +828,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
case B43legacy_PHYTYPE_B: {
if (phy->radio_ver != 0x2050)
return;
- if (!(dev->dev->bus->sprom.r1.boardflags_lo &
+ if (!(dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI))
return;
@@ -857,7 +858,7 @@ void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev)
}
case B43legacy_PHYTYPE_G:
if (!phy->gmode ||
- !(dev->dev->bus->sprom.r1.boardflags_lo &
+ !(dev->dev->bus->sprom.boardflags_lo &
B43legacy_BFL_RSSI)) {
tmp16 = b43legacy_nrssi_hw_read(dev, 0x20);
if (tmp16 >= 0x20)
@@ -1406,7 +1407,7 @@ static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
if (!phy->gmode)
return 0;
if (!has_loopback_gain(phy)) {
- if (phy->rev < 7 || !(dev->dev->bus->sprom.r1.boardflags_lo
+ if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA)) {
switch (lpd) {
case LPD(0, 1, 1):
@@ -1459,7 +1460,7 @@ static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd)
}
loop_or = (loop << 8) | extern_lna_control;
- if (phy->rev >= 7 && dev->dev->bus->sprom.r1.boardflags_lo
+ if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA) {
if (extern_lna_control)
loop_or |= 0x8000;
@@ -1550,7 +1551,7 @@ u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev)
b43legacy_get_812_value(dev,
LPD(0, 1, 1)));
if (phy->rev < 7 ||
- !(dev->dev->bus->sprom.r1.boardflags_lo
+ !(dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_EXTLNA))
b43legacy_phy_write(dev, 0x0811, 0x01B3);
else
@@ -1786,7 +1787,7 @@ int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
channel2freq_bg(channel));
if (channel == 14) {
- if (dev->dev->bus->sprom.r1.country_code == 5) /* JAPAN) */
+ if (dev->dev->bus->sprom.country_code == 5) /* JAPAN) */
b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
B43legacy_UCODEFLAGS_OFFSET,
b43legacy_shm_read32(dev,
@@ -2113,21 +2114,25 @@ void b43legacy_radio_turn_on(struct b43legacy_wldev *dev)
B43legacy_BUG_ON(1);
}
phy->radio_on = 1;
- b43legacy_leds_update(dev, 0);
}
-void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force)
{
struct b43legacy_phy *phy = &dev->phy;
+ if (!phy->radio_on && !force)
+ return;
+
if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) {
u16 rfover, rfoverval;
rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER);
rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL);
- phy->radio_off_context.rfover = rfover;
- phy->radio_off_context.rfoverval = rfoverval;
- phy->radio_off_context.valid = 1;
+ if (!force) {
+ phy->radio_off_context.rfover = rfover;
+ phy->radio_off_context.rfoverval = rfoverval;
+ phy->radio_off_context.valid = 1;
+ }
b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C);
b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL,
rfoverval & 0xFF73);
@@ -2135,7 +2140,6 @@ void b43legacy_radio_turn_off(struct b43legacy_wldev *dev)
b43legacy_phy_write(dev, 0x0015, 0xAA00);
phy->radio_on = 0;
b43legacydbg(dev->wl, "Radio initialized\n");
- b43legacy_leds_update(dev, 0);
}
void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev)
diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h
index 6c6a203439e1..ec4de2811c52 100644
--- a/drivers/net/wireless/b43legacy/radio.h
+++ b/drivers/net/wireless/b43legacy/radio.h
@@ -3,7 +3,7 @@
Broadcom B43legacy wireless driver
Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
- Stefano Brivio <st3@riseup.net>
+ Stefano Brivio <stefano.brivio@polimi.it>
Michael Buesch <mbuesch@freenet.de>
Danny van Dyk <kugelfang@gentoo.org>
Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -61,7 +61,7 @@ void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val);
u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev);
void b43legacy_radio_turn_on(struct b43legacy_wldev *dev);
-void b43legacy_radio_turn_off(struct b43legacy_wldev *dev);
+void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force);
int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, u8 channel,
int synthetic_pu_workaround);
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
new file mode 100644
index 000000000000..d178dfbb1c9f
--- /dev/null
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -0,0 +1,205 @@
+/*
+
+ Broadcom B43 wireless driver
+ RFKILL support
+
+ Copyright (c) 2007 Michael Buesch <mb@bu3sch.de>
+
+ 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; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*/
+
+#include "rfkill.h"
+#include "radio.h"
+#include "b43legacy.h"
+
+#include <linux/kmod.h>
+
+
+/* Returns TRUE, if the radio is enabled in hardware. */
+static bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
+{
+ if (dev->phy.rev >= 3) {
+ if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
+ & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
+ return 1;
+ } else {
+ if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
+ & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
+ return 1;
+ }
+ return 0;
+}
+
+/* The poll callback for the hardware button. */
+static void b43legacy_rfkill_poll(struct input_polled_dev *poll_dev)
+{
+ struct b43legacy_wldev *dev = poll_dev->private;
+ struct b43legacy_wl *wl = dev->wl;
+ bool enabled;
+ bool report_change = 0;
+
+ mutex_lock(&wl->mutex);
+ if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+ enabled = b43legacy_is_hw_radio_enabled(dev);
+ if (unlikely(enabled != dev->radio_hw_enable)) {
+ dev->radio_hw_enable = enabled;
+ report_change = 1;
+ b43legacyinfo(wl, "Radio hardware status changed to %s\n",
+ enabled ? "ENABLED" : "DISABLED");
+ }
+ mutex_unlock(&wl->mutex);
+
+ /* send the radio switch event to the system - note both a key press
+ * and a release are required */
+ if (unlikely(report_change)) {
+ input_report_key(poll_dev->input, KEY_WLAN, 1);
+ input_report_key(poll_dev->input, KEY_WLAN, 0);
+ }
+}
+
+/* Called when the RFKILL toggled in software.
+ * This is called without locking. */
+static int b43legacy_rfkill_soft_toggle(void *data, enum rfkill_state state)
+{
+ struct b43legacy_wldev *dev = data;
+ struct b43legacy_wl *wl = dev->wl;
+ int err = -EBUSY;
+
+ if (!wl->rfkill.registered)
+ return 0;
+
+ mutex_lock(&wl->mutex);
+ if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)
+ goto out_unlock;
+ err = 0;
+ switch (state) {
+ case RFKILL_STATE_ON:
+ if (!dev->radio_hw_enable) {
+ /* No luck. We can't toggle the hardware RF-kill
+ * button from software. */
+ err = -EBUSY;
+ goto out_unlock;
+ }
+ if (!dev->phy.radio_on)
+ b43legacy_radio_turn_on(dev);
+ break;
+ case RFKILL_STATE_OFF:
+ if (dev->phy.radio_on)
+ b43legacy_radio_turn_off(dev, 0);
+ break;
+ }
+
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
+
+char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!rfk->registered)
+ return NULL;
+ return rfkill_get_led_name(rfk->rfkill);
+}
+
+void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_wl *wl = dev->wl;
+ struct b43legacy_rfkill *rfk = &(wl->rfkill);
+ int err;
+
+ rfk->registered = 0;
+
+ rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN);
+ if (!rfk->rfkill)
+ goto out_error;
+ snprintf(rfk->name, sizeof(rfk->name),
+ "b43legacy-%s", wiphy_name(wl->hw->wiphy));
+ rfk->rfkill->name = rfk->name;
+ rfk->rfkill->state = RFKILL_STATE_ON;
+ rfk->rfkill->data = dev;
+ rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
+ rfk->rfkill->user_claim_unsupported = 1;
+
+ rfk->poll_dev = input_allocate_polled_device();
+ if (!rfk->poll_dev) {
+ rfkill_free(rfk->rfkill);
+ goto err_freed_rfk;
+ }
+
+ rfk->poll_dev->private = dev;
+ rfk->poll_dev->poll = b43legacy_rfkill_poll;
+ rfk->poll_dev->poll_interval = 1000; /* msecs */
+
+ rfk->poll_dev->input->name = rfk->name;
+ rfk->poll_dev->input->id.bustype = BUS_HOST;
+ rfk->poll_dev->input->id.vendor = dev->dev->bus->boardinfo.vendor;
+ rfk->poll_dev->input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, rfk->poll_dev->input->keybit);
+
+ err = rfkill_register(rfk->rfkill);
+ if (err)
+ goto err_free_polldev;
+
+#ifdef CONFIG_RFKILL_INPUT_MODULE
+ /* B43legacy RF-kill isn't useful without the rfkill-input subsystem.
+ * Try to load the module. */
+ err = request_module("rfkill-input");
+ if (err)
+ b43legacywarn(wl, "Failed to load the rfkill-input module."
+ "The built-in radio LED will not work.\n");
+#endif /* CONFIG_RFKILL_INPUT */
+
+ err = input_register_polled_device(rfk->poll_dev);
+ if (err)
+ goto err_unreg_rfk;
+
+ rfk->registered = 1;
+
+ return;
+err_unreg_rfk:
+ rfkill_unregister(rfk->rfkill);
+err_free_polldev:
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+err_freed_rfk:
+ rfk->rfkill = NULL;
+out_error:
+ rfk->registered = 0;
+ b43legacywarn(wl, "RF-kill button init failed\n");
+}
+
+void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
+{
+ struct b43legacy_rfkill *rfk = &(dev->wl->rfkill);
+
+ if (!rfk->registered)
+ return;
+ rfk->registered = 0;
+
+ input_unregister_polled_device(rfk->poll_dev);
+ rfkill_unregister(rfk->rfkill);
+ input_free_polled_device(rfk->poll_dev);
+ rfk->poll_dev = NULL;
+ rfk->rfkill = NULL;
+}
+
diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h
new file mode 100644
index 000000000000..11150a8032f0
--- /dev/null
+++ b/drivers/net/wireless/b43legacy/rfkill.h
@@ -0,0 +1,59 @@
+#ifndef B43legacy_RFKILL_H_
+#define B43legacy_RFKILL_H_
+
+struct b43legacy_wldev;
+
+#ifdef CONFIG_B43LEGACY_RFKILL
+
+#include <linux/rfkill.h>
+#include <linux/workqueue.h>
+#include <linux/input-polldev.h>
+
+
+
+struct b43legacy_rfkill {
+ /* The RFKILL subsystem data structure */
+ struct rfkill *rfkill;
+ /* The poll device for the RFKILL input button */
+ struct input_polled_dev *poll_dev;
+ /* Did initialization succeed? Used for freeing. */
+ bool registered;
+ /* The unique name of this rfkill switch */
+ char name[sizeof("b43legacy-phy4294967295")];
+};
+
+/* The init function returns void, because we are not interested
+ * in failing the b43 init process when rfkill init failed. */
+void b43legacy_rfkill_init(struct b43legacy_wldev *dev);
+void b43legacy_rfkill_exit(struct b43legacy_wldev *dev);
+
+char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev);
+
+
+#else /* CONFIG_B43LEGACY_RFKILL */
+/* No RFKILL support. */
+
+struct b43legacy_rfkill {
+ /* empty */
+};
+
+static inline void b43legacy_rfkill_alloc(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_free(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
+{
+}
+static inline void b43legacy_rfkill_exit(struct b43legacy_wldev *dev)
+{
+}
+static inline char *b43legacy_rfkill_led_name(struct b43legacy_wldev *dev)
+{
+ return NULL;
+}
+
+#endif /* CONFIG_B43LEGACY_RFKILL */
+
+#endif /* B43legacy_RFKILL_H_ */
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index fa1e65687a63..e20c552442d5 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -5,7 +5,7 @@
Transmission (TX/RX) related functions.
Copyright (C) 2005 Martin Langer <martin-langer@gmx.de>
- Copyright (C) 2005 Stefano Brivio <st3@riseup.net>
+ Copyright (C) 2005 Stefano Brivio <stefano.brivio@polimi.it>
Copyright (C) 2005, 2006 Michael Buesch <mb@bu3sch.de>
Copyright (C) 2005 Danny van Dyk <kugelfang@gentoo.org>
Copyright (C) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
@@ -223,7 +223,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
} else {
int fbrate_base100kbps = B43legacy_RATE_TO_100KBPS(rate_fb);
txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_len,
fbrate_base100kbps);
}
@@ -290,6 +290,8 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
mac_ctl |= B43legacy_TX4_MAC_STMSDU;
if (rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
+ if (txctl->flags & IEEE80211_TXCTL_LONG_RETRY_LIMIT)
+ mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
/* Generate the RTS or CTS-to-self frame */
if ((txctl->flags & IEEE80211_TXCTL_USE_RTS_CTS) ||
@@ -310,7 +312,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
if (txctl->flags & IEEE80211_TXCTL_USE_CTS_PROTECT) {
ieee80211_ctstoself_get(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_data,
fragment_len, txctl,
(struct ieee80211_cts *)
@@ -319,7 +321,7 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
len = sizeof(struct ieee80211_cts);
} else {
ieee80211_rts_get(dev->wl->hw,
- dev->wl->if_id,
+ txctl->vif,
fragment_data, fragment_len, txctl,
(struct ieee80211_rts *)
(txhdr->rts_frame));
@@ -335,7 +337,6 @@ static void generate_txhdr_fw3(struct b43legacy_wldev *dev,
len, rts_rate_fb);
hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame);
txhdr->rts_dur_fb = hdr->duration_id;
- mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
}
/* Magic cookie */
@@ -378,7 +379,7 @@ static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev,
else
tmp -= 3;
} else {
- if (dev->dev->bus->sprom.r1.boardflags_lo
+ if (dev->dev->bus->sprom.boardflags_lo
& B43legacy_BFL_RSSI) {
if (in_rssi > 63)
in_rssi = 63;
@@ -531,7 +532,24 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
else
status.rate = b43legacy_plcp_get_bitrate_cck(plcp);
status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT);
- status.mactime = mactime;
+
+ /*
+ * If monitors are present get full 64-bit timestamp. This
+ * code assumes we get to process the packet within 16 bits
+ * of timestamp, i.e. about 65 milliseconds after the PHY
+ * received the first symbol.
+ */
+ if (dev->wl->radiotap_enabled) {
+ u16 low_mactime_now;
+
+ b43legacy_tsf_read(dev, &status.mactime);
+ low_mactime_now = status.mactime;
+ status.mactime = status.mactime & ~0xFFFFULL;
+ status.mactime += mactime;
+ if (low_mactime_now <= mactime)
+ status.mactime -= 0x10000;
+ status.flag |= RX_FLAG_TSFT;
+ }
chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
B43legacy_RX_CHAN_ID_SHIFT;
diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig
index ce397e4284f4..0159701e8456 100644
--- a/drivers/net/wireless/bcm43xx/Kconfig
+++ b/drivers/net/wireless/bcm43xx/Kconfig
@@ -1,12 +1,15 @@
config BCM43XX
- tristate "Broadcom BCM43xx wireless support"
+ tristate "Broadcom BCM43xx wireless support (DEPRECATED)"
depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && EXPERIMENTAL
select WIRELESS_EXT
select FW_LOADER
select HW_RANDOM
---help---
- This is an experimental driver for the Broadcom 43xx wireless chip,
- found in the Apple Airport Extreme and various other devices.
+ This is an experimental driver for the Broadcom 43xx wireless
+ chip, found in the Apple Airport Extreme and various other
+ devices. This driver is deprecated and will be removed
+ from the kernel in the near future. It has been replaced
+ by the b43 and b43legacy drivers.
config BCM43XX_DEBUG
bool "Broadcom BCM43xx debugging (RECOMMENDED)"
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h
index 5fdbf24d2443..2ebd2edf5862 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx.h
+++ b/drivers/net/wireless/bcm43xx/bcm43xx.h
@@ -481,9 +481,9 @@ struct bcm43xx_dmaring;
struct bcm43xx_pioqueue;
struct bcm43xx_initval {
- u16 offset;
- u16 size;
- u32 value;
+ __be16 offset;
+ __be16 size;
+ __be32 value;
} __attribute__((__packed__));
/* Values for bcm430x_sprominfo.locale */
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
index 45683437a98d..b96a325b6ec8 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c
@@ -793,27 +793,27 @@ static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm)
/* il0macaddr */
value = sprom[BCM43xx_SPROM_IL0MACADDR + 0];
- *(((u16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_IL0MACADDR + 1];
- *(((u16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_IL0MACADDR + 2];
- *(((u16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value);
/* et0macaddr */
value = sprom[BCM43xx_SPROM_ET0MACADDR + 0];
- *(((u16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_ET0MACADDR + 1];
- *(((u16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_ET0MACADDR + 2];
- *(((u16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value);
/* et1macaddr */
value = sprom[BCM43xx_SPROM_ET1MACADDR + 0];
- *(((u16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_ET1MACADDR + 1];
- *(((u16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value);
value = sprom[BCM43xx_SPROM_ET1MACADDR + 2];
- *(((u16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
+ *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value);
/* ethernet phy settings */
value = sprom[BCM43xx_SPROM_ETHPHY];
@@ -1059,7 +1059,7 @@ void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm)
}
static void key_write(struct bcm43xx_private *bcm,
- u8 index, u8 algorithm, const u16 *key)
+ u8 index, u8 algorithm, const __le16 *key)
{
unsigned int i, basic_wep = 0;
u32 offset;
@@ -1077,7 +1077,7 @@ static void key_write(struct bcm43xx_private *bcm,
/* Write key payload, 8 little endian words */
offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE);
for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) {
- value = cpu_to_le16(key[i]);
+ value = le16_to_cpu(key[i]);
bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED,
offset + (i * 2), value);
@@ -1091,7 +1091,7 @@ static void key_write(struct bcm43xx_private *bcm,
}
static void keymac_write(struct bcm43xx_private *bcm,
- u8 index, const u32 *addr)
+ u8 index, const __be32 *addr)
{
/* for keys 0-3 there is no associated mac address */
if (index < 4)
@@ -1102,11 +1102,11 @@ static void keymac_write(struct bcm43xx_private *bcm,
bcm43xx_shm_write32(bcm,
BCM43xx_SHM_HWMAC,
index * 2,
- cpu_to_be32(*addr));
+ be32_to_cpu(*addr));
bcm43xx_shm_write16(bcm,
BCM43xx_SHM_HWMAC,
(index * 2) + 1,
- cpu_to_be16(*((u16 *)(addr + 1))));
+ be16_to_cpu(*((__be16 *)(addr + 1))));
} else {
if (index < 8) {
TODO(); /* Put them in the macaddress filter */
@@ -1133,8 +1133,8 @@ static int bcm43xx_key_write(struct bcm43xx_private *bcm,
return -EINVAL;
memcpy(key, _key, key_len);
- key_write(bcm, index, algorithm, (const u16 *)key);
- keymac_write(bcm, index, (const u32 *)mac_addr);
+ key_write(bcm, index, algorithm, (const __le16 *)key);
+ keymac_write(bcm, index, (const __be32 *)mac_addr);
bcm->key[index].algorithm = algorithm;
@@ -1143,7 +1143,7 @@ static int bcm43xx_key_write(struct bcm43xx_private *bcm,
static void bcm43xx_clear_keys(struct bcm43xx_private *bcm)
{
- static const u32 zero_mac[2] = { 0 };
+ static const __be32 zero_mac[2] = { 0 };
unsigned int i,j, nr_keys = 54;
u16 offset;
@@ -2011,11 +2011,11 @@ err_noinitval:
static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
{
struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm);
- const u32 *data;
+ const __be32 *data;
unsigned int i, len;
/* Upload Microcode. */
- data = (u32 *)(phy->ucode->data);
+ data = (__be32 *)(phy->ucode->data);
len = phy->ucode->size / sizeof(u32);
bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000);
for (i = 0; i < len; i++) {
@@ -2025,7 +2025,7 @@ static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm)
}
/* Upload PCM data. */
- data = (u32 *)(phy->pcm->data);
+ data = (__be32 *)(phy->pcm->data);
len = phy->pcm->size / sizeof(u32);
bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea);
bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
index c60c1743ea06..76ab109cd2db 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c
@@ -68,7 +68,7 @@ static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr,
source = packet;
i -= sizeof(*txhdr);
}
- ret = le16_to_cpu( *((u16 *)(source + i)) );
+ ret = le16_to_cpu( *((__le16 *)(source + i)) );
*pos += 2;
return ret;
@@ -526,7 +526,7 @@ static void pio_rx_error(struct bcm43xx_pioqueue *queue,
void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue)
{
- u16 preamble[21] = { 0 };
+ __le16 preamble[21] = { 0 };
struct bcm43xx_rxhdr *rxhdr;
u16 tmp, len, rxflags2;
int i, preamble_readwords;
@@ -601,7 +601,7 @@ data_ready:
skb_put(skb, len);
for (i = 0; i < len - 1; i += 2) {
tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
- *((u16 *)(skb->data + i)) = cpu_to_le16(tmp);
+ *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp);
}
if (len % 2) {
tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA);
diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
index 3e2462671690..f79fe11f9e81 100644
--- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
+++ b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c
@@ -122,10 +122,10 @@ static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp,
__u8 *raw = plcp->raw;
if (ofdm_modulation) {
- *data = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
+ u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate);
assert(!(octets & 0xF000));
- *data |= (octets << 5);
- *data = cpu_to_le32(*data);
+ val |= (octets << 5);
+ *data = cpu_to_le32(val);
} else {
u32 plen;
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index cc1ee7f4f5f8..d6b9362a3d5c 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -5,52 +5,52 @@
#include <net/ieee80211_crypt.h>
struct hostap_ieee80211_mgmt {
- u16 frame_control;
- u16 duration;
+ __le16 frame_control;
+ __le16 duration;
u8 da[6];
u8 sa[6];
u8 bssid[6];
- u16 seq_ctrl;
+ __le16 seq_ctrl;
union {
struct {
- u16 auth_alg;
- u16 auth_transaction;
- u16 status_code;
+ __le16 auth_alg;
+ __le16 auth_transaction;
+ __le16 status_code;
/* possibly followed by Challenge text */
u8 variable[0];
} __attribute__ ((packed)) auth;
struct {
- u16 reason_code;
+ __le16 reason_code;
} __attribute__ ((packed)) deauth;
struct {
- u16 capab_info;
- u16 listen_interval;
+ __le16 capab_info;
+ __le16 listen_interval;
/* followed by SSID and Supported rates */
u8 variable[0];
} __attribute__ ((packed)) assoc_req;
struct {
- u16 capab_info;
- u16 status_code;
- u16 aid;
+ __le16 capab_info;
+ __le16 status_code;
+ __le16 aid;
/* followed by Supported rates */
u8 variable[0];
} __attribute__ ((packed)) assoc_resp, reassoc_resp;
struct {
- u16 capab_info;
- u16 listen_interval;
+ __le16 capab_info;
+ __le16 listen_interval;
u8 current_ap[6];
/* followed by SSID and Supported rates */
u8 variable[0];
} __attribute__ ((packed)) reassoc_req;
struct {
- u16 reason_code;
+ __le16 reason_code;
} __attribute__ ((packed)) disassoc;
struct {
} __attribute__ ((packed)) probe_req;
struct {
u8 timestamp[8];
- u16 beacon_int;
- u16 capab_info;
+ __le16 beacon_int;
+ __le16 capab_info;
/* followed by some of SSID, Supported rates,
* FH Params, DS Params, CF Params, IBSS Params, TIM */
u8 variable[0];
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index ef084df3d48e..49978bdb4324 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1039,7 +1039,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
} else {
- u16 len;
+ __be16 len;
/* Leave Ethernet header part of hdr and full payload */
skb_pull(skb, hdrlen);
len = htons(skb->len);
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index 6bbdb76b32df..ad040a3bb8a7 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -258,7 +258,7 @@ static void ap_handle_timer(unsigned long data)
sta->addr, ap->tx_callback_poll);
} else {
int deauth = sta->timeout_next == STA_DEAUTH;
- u16 resp;
+ __le16 resp;
PDEBUG(DEBUG_AP, "%s: sending %s info to STA %s"
"(last=%lu, jiffies=%lu)\n",
local->dev->name,
@@ -300,13 +300,13 @@ void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap,
int resend)
{
u8 addr[ETH_ALEN];
- u16 resp;
+ __le16 resp;
int i;
PDEBUG(DEBUG_AP, "%s: Deauthenticate all stations\n", dev->name);
memset(addr, 0xff, ETH_ALEN);
- resp = __constant_cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
+ resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID);
/* deauth message sent; try to resend it few times; the message is
* broadcast, so it may be delayed until next DTIM; there is not much
@@ -462,7 +462,7 @@ void ap_control_flush_macs(struct mac_restrictions *mac_restrictions)
int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac)
{
struct sta_info *sta;
- u16 resp;
+ __le16 resp;
spin_lock_bh(&ap->sta_table_lock);
sta = ap_get_sta(ap, mac);
@@ -628,7 +628,8 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
struct ieee80211_hdr_4addr *hdr;
- u16 fc, *pos, auth_alg, auth_transaction, status;
+ u16 fc, auth_alg, auth_transaction, status;
+ __le16 *pos;
struct sta_info *sta = NULL;
char *txt = NULL;
DECLARE_MAC_BUF(mac);
@@ -649,7 +650,7 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
return;
}
- pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
auth_alg = le16_to_cpu(*pos++);
auth_transaction = le16_to_cpu(*pos++);
status = le16_to_cpu(*pos++);
@@ -698,7 +699,8 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
struct ap_data *ap = data;
struct net_device *dev = ap->local->dev;
struct ieee80211_hdr_4addr *hdr;
- u16 fc, *pos, status;
+ u16 fc, status;
+ __le16 *pos;
struct sta_info *sta = NULL;
char *txt = NULL;
DECLARE_MAC_BUF(mac);
@@ -736,7 +738,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
goto done;
}
- pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
pos++;
status = le16_to_cpu(*pos++);
if (status == WLAN_STATUS_SUCCESS) {
@@ -1298,7 +1300,8 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
struct ap_data *ap = local->ap;
char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL;
int len, olen;
- u16 auth_alg, auth_transaction, status_code, *pos;
+ u16 auth_alg, auth_transaction, status_code;
+ __le16 *pos;
u16 resp = WLAN_STATUS_SUCCESS, fc;
struct sta_info *sta = NULL;
struct ieee80211_crypt_data *crypt;
@@ -1332,7 +1335,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
crypt = local->crypt[idx];
}
- pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
auth_alg = __le16_to_cpu(*pos);
pos++;
auth_transaction = __le16_to_cpu(*pos);
@@ -1465,7 +1468,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
}
fail:
- pos = (u16 *) body;
+ pos = (__le16 *) body;
*pos = cpu_to_le16(auth_alg);
pos++;
*pos = cpu_to_le16(auth_transaction + 1);
@@ -1510,7 +1513,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char body[12], *p, *lpos;
int len, left;
- u16 *pos;
+ __le16 *pos;
u16 resp = WLAN_STATUS_SUCCESS;
struct sta_info *sta = NULL;
int send_deauth = 0;
@@ -1540,7 +1543,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
atomic_inc(&sta->users);
spin_unlock_bh(&local->ap->sta_table_lock);
- pos = (u16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
+ pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
sta->capability = __le16_to_cpu(*pos);
pos++; left -= 2;
sta->listen_interval = __le16_to_cpu(*pos);
@@ -1636,25 +1639,24 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
}
fail:
- pos = (u16 *) body;
+ pos = (__le16 *) body;
if (send_deauth) {
- *pos = __constant_cpu_to_le16(
- WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
+ *pos = cpu_to_le16(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH);
pos++;
} else {
/* FIX: CF-Pollable and CF-PollReq should be set to match the
* values in beacons/probe responses */
/* FIX: how about privacy and WEP? */
/* capability */
- *pos = __constant_cpu_to_le16(WLAN_CAPABILITY_ESS);
+ *pos = cpu_to_le16(WLAN_CAPABILITY_ESS);
pos++;
/* status_code */
- *pos = __cpu_to_le16(resp);
+ *pos = cpu_to_le16(resp);
pos++;
- *pos = __cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) |
+ *pos = cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) |
BIT(14) | BIT(15)); /* AID */
pos++;
@@ -1681,7 +1683,7 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
0x96 : 0x16;
(*lpos)++;
}
- pos = (u16 *) p;
+ pos = (__le16 *) p;
}
prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
@@ -1718,7 +1720,8 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN);
int len;
- u16 reason_code, *pos;
+ u16 reason_code;
+ __le16 *pos;
struct sta_info *sta = NULL;
DECLARE_MAC_BUF(mac);
@@ -1729,8 +1732,8 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
return;
}
- pos = (u16 *) body;
- reason_code = __le16_to_cpu(*pos);
+ pos = (__le16 *) body;
+ reason_code = le16_to_cpu(*pos);
PDEBUG(DEBUG_AP, "%s: deauthentication: %s len=%d, "
"reason_code=%d\n", dev->name, print_mac(mac, hdr->addr2), len,
@@ -1760,7 +1763,8 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len;
- u16 reason_code, *pos;
+ u16 reason_code;
+ __le16 *pos;
struct sta_info *sta = NULL;
DECLARE_MAC_BUF(mac);
@@ -1771,8 +1775,8 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
return;
}
- pos = (u16 *) body;
- reason_code = __le16_to_cpu(*pos);
+ pos = (__le16 *) body;
+ reason_code = le16_to_cpu(*pos);
PDEBUG(DEBUG_AP, "%s: disassociation: %s len=%d, "
"reason_code=%d\n", dev->name, print_mac(mac, hdr->addr2), len,
@@ -1817,7 +1821,7 @@ static void ap_handle_dropped_data(local_info_t *local,
{
struct net_device *dev = local->dev;
struct sta_info *sta;
- u16 reason;
+ __le16 reason;
spin_lock_bh(&local->ap->sta_table_lock);
sta = ap_get_sta(local->ap, hdr->addr2);
@@ -1831,8 +1835,7 @@ static void ap_handle_dropped_data(local_info_t *local,
return;
}
- reason = __constant_cpu_to_le16(
- WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+ reason = cpu_to_le16(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT |
((sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) ?
IEEE80211_STYPE_DEAUTH : IEEE80211_STYPE_DISASSOC),
@@ -1892,7 +1895,7 @@ static void handle_pspoll(local_info_t *local,
return;
}
- aid = __le16_to_cpu(hdr->duration_id);
+ aid = le16_to_cpu(hdr->duration_id);
if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) {
PDEBUG(DEBUG_PS, " PSPOLL and AID[15:14] not set\n");
return;
@@ -1998,7 +2001,8 @@ static void handle_beacon(local_info_t *local, struct sk_buff *skb,
struct ieee80211_hdr_4addr *hdr = (struct ieee80211_hdr_4addr *) skb->data;
char *body = skb->data + IEEE80211_MGMT_HDR_LEN;
int len, left;
- u16 *pos, beacon_int, capability;
+ u16 beacon_int, capability;
+ __le16 *pos;
char *ssid = NULL;
unsigned char *supp_rates = NULL;
int ssid_len = 0, supp_rates_len = 0;
@@ -2013,16 +2017,16 @@ static void handle_beacon(local_info_t *local, struct sk_buff *skb,
return;
}
- pos = (u16 *) body;
+ pos = (__le16 *) body;
left = len;
/* Timestamp (8 octets) */
pos += 4; left -= 8;
/* Beacon interval (2 octets) */
- beacon_int = __le16_to_cpu(*pos);
+ beacon_int = le16_to_cpu(*pos);
pos++; left -= 2;
/* Capability information (2 octets) */
- capability = __le16_to_cpu(*pos);
+ capability = le16_to_cpu(*pos);
pos++; left -= 2;
if (local->ap->ap_policy != AP_OTHER_AP_EVEN_IBSS &&
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index 517f89845144..b470c743c2d1 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -188,10 +188,10 @@
struct hfa384x_comp_ident
{
- u16 id;
- u16 variant;
- u16 major;
- u16 minor;
+ __le16 id;
+ __le16 variant;
+ __le16 major;
+ __le16 minor;
} __attribute__ ((packed));
#define HFA384X_COMP_ID_PRI 0x15
@@ -200,33 +200,33 @@ struct hfa384x_comp_ident
struct hfa384x_sup_range
{
- u16 role;
- u16 id;
- u16 variant;
- u16 bottom;
- u16 top;
+ __le16 role;
+ __le16 id;
+ __le16 variant;
+ __le16 bottom;
+ __le16 top;
} __attribute__ ((packed));
struct hfa384x_build_id
{
- u16 pri_seq;
- u16 sec_seq;
+ __le16 pri_seq;
+ __le16 sec_seq;
} __attribute__ ((packed));
/* FD01 - Download Buffer */
struct hfa384x_rid_download_buffer
{
- u16 page;
- u16 offset;
- u16 length;
+ __le16 page;
+ __le16 offset;
+ __le16 length;
} __attribute__ ((packed));
/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */
struct hfa384x_comms_quality {
- u16 comm_qual; /* 0 .. 92 */
- u16 signal_level; /* 27 .. 154 */
- u16 noise_level; /* 27 .. 154 */
+ __le16 comm_qual; /* 0 .. 92 */
+ __le16 signal_level; /* 27 .. 154 */
+ __le16 noise_level; /* 27 .. 154 */
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c
index 877d3bdd37a0..07593803065a 100644
--- a/drivers/net/wireless/hostap/hostap_cs.c
+++ b/drivers/net/wireless/hostap/hostap_cs.c
@@ -845,15 +845,13 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
0x4b801a17),
PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus",
0x7a954bd9, 0x74be00c6),
- PCMCIA_DEVICE_PROD_ID1234(
+ PCMCIA_DEVICE_PROD_ID123(
"Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P",
- "Eval-RevA",
- 0x4b801a17, 0x6345a0bf, 0xc9049a39, 0xc23adc0e),
+ 0x4b801a17, 0x6345a0bf, 0xc9049a39),
/* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */
- PCMCIA_DEVICE_PROD_ID1234(
+ PCMCIA_DEVICE_PROD_ID123(
"D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10",
- "A3",
- 0x1a424a1c, 0x6ea57632, 0xdd97a26b, 0x56b21f52),
+ 0x1a424a1c, 0x6ea57632, 0xdd97a26b),
PCMCIA_DEVICE_PROD_ID123(
"Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02",
0xe6ec52ce, 0x08649af2, 0x4b74baa0),
@@ -890,10 +888,9 @@ static struct pcmcia_device_id hostap_cs_ids[] = {
PCMCIA_DEVICE_PROD_ID123(
"corega", "WL PCCL-11", "ISL37300P",
0xa21501a, 0x59868926, 0xc9049a39),
- PCMCIA_DEVICE_PROD_ID1234(
+ PCMCIA_DEVICE_PROD_ID123(
"The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P",
- "RevA",
- 0xa5f472c2, 0x9c05598d, 0xc9049a39, 0x57a66194),
+ 0xa5f472c2, 0x9c05598d, 0xc9049a39),
PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids);
diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c
index c7678e67697d..89d3849abfe0 100644
--- a/drivers/net/wireless/hostap/hostap_download.c
+++ b/drivers/net/wireless/hostap/hostap_download.c
@@ -100,7 +100,7 @@ static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
#ifdef PRISM2_PCI
{
- u16 *pos = (u16 *) buf;
+ __le16 *pos = (__le16 *) buf;
while (len > 0) {
*pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
len -= 2;
@@ -131,7 +131,7 @@ static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
#ifdef PRISM2_PCI
{
- u16 *pos = (u16 *) buf;
+ __le16 *pos = (__le16 *) buf;
while (len > 0) {
HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
len -= 2;
@@ -147,7 +147,7 @@ static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
static int prism2_pda_ok(u8 *buf)
{
- u16 *pda = (u16 *) buf;
+ __le16 *pda = (__le16 *) buf;
int pos;
u16 len, pdr;
@@ -544,9 +544,9 @@ static int prism2_download_nonvolatile(local_info_t *local,
struct net_device *dev = local->dev;
int ret = 0, i;
struct {
- u16 page;
- u16 offset;
- u16 len;
+ __le16 page;
+ __le16 offset;
+ __le16 len;
} dlbuffer;
u32 bufaddr;
@@ -565,14 +565,12 @@ static int prism2_download_nonvolatile(local_info_t *local,
goto out;
}
- dlbuffer.page = le16_to_cpu(dlbuffer.page);
- dlbuffer.offset = le16_to_cpu(dlbuffer.offset);
- dlbuffer.len = le16_to_cpu(dlbuffer.len);
-
printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
- dlbuffer.len, dlbuffer.page, dlbuffer.offset);
+ le16_to_cpu(dlbuffer.len),
+ le16_to_cpu(dlbuffer.page),
+ le16_to_cpu(dlbuffer.offset));
- bufaddr = (dlbuffer.page << 7) + dlbuffer.offset;
+ bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
local->hw_downloading = 1;
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index c592641e914e..7be68db6f300 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -1075,7 +1075,7 @@ static int prism2_setup_rids(struct net_device *dev)
{
struct hostap_interface *iface;
local_info_t *local;
- u16 tmp;
+ __le16 tmp;
int ret = 0;
iface = netdev_priv(dev);
@@ -1084,11 +1084,11 @@ static int prism2_setup_rids(struct net_device *dev)
hostap_set_word(dev, HFA384X_RID_TICKTIME, 2000);
if (!local->fw_ap) {
- tmp = hostap_get_porttype(local);
- ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp);
+ u16 tmp1 = hostap_get_porttype(local);
+ ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp1);
if (ret) {
printk("%s: Port type setting to %d failed\n",
- dev->name, tmp);
+ dev->name, tmp1);
goto fail;
}
}
@@ -1117,7 +1117,7 @@ static int prism2_setup_rids(struct net_device *dev)
ret = -EINVAL;
goto fail;
}
- local->channel_mask = __le16_to_cpu(tmp);
+ local->channel_mask = le16_to_cpu(tmp);
if (local->channel < 1 || local->channel > 14 ||
!(local->channel_mask & (1 << (local->channel - 1)))) {
@@ -1852,7 +1852,7 @@ static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev)
tx_control = local->tx_control;
if (meta->tx_cb_idx) {
tx_control |= HFA384X_TX_CTRL_TX_OK;
- txdesc.sw_support = cpu_to_le16(meta->tx_cb_idx);
+ txdesc.sw_support = cpu_to_le32(meta->tx_cb_idx);
}
txdesc.tx_control = cpu_to_le16(tx_control);
txdesc.tx_rate = meta->rate;
@@ -2190,7 +2190,7 @@ static void hostap_tx_callback(local_info_t *local,
return;
}
- sw_support = le16_to_cpu(txdesc->sw_support);
+ sw_support = le32_to_cpu(txdesc->sw_support);
spin_lock(&local->lock);
cb = local->tx_callback;
@@ -2448,18 +2448,16 @@ static void prism2_info(local_info_t *local)
goto out;
}
- le16_to_cpus(&info.len);
- le16_to_cpus(&info.type);
- left = (info.len - 1) * 2;
+ left = (le16_to_cpu(info.len) - 1) * 2;
- if (info.len & 0x8000 || info.len == 0 || left > 2060) {
+ if (info.len & cpu_to_le16(0x8000) || info.len == 0 || left > 2060) {
/* data register seems to give 0x8000 in some error cases even
* though busy bit is not set in offset register;
* in addition, length must be at least 1 due to type field */
spin_unlock(&local->baplock);
printk(KERN_DEBUG "%s: Received info frame with invalid "
- "length 0x%04x (type 0x%04x)\n", dev->name, info.len,
- info.type);
+ "length 0x%04x (type 0x%04x)\n", dev->name,
+ le16_to_cpu(info.len), le16_to_cpu(info.type));
goto out;
}
@@ -2476,8 +2474,8 @@ static void prism2_info(local_info_t *local)
{
spin_unlock(&local->baplock);
printk(KERN_WARNING "%s: Info frame read failed (fid=0x%04x, "
- "len=0x%04x, type=0x%04x\n",
- dev->name, fid, info.len, info.type);
+ "len=0x%04x, type=0x%04x\n", dev->name, fid,
+ le16_to_cpu(info.len), le16_to_cpu(info.type));
dev_kfree_skb(skb);
goto out;
}
@@ -2624,7 +2622,7 @@ static void prism2_check_magic(local_info_t *local)
/* Called only from hardware IRQ */
static irqreturn_t prism2_interrupt(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
+ struct net_device *dev = dev_id;
struct hostap_interface *iface;
local_info_t *local;
int events = 0;
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 636f4b2382ea..7cd3fb79230e 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -303,7 +303,7 @@ static void prism2_info_hostscanresults(local_info_t *local,
int i, result_size, copy_len, new_count;
struct hfa384x_hostscan_result *results, *prev;
unsigned long flags;
- u16 *pos;
+ __le16 *pos;
u8 *ptr;
wake_up_interruptible(&local->hostscan_wq);
@@ -314,7 +314,7 @@ static void prism2_info_hostscanresults(local_info_t *local,
return;
}
- pos = (u16 *) buf;
+ pos = (__le16 *) buf;
copy_len = result_size = le16_to_cpu(*pos);
if (result_size == 0) {
printk(KERN_DEBUG "%s: invalid result_size (0) in "
@@ -373,7 +373,7 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb)
buf = skb->data + sizeof(*info);
left = skb->len - sizeof(*info);
- switch (info->type) {
+ switch (le16_to_cpu(info->type)) {
case HFA384X_INFO_COMMTALLIES:
prism2_info_commtallies(local, buf, left);
break;
@@ -395,7 +395,8 @@ void hostap_info_process(local_info_t *local, struct sk_buff *skb)
#ifndef PRISM2_NO_DEBUG
default:
PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n",
- local->dev->name, info->len, info->type);
+ local->dev->name, le16_to_cpu(info->len),
+ le16_to_cpu(info->type));
PDEBUG(DEBUG_EXTRA, "Unknown info frame:");
for (i = 0; i < (left < 100 ? left : 100); i++)
PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]);
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index d8f5efcfcab9..0ca0bfeb0ada 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -84,7 +84,7 @@ static int prism2_get_datarates(struct net_device *dev, u8 *rates)
if (len < 2)
return 0;
- val = le16_to_cpu(*(u16 *) buf); /* string length */
+ val = le16_to_cpu(*(__le16 *) buf); /* string length */
if (len - 2 < val || val > 10)
return 0;
@@ -496,7 +496,7 @@ static int prism2_ioctl_giwsens(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 val;
+ __le16 val;
iface = netdev_priv(dev);
local = iface->local;
@@ -506,7 +506,7 @@ static int prism2_ioctl_giwsens(struct net_device *dev,
0)
return -EINVAL;
- sens->value = __le16_to_cpu(val);
+ sens->value = le16_to_cpu(val);
sens->fixed = 1;
return 0;
@@ -561,17 +561,17 @@ static int prism2_ioctl_siwrts(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 val;
+ __le16 val;
iface = netdev_priv(dev);
local = iface->local;
if (rts->disabled)
- val = __constant_cpu_to_le16(2347);
+ val = cpu_to_le16(2347);
else if (rts->value < 0 || rts->value > 2347)
return -EINVAL;
else
- val = __cpu_to_le16(rts->value);
+ val = cpu_to_le16(rts->value);
if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) ||
local->func->reset_port(dev))
@@ -588,7 +588,7 @@ static int prism2_ioctl_giwrts(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 val;
+ __le16 val;
iface = netdev_priv(dev);
local = iface->local;
@@ -597,7 +597,7 @@ static int prism2_ioctl_giwrts(struct net_device *dev,
0)
return -EINVAL;
- rts->value = __le16_to_cpu(val);
+ rts->value = le16_to_cpu(val);
rts->disabled = (rts->value == 2347);
rts->fixed = 1;
@@ -611,17 +611,17 @@ static int prism2_ioctl_siwfrag(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 val;
+ __le16 val;
iface = netdev_priv(dev);
local = iface->local;
if (rts->disabled)
- val = __constant_cpu_to_le16(2346);
+ val = cpu_to_le16(2346);
else if (rts->value < 256 || rts->value > 2346)
return -EINVAL;
else
- val = __cpu_to_le16(rts->value & ~0x1); /* even numbers only */
+ val = cpu_to_le16(rts->value & ~0x1); /* even numbers only */
local->fragm_threshold = rts->value & ~0x1;
if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val,
@@ -638,7 +638,7 @@ static int prism2_ioctl_giwfrag(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 val;
+ __le16 val;
iface = netdev_priv(dev);
local = iface->local;
@@ -647,7 +647,7 @@ static int prism2_ioctl_giwfrag(struct net_device *dev,
&val, 2, 1) < 0)
return -EINVAL;
- rts->value = __le16_to_cpu(val);
+ rts->value = le16_to_cpu(val);
rts->disabled = (rts->value == 2346);
rts->fixed = 1;
@@ -718,8 +718,8 @@ static int prism2_ioctl_siwap(struct net_device *dev,
if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) {
struct hfa384x_scan_request scan_req;
memset(&scan_req, 0, sizeof(scan_req));
- scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
- scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
+ scan_req.channel_list = cpu_to_le16(0x3fff);
+ scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS);
if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST,
&scan_req, sizeof(scan_req))) {
printk(KERN_DEBUG "%s: ScanResults request failed - "
@@ -812,7 +812,7 @@ static int prism2_ioctl_giwnickn(struct net_device *dev,
len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME,
&name, MAX_NAME_LEN + 2, 0);
- val = __le16_to_cpu(*(u16 *) name);
+ val = le16_to_cpu(*(__le16 *) name);
if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN)
return -EOPNOTSUPP;
@@ -963,7 +963,7 @@ static int prism2_ioctl_giwessid(struct net_device *dev,
memset(ssid, 0, sizeof(ssid));
len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID,
&ssid, MAX_SSID_LEN + 2, 0);
- val = __le16_to_cpu(*(u16 *) ssid);
+ val = le16_to_cpu(*(__le16 *) ssid);
if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) {
return -EOPNOTSUPP;
}
@@ -1089,6 +1089,9 @@ static int prism2_ioctl_giwrange(struct net_device *dev,
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+ if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
+ range->scan_capa = IW_SCAN_CAPA_ESSID;
+
return 0;
}
@@ -1316,7 +1319,7 @@ static int prism2_ioctl_giwpower(struct net_device *dev,
#else /* PRISM2_NO_STATION_MODES */
struct hostap_interface *iface;
local_info_t *local;
- u16 enable, mcast;
+ __le16 enable, mcast;
iface = netdev_priv(dev);
local = iface->local;
@@ -1325,7 +1328,7 @@ static int prism2_ioctl_giwpower(struct net_device *dev,
< 0)
return -EINVAL;
- if (!__le16_to_cpu(enable)) {
+ if (!le16_to_cpu(enable)) {
rrq->disabled = 1;
return 0;
}
@@ -1333,29 +1336,29 @@ static int prism2_ioctl_giwpower(struct net_device *dev,
rrq->disabled = 0;
if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
- u16 timeout;
+ __le16 timeout;
if (local->func->get_rid(dev,
HFA384X_RID_CNFPMHOLDOVERDURATION,
&timeout, 2, 1) < 0)
return -EINVAL;
rrq->flags = IW_POWER_TIMEOUT;
- rrq->value = __le16_to_cpu(timeout) * 1024;
+ rrq->value = le16_to_cpu(timeout) * 1024;
} else {
- u16 period;
+ __le16 period;
if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
&period, 2, 1) < 0)
return -EINVAL;
rrq->flags = IW_POWER_PERIOD;
- rrq->value = __le16_to_cpu(period) * 1024;
+ rrq->value = le16_to_cpu(period) * 1024;
}
if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast,
2, 1) < 0)
return -EINVAL;
- if (__le16_to_cpu(mcast))
+ if (le16_to_cpu(mcast))
rrq->flags |= IW_POWER_ALL_R;
else
rrq->flags |= IW_POWER_UNICAST_R;
@@ -1432,7 +1435,7 @@ static int prism2_ioctl_giwretry(struct net_device *dev,
{
struct hostap_interface *iface;
local_info_t *local;
- u16 shortretry, longretry, lifetime, altretry;
+ __le16 shortretry, longretry, lifetime, altretry;
iface = netdev_priv(dev);
local = iface->local;
@@ -1445,15 +1448,11 @@ static int prism2_ioctl_giwretry(struct net_device *dev,
&lifetime, 2, 1) < 0)
return -EINVAL;
- le16_to_cpus(&shortretry);
- le16_to_cpus(&longretry);
- le16_to_cpus(&lifetime);
-
rrq->disabled = 0;
if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
rrq->flags = IW_RETRY_LIFETIME;
- rrq->value = lifetime * 1024;
+ rrq->value = le16_to_cpu(lifetime) * 1024;
} else {
if (local->manual_retry_count >= 0) {
rrq->flags = IW_RETRY_LIMIT;
@@ -1465,10 +1464,10 @@ static int prism2_ioctl_giwretry(struct net_device *dev,
rrq->value = local->manual_retry_count;
} else if ((rrq->flags & IW_RETRY_LONG)) {
rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
- rrq->value = longretry;
+ rrq->value = le16_to_cpu(longretry);
} else {
rrq->flags = IW_RETRY_LIMIT;
- rrq->value = shortretry;
+ rrq->value = le16_to_cpu(shortretry);
if (shortretry != longretry)
rrq->flags |= IW_RETRY_SHORT;
}
@@ -3098,7 +3097,7 @@ static int prism2_set_genericelement(struct net_device *dev, u8 *elem,
if (buf == NULL)
return -ENOMEM;
- *((u16 *) buf) = cpu_to_le16(len);
+ *((__le16 *) buf) = cpu_to_le16(len);
memcpy(buf + 2, elem, len);
kfree(local->generic_elem);
@@ -3758,7 +3757,7 @@ static int prism2_ioctl_siwmlme(struct net_device *dev,
struct hostap_interface *iface = netdev_priv(dev);
local_info_t *local = iface->local;
struct iw_mlme *mlme = (struct iw_mlme *) extra;
- u16 reason;
+ __le16 reason;
reason = cpu_to_le16(mlme->reason_code);
@@ -3780,7 +3779,7 @@ static int prism2_ioctl_siwmlme(struct net_device *dev,
static int prism2_ioctl_mlme(local_info_t *local,
struct prism2_hostapd_param *param)
{
- u16 reason;
+ __le16 reason;
reason = cpu_to_le16(param->u.mlme.reason_code);
switch (param->u.mlme.cmd) {
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 17c58e9bdad5..20d387f6658c 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -296,7 +296,7 @@ int hostap_tx_callback_unregister(local_info_t *local, u16 idx)
int hostap_set_word(struct net_device *dev, int rid, u16 val)
{
struct hostap_interface *iface;
- u16 tmp = cpu_to_le16(val);
+ __le16 tmp = cpu_to_le16(val);
iface = netdev_priv(dev);
return iface->local->func->set_rid(dev, rid, &tmp, 2);
}
@@ -1095,15 +1095,15 @@ int prism2_sta_deauth(local_info_t *local, u16 reason)
{
union iwreq_data wrqu;
int ret;
+ __le16 val = cpu_to_le16(reason);
if (local->iw_mode != IW_MODE_INFRA ||
memcmp(local->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 ||
memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0)
return 0;
- reason = cpu_to_le16(reason);
ret = prism2_sta_send_mgmt(local, local->bssid, IEEE80211_STYPE_DEAUTH,
- (u8 *) &reason, 2);
+ (u8 *) &val, 2);
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL);
return ret;
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index fc876ba18572..3a874fc621d3 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -128,8 +128,8 @@ static inline u16 hfa384x_inw_debug(struct net_device *dev, int a)
#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a))
#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v))
#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a))
-#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), cpu_to_le16((v)))
-#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw_debug(dev, (a)))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), le16_to_cpu((v)))
+#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw_debug(dev, (a)))
#else /* PRISM2_IO_DEBUG */
@@ -173,8 +173,8 @@ static inline u16 hfa384x_inw(struct net_device *dev, int a)
#define HFA384X_INB(a) hfa384x_inb(dev, (a))
#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v))
#define HFA384X_INW(a) hfa384x_inw(dev, (a))
-#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), cpu_to_le16((v)))
-#define HFA384X_INW_DATA(a) (u16) le16_to_cpu(hfa384x_inw(dev, (a)))
+#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), le16_to_cpu((v)))
+#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw(dev, (a)))
#endif /* PRISM2_IO_DEBUG */
@@ -183,10 +183,10 @@ static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
int len)
{
u16 d_off;
- u16 *pos;
+ __le16 *pos;
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
- pos = (u16 *) buf;
+ pos = (__le16 *) buf;
for ( ; len > 1; len -= 2)
*pos++ = HFA384X_INW_DATA(d_off);
@@ -201,10 +201,10 @@ static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf,
static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len)
{
u16 d_off;
- u16 *pos;
+ __le16 *pos;
d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF;
- pos = (u16 *) buf;
+ pos = (__le16 *) buf;
for ( ; len > 1; len -= 2)
HFA384X_OUTW_DATA(*pos++, d_off);
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index e6516a186d0e..15445bce2ac7 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -39,20 +39,20 @@ struct linux_wlan_ng_prism_hdr {
} __attribute__ ((packed));
struct linux_wlan_ng_cap_hdr {
- u32 version;
- u32 length;
- u64 mactime;
- u64 hosttime;
- u32 phytype;
- u32 channel;
- u32 datarate;
- u32 antenna;
- u32 priority;
- u32 ssi_type;
- s32 ssi_signal;
- s32 ssi_noise;
- u32 preamble;
- u32 encoding;
+ __be32 version;
+ __be32 length;
+ __be64 mactime;
+ __be64 hosttime;
+ __be32 phytype;
+ __be32 channel;
+ __be32 datarate;
+ __be32 antenna;
+ __be32 priority;
+ __be32 ssi_type;
+ __be32 ssi_signal;
+ __be32 ssi_noise;
+ __be32 preamble;
+ __be32 encoding;
} __attribute__ ((packed));
#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */
@@ -60,28 +60,28 @@ struct linux_wlan_ng_cap_hdr {
struct hfa384x_rx_frame {
/* HFA384X RX frame descriptor */
- u16 status; /* HFA384X_RX_STATUS_ flags */
- u32 time; /* timestamp, 1 microsecond resolution */
+ __le16 status; /* HFA384X_RX_STATUS_ flags */
+ __le32 time; /* timestamp, 1 microsecond resolution */
u8 silence; /* 27 .. 154; seems to be 0 */
u8 signal; /* 27 .. 154 */
u8 rate; /* 10, 20, 55, or 110 */
u8 rxflow;
- u32 reserved;
+ __le32 reserved;
/* 802.11 */
- u16 frame_control;
- u16 duration_id;
+ __le16 frame_control;
+ __le16 duration_id;
u8 addr1[6];
u8 addr2[6];
u8 addr3[6];
- u16 seq_ctrl;
+ __le16 seq_ctrl;
u8 addr4[6];
- u16 data_len;
+ __le16 data_len;
/* 802.3 */
u8 dst_addr[6];
u8 src_addr[6];
- u16 len;
+ __be16 len;
/* followed by frame data; max 2304 bytes */
} __attribute__ ((packed));
@@ -89,28 +89,28 @@ struct hfa384x_rx_frame {
struct hfa384x_tx_frame {
/* HFA384X TX frame descriptor */
- u16 status; /* HFA384X_TX_STATUS_ flags */
- u16 reserved1;
- u16 reserved2;
- u32 sw_support;
+ __le16 status; /* HFA384X_TX_STATUS_ flags */
+ __le16 reserved1;
+ __le16 reserved2;
+ __le32 sw_support;
u8 retry_count; /* not yet implemented */
u8 tx_rate; /* Host AP only; 0 = firmware, or 10, 20, 55, 110 */
- u16 tx_control; /* HFA384X_TX_CTRL_ flags */
+ __le16 tx_control; /* HFA384X_TX_CTRL_ flags */
/* 802.11 */
- u16 frame_control; /* parts not used */
- u16 duration_id;
+ __le16 frame_control; /* parts not used */
+ __le16 duration_id;
u8 addr1[6];
u8 addr2[6]; /* filled by firmware */
u8 addr3[6];
- u16 seq_ctrl; /* filled by firmware */
+ __le16 seq_ctrl; /* filled by firmware */
u8 addr4[6];
- u16 data_len;
+ __le16 data_len;
/* 802.3 */
u8 dst_addr[6];
u8 src_addr[6];
- u16 len;
+ __be16 len;
/* followed by frame data; max 2304 bytes */
} __attribute__ ((packed));
@@ -118,8 +118,8 @@ struct hfa384x_tx_frame {
struct hfa384x_rid_hdr
{
- u16 len;
- u16 rid;
+ __le16 len;
+ __le16 rid;
} __attribute__ ((packed));
@@ -130,78 +130,78 @@ struct hfa384x_rid_hdr
#define HFA384X_LEVEL_TO_dBm_sign(v) (v) * 100 / 255 - 100
struct hfa384x_scan_request {
- u16 channel_list;
- u16 txrate; /* HFA384X_RATES_* */
+ __le16 channel_list;
+ __le16 txrate; /* HFA384X_RATES_* */
} __attribute__ ((packed));
struct hfa384x_hostscan_request {
- u16 channel_list;
- u16 txrate;
- u16 target_ssid_len;
+ __le16 channel_list;
+ __le16 txrate;
+ __le16 target_ssid_len;
u8 target_ssid[32];
} __attribute__ ((packed));
struct hfa384x_join_request {
u8 bssid[6];
- u16 channel;
+ __le16 channel;
} __attribute__ ((packed));
struct hfa384x_info_frame {
- u16 len;
- u16 type;
+ __le16 len;
+ __le16 type;
} __attribute__ ((packed));
struct hfa384x_comm_tallies {
- u16 tx_unicast_frames;
- u16 tx_multicast_frames;
- u16 tx_fragments;
- u16 tx_unicast_octets;
- u16 tx_multicast_octets;
- u16 tx_deferred_transmissions;
- u16 tx_single_retry_frames;
- u16 tx_multiple_retry_frames;
- u16 tx_retry_limit_exceeded;
- u16 tx_discards;
- u16 rx_unicast_frames;
- u16 rx_multicast_frames;
- u16 rx_fragments;
- u16 rx_unicast_octets;
- u16 rx_multicast_octets;
- u16 rx_fcs_errors;
- u16 rx_discards_no_buffer;
- u16 tx_discards_wrong_sa;
- u16 rx_discards_wep_undecryptable;
- u16 rx_message_in_msg_fragments;
- u16 rx_message_in_bad_msg_fragments;
+ __le16 tx_unicast_frames;
+ __le16 tx_multicast_frames;
+ __le16 tx_fragments;
+ __le16 tx_unicast_octets;
+ __le16 tx_multicast_octets;
+ __le16 tx_deferred_transmissions;
+ __le16 tx_single_retry_frames;
+ __le16 tx_multiple_retry_frames;
+ __le16 tx_retry_limit_exceeded;
+ __le16 tx_discards;
+ __le16 rx_unicast_frames;
+ __le16 rx_multicast_frames;
+ __le16 rx_fragments;
+ __le16 rx_unicast_octets;
+ __le16 rx_multicast_octets;
+ __le16 rx_fcs_errors;
+ __le16 rx_discards_no_buffer;
+ __le16 tx_discards_wrong_sa;
+ __le16 rx_discards_wep_undecryptable;
+ __le16 rx_message_in_msg_fragments;
+ __le16 rx_message_in_bad_msg_fragments;
} __attribute__ ((packed));
struct hfa384x_comm_tallies32 {
- u32 tx_unicast_frames;
- u32 tx_multicast_frames;
- u32 tx_fragments;
- u32 tx_unicast_octets;
- u32 tx_multicast_octets;
- u32 tx_deferred_transmissions;
- u32 tx_single_retry_frames;
- u32 tx_multiple_retry_frames;
- u32 tx_retry_limit_exceeded;
- u32 tx_discards;
- u32 rx_unicast_frames;
- u32 rx_multicast_frames;
- u32 rx_fragments;
- u32 rx_unicast_octets;
- u32 rx_multicast_octets;
- u32 rx_fcs_errors;
- u32 rx_discards_no_buffer;
- u32 tx_discards_wrong_sa;
- u32 rx_discards_wep_undecryptable;
- u32 rx_message_in_msg_fragments;
- u32 rx_message_in_bad_msg_fragments;
+ __le32 tx_unicast_frames;
+ __le32 tx_multicast_frames;
+ __le32 tx_fragments;
+ __le32 tx_unicast_octets;
+ __le32 tx_multicast_octets;
+ __le32 tx_deferred_transmissions;
+ __le32 tx_single_retry_frames;
+ __le32 tx_multiple_retry_frames;
+ __le32 tx_retry_limit_exceeded;
+ __le32 tx_discards;
+ __le32 rx_unicast_frames;
+ __le32 rx_multicast_frames;
+ __le32 rx_fragments;
+ __le32 rx_unicast_octets;
+ __le32 rx_multicast_octets;
+ __le32 rx_fcs_errors;
+ __le32 rx_discards_no_buffer;
+ __le32 tx_discards_wrong_sa;
+ __le32 rx_discards_wep_undecryptable;
+ __le32 rx_message_in_msg_fragments;
+ __le32 rx_message_in_bad_msg_fragments;
} __attribute__ ((packed));
struct hfa384x_scan_result_hdr {
- u16 reserved;
- u16 scan_reason;
+ __le16 reserved;
+ __le16 scan_reason;
#define HFA384X_SCAN_IN_PROGRESS 0 /* no results available yet */
#define HFA384X_SCAN_HOST_INITIATED 1
#define HFA384X_SCAN_FIRMWARE_INITIATED 2
@@ -211,30 +211,30 @@ struct hfa384x_scan_result_hdr {
#define HFA384X_SCAN_MAX_RESULTS 32
struct hfa384x_scan_result {
- u16 chid;
- u16 anl;
- u16 sl;
+ __le16 chid;
+ __le16 anl;
+ __le16 sl;
u8 bssid[6];
- u16 beacon_interval;
- u16 capability;
- u16 ssid_len;
+ __le16 beacon_interval;
+ __le16 capability;
+ __le16 ssid_len;
u8 ssid[32];
u8 sup_rates[10];
- u16 rate;
+ __le16 rate;
} __attribute__ ((packed));
struct hfa384x_hostscan_result {
- u16 chid;
- u16 anl;
- u16 sl;
+ __le16 chid;
+ __le16 anl;
+ __le16 sl;
u8 bssid[6];
- u16 beacon_interval;
- u16 capability;
- u16 ssid_len;
+ __le16 beacon_interval;
+ __le16 capability;
+ __le16 ssid_len;
u8 ssid[32];
u8 sup_rates[10];
- u16 rate;
- u16 atim;
+ __le16 rate;
+ __le16 atim;
} __attribute__ ((packed));
struct comm_tallies_sums {
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c
index fc6cdd8086c1..2ab107f45793 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2100.c
@@ -2509,9 +2509,9 @@ static void isr_rx_monitor(struct ipw2100_priv *priv, int i,
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
- ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total hdr+data */
+ ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total hdr+data */
- ipw_rt->rt_hdr.it_present = 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL;
+ ipw_rt->rt_hdr.it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM;
@@ -2558,7 +2558,7 @@ static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i)
#ifdef CONFIG_IPW2100_MONITOR
return 0;
#else
- switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
+ switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) {
case IEEE80211_FTYPE_MGMT:
case IEEE80211_FTYPE_CTL:
return 0;
@@ -2677,7 +2677,7 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
#endif
if (stats.len < sizeof(struct ieee80211_hdr_3addr))
break;
- switch (WLAN_FC_GET_TYPE(u->rx_data.header.frame_ctl)) {
+ switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) {
case IEEE80211_FTYPE_MGMT:
ieee80211_rx_mgt(priv->ieee,
&u->rx_data.header, &stats);
@@ -6591,8 +6591,7 @@ static const long ipw2100_frequencies[] = {
2472, 2484
};
-#define FREQ_COUNT (sizeof(ipw2100_frequencies) / \
- sizeof(ipw2100_frequencies[0]))
+#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies)
static const long ipw2100_rates_11b[] = {
1000000,
@@ -7796,7 +7795,7 @@ static int ipw2100_wx_set_mlme(struct net_device *dev,
{
struct ipw2100_priv *priv = ieee80211_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- u16 reason;
+ __le16 reason;
reason = cpu_to_le16(mlme->reason_code);
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c
index 003f73f89efa..3e6ad7b92c83 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2200.c
@@ -2352,27 +2352,13 @@ static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens)
static int ipw_send_associate(struct ipw_priv *priv,
struct ipw_associate *associate)
{
- struct ipw_associate tmp_associate;
-
if (!priv || !associate) {
IPW_ERROR("Invalid args\n");
return -1;
}
- memcpy(&tmp_associate, associate, sizeof(*associate));
- tmp_associate.policy_support =
- cpu_to_le16(tmp_associate.policy_support);
- tmp_associate.assoc_tsf_msw = cpu_to_le32(tmp_associate.assoc_tsf_msw);
- tmp_associate.assoc_tsf_lsw = cpu_to_le32(tmp_associate.assoc_tsf_lsw);
- tmp_associate.capability = cpu_to_le16(tmp_associate.capability);
- tmp_associate.listen_interval =
- cpu_to_le16(tmp_associate.listen_interval);
- tmp_associate.beacon_interval =
- cpu_to_le16(tmp_associate.beacon_interval);
- tmp_associate.atim_window = cpu_to_le16(tmp_associate.atim_window);
-
- return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(tmp_associate),
- &tmp_associate);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(*associate),
+ associate);
}
static int ipw_send_supported_rates(struct ipw_priv *priv,
@@ -2403,14 +2389,13 @@ static int ipw_set_random_seed(struct ipw_priv *priv)
static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off)
{
+ __le32 v = cpu_to_le32(phy_off);
if (!priv) {
IPW_ERROR("Invalid args\n");
return -1;
}
- phy_off = cpu_to_le32(phy_off);
- return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(phy_off),
- &phy_off);
+ return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(v), &v);
}
static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power)
@@ -2499,7 +2484,7 @@ static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag)
static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
{
- u32 param;
+ __le32 param;
if (!priv) {
IPW_ERROR("Invalid args\n");
@@ -2510,17 +2495,16 @@ static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode)
* level */
switch (mode) {
case IPW_POWER_BATTERY:
- param = IPW_POWER_INDEX_3;
+ param = cpu_to_le32(IPW_POWER_INDEX_3);
break;
case IPW_POWER_AC:
- param = IPW_POWER_MODE_CAM;
+ param = cpu_to_le32(IPW_POWER_MODE_CAM);
break;
default:
- param = mode;
+ param = cpu_to_le32(mode);
break;
}
- param = cpu_to_le32(param);
return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param),
&param);
}
@@ -2654,13 +2638,13 @@ static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac)
static void ipw_eeprom_init_sram(struct ipw_priv *priv)
{
int i;
- u16 *eeprom = (u16 *) priv->eeprom;
+ __le16 *eeprom = (__le16 *) priv->eeprom;
IPW_DEBUG_TRACE(">>\n");
/* read entire contents of eeprom into private buffer */
for (i = 0; i < 128; i++)
- eeprom[i] = le16_to_cpu(eeprom_read_u16(priv, (u8) i));
+ eeprom[i] = cpu_to_le16(eeprom_read_u16(priv, (u8) i));
/*
If the data looks correct, then copy it to our private
@@ -3040,17 +3024,17 @@ static void ipw_arc_release(struct ipw_priv *priv)
}
struct fw_chunk {
- u32 address;
- u32 length;
+ __le32 address;
+ __le32 length;
};
static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
{
int rc = 0, i, addr;
u8 cr = 0;
- u16 *image;
+ __le16 *image;
- image = (u16 *) data;
+ image = (__le16 *) data;
IPW_DEBUG_TRACE(">> \n");
@@ -3097,7 +3081,7 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
/* load new ipw uCode */
for (i = 0; i < len / 2; i++)
ipw_write_reg16(priv, IPW_BASEBAND_CONTROL_STORE,
- cpu_to_le16(image[i]));
+ le16_to_cpu(image[i]));
/* enable DINO */
ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0);
@@ -3116,11 +3100,11 @@ static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len)
if (cr & DINO_RXFIFO_DATA) {
/* alive_command_responce size is NOT multiple of 4 */
- u32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4];
+ __le32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4];
for (i = 0; i < ARRAY_SIZE(response_buffer); i++)
response_buffer[i] =
- le32_to_cpu(ipw_read_reg32(priv,
+ cpu_to_le32(ipw_read_reg32(priv,
IPW_BASEBAND_RX_FIFO_READ));
memcpy(&priv->dino_alive, response_buffer,
sizeof(priv->dino_alive));
@@ -4170,7 +4154,7 @@ static void ipw_gather_stats(struct ipw_priv *priv)
priv->last_missed_beacons = priv->missed_beacons;
if (priv->assoc_request.beacon_interval) {
missed_beacons_percent = missed_beacons_delta *
- (HZ * priv->assoc_request.beacon_interval) /
+ (HZ * le16_to_cpu(priv->assoc_request.beacon_interval)) /
(IPW_STATS_INTERVAL * 10);
} else {
missed_beacons_percent = 0;
@@ -4396,9 +4380,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
DECLARE_MAC_BUF(mac);
+ u16 size = le16_to_cpu(notif->size);
notif->size = le16_to_cpu(notif->size);
- IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, notif->size);
+ IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size);
switch (notif->subtype) {
case HOST_NOTIFICATION_STATUS_ASSOCIATED:{
@@ -4433,9 +4418,9 @@ static void ipw_rx_notification(struct ipw_priv *priv,
workqueue,
&priv->
adhoc_check,
- priv->
+ le16_to_cpu(priv->
assoc_request.
- beacon_interval);
+ beacon_interval));
break;
}
@@ -4453,20 +4438,17 @@ static void ipw_rx_notification(struct ipw_priv *priv,
if ((sizeof
(struct
ieee80211_assoc_response)
- <= notif->size)
- && (notif->size <= 2314)) {
+ <= size)
+ && (size <= 2314)) {
struct
ieee80211_rx_stats
stats = {
- .len =
- notif->
- size - 1,
+ .len = size - 1,
};
IPW_DEBUG_QOS
("QoS Associate "
- "size %d\n",
- notif->size);
+ "size %d\n", size);
ieee80211_rx_mgt(priv->
ieee,
(struct
@@ -4671,20 +4653,20 @@ static void ipw_rx_notification(struct ipw_priv *priv,
struct notif_channel_result *x =
&notif->u.channel_result;
- if (notif->size == sizeof(*x)) {
+ if (size == sizeof(*x)) {
IPW_DEBUG_SCAN("Scan result for channel %d\n",
x->channel_num);
} else {
IPW_DEBUG_SCAN("Scan result of wrong size %d "
"(should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
}
break;
}
case HOST_NOTIFICATION_STATUS_SCAN_COMPLETED:{
struct notif_scan_complete *x = &notif->u.scan_complete;
- if (notif->size == sizeof(*x)) {
+ if (size == sizeof(*x)) {
IPW_DEBUG_SCAN
("Scan completed: type %d, %d channels, "
"%d status\n", x->scan_type,
@@ -4692,7 +4674,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
} else {
IPW_ERROR("Scan completed of wrong size %d "
"(should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
}
priv->status &=
@@ -4758,13 +4740,13 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{
struct notif_frag_length *x = &notif->u.frag_len;
- if (notif->size == sizeof(*x))
+ if (size == sizeof(*x))
IPW_ERROR("Frag length: %d\n",
le16_to_cpu(x->frag_length));
else
IPW_ERROR("Frag length of wrong size %d "
"(should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
break;
}
@@ -4772,7 +4754,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
struct notif_link_deterioration *x =
&notif->u.link_deterioration;
- if (notif->size == sizeof(*x)) {
+ if (size == sizeof(*x)) {
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
"link deterioration: type %d, cnt %d\n",
x->silence_notification_type,
@@ -4782,7 +4764,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
} else {
IPW_ERROR("Link Deterioration of wrong size %d "
"(should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
}
break;
}
@@ -4798,10 +4780,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_STATUS_BEACON_STATE:{
struct notif_beacon_state *x = &notif->u.beacon_state;
- if (notif->size != sizeof(*x)) {
+ if (size != sizeof(*x)) {
IPW_ERROR
("Beacon state of wrong size %d (should "
- "be %zd)\n", notif->size, sizeof(*x));
+ "be %zd)\n", size, sizeof(*x));
break;
}
@@ -4816,7 +4798,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case HOST_NOTIFICATION_STATUS_TGI_TX_KEY:{
struct notif_tgi_tx_key *x = &notif->u.tgi_tx_key;
- if (notif->size == sizeof(*x)) {
+ if (size == sizeof(*x)) {
IPW_ERROR("TGi Tx Key: state 0x%02x sec type "
"0x%02x station %d\n",
x->key_state, x->security_type,
@@ -4826,14 +4808,14 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_ERROR
("TGi Tx Key of wrong size %d (should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
break;
}
case HOST_NOTIFICATION_CALIB_KEEP_RESULTS:{
struct notif_calibration *x = &notif->u.calibration;
- if (notif->size == sizeof(*x)) {
+ if (size == sizeof(*x)) {
memcpy(&priv->calib, x, sizeof(*x));
IPW_DEBUG_INFO("TODO: Calibration\n");
break;
@@ -4841,12 +4823,12 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_ERROR
("Calibration of wrong size %d (should be %zd)\n",
- notif->size, sizeof(*x));
+ size, sizeof(*x));
break;
}
case HOST_NOTIFICATION_NOISE_STATS:{
- if (notif->size == sizeof(u32)) {
+ if (size == sizeof(u32)) {
priv->exp_avg_noise =
exponential_average(priv->exp_avg_noise,
(u8) (le32_to_cpu(notif->u.noise.value) & 0xff),
@@ -4856,14 +4838,14 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_ERROR
("Noise stat is wrong size %d (should be %zd)\n",
- notif->size, sizeof(u32));
+ size, sizeof(u32));
break;
}
default:
IPW_DEBUG_NOTIF("Unknown notification: "
"subtype=%d,flags=0x%2x,size=%d\n",
- notif->subtype, notif->flags, notif->size);
+ notif->subtype, notif->flags, size);
}
}
@@ -6048,7 +6030,7 @@ static void ipw_adhoc_check(void *data)
}
queue_delayed_work(priv->workqueue, &priv->adhoc_check,
- priv->assoc_request.beacon_interval);
+ le16_to_cpu(priv->assoc_request.beacon_interval));
}
static void ipw_bg_adhoc_check(struct work_struct *work)
@@ -6767,7 +6749,7 @@ static int ipw_wx_set_mlme(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
- u16 reason;
+ __le16 reason;
reason = cpu_to_le16(mlme->reason_code);
@@ -6904,7 +6886,7 @@ static int ipw_qos_activate(struct ipw_priv *priv,
burst_duration = ipw_qos_get_burst_duration(priv);
for (i = 0; i < QOS_QUEUE_NUM; i++)
qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] =
- (u16)burst_duration;
+ cpu_to_le16(burst_duration);
} else if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
if (type == IEEE_B) {
IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n",
@@ -6936,20 +6918,11 @@ static int ipw_qos_activate(struct ipw_priv *priv,
burst_duration = ipw_qos_get_burst_duration(priv);
for (i = 0; i < QOS_QUEUE_NUM; i++)
qos_parameters[QOS_PARAM_SET_ACTIVE].
- tx_op_limit[i] = (u16)burst_duration;
+ tx_op_limit[i] = cpu_to_le16(burst_duration);
}
}
IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n");
- for (i = 0; i < 3; i++) {
- int j;
- for (j = 0; j < QOS_QUEUE_NUM; j++) {
- qos_parameters[i].cw_min[j] = cpu_to_le16(qos_parameters[i].cw_min[j]);
- qos_parameters[i].cw_max[j] = cpu_to_le16(qos_parameters[i].cw_max[j]);
- qos_parameters[i].tx_op_limit[j] = cpu_to_le16(qos_parameters[i].tx_op_limit[j]);
- }
- }
-
err = ipw_send_qos_params_command(priv,
(struct ieee80211_qos_parameters *)
&(qos_parameters[0]));
@@ -7300,7 +7273,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
priv->assoc_request.auth_type = AUTH_OPEN;
if (priv->ieee->wpa_ie_len) {
- priv->assoc_request.policy_support = 0x02; /* RSN active */
+ priv->assoc_request.policy_support = cpu_to_le16(0x02); /* RSN active */
ipw_set_rsn_capa(priv, priv->ieee->wpa_ie,
priv->ieee->wpa_ie_len);
}
@@ -7317,7 +7290,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
else if (network->mode & priv->ieee->mode & IEEE_B)
priv->assoc_request.ieee_mode = IPW_B_MODE;
- priv->assoc_request.capability = network->capability;
+ priv->assoc_request.capability = cpu_to_le16(network->capability);
if ((network->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
&& !(priv->config & CFG_PREAMBLE_LONG)) {
priv->assoc_request.preamble_length = DCT_FLAG_SHORT_PREAMBLE;
@@ -7326,13 +7299,13 @@ static int ipw_associate_network(struct ipw_priv *priv,
/* Clear the short preamble if we won't be supporting it */
priv->assoc_request.capability &=
- ~WLAN_CAPABILITY_SHORT_PREAMBLE;
+ ~cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
}
/* Clear capability bits that aren't used in Ad Hoc */
if (priv->ieee->iw_mode == IW_MODE_ADHOC)
priv->assoc_request.capability &=
- ~WLAN_CAPABILITY_SHORT_SLOT_TIME;
+ ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME);
IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, "
"802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
@@ -7354,7 +7327,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
'1' + priv->ieee->sec.active_key : '.',
priv->capability & CAP_PRIVACY_ON ? '.' : ' ');
- priv->assoc_request.beacon_interval = network->beacon_interval;
+ priv->assoc_request.beacon_interval = cpu_to_le16(network->beacon_interval);
if ((priv->ieee->iw_mode == IW_MODE_ADHOC) &&
(network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) {
priv->assoc_request.assoc_type = HC_IBSS_START;
@@ -7365,21 +7338,21 @@ static int ipw_associate_network(struct ipw_priv *priv,
priv->assoc_request.assoc_type = HC_REASSOCIATE;
else
priv->assoc_request.assoc_type = HC_ASSOCIATE;
- priv->assoc_request.assoc_tsf_msw = network->time_stamp[1];
- priv->assoc_request.assoc_tsf_lsw = network->time_stamp[0];
+ priv->assoc_request.assoc_tsf_msw = cpu_to_le32(network->time_stamp[1]);
+ priv->assoc_request.assoc_tsf_lsw = cpu_to_le32(network->time_stamp[0]);
}
memcpy(priv->assoc_request.bssid, network->bssid, ETH_ALEN);
if (priv->ieee->iw_mode == IW_MODE_ADHOC) {
memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN);
- priv->assoc_request.atim_window = network->atim_window;
+ priv->assoc_request.atim_window = cpu_to_le16(network->atim_window);
} else {
memcpy(priv->assoc_request.dest, network->bssid, ETH_ALEN);
priv->assoc_request.atim_window = 0;
}
- priv->assoc_request.listen_interval = network->listen_interval;
+ priv->assoc_request.listen_interval = cpu_to_le16(network->listen_interval);
err = ipw_send_ssid(priv, priv->essid, priv->essid_len);
if (err) {
@@ -7768,11 +7741,11 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
- ipw_rt->rt_hdr.it_len = sizeof(struct ipw_rt_hdr); /* total header+data */
+ ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total header+data */
/* Big bitfield of all the fields we provide in radiotap */
- ipw_rt->rt_hdr.it_present =
- ((1 << IEEE80211_RADIOTAP_TSFT) |
+ ipw_rt->rt_hdr.it_present = cpu_to_le32(
+ (1 << IEEE80211_RADIOTAP_TSFT) |
(1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_RATE) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
@@ -7801,7 +7774,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
} else { /* 802.11g */
ipw_rt->rt_chbitmask =
- (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
+ cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
}
/* set the rate in multiples of 500k/s */
@@ -7982,14 +7955,14 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
- ipw_rt->rt_hdr.it_len = sizeof(*ipw_rt); /* total header+data */
+ ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*ipw_rt)); /* total header+data */
/* Set the size of the skb to the size of the frame */
- skb_put(skb, ipw_rt->rt_hdr.it_len + len);
+ skb_put(skb, sizeof(*ipw_rt) + len);
/* Big bitfield of all the fields we provide in radiotap */
- ipw_rt->rt_hdr.it_present =
- ((1 << IEEE80211_RADIOTAP_TSFT) |
+ ipw_rt->rt_hdr.it_present = cpu_to_le32(
+ (1 << IEEE80211_RADIOTAP_TSFT) |
(1 << IEEE80211_RADIOTAP_FLAGS) |
(1 << IEEE80211_RADIOTAP_RATE) |
(1 << IEEE80211_RADIOTAP_CHANNEL) |
@@ -8018,7 +7991,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
} else { /* 802.11g */
ipw_rt->rt_chbitmask =
- (IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
+ cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ);
}
/* set the rate in multiples of 500k/s */
@@ -8912,6 +8885,8 @@ static int ipw_wx_get_range(struct net_device *dev,
range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
+ range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE;
+
IPW_DEBUG_WX("GET Range\n");
return 0;
}
@@ -10348,7 +10323,7 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
tfd->u.data.chunk_ptr[i] =
cpu_to_le32(pci_map_single
(priv->pci_dev, skb->data,
- tfd->u.data.chunk_len[i],
+ remaining_bytes,
PCI_DMA_TODEVICE));
tfd->u.data.num_chunks =
@@ -10443,24 +10418,24 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
rt_hdr->it_pad = 0;
rt_hdr->it_present = 0; /* after all, it's just an idea */
- rt_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL);
+ rt_hdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL);
- *(u16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(
+ *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16(
ieee80211chan2mhz(priv->channel));
if (priv->channel > 14) /* 802.11a */
- *(u16*)skb_put(dst, sizeof(u16)) =
+ *(__le16*)skb_put(dst, sizeof(u16)) =
cpu_to_le16(IEEE80211_CHAN_OFDM |
IEEE80211_CHAN_5GHZ);
else if (priv->ieee->mode == IEEE_B) /* 802.11b */
- *(u16*)skb_put(dst, sizeof(u16)) =
+ *(__le16*)skb_put(dst, sizeof(u16)) =
cpu_to_le16(IEEE80211_CHAN_CCK |
IEEE80211_CHAN_2GHZ);
else /* 802.11g */
- *(u16*)skb_put(dst, sizeof(u16)) =
+ *(__le16*)skb_put(dst, sizeof(u16)) =
cpu_to_le16(IEEE80211_CHAN_OFDM |
IEEE80211_CHAN_2GHZ);
- rt_hdr->it_len = dst->len;
+ rt_hdr->it_len = cpu_to_le16(dst->len);
skb_copy_from_linear_data(src, skb_put(dst, len), len);
@@ -10873,9 +10848,9 @@ static void shim__set_security(struct net_device *dev,
#if 0
if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) &&
(((priv->assoc_request.capability &
- WLAN_CAPABILITY_PRIVACY) && !sec->enabled) ||
+ cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && !sec->enabled) ||
(!(priv->assoc_request.capability &
- WLAN_CAPABILITY_PRIVACY) && sec->enabled))) {
+ cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && sec->enabled))) {
IPW_DEBUG_ASSOC("Disassociating due to capability "
"change.\n");
ipw_disassociate(priv);
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h
index bec8e37a1738..fdc187e0769d 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2200.h
@@ -267,25 +267,25 @@ enum connection_manager_assoc_states {
#define CW_MIN_CCK 31
#define CW_MAX_CCK 1023
-#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM
-#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM
-#define QOS_TX2_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 )
-#define QOS_TX3_CW_MIN_OFDM ( (CW_MIN_OFDM + 1) / 4 - 1 )
-
-#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK
-#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK
-#define QOS_TX2_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 2 - 1 )
-#define QOS_TX3_CW_MIN_CCK ( (CW_MIN_CCK + 1) / 4 - 1 )
-
-#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM
-#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM
-#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM
-#define QOS_TX3_CW_MAX_OFDM ( (CW_MIN_OFDM + 1) / 2 - 1 )
-
-#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK
-#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK
-#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK
-#define QOS_TX3_CW_MAX_CCK ( (CW_MIN_CCK + 1) / 2 - 1 )
+#define QOS_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define QOS_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define QOS_TX2_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1)
+#define QOS_TX3_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/4 - 1)
+
+#define QOS_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
+#define QOS_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
+#define QOS_TX2_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1)
+#define QOS_TX3_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/4 - 1)
+
+#define QOS_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
+#define QOS_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
+#define QOS_TX2_CW_MAX_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define QOS_TX3_CW_MAX_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1)
+
+#define QOS_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
+#define QOS_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
+#define QOS_TX2_CW_MAX_CCK cpu_to_le16(CW_MIN_CCK)
+#define QOS_TX3_CW_MAX_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1)
#define QOS_TX0_AIFS (3 - QOS_AIFSN_MIN_VALUE)
#define QOS_TX1_AIFS (7 - QOS_AIFSN_MIN_VALUE)
@@ -299,33 +299,33 @@ enum connection_manager_assoc_states {
#define QOS_TX0_TXOP_LIMIT_CCK 0
#define QOS_TX1_TXOP_LIMIT_CCK 0
-#define QOS_TX2_TXOP_LIMIT_CCK 6016
-#define QOS_TX3_TXOP_LIMIT_CCK 3264
+#define QOS_TX2_TXOP_LIMIT_CCK cpu_to_le16(6016)
+#define QOS_TX3_TXOP_LIMIT_CCK cpu_to_le16(3264)
#define QOS_TX0_TXOP_LIMIT_OFDM 0
#define QOS_TX1_TXOP_LIMIT_OFDM 0
-#define QOS_TX2_TXOP_LIMIT_OFDM 3008
-#define QOS_TX3_TXOP_LIMIT_OFDM 1504
+#define QOS_TX2_TXOP_LIMIT_OFDM cpu_to_le16(3008)
+#define QOS_TX3_TXOP_LIMIT_OFDM cpu_to_le16(1504)
-#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM
+#define DEF_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define DEF_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define DEF_TX2_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
+#define DEF_TX3_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM)
-#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK
+#define DEF_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
+#define DEF_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
+#define DEF_TX2_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
+#define DEF_TX3_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK)
-#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM
+#define DEF_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
+#define DEF_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
+#define DEF_TX2_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
+#define DEF_TX3_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM)
-#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK
+#define DEF_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
+#define DEF_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
+#define DEF_TX2_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
+#define DEF_TX3_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK)
#define DEF_TX0_AIFS 0
#define DEF_TX1_AIFS 0
@@ -388,18 +388,18 @@ struct clx2_queue {
} __attribute__ ((packed));
struct machdr32 {
- u16 frame_ctl;
+ __le16 frame_ctl;
u16 duration; // watch out for endians!
u8 addr1[MACADRR_BYTE_LEN];
u8 addr2[MACADRR_BYTE_LEN];
u8 addr3[MACADRR_BYTE_LEN];
u16 seq_ctrl; // more endians!
u8 addr4[MACADRR_BYTE_LEN];
- u16 qos_ctrl;
+ __le16 qos_ctrl;
} __attribute__ ((packed));
struct machdr30 {
- u16 frame_ctl;
+ __le16 frame_ctl;
u16 duration; // watch out for endians!
u8 addr1[MACADRR_BYTE_LEN];
u8 addr2[MACADRR_BYTE_LEN];
@@ -409,17 +409,17 @@ struct machdr30 {
} __attribute__ ((packed));
struct machdr26 {
- u16 frame_ctl;
+ __le16 frame_ctl;
u16 duration; // watch out for endians!
u8 addr1[MACADRR_BYTE_LEN];
u8 addr2[MACADRR_BYTE_LEN];
u8 addr3[MACADRR_BYTE_LEN];
u16 seq_ctrl; // more endians!
- u16 qos_ctrl;
+ __le16 qos_ctrl;
} __attribute__ ((packed));
struct machdr24 {
- u16 frame_ctl;
+ __le16 frame_ctl;
u16 duration; // watch out for endians!
u8 addr1[MACADRR_BYTE_LEN];
u8 addr2[MACADRR_BYTE_LEN];
@@ -466,15 +466,15 @@ struct tfd_command {
struct tfd_data {
/* Header */
- u32 work_area_ptr;
+ __le32 work_area_ptr;
u8 station_number; /* 0 for BSS */
u8 reserved1;
- u16 reserved2;
+ __le16 reserved2;
/* Tx Parameters */
u8 cmd_id;
u8 seq_num;
- u16 len;
+ __le16 len;
u8 priority;
u8 tx_flags;
u8 tx_flags_ext;
@@ -482,11 +482,11 @@ struct tfd_data {
u8 wepkey[DCT_WEP_KEY_FIELD_LENGTH];
u8 rate;
u8 antenna;
- u16 next_packet_duration;
- u16 next_frag_len;
- u16 back_off_counter; //////txop;
+ __le16 next_packet_duration;
+ __le16 next_frag_len;
+ __le16 back_off_counter; //////txop;
u8 retrylimit;
- u16 cwcurrent;
+ __le16 cwcurrent;
u8 reserved3;
/* 802.11 MAC Header */
@@ -498,9 +498,9 @@ struct tfd_data {
} tfd;
/* Payload DMA info */
- u32 num_chunks;
- u32 chunk_ptr[NUM_TFD_CHUNKS];
- u16 chunk_len[NUM_TFD_CHUNKS];
+ __le32 num_chunks;
+ __le32 chunk_ptr[NUM_TFD_CHUNKS];
+ __le16 chunk_len[NUM_TFD_CHUNKS];
} __attribute__ ((packed));
struct txrx_control_flags {
@@ -547,14 +547,14 @@ struct clx2_tx_queue {
// Used for passing to driver number of successes and failures per rate
struct rate_histogram {
union {
- u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
- u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
- u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
} success;
union {
- u32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
- u32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
- u32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
} failed;
} __attribute__ ((packed));
@@ -602,13 +602,13 @@ struct notif_scan_complete {
} __attribute__ ((packed));
struct notif_frag_length {
- u16 frag_length;
- u16 reserved;
+ __le16 frag_length;
+ __le16 reserved;
} __attribute__ ((packed));
struct notif_beacon_state {
- u32 state;
- u32 number;
+ __le32 state;
+ __le32 number;
} __attribute__ ((packed));
struct notif_tgi_tx_key {
@@ -627,7 +627,7 @@ struct notif_link_deterioration {
u8 modulation;
struct rate_histogram histogram;
u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */
- u16 silence_count;
+ __le16 silence_count;
} __attribute__ ((packed));
struct notif_association {
@@ -645,14 +645,14 @@ struct notif_calibration {
} __attribute__ ((packed));
struct notif_noise {
- u32 value;
+ __le32 value;
} __attribute__ ((packed));
struct ipw_rx_notification {
u8 reserved[8];
u8 subtype;
u8 flags;
- u16 size;
+ __le16 size;
union {
struct notif_association assoc;
struct notif_authenticate auth;
@@ -669,7 +669,7 @@ struct ipw_rx_notification {
} __attribute__ ((packed));
struct ipw_rx_frame {
- u32 reserved1;
+ __le32 reserved1;
u8 parent_tsf[4]; // fw_use[0] is boolean for OUR_TSF_IS_GREATER
u8 received_channel; // The channel that this frame was received on.
// Note that for .11b this does not have to be
@@ -680,14 +680,14 @@ struct ipw_rx_frame {
u8 rssi;
u8 agc;
u8 rssi_dbm;
- u16 signal;
- u16 noise;
+ __le16 signal;
+ __le16 noise;
u8 antennaAndPhy;
u8 control; // control bit should be on in bg
u8 rtscts_rate; // rate of rts or cts (in rts cts sequence rate
// is identical)
u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen
- u16 length;
+ __le16 length;
u8 data[0];
} __attribute__ ((packed));
@@ -827,14 +827,14 @@ struct ipw_tgi_tx_key {
u8 station_index;
u8 flags;
u8 key[16];
- u32 tx_counter[2];
+ __le32 tx_counter[2];
} __attribute__ ((packed));
#define IPW_SCAN_CHANNELS 54
struct ipw_scan_request {
u8 scan_type;
- u16 dwell_time;
+ __le16 dwell_time;
u8 channels_list[IPW_SCAN_CHANNELS];
u8 channels_reserved[3];
} __attribute__ ((packed));
@@ -849,11 +849,11 @@ enum {
};
struct ipw_scan_request_ext {
- u32 full_scan_index;
+ __le32 full_scan_index;
u8 channels_list[IPW_SCAN_CHANNELS];
u8 scan_type[IPW_SCAN_CHANNELS / 2];
u8 reserved;
- u16 dwell_time[IPW_SCAN_TYPES];
+ __le16 dwell_time[IPW_SCAN_TYPES];
} __attribute__ ((packed));
static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index)
@@ -881,20 +881,20 @@ struct ipw_associate {
u8 auth_type:4, auth_key:4;
u8 assoc_type;
u8 reserved;
- u16 policy_support;
+ __le16 policy_support;
u8 preamble_length;
u8 ieee_mode;
u8 bssid[ETH_ALEN];
- u32 assoc_tsf_msw;
- u32 assoc_tsf_lsw;
- u16 capability;
- u16 listen_interval;
- u16 beacon_interval;
+ __le32 assoc_tsf_msw;
+ __le32 assoc_tsf_lsw;
+ __le16 capability;
+ __le16 listen_interval;
+ __le16 beacon_interval;
u8 dest[ETH_ALEN];
- u16 atim_window;
+ __le16 atim_window;
u8 smr;
u8 reserved1;
- u16 reserved2;
+ __le16 reserved2;
} __attribute__ ((packed));
struct ipw_supported_rates {
@@ -906,13 +906,13 @@ struct ipw_supported_rates {
} __attribute__ ((packed));
struct ipw_rts_threshold {
- u16 rts_threshold;
- u16 reserved;
+ __le16 rts_threshold;
+ __le16 reserved;
} __attribute__ ((packed));
struct ipw_frag_threshold {
- u16 frag_threshold;
- u16 reserved;
+ __le16 frag_threshold;
+ __le16 reserved;
} __attribute__ ((packed));
struct ipw_retry_limit {
@@ -931,7 +931,7 @@ struct ipw_dino_config {
struct ipw_aironet_info {
u8 id;
u8 length;
- u16 reserved;
+ __le16 reserved;
} __attribute__ ((packed));
struct ipw_rx_key {
@@ -977,12 +977,12 @@ struct ipw_tx_power {
struct ipw_rsn_capabilities {
u8 id;
u8 length;
- u16 version;
+ __le16 version;
} __attribute__ ((packed));
struct ipw_sensitivity_calib {
- u16 beacon_rssi_raw;
- u16 reserved;
+ __le16 beacon_rssi_raw;
+ __le16 reserved;
} __attribute__ ((packed));
/**
@@ -1156,8 +1156,8 @@ struct ipw_rt_hdr {
u64 rt_tsf; /* TSF */
u8 rt_flags; /* radiotap packet flags */
u8 rt_rate; /* rate in 500kb/s */
- u16 rt_channel; /* channel in mhz */
- u16 rt_chbitmask; /* channel bitfield */
+ __le16 rt_channel; /* channel in mhz */
+ __le16 rt_chbitmask; /* channel bitfield */
s8 rt_dbmsignal; /* signal in dbM, kluged to signed */
s8 rt_dbmnoise;
u8 rt_antenna; /* antenna number */
@@ -1759,7 +1759,7 @@ enum {
#define HC_IBSS_RECONF 4
#define HC_DISASSOC_QUIET 5
-#define HC_QOS_SUPPORT_ASSOC 0x01
+#define HC_QOS_SUPPORT_ASSOC cpu_to_le16(0x01)
#define IPW_RATE_CAPABILITIES 1
#define IPW_RATE_CONNECT 0
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 8d52a26c248a..d1af938b9aa6 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -1,24 +1,64 @@
-config IWLWIFI
- bool "Intel Wireless WiFi Link Drivers"
+config IWL4965
+ tristate "Intel Wireless WiFi 4965AGN"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
- default n
---help---
- Select to enable drivers based on the iwlwifi project. This
- project provides a common foundation for Intel's wireless
- drivers designed to use the mac80211 subsystem.
-
- See <file:Documentation/networking/README.iwlwifi> for
- information on the capabilities currently enabled in this
- driver and for tips for debugging issues and problems.
-
-config IWLWIFI_DEBUG
- bool "Enable full debugging output in iwlwifi drivers"
- depends on IWLWIFI
- default y
+ Select to build the driver supporting the:
+
+ Intel Wireless WiFi Link 4965AGN
+
+ This driver uses the kernel's mac80211 subsystem.
+
+ In order to use this driver, you will need a microcode (uCode)
+ image for it. You can obtain the microcode from:
+
+ <http://intellinuxwireless.org/>.
+
+ The microcode is typically installed in /lib/firmware. You can
+ look in the hotplug script /etc/hotplug/firmware.agent to
+ determine which directory FIRMWARE_DIR is set to when the script
+ runs.
+
+ If you want to compile the driver as a module ( = code which can be
+ inserted in and remvoed from the running kernel whenever you want),
+ say M here and read <file:Documentation/kbuild/modules.txt>. The
+ module will be called iwl4965.ko.
+
+config IWL4965_QOS
+ bool "Enable Wireless QoS in iwl4965 driver"
+ depends on IWL4965
---help---
- This option will enable debug tracing output for the iwlwifi
- drivers.
+ This option will enable wireless quality of service (QoS) for the
+ iwl4965 driver.
+
+config IWL4965_HT
+ bool "Enable 802.11n HT features in iwl4965 driver"
+ depends on EXPERIMENTAL
+ depends on IWL4965 && IWL4965_QOS
+ depends on n
+ ---help---
+ This option enables IEEE 802.11n High Throughput features
+ for the iwl4965 driver.
+
+config IWL4965_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwl4965 driver"
+ depends on IWL4965
+ ---help---
+ This option will enable spectrum measurement for the iwl4965 driver.
+
+config IWL4965_SENSITIVITY
+ bool "Enable Sensitivity Calibration in iwl4965 driver"
+ depends on IWL4965
+ ---help---
+ This option will enable sensitivity calibration for the iwl4965
+ driver.
+
+config IWL4965_DEBUG
+ bool "Enable full debugging output in iwl4965 driver"
+ depends on IWL4965
+ ---help---
+ This option will enable debug tracing output for the iwl4965
+ driver.
This will result in the kernel module being ~100k larger. You can
control which debug output is sent to the kernel log by setting the
@@ -33,96 +73,74 @@ config IWLWIFI_DEBUG
% echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level
You can find the list of debug mask values in:
- drivers/net/wireless/mac80211/iwlwifi/iwl-debug.h
+ drivers/net/wireless/iwlwifi/iwl-4965-debug.h
If this is your first time using this driver, you should say Y here
as the debug information can assist others in helping you resolve
any problems you may encounter.
-config IWLWIFI_SENSITIVITY
- bool "Enable Sensitivity Calibration in iwlwifi drivers"
- depends on IWLWIFI
- default y
- ---help---
- This option will enable sensitivity calibration for the iwlwifi
- drivers.
-
-config IWLWIFI_SPECTRUM_MEASUREMENT
- bool "Enable Spectrum Measurement in iwlwifi drivers"
- depends on IWLWIFI
- default y
- ---help---
- This option will enable spectrum measurement for the iwlwifi drivers.
-
-config IWLWIFI_QOS
- bool "Enable Wireless QoS in iwlwifi drivers"
- depends on IWLWIFI
- default y
- ---help---
- This option will enable wireless quality of service (QoS) for the
- iwlwifi drivers.
-
-config IWLWIFI_HT
- bool "Enable 802.11n HT features in iwlwifi drivers"
- depends on EXPERIMENTAL
- depends on IWLWIFI && MAC80211_HT
- default n
- ---help---
- This option enables IEEE 802.11n High Throughput features
- for the iwlwifi drivers.
-
-config IWL4965
- tristate "Intel Wireless WiFi 4965AGN"
- depends on m && IWLWIFI && EXPERIMENTAL
- default m
+config IWL3945
+ tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
+ depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ select FW_LOADER
---help---
Select to build the driver supporting the:
- Intel Wireless WiFi Link 4965AGN
+ Intel PRO/Wireless 3945ABG/BG Network Connection
This driver uses the kernel's mac80211 subsystem.
- See <file:Documentation/networking/README.iwlwifi> for
- information on the capabilities currently enabled in this
- driver and for tips for debugging any issues or problems.
-
In order to use this driver, you will need a microcode (uCode)
image for it. You can obtain the microcode from:
<http://intellinuxwireless.org/>.
- See the above referenced README.iwlwifi for information on where
- to install the microcode images.
+ The microcode is typically installed in /lib/firmware. You can
+ look in the hotplug script /etc/hotplug/firmware.agent to
+ determine which directory FIRMWARE_DIR is set to when the script
+ runs.
If you want to compile the driver as a module ( = code which can be
inserted in and remvoed from the running kernel whenever you want),
say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called iwl4965.ko.
+ module will be called iwl3945.ko.
-config IWL3945
- tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
- depends on m && IWLWIFI && EXPERIMENTAL
- default m
+config IWL3945_QOS
+ bool "Enable Wireless QoS in iwl3945 driver"
+ depends on IWL3945
---help---
- Select to build the driver supporting the:
+ This option will enable wireless quality of service (QoS) for the
+ iwl3945 driver.
- Intel PRO/Wireless 3945ABG/BG Network Connection
+config IWL3945_SPECTRUM_MEASUREMENT
+ bool "Enable Spectrum Measurement in iwl3945 drivers"
+ depends on IWL3945
+ ---help---
+ This option will enable spectrum measurement for the iwl3945 driver.
- This driver uses the kernel's mac80211 subsystem.
+config IWL3945_DEBUG
+ bool "Enable full debugging output in iwl3945 driver"
+ depends on IWL3945
+ ---help---
+ This option will enable debug tracing output for the iwl3945
+ driver.
+
+ This will result in the kernel module being ~100k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
- See <file:Documentation/networking/README.iwlwifi> for
- information on the capabilities currently enabled in this
- driver and for tips for debugging any issues or problems.
+ /sys/bus/pci/drivers/${DRIVER}/debug_level
- In order to use this driver, you will need a microcode (uCode)
- image for it. You can obtain the microcode from:
+ This entry will only exist if this option is enabled.
- <http://intellinuxwireless.org/>.
+ To set a value, simply echo an 8-byte hex value to the same file:
+
+ % echo 0x43fff > /sys/bus/pci/drivers/${DRIVER}/debug_level
- See the above referenced README.iwlwifi for information on where
- to install the microcode images.
+ You can find the list of debug mask values in:
+ drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+
+ If this is your first time using this driver, you should say Y here
+ as the debug information can assist others in helping you resolve
+ any problems you may encounter.
- If you want to compile the driver as a module ( = code which can be
- inserted in and remvoed from the running kernel whenever you want),
- say M here and read <file:Documentation/kbuild/modules.txt>. The
- module will be called iwl3945.ko.
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
index 9de8d7f6efa3..46bb2c7d11dd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
+ * it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
@@ -60,9 +60,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+/*
+ * Please use this file (iwl-3945-commands.h) only for uCode API definitions.
+ * Please use iwl-3945-hw.h for hardware-related definitions.
+ * Please use iwl-3945.h for driver implementation definitions.
+ */
-#ifndef __iwl_commands_h__
-#define __iwl_commands_h__
+#ifndef __iwl_3945_commands_h__
+#define __iwl_3945_commands_h__
enum {
REPLY_ALIVE = 0x1,
@@ -80,9 +85,7 @@ enum {
REPLY_REMOVE_ALL_STA = 0x1a, /* not used */
/* RX, TX, LEDs */
-#if IWL == 3945
REPLY_3945_RX = 0x1b, /* 3945 only */
-#endif
REPLY_TX = 0x1c,
REPLY_RATE_SCALE = 0x47, /* 3945 only */
REPLY_LEDS_CMD = 0x48,
@@ -118,10 +121,10 @@ enum {
REPLY_TX_PWR_TABLE_CMD = 0x97,
MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */
- /* BT config command */
+ /* Bluetooth device coexistance config command */
REPLY_BT_CONFIG = 0x9b,
- /* 4965 Statistics */
+ /* Statistics */
REPLY_STATISTICS_CMD = 0x9c,
STATISTICS_NOTIFICATION = 0x9d,
@@ -132,46 +135,85 @@ enum {
/* Missed beacons notification */
MISSED_BEACONS_NOTIFICATION = 0xa2,
-#if IWL == 4965
- REPLY_CT_KILL_CONFIG_CMD = 0xa4,
- SENSITIVITY_CMD = 0xa8,
- REPLY_PHY_CALIBRATION_CMD = 0xb0,
- REPLY_RX_PHY_CMD = 0xc0,
- REPLY_RX_MPDU_CMD = 0xc1,
- REPLY_4965_RX = 0xc3,
- REPLY_COMPRESSED_BA = 0xc5,
-#endif
REPLY_MAX = 0xff
};
/******************************************************************************
* (0)
- * Header
+ * Commonly used structures and definitions:
+ * Command header, txpower
*
*****************************************************************************/
+/* iwl3945_cmd_header flags value */
#define IWL_CMD_FAILED_MSK 0x40
-struct iwl_cmd_header {
- u8 cmd;
- u8 flags;
- /* We have 15 LSB to use as we please (MSB indicates
- * a frame Rx'd from the HW). We encode the following
- * information into the sequence field:
+/**
+ * struct iwl3945_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl3945_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 flags; /* IWL_CMD_* */
+ /*
+ * The driver sets up the sequence number to values of its chosing.
+ * uCode does not use this value, but passes it back to the driver
+ * when sending the response to each driver-originated command, so
+ * the driver can match the response to the command. Since the values
+ * don't get used by uCode, the driver may set up an arbitrary format.
*
- * 0:7 index in fifo
- * 8:13 fifo selection
- * 14:14 bit indicating if this packet references the 'extra'
- * storage at the end of the memory queue
- * 15:15 (Rx indication)
+ * There is one exception: uCode sets bit 15 when it originates
+ * the response/notification, i.e. when the response/notification
+ * is not a direct response to a command sent by the driver. For
+ * example, uCode issues REPLY_3945_RX when it sends a received frame
+ * to the driver; it is not a direct response to any driver command.
*
+ * The Linux driver uses the following format:
+ *
+ * 0:7 index/position within Tx queue
+ * 8:13 Tx queue selection
+ * 14:14 driver sets this to indicate command is in the 'huge'
+ * storage at the end of the command buffers, i.e. scan cmd
+ * 15:15 uCode sets this in uCode-originated response/notification
*/
__le16 sequence;
- /* command data follows immediately */
+ /* command or response/notification data follows immediately */
u8 data[0];
} __attribute__ ((packed));
+/**
+ * struct iwl3945_tx_power
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Each entry contains two values:
+ * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained
+ * linear value that multiplies the output of the digital signal processor,
+ * before being sent to the analog radio.
+ * 2) Radio gain. This sets the analog gain of the radio Tx path.
+ * It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
+ */
+struct iwl3945_tx_power {
+ u8 tx_gain; /* gain for analog radio */
+ u8 dsp_atten; /* gain for DSP */
+} __attribute__ ((packed));
+
+/**
+ * struct iwl3945_power_per_rate
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl3945_power_per_rate {
+ u8 rate; /* plcp */
+ struct iwl3945_tx_power tpc;
+ u8 reserved;
+} __attribute__ ((packed));
+
/******************************************************************************
* (0a)
* Alive and Error Commands & Responses:
@@ -182,15 +224,22 @@ struct iwl_cmd_header {
#define INITIALIZE_SUBTYPE (9)
/*
- * REPLY_ALIVE = 0x1 (response only, not a command)
+ * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "initialize alive" notification once the initialization
+ * uCode image has completed its work, and is ready to load the runtime image.
+ * This is the *first* "alive" notification that the driver will receive after
+ * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
*/
-struct iwl_alive_resp {
+struct iwl3945_init_alive_resp {
u8 ucode_minor;
u8 ucode_major;
__le16 reserved1;
u8 sw_rev[8];
u8 ver_type;
- u8 ver_subtype;
+ u8 ver_subtype; /* "9" for initialize alive */
__le16 reserved2;
__le32 log_event_table_ptr;
__le32 error_event_table_ptr;
@@ -198,29 +247,41 @@ struct iwl_alive_resp {
__le32 is_valid;
} __attribute__ ((packed));
-struct iwl_init_alive_resp {
+
+/**
+ * REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver. This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * This response includes two pointers to structures within the device's
+ * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
+ *
+ * 1) log_event_table_ptr indicates base of the event log. This traces
+ * a 256-entry history of uCode execution within a circular buffer.
+ *
+ * 2) error_event_table_ptr indicates base of the error log. This contains
+ * information about any uCode error that occurs.
+ *
+ * The Linux driver can print both logs to the system log when a uCode error
+ * occurs.
+ */
+struct iwl3945_alive_resp {
u8 ucode_minor;
u8 ucode_major;
__le16 reserved1;
u8 sw_rev[8];
u8 ver_type;
- u8 ver_subtype;
+ u8 ver_subtype; /* not "9" for runtime alive */
__le16 reserved2;
- __le32 log_event_table_ptr;
- __le32 error_event_table_ptr;
+ __le32 log_event_table_ptr; /* SRAM address for event log */
+ __le32 error_event_table_ptr; /* SRAM address for error log */
__le32 timestamp;
__le32 is_valid;
-
-#if IWL == 4965
- /* calibration values from "initialize" uCode */
- __le32 voltage; /* signed */
- __le32 therm_r1[2]; /* signed 1st for normal, 2nd for FAT channel */
- __le32 therm_r2[2]; /* signed */
- __le32 therm_r3[2]; /* signed */
- __le32 therm_r4[2]; /* signed */
- __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups,
- * 2 Tx chains */
-#endif
} __attribute__ ((packed));
union tsf {
@@ -232,14 +293,12 @@ union tsf {
/*
* REPLY_ERROR = 0x2 (response only, not a command)
*/
-struct iwl_error_resp {
+struct iwl3945_error_resp {
__le32 error_type;
u8 cmd_id;
u8 reserved1;
__le16 bad_cmd_seq_num;
-#if IWL == 3945
__le16 reserved2;
-#endif
__le32 error_info;
union tsf timestamp;
} __attribute__ ((packed));
@@ -300,10 +359,24 @@ enum {
/* transfer to host non bssid beacons in associated state */
#define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6)
-/*
+/**
* REPLY_RXON = 0x10 (command, has simple generic response)
+ *
+ * RXON tunes the radio tuner to a service channel, and sets up a number
+ * of parameters that are used primarily for Rx, but also for Tx operations.
+ *
+ * NOTE: When tuning to a new channel, driver must set the
+ * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent
+ * info within the device, including the station tables, tx retry
+ * rate tables, and txpower tables. Driver must build a new station
+ * table and txpower table before transmitting anything on the RXON
+ * channel.
+ *
+ * NOTE: All RXONs wipe clean the internal txpower table. Driver must
+ * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ * regardless of whether RXON_FILTER_ASSOC_MSK is set.
*/
-struct iwl_rxon_cmd {
+struct iwl3945_rxon_cmd {
u8 node_addr[6];
__le16 reserved1;
u8 bssid_addr[6];
@@ -312,45 +385,31 @@ struct iwl_rxon_cmd {
__le16 reserved3;
u8 dev_type;
u8 air_propagation;
-#if IWL == 3945
__le16 reserved4;
-#elif IWL == 4965
- __le16 rx_chain;
-#endif
u8 ofdm_basic_rates;
u8 cck_basic_rates;
__le16 assoc_id;
__le32 flags;
__le32 filter_flags;
__le16 channel;
-#if IWL == 3945
__le16 reserved5;
-#elif IWL == 4965
- u8 ofdm_ht_single_stream_basic_rates;
- u8 ofdm_ht_dual_stream_basic_rates;
-#endif
} __attribute__ ((packed));
/*
* REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
*/
-struct iwl_rxon_assoc_cmd {
+struct iwl3945_rxon_assoc_cmd {
__le32 flags;
__le32 filter_flags;
u8 ofdm_basic_rates;
u8 cck_basic_rates;
-#if IWL == 4965
- u8 ofdm_ht_single_stream_basic_rates;
- u8 ofdm_ht_dual_stream_basic_rates;
- __le16 rx_chain_select_flags;
-#endif
__le16 reserved;
} __attribute__ ((packed));
/*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
*/
-struct iwl_rxon_time_cmd {
+struct iwl3945_rxon_time_cmd {
union tsf timestamp;
__le16 beacon_interval;
__le16 atim_window;
@@ -359,52 +418,23 @@ struct iwl_rxon_time_cmd {
__le16 reserved;
} __attribute__ ((packed));
-struct iwl_tx_power {
- u8 tx_gain; /* gain for analog radio */
- u8 dsp_atten; /* gain for DSP */
-} __attribute__ ((packed));
-
-#if IWL == 3945
-struct iwl_power_per_rate {
- u8 rate; /* plcp */
- struct iwl_tx_power tpc;
- u8 reserved;
-} __attribute__ ((packed));
-
-#elif IWL == 4965
-#define POWER_TABLE_NUM_ENTRIES 33
-#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
-#define POWER_TABLE_CCK_ENTRY 32
-struct tx_power_dual_stream {
- __le32 dw;
-} __attribute__ ((packed));
-
-struct iwl_tx_power_db {
- struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
-} __attribute__ ((packed));
-#endif
-
/*
* REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
*/
-struct iwl_channel_switch_cmd {
+struct iwl3945_channel_switch_cmd {
u8 band;
u8 expect_beacon;
__le16 channel;
__le32 rxon_flags;
__le32 rxon_filter_flags;
__le32 switch_time;
-#if IWL == 3945
- struct iwl_power_per_rate power[IWL_MAX_RATES];
-#elif IWL == 4965
- struct iwl_tx_power_db tx_power;
-#endif
+ struct iwl3945_power_per_rate power[IWL_MAX_RATES];
} __attribute__ ((packed));
/*
* CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
*/
-struct iwl_csa_notification {
+struct iwl3945_csa_notification {
__le16 band;
__le16 channel;
__le32 status; /* 0 - OK, 1 - fail */
@@ -415,7 +445,24 @@ struct iwl_csa_notification {
* Quality-of-Service (QOS) Commands & Responses:
*
*****************************************************************************/
-struct iwl_ac_qos {
+
+/**
+ * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ *
+ * @cw_min: Contention window, start value in numbers of slots.
+ * Should be a power-of-2, minus 1. Device's default is 0x0f.
+ * @cw_max: Contention window, max value in numbers of slots.
+ * Should be a power-of-2, minus 1. Device's default is 0x3f.
+ * @aifsn: Number of slots in Arbitration Interframe Space (before
+ * performing random backoff timing prior to Tx). Device default 1.
+ * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0.
+ *
+ * Device will automatically increase contention window by (2*CW) + 1 for each
+ * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
+ * value, to cap the CW value.
+ */
+struct iwl3945_ac_qos {
__le16 cw_min;
__le16 cw_max;
u8 aifsn;
@@ -428,18 +475,18 @@ struct iwl_ac_qos {
#define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02)
#define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10)
-/*
- * TXFIFO Queue number defines
- */
-/* number of Access categories (AC) (EDCA), queues 0..3 */
+/* Number of Access Categories (AC) (EDCA), queues 0..3 */
#define AC_NUM 4
/*
* REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ *
+ * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
+ * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
*/
-struct iwl_qosparam_cmd {
+struct iwl3945_qosparam_cmd {
__le32 qos_flags;
- struct iwl_ac_qos ac[AC_NUM];
+ struct iwl3945_ac_qos ac[AC_NUM];
} __attribute__ ((packed));
/******************************************************************************
@@ -450,24 +497,21 @@ struct iwl_qosparam_cmd {
/*
* Multi station support
*/
+
+/* Special, dedicated locations within device's station table */
#define IWL_AP_ID 0
#define IWL_MULTICAST_ID 1
#define IWL_STA_ID 2
-
#define IWL3945_BROADCAST_ID 24
#define IWL3945_STATION_COUNT 25
-#define IWL4965_BROADCAST_ID 31
-#define IWL4965_STATION_COUNT 32
-
#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/
#define IWL_INVALID_STATION 255
-#if IWL == 3945
-#define STA_FLG_TX_RATE_MSK __constant_cpu_to_le32(1<<2);
-#endif
-#define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1<<8);
+#define STA_FLG_TX_RATE_MSK __constant_cpu_to_le32(1 << 2);
+#define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1 << 8);
+/* Use in mode field. 1: modify existing entry, 0: add new station entry */
#define STA_CONTROL_MODIFY_MSK 0x01
/* key flags __le16*/
@@ -480,13 +524,10 @@ struct iwl_qosparam_cmd {
#define STA_KEY_FLG_KEYID_POS 8
#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
-/* modify flags */
+/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
#define STA_MODIFY_TID_DISABLE_TX 0x02
#define STA_MODIFY_TX_RATE_MSK 0x04
-#define STA_MODIFY_ADDBA_TID_MSK 0x08
-#define STA_MODIFY_DELBA_TID_MSK 0x10
-#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
/*
* Antenna masks:
@@ -500,7 +541,7 @@ struct iwl_qosparam_cmd {
#define RATE_MCS_ANT_B_MSK 0x8000
#define RATE_MCS_ANT_AB_MSK 0xc000
-struct iwl_keyinfo {
+struct iwl3945_keyinfo {
__le16 key_flags;
u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
u8 reserved1;
@@ -509,6 +550,18 @@ struct iwl_keyinfo {
u8 key[16]; /* 16-byte unicast decryption key */
} __attribute__ ((packed));
+/**
+ * struct sta_id_modify
+ * @addr[ETH_ALEN]: station's MAC address
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
+ *
+ * Driver selects unused table index when adding new station,
+ * or the index to a pre-existing station entry when modifying that station.
+ * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ *
+ * modify_mask flags select which parameters to modify vs. leave alone.
+ */
struct sta_id_modify {
u8 addr[ETH_ALEN];
__le16 reserved1;
@@ -519,36 +572,67 @@ struct sta_id_modify {
/*
* REPLY_ADD_STA = 0x18 (command)
+ *
+ * The device contains an internal table of per-station information,
+ * with info on security keys, aggregation parameters, and Tx rates for
+ * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD,
+ * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ *
+ * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * a new entry, or modifying a pre-existing one.
+ *
+ * NOTE: RXON command (without "associated" bit set) wipes the station table
+ * clean. Moving into RF_KILL state does this also. Driver must set up
+ * new station table before transmitting anything on the RXON channel
+ * (except active scans or active measurements; those commands carry
+ * their own txpower/rate setup data).
+ *
+ * When getting started on a new channel, driver must set up the
+ * IWL_BROADCAST_ID entry (last entry in the table). For a client
+ * station in a BSS, once an AP is selected, driver sets up the AP STA
+ * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP
+ * are all that are needed for a BSS client station. If the device is
+ * used as AP, or in an IBSS network, driver must set up station table
+ * entries for all STAs in network, starting with index IWL_STA_ID.
*/
-struct iwl_addsta_cmd {
- u8 mode;
+struct iwl3945_addsta_cmd {
+ u8 mode; /* 1: modify existing, 0: add new station */
u8 reserved[3];
struct sta_id_modify sta;
- struct iwl_keyinfo key;
- __le32 station_flags;
- __le32 station_flags_msk;
+ struct iwl3945_keyinfo key;
+ __le32 station_flags; /* STA_FLG_* */
+ __le32 station_flags_msk; /* STA_FLG_* */
+
+ /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+ * corresponding to bit (e.g. bit 5 controls TID 5).
+ * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
__le16 tid_disable_tx;
-#if IWL == 3945
+
__le16 rate_n_flags;
-#else
- __le16 reserved1;
-#endif
+
+ /* TID for which to add block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
u8 add_immediate_ba_tid;
+
+ /* TID for which to remove block-ack support.
+ * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
u8 remove_immediate_ba_tid;
+
+ /* Starting Sequence Number for added block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
__le16 add_immediate_ba_ssn;
-#if IWL == 4965
- __le32 reserved2;
-#endif
} __attribute__ ((packed));
+#define ADD_STA_SUCCESS_MSK 0x1
+#define ADD_STA_NO_ROOM_IN_TABLE 0x2
+#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4
/*
* REPLY_ADD_STA = 0x18 (response)
*/
-struct iwl_add_sta_resp {
- u8 status;
+struct iwl3945_add_sta_resp {
+ u8 status; /* ADD_STA_* */
} __attribute__ ((packed));
-#define ADD_STA_SUCCESS_MSK 0x1
/******************************************************************************
* (4)
@@ -556,7 +640,7 @@ struct iwl_add_sta_resp {
*
*****************************************************************************/
-struct iwl_rx_frame_stats {
+struct iwl3945_rx_frame_stats {
u8 phy_count;
u8 id;
u8 rssi;
@@ -566,7 +650,7 @@ struct iwl_rx_frame_stats {
u8 payload[0];
} __attribute__ ((packed));
-struct iwl_rx_frame_hdr {
+struct iwl3945_rx_frame_hdr {
__le16 channel;
__le16 phy_flags;
u8 reserved1;
@@ -596,7 +680,7 @@ struct iwl_rx_frame_hdr {
#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
-struct iwl_rx_frame_end {
+struct iwl3945_rx_frame_end {
__le32 status;
__le64 timestamp;
__le32 beacon_timestamp;
@@ -610,10 +694,10 @@ struct iwl_rx_frame_end {
* The actual offsets of the hdr and end are dynamic based on
* stats.phy_count
*/
-struct iwl_rx_frame {
- struct iwl_rx_frame_stats stats;
- struct iwl_rx_frame_hdr hdr;
- struct iwl_rx_frame_end end;
+struct iwl3945_rx_frame {
+ struct iwl3945_rx_frame_stats stats;
+ struct iwl3945_rx_frame_hdr hdr;
+ struct iwl3945_rx_frame_end end;
} __attribute__ ((packed));
/* Fixed (non-configurable) rx data from phy */
@@ -659,36 +743,86 @@ struct iwl4965_rx_mpdu_res_start {
* (5)
* Tx Commands & Responses:
*
+ * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * queues in host DRAM, shared between driver and device. When the device's
+ * Tx scheduler and uCode are preparing to transmit, the device pulls the
+ * Tx command over the PCI bus via one of the device's Tx DMA channels,
+ * to fill an internal FIFO from which data will be transmitted.
+ *
+ * uCode handles all timing and protocol related to control frames
+ * (RTS/CTS/ACK), based on flags in the Tx command.
+ *
+ * uCode handles retrying Tx when an ACK is expected but not received.
+ * This includes trying lower data rates than the one requested in the Tx
+ * command, as set up by the REPLY_RATE_SCALE (for 3945) or
+ * REPLY_TX_LINK_QUALITY_CMD (4965).
+ *
+ * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * This command must be executed after every RXON command, before Tx can occur.
*****************************************************************************/
-/* Tx flags */
+/* REPLY_TX Tx flags field */
+
+/* 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
+
+/* 1: Transmit Clear-To-Send to self before this frame.
+ * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
+
+/* 1: Expect ACK from receiving station
+ * 0: Don't expect ACK (MAC header's duration field s/b 0)
+ * Set this for unicast frames, but not broadcast/multicast. */
#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
+
+/* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
+ * Tx command's initial_rate_index indicates first rate to try;
+ * uCode walks through table for additional Tx attempts.
+ * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
+ * This rate will be used for all Tx attempts; it will not be scaled. */
#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
+
+/* 1: Expect immediate block-ack.
+ * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
#define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6)
+
+/* 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set. */
#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
+
+/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
+ * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
-/* ucode ignores BT priority for this frame */
+/* 1: Ignore Bluetooth priority for this frame.
+ * 0: Delay Tx until Bluetooth device is done (normal usage). */
#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
-/* ucode overrides sequence control */
+/* 1: uCode overrides sequence control field in MAC header.
+ * 0: Driver provides sequence control field in MAC header.
+ * Set this for management frames, non-QOS data frames, non-unicast frames,
+ * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
-/* signal that this frame is non-last MPDU */
+/* 1: This frame is non-last MPDU; more fragments are coming.
+ * 0: Last fragment, or not using fragmentation. */
#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
-/* calculate TSF in outgoing frame */
+/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
+ * 0: No TSF required in outgoing frame.
+ * Set this for transmitting beacons and probe responses. */
#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
-/* activate TX calibration. */
-#define TX_CMD_FLG_CALIB_MSK __constant_cpu_to_le32(1 << 17)
-
-/* signals that 2 bytes pad was inserted
- after the MAC header */
+/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
+ * alignment of frame's payload data field.
+ * 0: No pad
+ * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
+ * field (but not both). Driver must align frame data (i.e. data following
+ * MAC header) to DWORD boundary. */
#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
/* HCCA-AP - disable duration overwriting. */
@@ -705,68 +839,65 @@ struct iwl4965_rx_mpdu_res_start {
#define TX_CMD_SEC_KEY128 0x08
/*
- * TX command Frame life time
- */
-
-struct iwl_dram_scratch {
- u8 try_cnt;
- u8 bt_kill_cnt;
- __le16 reserved;
-} __attribute__ ((packed));
-
-/*
* REPLY_TX = 0x1c (command)
*/
-struct iwl_tx_cmd {
+struct iwl3945_tx_cmd {
+ /*
+ * MPDU byte count:
+ * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+ * + 8 byte IV for CCM or TKIP (not used for WEP)
+ * + Data payload
+ * + 8-byte MIC (not used for CCM/WEP)
+ * NOTE: Does not include Tx command bytes, post-MAC pad bytes,
+ * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+ * Range: 14-2342 bytes.
+ */
__le16 len;
+
+ /*
+ * MPDU or MSDU byte count for next frame.
+ * Used for fragmentation and bursting, but not 11n aggregation.
+ * Same as "len", but for next frame. Set to 0 if not applicable.
+ */
__le16 next_frame_len;
- __le32 tx_flags;
-#if IWL == 3945
+
+ __le32 tx_flags; /* TX_CMD_FLG_* */
+
u8 rate;
+
+ /* Index of recipient station in uCode's station table */
u8 sta_id;
u8 tid_tspec;
-#elif IWL == 4965
- struct iwl_dram_scratch scratch;
- __le32 rate_n_flags;
- u8 sta_id;
-#endif
u8 sec_ctl;
-#if IWL == 4965
- u8 initial_rate_index;
- u8 reserved;
-#endif
u8 key[16];
-#if IWL == 3945
union {
u8 byte[8];
__le16 word[4];
__le32 dw[2];
} tkip_mic;
__le32 next_frame_info;
-#elif IWL == 4965
- __le16 next_frame_flags;
- __le16 reserved2;
-#endif
union {
__le32 life_time;
__le32 attempt;
} stop_time;
-#if IWL == 3945
u8 supp_rates[2];
-#elif IWL == 4965
- __le32 dram_lsb_ptr;
- u8 dram_msb_ptr;
-#endif
u8 rts_retry_limit; /*byte 50 */
u8 data_retry_limit; /*byte 51 */
-#if IWL == 4965
- u8 tid_tspec;
-#endif
union {
__le16 pm_frame_timeout;
__le16 attempt_duration;
} timeout;
+
+ /*
+ * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+ * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+ */
__le16 driver_txop;
+
+ /*
+ * MAC header goes here, followed by 2 bytes padding if MAC header
+ * length is 26 or 30 bytes, followed by payload data
+ */
u8 payload[0];
struct ieee80211_hdr hdr[0];
} __attribute__ ((packed));
@@ -838,104 +969,36 @@ enum {
TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */
};
-/* *******************************
- * TX aggregation state
- ******************************* */
-
-enum {
- AGG_TX_STATE_TRANSMITTED = 0x00,
- AGG_TX_STATE_UNDERRUN_MSK = 0x01,
- AGG_TX_STATE_BT_PRIO_MSK = 0x02,
- AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
- AGG_TX_STATE_ABORT_MSK = 0x08,
- AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
- AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
- AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40,
- AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
- AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
- AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
- AGG_TX_STATE_DUMP_TX_MSK = 0x200,
- AGG_TX_STATE_DELAY_TX_MSK = 0x400
-};
-
-#define AGG_TX_STATE_LAST_SENT_MSK \
-(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
- AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
- AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
-
-#define AGG_TX_STATE_TRY_CNT_POS 12
-#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
-
-#define AGG_TX_STATE_SEQ_NUM_POS 16
-#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
-
/*
* REPLY_TX = 0x1c (response)
*/
-#if IWL == 4965
-struct iwl_tx_resp {
- u8 frame_count; /* 1 no aggregation, >1 aggregation */
- u8 bt_kill_count;
- u8 failure_rts;
- u8 failure_frame;
- __le32 rate_n_flags;
- __le16 wireless_media_time;
- __le16 reserved;
- __le32 pa_power1;
- __le32 pa_power2;
- __le32 status; /* TX status (for aggregation status of 1st frame) */
-} __attribute__ ((packed));
-
-#elif IWL == 3945
-struct iwl_tx_resp {
+struct iwl3945_tx_resp {
u8 failure_rts;
u8 failure_frame;
u8 bt_kill_count;
u8 rate;
__le32 wireless_media_time;
- __le32 status; /* TX status (for aggregation status of 1st frame) */
-} __attribute__ ((packed));
-#endif
-
-/*
- * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
- */
-struct iwl_compressed_ba_resp {
- __le32 sta_addr_lo32;
- __le16 sta_addr_hi16;
- __le16 reserved;
- u8 sta_id;
- u8 tid;
- __le16 ba_seq_ctl;
- __le32 ba_bitmap0;
- __le32 ba_bitmap1;
- __le16 scd_flow;
- __le16 scd_ssn;
+ __le32 status; /* TX status */
} __attribute__ ((packed));
/*
* REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
*/
-struct iwl_txpowertable_cmd {
+struct iwl3945_txpowertable_cmd {
u8 band; /* 0: 5 GHz, 1: 2.4 GHz */
u8 reserved;
__le16 channel;
-#if IWL == 3945
- struct iwl_power_per_rate power[IWL_MAX_RATES];
-#elif IWL == 4965
- struct iwl_tx_power_db tx_power;
-#endif
+ struct iwl3945_power_per_rate power[IWL_MAX_RATES];
} __attribute__ ((packed));
-#if IWL == 3945
-struct iwl_rate_scaling_info {
+struct iwl3945_rate_scaling_info {
__le16 rate_n_flags;
u8 try_cnt;
u8 next_rate_index;
} __attribute__ ((packed));
/**
- * struct iwl_rate_scaling_cmd - Rate Scaling Command & Response
+ * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
*
* REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
*
@@ -947,61 +1010,22 @@ struct iwl_rate_scaling_info {
* For example, if you set 9MB (PLCP 0x0f) as the first
* rate in the rate table, the bit mask for that rate
* when passed through ofdm_basic_rates on the REPLY_RXON
- * command would be bit 0 (1<<0)
+ * command would be bit 0 (1 << 0)
*/
-struct iwl_rate_scaling_cmd {
+struct iwl3945_rate_scaling_cmd {
u8 table_id;
u8 reserved[3];
- struct iwl_rate_scaling_info table[IWL_MAX_RATES];
-} __attribute__ ((packed));
-
-#elif IWL == 4965
-
-/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
-#define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1<<0)
-
-#define LINK_QUAL_AC_NUM AC_NUM
-#define LINK_QUAL_MAX_RETRY_NUM 16
-
-#define LINK_QUAL_ANT_A_MSK (1<<0)
-#define LINK_QUAL_ANT_B_MSK (1<<1)
-#define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
-
-struct iwl_link_qual_general_params {
- u8 flags;
- u8 mimo_delimiter;
- u8 single_stream_ant_msk;
- u8 dual_stream_ant_msk;
- u8 start_rate_index[LINK_QUAL_AC_NUM];
-} __attribute__ ((packed));
-
-struct iwl_link_qual_agg_params {
- __le16 agg_time_limit;
- u8 agg_dis_start_th;
- u8 agg_frame_cnt_limit;
- __le32 reserved;
-} __attribute__ ((packed));
-
-/*
- * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
- */
-struct iwl_link_quality_cmd {
- u8 sta_id;
- u8 reserved1;
- __le16 control;
- struct iwl_link_qual_general_params general_params;
- struct iwl_link_qual_agg_params agg_params;
- struct {
- __le32 rate_n_flags;
- } rs_table[LINK_QUAL_MAX_RETRY_NUM];
- __le32 reserved2;
+ struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
} __attribute__ ((packed));
-#endif
/*
* REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ *
+ * 3945 and 4965 support hardware handshake with Bluetooth device on
+ * same platform. Bluetooth device alerts wireless device when it will Tx;
+ * wireless device can delay or kill its own Tx to accomodate.
*/
-struct iwl_bt_cmd {
+struct iwl3945_bt_cmd {
u8 flags;
u8 lead_time;
u8 max_kill;
@@ -1027,18 +1051,18 @@ struct iwl_bt_cmd {
RXON_FILTER_ASSOC_MSK | \
RXON_FILTER_BCON_AWARE_MSK)
-struct iwl_measure_channel {
+struct iwl3945_measure_channel {
__le32 duration; /* measurement duration in extended beacon
* format */
u8 channel; /* channel to measure */
- u8 type; /* see enum iwl_measure_type */
+ u8 type; /* see enum iwl3945_measure_type */
__le16 reserved;
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
*/
-struct iwl_spectrum_cmd {
+struct iwl3945_spectrum_cmd {
__le16 len; /* number of bytes starting from token */
u8 token; /* token id */
u8 id; /* measurement id -- 0 or 1 */
@@ -1051,13 +1075,13 @@ struct iwl_spectrum_cmd {
__le32 filter_flags; /* rxon filter flags */
__le16 channel_count; /* minimum 1, maximum 10 */
__le16 reserved3;
- struct iwl_measure_channel channels[10];
+ struct iwl3945_measure_channel channels[10];
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
*/
-struct iwl_spectrum_resp {
+struct iwl3945_spectrum_resp {
u8 token;
u8 id; /* id of the prior command replaced, or 0xff */
__le16 status; /* 0 - command will be handled
@@ -1065,12 +1089,12 @@ struct iwl_spectrum_resp {
* measurement) */
} __attribute__ ((packed));
-enum iwl_measurement_state {
+enum iwl3945_measurement_state {
IWL_MEASUREMENT_START = 0,
IWL_MEASUREMENT_STOP = 1,
};
-enum iwl_measurement_status {
+enum iwl3945_measurement_status {
IWL_MEASUREMENT_OK = 0,
IWL_MEASUREMENT_CONCURRENT = 1,
IWL_MEASUREMENT_CSA_CONFLICT = 2,
@@ -1083,18 +1107,18 @@ enum iwl_measurement_status {
#define NUM_ELEMENTS_IN_HISTOGRAM 8
-struct iwl_measurement_histogram {
+struct iwl3945_measurement_histogram {
__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */
__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */
} __attribute__ ((packed));
/* clear channel availability counters */
-struct iwl_measurement_cca_counters {
+struct iwl3945_measurement_cca_counters {
__le32 ofdm;
__le32 cck;
} __attribute__ ((packed));
-enum iwl_measure_type {
+enum iwl3945_measure_type {
IWL_MEASURE_BASIC = (1 << 0),
IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
@@ -1107,7 +1131,7 @@ enum iwl_measure_type {
/*
* SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
*/
-struct iwl_spectrum_notification {
+struct iwl3945_spectrum_notification {
u8 id; /* measurement id -- 0 or 1 */
u8 token;
u8 channel_index; /* index in measurement channel list */
@@ -1115,7 +1139,7 @@ struct iwl_spectrum_notification {
__le32 start_time; /* lower 32-bits of TSF */
u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */
u8 channel;
- u8 type; /* see enum iwl_measurement_type */
+ u8 type; /* see enum iwl3945_measurement_type */
u8 reserved1;
/* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
* valid if applicable for measurement type requested. */
@@ -1125,9 +1149,9 @@ struct iwl_spectrum_notification {
u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 -
* unidentified */
u8 reserved2[3];
- struct iwl_measurement_histogram histogram;
+ struct iwl3945_measurement_histogram histogram;
__le32 stop_time; /* lower 32-bits of TSF */
- __le32 status; /* see iwl_measurement_status */
+ __le32 status; /* see iwl3945_measurement_status */
} __attribute__ ((packed));
/******************************************************************************
@@ -1137,7 +1161,7 @@ struct iwl_spectrum_notification {
*****************************************************************************/
/**
- * struct iwl_powertable_cmd - Power Table Command
+ * struct iwl3945_powertable_cmd - Power Table Command
* @flags: See below:
*
* POWER_TABLE_CMD = 0x77 (command, has simple generic response)
@@ -1166,41 +1190,21 @@ struct iwl_spectrum_notification {
*/
#define IWL_POWER_VEC_SIZE 5
-
-#if IWL == 3945
-
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le32(1<<0)
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le32(1<<2)
-#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le32(1<<3)
-struct iwl_powertable_cmd {
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le32(1 << 0)
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le32(1 << 2)
+#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le32(1 << 3)
+struct iwl3945_powertable_cmd {
__le32 flags;
__le32 rx_data_timeout;
__le32 tx_data_timeout;
__le32 sleep_interval[IWL_POWER_VEC_SIZE];
} __attribute__((packed));
-#elif IWL == 4965
-
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le16(1<<0)
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le16(1<<2)
-#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1<<3)
-
-struct iwl_powertable_cmd {
- __le16 flags;
- u8 keep_alive_seconds;
- u8 debug_flags;
- __le32 rx_data_timeout;
- __le32 tx_data_timeout;
- __le32 sleep_interval[IWL_POWER_VEC_SIZE];
- __le32 keep_alive_beacons;
-} __attribute__ ((packed));
-#endif
-
/*
* PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
* 3945 and 4965 identical.
*/
-struct iwl_sleep_notification {
+struct iwl3945_sleep_notification {
u8 pm_sleep_mode;
u8 pm_wakeup_src;
__le16 reserved;
@@ -1230,14 +1234,14 @@ enum {
#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */
#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */
#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */
-struct iwl_card_state_cmd {
+struct iwl3945_card_state_cmd {
__le32 status; /* CARD_STATE_CMD_* request new power state */
} __attribute__ ((packed));
/*
* CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
*/
-struct iwl_card_state_notif {
+struct iwl3945_card_state_notif {
__le32 flags;
} __attribute__ ((packed));
@@ -1246,7 +1250,7 @@ struct iwl_card_state_notif {
#define RF_CARD_DISABLED 0x04
#define RXON_CARD_DISABLED 0x10
-struct iwl_ct_kill_config {
+struct iwl3945_ct_kill_config {
__le32 reserved;
__le32 critical_temperature_M;
__le32 critical_temperature_R;
@@ -1258,21 +1262,48 @@ struct iwl_ct_kill_config {
*
*****************************************************************************/
-struct iwl_scan_channel {
- /* type is defined as:
- * 0:0 active (0 - passive)
- * 1:4 SSID direct
- * If 1 is set then corresponding SSID IE is transmitted in probe
+/**
+ * struct iwl3945_scan_channel - entry in REPLY_SCAN_CMD channel table
+ *
+ * One for each channel in the scan list.
+ * Each channel can independently select:
+ * 1) SSID for directed active scans
+ * 2) Txpower setting (for rate specified within Tx command)
+ * 3) How long to stay on-channel (behavior may be modified by quiet_time,
+ * quiet_plcp_th, good_CRC_th)
+ *
+ * To avoid uCode errors, make sure the following are true (see comments
+ * under struct iwl3945_scan_cmd about max_out_time and quiet_time):
+ * 1) If using passive_dwell (i.e. passive_dwell != 0):
+ * active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
+ * 2) quiet_time <= active_dwell
+ * 3) If restricting off-channel time (i.e. max_out_time !=0):
+ * passive_dwell < max_out_time
+ * active_dwell < max_out_time
+ */
+struct iwl3945_scan_channel {
+ /*
+ * type is defined as:
+ * 0:0 1 = active, 0 = passive
+ * 1:4 SSID direct bit map; if a bit is set, then corresponding
+ * SSID IE is transmitted in probe request.
* 5:7 reserved
*/
u8 type;
- u8 channel;
- struct iwl_tx_power tpc;
- __le16 active_dwell;
- __le16 passive_dwell;
+ u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */
+ struct iwl3945_tx_power tpc;
+ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */
+ __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */
} __attribute__ ((packed));
-struct iwl_ssid_ie {
+/**
+ * struct iwl3945_ssid_ie - directed scan network information element
+ *
+ * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
+ * in struct iwl3945_scan_channel; each channel may select different ssids from
+ * among the 4 entries. SSID IEs get transmitted in reverse order of entry.
+ */
+struct iwl3945_ssid_ie {
u8 id;
u8 len;
u8 ssid[32];
@@ -1285,44 +1316,98 @@ struct iwl_ssid_ie {
/*
* REPLY_SCAN_CMD = 0x80 (command)
+ *
+ * The hardware scan command is very powerful; the driver can set it up to
+ * maintain (relatively) normal network traffic while doing a scan in the
+ * background. The max_out_time and suspend_time control the ratio of how
+ * long the device stays on an associated network channel ("service channel")
+ * vs. how long it's away from the service channel, tuned to other channels
+ * for scanning.
+ *
+ * max_out_time is the max time off-channel (in usec), and suspend_time
+ * is how long (in "extended beacon" format) that the scan is "suspended"
+ * after returning to the service channel. That is, suspend_time is the
+ * time that we stay on the service channel, doing normal work, between
+ * scan segments. The driver may set these parameters differently to support
+ * scanning when associated vs. not associated, and light vs. heavy traffic
+ * loads when associated.
+ *
+ * After receiving this command, the device's scan engine does the following;
+ *
+ * 1) Sends SCAN_START notification to driver
+ * 2) Checks to see if it has time to do scan for one channel
+ * 3) Sends NULL packet, with power-save (PS) bit set to 1,
+ * to tell AP that we're going off-channel
+ * 4) Tunes to first channel in scan list, does active or passive scan
+ * 5) Sends SCAN_RESULT notification to driver
+ * 6) Checks to see if it has time to do scan on *next* channel in list
+ * 7) Repeats 4-6 until it no longer has time to scan the next channel
+ * before max_out_time expires
+ * 8) Returns to service channel
+ * 9) Sends NULL packet with PS=0 to tell AP that we're back
+ * 10) Stays on service channel until suspend_time expires
+ * 11) Repeats entire process 2-10 until list is complete
+ * 12) Sends SCAN_COMPLETE notification
+ *
+ * For fast, efficient scans, the scan command also has support for staying on
+ * a channel for just a short time, if doing active scanning and getting no
+ * responses to the transmitted probe request. This time is controlled by
+ * quiet_time, and the number of received packets below which a channel is
+ * considered "quiet" is controlled by quiet_plcp_threshold.
+ *
+ * For active scanning on channels that have regulatory restrictions against
+ * blindly transmitting, the scan can listen before transmitting, to make sure
+ * that there is already legitimate activity on the channel. If enough
+ * packets are cleanly received on the channel (controlled by good_CRC_th,
+ * typical value 1), the scan engine starts transmitting probe requests.
+ *
+ * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
+ *
+ * To avoid uCode errors, see timing restrictions described under
+ * struct iwl3945_scan_channel.
*/
-struct iwl_scan_cmd {
+struct iwl3945_scan_cmd {
__le16 len;
u8 reserved0;
- u8 channel_count;
- __le16 quiet_time; /* dwell only this long on quiet chnl
- * (active scan) */
- __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */
- __le16 good_CRC_th; /* passive -> active promotion threshold */
-#if IWL == 3945
+ u8 channel_count; /* # channels in channel list */
+ __le16 quiet_time; /* dwell only this # millisecs on quiet channel
+ * (only for active scan) */
+ __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */
+ __le16 good_CRC_th; /* passive -> active promotion threshold */
__le16 reserved1;
-#elif IWL == 4965
- __le16 rx_chain;
-#endif
- __le32 max_out_time; /* max usec to be out of associated (service)
- * chnl */
- __le32 suspend_time; /* pause scan this long when returning to svc
- * chnl.
- * 3945 -- 31:24 # beacons, 19:0 additional usec,
- * 4965 -- 31:22 # beacons, 21:0 additional usec.
- */
- __le32 flags;
- __le32 filter_flags;
+ __le32 max_out_time; /* max usec to be away from associated (service)
+ * channel */
+ __le32 suspend_time; /* pause scan this long (in "extended beacon
+ * format") when returning to service channel:
+ * 3945; 31:24 # beacons, 19:0 additional usec,
+ * 4965; 31:22 # beacons, 21:0 additional usec.
+ */
+ __le32 flags; /* RXON_FLG_* */
+ __le32 filter_flags; /* RXON_FILTER_* */
+
+ /* For active scans (set to all-0s for passive scans).
+ * Does not include payload. Must specify Tx rate; no rate scaling. */
+ struct iwl3945_tx_cmd tx_cmd;
+
+ /* For directed active scans (set to all-0s otherwise) */
+ struct iwl3945_ssid_ie direct_scan[PROBE_OPTION_MAX];
- struct iwl_tx_cmd tx_cmd;
- struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
-
- u8 data[0];
/*
- * The channels start after the probe request payload and are of type:
+ * Probe request frame, followed by channel list.
*
- * struct iwl_scan_channel channels[0];
+ * Size of probe request frame is specified by byte count in tx_cmd.
+ * Channel list follows immediately after probe request frame.
+ * Number of channels in list is specified by channel_count.
+ * Each channel in list is of type:
*
- * NOTE: Only one band of channels can be scanned per pass. You
- * can not mix 2.4GHz channels and 5.2GHz channels and must
- * request a scan multiple times (not concurrently)
+ * struct iwl3945_scan_channel channels[0];
*
+ * NOTE: Only one band of channels can be scanned per pass. You
+ * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+ * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+ * before requesting another scan.
*/
+ u8 data[0];
} __attribute__ ((packed));
/* Can abort will notify by complete notification with abort status. */
@@ -1333,14 +1418,14 @@ struct iwl_scan_cmd {
/*
* REPLY_SCAN_CMD = 0x80 (response)
*/
-struct iwl_scanreq_notification {
+struct iwl3945_scanreq_notification {
__le32 status; /* 1: okay, 2: cannot fulfill request */
} __attribute__ ((packed));
/*
* SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
*/
-struct iwl_scanstart_notification {
+struct iwl3945_scanstart_notification {
__le32 tsf_low;
__le32 tsf_high;
__le32 beacon_timer;
@@ -1357,7 +1442,7 @@ struct iwl_scanstart_notification {
/*
* SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
*/
-struct iwl_scanresults_notification {
+struct iwl3945_scanresults_notification {
u8 channel;
u8 band;
u8 reserved[2];
@@ -1369,7 +1454,7 @@ struct iwl_scanresults_notification {
/*
* SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
*/
-struct iwl_scancomplete_notification {
+struct iwl3945_scancomplete_notification {
u8 scanned_channels;
u8 status;
u8 reserved;
@@ -1388,8 +1473,8 @@ struct iwl_scancomplete_notification {
/*
* BEACON_NOTIFICATION = 0x90 (notification only, not a command)
*/
-struct iwl_beacon_notif {
- struct iwl_tx_resp beacon_notify_hdr;
+struct iwl3945_beacon_notif {
+ struct iwl3945_tx_resp beacon_notify_hdr;
__le32 low_tsf;
__le32 high_tsf;
__le32 ibss_mgr_status;
@@ -1398,8 +1483,8 @@ struct iwl_beacon_notif {
/*
* REPLY_TX_BEACON = 0x91 (command, has simple generic response)
*/
-struct iwl_tx_beacon_cmd {
- struct iwl_tx_cmd tx;
+struct iwl3945_tx_beacon_cmd {
+ struct iwl3945_tx_cmd tx;
__le16 tim_idx;
u8 tim_size;
u8 reserved1;
@@ -1450,30 +1535,8 @@ struct statistics_rx_phy {
__le32 rxe_frame_limit_overrun;
__le32 sent_ack_cnt;
__le32 sent_cts_cnt;
-#if IWL == 4965
- __le32 sent_ba_rsp_cnt;
- __le32 dsp_self_kill;
- __le32 mh_format_err;
- __le32 re_acq_main_rssi_sum;
- __le32 reserved3;
-#endif
} __attribute__ ((packed));
-#if IWL == 4965
-struct statistics_rx_ht_phy {
- __le32 plcp_err;
- __le32 overrun_err;
- __le32 early_overrun_err;
- __le32 crc32_good;
- __le32 crc32_err;
- __le32 mh_format_err;
- __le32 agg_crc32_good;
- __le32 agg_mpdu_cnt;
- __le32 agg_cnt;
- __le32 reserved2;
-} __attribute__ ((packed));
-#endif
-
struct statistics_rx_non_phy {
__le32 bogus_cts; /* CTS received when not expecting CTS */
__le32 bogus_ack; /* ACK received when not expecting ACK */
@@ -1483,57 +1546,13 @@ struct statistics_rx_non_phy {
* filtering process */
__le32 non_channel_beacons; /* beacons with our bss id but not on
* our serving channel */
-#if IWL == 4965
- __le32 channel_beacons; /* beacons with our bss id and in our
- * serving channel */
- __le32 num_missed_bcon; /* number of missed beacons */
- __le32 adc_rx_saturation_time; /* count in 0.8us units the time the
- * ADC was in saturation */
- __le32 ina_detection_search_time;/* total time (in 0.8us) searched
- * for INA */
- __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */
- __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */
- __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */
- __le32 interference_data_flag; /* flag for interference data
- * availability. 1 when data is
- * available. */
- __le32 channel_load; /* counts RX Enable time */
- __le32 dsp_false_alarms; /* DSP false alarm (both OFDM
- * and CCK) counter */
- __le32 beacon_rssi_a;
- __le32 beacon_rssi_b;
- __le32 beacon_rssi_c;
- __le32 beacon_energy_a;
- __le32 beacon_energy_b;
- __le32 beacon_energy_c;
-#endif
} __attribute__ ((packed));
struct statistics_rx {
struct statistics_rx_phy ofdm;
struct statistics_rx_phy cck;
struct statistics_rx_non_phy general;
-#if IWL == 4965
- struct statistics_rx_ht_phy ofdm_ht;
-#endif
-} __attribute__ ((packed));
-
-#if IWL == 4965
-struct statistics_tx_non_phy_agg {
- __le32 ba_timeout;
- __le32 ba_reschedule_frames;
- __le32 scd_query_agg_frame_cnt;
- __le32 scd_query_no_agg;
- __le32 scd_query_agg;
- __le32 scd_query_mismatch;
- __le32 frame_not_ready;
- __le32 underrun;
- __le32 bt_prio_kill;
- __le32 rx_ba_rsp_cnt;
- __le32 reserved2;
- __le32 reserved3;
} __attribute__ ((packed));
-#endif
struct statistics_tx {
__le32 preamble_cnt;
@@ -1545,14 +1564,6 @@ struct statistics_tx {
__le32 ack_timeout;
__le32 expected_ack_cnt;
__le32 actual_ack_cnt;
-#if IWL == 4965
- __le32 dump_msdu_cnt;
- __le32 burst_abort_next_frame_mismatch_cnt;
- __le32 burst_abort_missing_next_frame_cnt;
- __le32 cts_timeout_collision;
- __le32 ack_or_ba_timeout_collision;
- struct statistics_tx_non_phy_agg agg;
-#endif
} __attribute__ ((packed));
struct statistics_dbg {
@@ -1566,29 +1577,16 @@ struct statistics_div {
__le32 tx_on_b;
__le32 exec_time;
__le32 probe_time;
-#if IWL == 4965
- __le32 reserved1;
- __le32 reserved2;
-#endif
} __attribute__ ((packed));
struct statistics_general {
__le32 temperature;
-#if IWL == 4965
- __le32 temperature_m;
-#endif
struct statistics_dbg dbg;
__le32 sleep_time;
__le32 slots_out;
__le32 slots_idle;
__le32 ttl_timestamp;
struct statistics_div div;
-#if IWL == 4965
- __le32 rx_enable_counter;
- __le32 reserved1;
- __le32 reserved2;
- __le32 reserved3;
-#endif
} __attribute__ ((packed));
/*
@@ -1608,7 +1606,7 @@ struct statistics_general {
*/
#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
-struct iwl_statistics_cmd {
+struct iwl3945_statistics_cmd {
__le32 configuration_flags; /* IWL_STATS_CONF_* */
} __attribute__ ((packed));
@@ -1629,7 +1627,7 @@ struct iwl_statistics_cmd {
*/
#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
-struct iwl_notif_statistics {
+struct iwl3945_notif_statistics {
__le32 flag;
struct statistics_rx rx;
struct statistics_tx tx;
@@ -1644,7 +1642,7 @@ struct iwl_notif_statistics {
* then this notification will be sent. */
#define CONSECUTIVE_MISSED_BCONS_TH 20
-struct iwl_missed_beacon_notif {
+struct iwl3945_missed_beacon_notif {
__le32 consequtive_missed_beacons;
__le32 total_missed_becons;
__le32 num_expected_beacons;
@@ -1660,12 +1658,12 @@ struct iwl_missed_beacon_notif {
#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
#define HD_TABLE_SIZE (11)
-struct iwl_sensitivity_cmd {
+struct iwl3945_sensitivity_cmd {
__le16 control;
__le16 table[HD_TABLE_SIZE];
} __attribute__ ((packed));
-struct iwl_calibration_cmd {
+struct iwl3945_calibration_cmd {
u8 opCode;
u8 flags;
__le16 reserved;
@@ -1688,7 +1686,7 @@ struct iwl_calibration_cmd {
* For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
* this command turns it on or off, or sets up a periodic blinking cycle.
*/
-struct iwl_led_cmd {
+struct iwl3945_led_cmd {
__le32 interval; /* "interval" in uSec */
u8 id; /* 1: Activity, 2: Link, 3: Tech */
u8 off; /* # intervals off while blinking;
@@ -1704,31 +1702,27 @@ struct iwl_led_cmd {
*
*****************************************************************************/
-struct iwl_rx_packet {
+struct iwl3945_rx_packet {
__le32 len;
- struct iwl_cmd_header hdr;
+ struct iwl3945_cmd_header hdr;
union {
- struct iwl_alive_resp alive_frame;
- struct iwl_rx_frame rx_frame;
- struct iwl_tx_resp tx_resp;
- struct iwl_spectrum_notification spectrum_notif;
- struct iwl_csa_notification csa_notif;
- struct iwl_error_resp err_resp;
- struct iwl_card_state_notif card_state_notif;
- struct iwl_beacon_notif beacon_status;
- struct iwl_add_sta_resp add_sta;
- struct iwl_sleep_notification sleep_notif;
- struct iwl_spectrum_resp spectrum;
- struct iwl_notif_statistics stats;
-#if IWL == 4965
- struct iwl_compressed_ba_resp compressed_ba;
- struct iwl_missed_beacon_notif missed_beacon;
-#endif
+ struct iwl3945_alive_resp alive_frame;
+ struct iwl3945_rx_frame rx_frame;
+ struct iwl3945_tx_resp tx_resp;
+ struct iwl3945_spectrum_notification spectrum_notif;
+ struct iwl3945_csa_notification csa_notif;
+ struct iwl3945_error_resp err_resp;
+ struct iwl3945_card_state_notif card_state_notif;
+ struct iwl3945_beacon_notif beacon_status;
+ struct iwl3945_add_sta_resp add_sta;
+ struct iwl3945_sleep_notification sleep_notif;
+ struct iwl3945_spectrum_resp spectrum;
+ struct iwl3945_notif_statistics stats;
__le32 status;
u8 raw[0];
} u;
} __attribute__ ((packed));
-#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl_rx_frame))
+#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame))
-#endif /* __iwl_commands_h__ */
+#endif /* __iwl3945_3945_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
index 72318d78957e..f853c6b9f76e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
@@ -26,18 +26,18 @@
*
*****************************************************************************/
-#ifndef __iwl_debug_h__
-#define __iwl_debug_h__
+#ifndef __iwl3945_debug_h__
+#define __iwl3945_debug_h__
-#ifdef CONFIG_IWLWIFI_DEBUG
-extern u32 iwl_debug_level;
+#ifdef CONFIG_IWL3945_DEBUG
+extern u32 iwl3945_debug_level;
#define IWL_DEBUG(level, fmt, args...) \
-do { if (iwl_debug_level & (level)) \
+do { if (iwl3945_debug_level & (level)) \
printk(KERN_ERR DRV_NAME": %c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
#define IWL_DEBUG_LIMIT(level, fmt, args...) \
-do { if ((iwl_debug_level & (level)) && net_ratelimit()) \
+do { if ((iwl3945_debug_level & (level)) && net_ratelimit()) \
printk(KERN_ERR DRV_NAME": %c %s " fmt, \
in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
#else
@@ -47,7 +47,7 @@ static inline void IWL_DEBUG(int level, const char *fmt, ...)
static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
{
}
-#endif /* CONFIG_IWLWIFI_DEBUG */
+#endif /* CONFIG_IWL3945_DEBUG */
/*
* To use the debug system;
@@ -68,51 +68,51 @@ static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
*
* % cat /proc/net/iwl/debug_level
*
- * you simply need to add your entry to the iwl_debug_levels array.
+ * you simply need to add your entry to the iwl3945_debug_levels array.
*
* If you do not see debug_level in /proc/net/iwl then you do not have
- * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
+ * CONFIG_IWL3945_DEBUG defined in your kernel configuration
*
*/
-#define IWL_DL_INFO (1<<0)
-#define IWL_DL_MAC80211 (1<<1)
-#define IWL_DL_HOST_COMMAND (1<<2)
-#define IWL_DL_STATE (1<<3)
+#define IWL_DL_INFO (1 << 0)
+#define IWL_DL_MAC80211 (1 << 1)
+#define IWL_DL_HOST_COMMAND (1 << 2)
+#define IWL_DL_STATE (1 << 3)
-#define IWL_DL_RADIO (1<<7)
-#define IWL_DL_POWER (1<<8)
-#define IWL_DL_TEMP (1<<9)
+#define IWL_DL_RADIO (1 << 7)
+#define IWL_DL_POWER (1 << 8)
+#define IWL_DL_TEMP (1 << 9)
-#define IWL_DL_NOTIF (1<<10)
-#define IWL_DL_SCAN (1<<11)
-#define IWL_DL_ASSOC (1<<12)
-#define IWL_DL_DROP (1<<13)
+#define IWL_DL_NOTIF (1 << 10)
+#define IWL_DL_SCAN (1 << 11)
+#define IWL_DL_ASSOC (1 << 12)
+#define IWL_DL_DROP (1 << 13)
-#define IWL_DL_TXPOWER (1<<14)
+#define IWL_DL_TXPOWER (1 << 14)
-#define IWL_DL_AP (1<<15)
+#define IWL_DL_AP (1 << 15)
-#define IWL_DL_FW (1<<16)
-#define IWL_DL_RF_KILL (1<<17)
-#define IWL_DL_FW_ERRORS (1<<18)
+#define IWL_DL_FW (1 << 16)
+#define IWL_DL_RF_KILL (1 << 17)
+#define IWL_DL_FW_ERRORS (1 << 18)
-#define IWL_DL_LED (1<<19)
+#define IWL_DL_LED (1 << 19)
-#define IWL_DL_RATE (1<<20)
+#define IWL_DL_RATE (1 << 20)
-#define IWL_DL_CALIB (1<<21)
-#define IWL_DL_WEP (1<<22)
-#define IWL_DL_TX (1<<23)
-#define IWL_DL_RX (1<<24)
-#define IWL_DL_ISR (1<<25)
-#define IWL_DL_HT (1<<26)
-#define IWL_DL_IO (1<<27)
-#define IWL_DL_11H (1<<28)
+#define IWL_DL_CALIB (1 << 21)
+#define IWL_DL_WEP (1 << 22)
+#define IWL_DL_TX (1 << 23)
+#define IWL_DL_RX (1 << 24)
+#define IWL_DL_ISR (1 << 25)
+#define IWL_DL_HT (1 << 26)
+#define IWL_DL_IO (1 << 27)
+#define IWL_DL_11H (1 << 28)
-#define IWL_DL_STATS (1<<29)
-#define IWL_DL_TX_REPLY (1<<30)
-#define IWL_DL_QOS (1<<31)
+#define IWL_DL_STATS (1 << 29)
+#define IWL_DL_TX_REPLY (1 << 30)
+#define IWL_DL_QOS (1 << 31)
#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index fb5f0649f4f6..6e0187393af4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
+ * it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
@@ -60,58 +60,646 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+/*
+ * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
+ * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-3945.h for driver implementation definitions.
+ */
#ifndef __iwl_3945_hw__
#define __iwl_3945_hw__
-#define IWL_RX_BUF_SIZE 3000
-/* card static random access memory (SRAM) for processor data and instructs */
+/*
+ * uCode queue management definitions ...
+ * Queue #4 is the command queue for 3945 and 4965.
+ */
+#define IWL_CMD_QUEUE_NUM 4
+
+/* Tx rates */
+#define IWL_CCK_RATES 4
+#define IWL_OFDM_RATES 8
+#define IWL_HT_RATES 0
+#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
+
+/* Time constants */
+#define SHORT_SLOT_TIME 9
+#define LONG_SLOT_TIME 20
+
+/* RSSI to dBm */
+#define IWL_RSSI_OFFSET 95
+
+/*
+ * EEPROM related constants, enums, and structures.
+ */
+
+/*
+ * EEPROM access time values:
+ *
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
+ * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
+ * CSR_EEPROM_REG_BIT_CMD (0x2).
+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+ */
+#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
+#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
+
+/*
+ * Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags.
+ *
+ * IBSS and/or AP operation is allowed *only* on those channels with
+ * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
+ * RADAR detection is not supported by the 3945 driver, but is a
+ * requirement for establishing a new network for legal operation on channels
+ * requiring RADAR detection or restricting ACTIVE scanning.
+ *
+ * NOTE: "WIDE" flag indicates that 20 MHz channel is supported;
+ * 3945 does not support FAT 40 MHz-wide channels.
+ *
+ * NOTE: Using a channel inappropriately will result in a uCode error!
+ */
+enum {
+ EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
+ EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
+ /* Bit 2 Reserved */
+ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
+ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
+ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
+ EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
+ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
+};
+
+/* SKU Capabilities */
+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
+#define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7)
+
+/* *regulatory* channel data from eeprom, one for each channel */
+struct iwl3945_eeprom_channel {
+ u8 flags; /* flags copied from EEPROM */
+ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
+} __attribute__ ((packed));
+
+/*
+ * Mapping of a Tx power level, at factory calibration temperature,
+ * to a radio/DSP gain table index.
+ * One for each of 5 "sample" power levels in each band.
+ * v_det is measured at the factory, using the 3945's built-in power amplifier
+ * (PA) output voltage detector. This same detector is used during Tx of
+ * long packets in normal operation to provide feedback as to proper output
+ * level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_sample {
+ u8 gain_index; /* index into power (gain) setup table ... */
+ s8 power; /* ... for this pwr level for this chnl group */
+ u16 v_det; /* PA output voltage */
+} __attribute__ ((packed));
+
+/*
+ * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
+ * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
+ * Tx power setup code interpolates between the 5 "sample" power levels
+ * to determine the nominal setup for a requested power level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_group {
+ struct iwl3945_eeprom_txpower_sample samples[5]; /* 5 power levels */
+ s32 a, b, c, d, e; /* coefficients for voltage->power
+ * formula (signed) */
+ s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on
+ * frequency (signed) */
+ s8 saturation_power; /* highest power possible by h/w in this
+ * band */
+ u8 group_channel; /* "representative" channel # in this band */
+ s16 temperature; /* h/w temperature at factory calib this band
+ * (signed) */
+} __attribute__ ((packed));
+
+/*
+ * Temperature-based Tx-power compensation data, not band-specific.
+ * These coefficients are use to modify a/b/c/d/e coeffs based on
+ * difference between current temperature and factory calib temperature.
+ * Data copied from EEPROM.
+ */
+struct iwl3945_eeprom_temperature_corr {
+ u32 Ta;
+ u32 Tb;
+ u32 Tc;
+ u32 Td;
+ u32 Te;
+} __attribute__ ((packed));
+
+/*
+ * EEPROM map
+ */
+struct iwl3945_eeprom {
+ u8 reserved0[16];
+#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+ u16 device_id; /* abs.ofs: 16 */
+ u8 reserved1[2];
+#define EEPROM_PMC (2*0x0A) /* 2 bytes */
+ u16 pmc; /* abs.ofs: 20 */
+ u8 reserved2[20];
+#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
+ u8 mac_address[6]; /* abs.ofs: 42 */
+ u8 reserved3[58];
+#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
+ u16 board_revision; /* abs.ofs: 106 */
+ u8 reserved4[11];
+#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
+ u8 board_pba_number[9]; /* abs.ofs: 119 */
+ u8 reserved5[8];
+#define EEPROM_VERSION (2*0x44) /* 2 bytes */
+ u16 version; /* abs.ofs: 136 */
+#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
+ u8 sku_cap; /* abs.ofs: 138 */
+#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
+ u8 leds_mode; /* abs.ofs: 139 */
+#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
+ u16 oem_mode;
+#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
+ u16 wowlan_mode; /* abs.ofs: 142 */
+#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
+ u16 leds_time_interval; /* abs.ofs: 144 */
+#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
+ u8 leds_off_time; /* abs.ofs: 146 */
+#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
+ u8 leds_on_time; /* abs.ofs: 147 */
+#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
+ u8 almgor_m_version; /* abs.ofs: 148 */
+#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
+ u8 antenna_switch_type; /* abs.ofs: 149 */
+ u8 reserved6[42];
+#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
+ u8 sku_id[4]; /* abs.ofs: 192 */
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by 3945 or 4965 has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
+ u16 band_1_count; /* abs.ofs: 196 */
+#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
+ struct iwl3945_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
+ u16 band_2_count; /* abs.ofs: 226 */
+#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
+ struct iwl3945_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
+ u16 band_3_count; /* abs.ofs: 254 */
+#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
+ struct iwl3945_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
+ u16 band_4_count; /* abs.ofs: 280 */
+#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
+ struct iwl3945_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
+ u16 band_5_count; /* abs.ofs: 304 */
+#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
+ struct iwl3945_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
+
+ u8 reserved9[194];
+
+/*
+ * 3945 Txpower calibration data.
+ */
+#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
+#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
+#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
+#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
+#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
+#define IWL_NUM_TX_CALIB_GROUPS 5
+ struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
+/* abs.ofs: 512 */
+#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
+ struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
+ u8 reserved16[172]; /* fill out to full 1024 byte block */
+} __attribute__ ((packed));
+
+#define IWL_EEPROM_IMAGE_SIZE 1024
+
+/* End of EEPROM */
+
+
+#include "iwl-3945-commands.h"
+
+#define PCI_LINK_CTRL 0x0F0
+#define PCI_POWER_SOURCE 0x0C8
+#define PCI_REG_WUM8 0x0E8
+#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
+
+/*=== CSR (control and status registers) ===*/
+#define CSR_BASE (0x000)
+
+#define CSR_SW_VER (CSR_BASE+0x000)
+#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
+#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
+#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
+#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
+#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
+#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
+#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+#define CSR_GP_CNTRL (CSR_BASE+0x024)
+
+/*
+ * Hardware revision info
+ * Bit fields:
+ * 31-8: Reserved
+ * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
+ * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
+ * 1-0: "Dash" value, as in A-1, etc.
+ */
+#define CSR_HW_REV (CSR_BASE+0x028)
+
+/* EEPROM reads */
+#define CSR_EEPROM_REG (CSR_BASE+0x02c)
+#define CSR_EEPROM_GP (CSR_BASE+0x030)
+#define CSR_GP_UCODE (CSR_BASE+0x044)
+#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
+#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
+#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
+#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
+#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+
+/* Analog phase-lock-loop configuration (3945 only)
+ * Set bit 24. */
+#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
+
+/* Bits for CSR_HW_IF_CONFIG_REG */
+#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100)
+#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200)
+#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
+#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
+#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
+#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
+#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
+
+/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+ * acknowledged (reset) by host writing "1" to flagged bits. */
+#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
+#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
+#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
+#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
+#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
+#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
+#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
+#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
+#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
+
+#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
+ CSR_INT_BIT_HW_ERR | \
+ CSR_INT_BIT_FH_TX | \
+ CSR_INT_BIT_SW_ERR | \
+ CSR_INT_BIT_RF_KILL | \
+ CSR_INT_BIT_SW_RX | \
+ CSR_INT_BIT_WAKEUP | \
+ CSR_INT_BIT_ALIVE)
+
+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
+#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
+#define CSR_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */
+#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
+#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
+#define CSR_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */
+#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
+#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
+
+#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
+ CSR_FH_INT_BIT_RX_CHNL2 | \
+ CSR_FH_INT_BIT_RX_CHNL1 | \
+ CSR_FH_INT_BIT_RX_CHNL0)
+
+#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \
+ CSR_FH_INT_BIT_TX_CHNL1 | \
+ CSR_FH_INT_BIT_TX_CHNL0)
+
+
+/* RESET */
+#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
+#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
+#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
+#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
+#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
+
+/* GP (general purpose) CONTROL */
+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
+
+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
+
+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
+
+
+/* EEPROM REG */
+#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
+#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
+
+/* EEPROM GP */
+#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
+#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
+#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
+
+/* UCODE DRV GP */
+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
+#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+
+/* GPIO */
+#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
+
+/* GI Chicken Bits */
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
+
+/* CSR_ANA_PLL_CFG */
+#define CSR_ANA_PLL_CFG_SH (0x00880300)
+
+/*=== HBUS (Host-side Bus) ===*/
+#define HBUS_BASE (0x400)
+
+/*
+ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+ * structures, error log, event log, verifying uCode load).
+ * First write to address register, then read from or write to data register
+ * to complete the job. Once the address register is set up, accesses to
+ * data registers auto-increment the address by one dword.
+ * Bit usage for address registers (read or write):
+ * 0-31: memory address within device
+ */
+#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
+#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
+#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
+#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
+
+/*
+ * Registers for accessing device's internal peripheral registers
+ * (e.g. SCD, BSM, etc.). First write to address register,
+ * then read from or write to data register to complete the job.
+ * Bit usage for address registers (read or write):
+ * 0-15: register address (offset) within device
+ * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
+ */
+#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
+#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
+#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
+#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
+
+/*
+ * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+ * Indicates index to next TFD that driver will fill (1 past latest filled).
+ * Bit usage:
+ * 0-7: queue write index
+ * 11-8: queue selector
+ */
+#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
+
+/* SCD (3945 Tx Frame Scheduler) */
+#define SCD_BASE (CSR_BASE + 0x2E00)
+
+#define SCD_MODE_REG (SCD_BASE + 0x000)
+#define SCD_ARASTAT_REG (SCD_BASE + 0x004)
+#define SCD_TXFACT_REG (SCD_BASE + 0x010)
+#define SCD_TXF4MF_REG (SCD_BASE + 0x014)
+#define SCD_TXF5MF_REG (SCD_BASE + 0x020)
+#define SCD_SBYP_MODE_1_REG (SCD_BASE + 0x02C)
+#define SCD_SBYP_MODE_2_REG (SCD_BASE + 0x030)
+
+/*=== FH (data Flow Handler) ===*/
+#define FH_BASE (0x800)
+
+#define FH_CBCC_TABLE (FH_BASE+0x140)
+#define FH_TFDB_TABLE (FH_BASE+0x180)
+#define FH_RCSR_TABLE (FH_BASE+0x400)
+#define FH_RSSR_TABLE (FH_BASE+0x4c0)
+#define FH_TCSR_TABLE (FH_BASE+0x500)
+#define FH_TSSR_TABLE (FH_BASE+0x680)
+
+/* TFDB (Transmit Frame Buffer Descriptor) */
+#define FH_TFDB(_channel, buf) \
+ (FH_TFDB_TABLE+((_channel)*2+(buf))*0x28)
+#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \
+ (FH_TFDB_TABLE + 0x50 * _channel)
+/* CBCC _channel is [0,2] */
+#define FH_CBCC(_channel) (FH_CBCC_TABLE+(_channel)*0x8)
+#define FH_CBCC_CTRL(_channel) (FH_CBCC(_channel)+0x00)
+#define FH_CBCC_BASE(_channel) (FH_CBCC(_channel)+0x04)
+
+/* RCSR _channel is [0,2] */
+#define FH_RCSR(_channel) (FH_RCSR_TABLE+(_channel)*0x40)
+#define FH_RCSR_CONFIG(_channel) (FH_RCSR(_channel)+0x00)
+#define FH_RCSR_RBD_BASE(_channel) (FH_RCSR(_channel)+0x04)
+#define FH_RCSR_WPTR(_channel) (FH_RCSR(_channel)+0x20)
+#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24)
+
+#define FH_RSCSR_CHNL0_WPTR (FH_RCSR_WPTR(0))
+
+/* RSSR */
+#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000)
+#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004)
+/* TCSR */
+#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20)
+#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00)
+#define FH_TCSR_CREDIT(_channel) (FH_TCSR(_channel)+0x04)
+#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08)
+/* TSSR */
+#define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000)
+#define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008)
+#define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010)
+
+
+/* DBM */
+
+#define ALM_FH_SRVC_CHNL (6)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20)
+#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000)
+
+#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000)
+
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001)
+
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
+
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
+
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
+
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
+#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
+
+#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000)
+
+#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001)
+
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000)
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000)
+
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400)
+
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100)
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080)
+
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020)
+#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005)
+
+#define ALM_TB_MAX_BYTES_COUNT (0xFFF0)
+
+#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \
+ ((1LU << _channel) << 24)
+#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \
+ ((1LU << _channel) << 16)
+
+#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \
+ (ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \
+ ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel))
+#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */
+#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */
+
+#define TFD_QUEUE_MIN 0
+#define TFD_QUEUE_MAX 6
+#define TFD_QUEUE_SIZE_MAX (256)
+
+#define IWL_NUM_SCAN_RATES (2)
+
+#define IWL_DEFAULT_TX_RETRY 15
+
+/*********************************************/
+
+#define RFD_SIZE 4
+#define NUM_TFD_CHUNKS 4
+
+#define RX_QUEUE_SIZE 256
+#define RX_QUEUE_MASK 255
+#define RX_QUEUE_SIZE_LOG 8
+
+#define U32_PAD(n) ((4-(n))&0x3)
+
+#define TFD_CTL_COUNT_SET(n) (n << 24)
+#define TFD_CTL_COUNT_GET(ctl) ((ctl >> 24) & 7)
+#define TFD_CTL_PAD_SET(n) (n << 28)
+#define TFD_CTL_PAD_GET(ctl) (ctl >> 28)
+
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \
+ sizeof(struct iwl3945_cmd_meta))
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
+#define RTC_INST_LOWER_BOUND (0x000000)
#define ALM_RTC_INST_UPPER_BOUND (0x014000)
+
+#define RTC_DATA_LOWER_BOUND (0x800000)
#define ALM_RTC_DATA_UPPER_BOUND (0x808000)
#define ALM_RTC_INST_SIZE (ALM_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
#define ALM_RTC_DATA_SIZE (ALM_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
-#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
#define IWL_MAX_INST_SIZE ALM_RTC_INST_SIZE
#define IWL_MAX_DATA_SIZE ALM_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL_MAX_BSM_SIZE ALM_RTC_INST_SIZE
+
#define IWL_MAX_NUM_QUEUES 8
-static inline int iwl_hw_valid_rtc_data_addr(u32 addr)
+static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= RTC_DATA_LOWER_BOUND) &&
(addr < ALM_RTC_DATA_UPPER_BOUND);
}
-/* Base physical address of iwl_shared is provided to FH_TSSR_CBB_BASE
- * and &iwl_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
-struct iwl_shared {
+/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
+ * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
+struct iwl3945_shared {
__le32 tx_base_ptr[8];
__le32 rx_read_ptr[3];
} __attribute__ ((packed));
-struct iwl_tfd_frame_data {
+struct iwl3945_tfd_frame_data {
__le32 addr;
__le32 len;
} __attribute__ ((packed));
-struct iwl_tfd_frame {
+struct iwl3945_tfd_frame {
__le32 control_flags;
- struct iwl_tfd_frame_data pa[4];
+ struct iwl3945_tfd_frame_data pa[4];
u8 reserved[28];
} __attribute__ ((packed));
-static inline u8 iwl_hw_get_rate(__le16 rate_n_flags)
+static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
{
return le16_to_cpu(rate_n_flags) & 0xFF;
}
-static inline u16 iwl_hw_get_rate_n_flags(__le16 rate_n_flags)
+static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
{
return le16_to_cpu(rate_n_flags);
}
-static inline __le16 iwl_hw_set_rate_n_flags(u8 rate, u16 flags)
+static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
{
return cpu_to_le16((u16)rate|flags);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
new file mode 100644
index 000000000000..75e20d0a20d1
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
@@ -0,0 +1,431 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl3945_io_h__
+#define __iwl3945_io_h__
+
+#include <linux/io.h>
+
+#include "iwl-3945-debug.h"
+
+/*
+ * IO, register, and NIC memory access functions
+ *
+ * NOTE on naming convention and macro usage for these
+ *
+ * A single _ prefix before a an access function means that no state
+ * check or debug information is printed when that function is called.
+ *
+ * A double __ prefix before an access function means that state is checked
+ * and the current line number is printed in addition to any other debug output.
+ *
+ * The non-prefixed name is the #define that maps the caller into a
+ * #define that provides the caller's __LINE__ to the double prefix version.
+ *
+ * If you wish to call the function without any debug or state checking,
+ * you should use the single _ prefix version (as is used by dependent IO
+ * routines, for example _iwl3945_read_direct32 calls the non-check version of
+ * _iwl3945_read32.)
+ *
+ * These declarations are *extremely* useful in quickly isolating code deltas
+ * which result in misconfiguring of the hardware I/O. In combination with
+ * git-bisect and the IO debug level you can quickly determine the specific
+ * commit which breaks the IO sequence to the hardware.
+ *
+ */
+
+#define _iwl3945_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_write32(const char *f, u32 l, struct iwl3945_priv *iwl,
+ u32 ofs, u32 val)
+{
+ IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+ _iwl3945_write32(iwl, ofs, val);
+}
+#define iwl3945_write32(iwl, ofs, val) \
+ __iwl3945_write32(__FILE__, __LINE__, iwl, ofs, val)
+#else
+#define iwl3945_write32(iwl, ofs, val) _iwl3945_write32(iwl, ofs, val)
+#endif
+
+#define _iwl3945_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
+#ifdef CONFIG_IWL3945_DEBUG
+static inline u32 __iwl3945_read32(char *f, u32 l, struct iwl3945_priv *iwl, u32 ofs)
+{
+ IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+ return _iwl3945_read32(iwl, ofs);
+}
+#define iwl3945_read32(iwl, ofs) __iwl3945_read32(__FILE__, __LINE__, iwl, ofs)
+#else
+#define iwl3945_read32(p, o) _iwl3945_read32(p, o)
+#endif
+
+static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr,
+ u32 bits, u32 mask, int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((_iwl3945_read32(priv, addr) & mask) == (bits & mask))
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIMEDOUT;
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline int __iwl3945_poll_bit(const char *f, u32 l,
+ struct iwl3945_priv *priv, u32 addr,
+ u32 bits, u32 mask, int timeout)
+{
+ int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
+ if (unlikely(ret == -ETIMEDOUT))
+ IWL_DEBUG_IO
+ ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+ addr, bits, mask, f, l);
+ else
+ IWL_DEBUG_IO
+ ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+ addr, bits, mask, ret, f, l);
+ return ret;
+}
+#define iwl3945_poll_bit(iwl, addr, bits, mask, timeout) \
+ __iwl3945_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
+#else
+#define iwl3945_poll_bit(p, a, b, m, t) _iwl3945_poll_bit(p, a, b, m, t)
+#endif
+
+static inline void _iwl3945_set_bit(struct iwl3945_priv *priv, u32 reg, u32 mask)
+{
+ _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) | mask);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_set_bit(const char *f, u32 l,
+ struct iwl3945_priv *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl3945_read32(priv, reg) | mask;
+ IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+ _iwl3945_write32(priv, reg, val);
+}
+#define iwl3945_set_bit(p, r, m) __iwl3945_set_bit(__FILE__, __LINE__, p, r, m)
+#else
+#define iwl3945_set_bit(p, r, m) _iwl3945_set_bit(p, r, m)
+#endif
+
+static inline void _iwl3945_clear_bit(struct iwl3945_priv *priv, u32 reg, u32 mask)
+{
+ _iwl3945_write32(priv, reg, _iwl3945_read32(priv, reg) & ~mask);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_clear_bit(const char *f, u32 l,
+ struct iwl3945_priv *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl3945_read32(priv, reg) & ~mask;
+ IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+ _iwl3945_write32(priv, reg, val);
+}
+#define iwl3945_clear_bit(p, r, m) __iwl3945_clear_bit(__FILE__, __LINE__, p, r, m)
+#else
+#define iwl3945_clear_bit(p, r, m) _iwl3945_clear_bit(p, r, m)
+#endif
+
+static inline int _iwl3945_grab_nic_access(struct iwl3945_priv *priv)
+{
+ int ret;
+ u32 gp_ctl;
+
+#ifdef CONFIG_IWL3945_DEBUG
+ if (atomic_read(&priv->restrict_refcnt))
+ return 0;
+#endif
+ if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+ test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+ IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
+ "wakes up NIC\n");
+
+ /* 10 msec allows time for NIC to complete its data save */
+ gp_ctl = _iwl3945_read32(priv, CSR_GP_CNTRL);
+ if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
+ IWL_DEBUG_RF_KILL("Wait for complete power-down, "
+ "gpctl = 0x%08x\n", gp_ctl);
+ mdelay(10);
+ } else
+ IWL_DEBUG_RF_KILL("power-down complete, "
+ "gpctl = 0x%08x\n", gp_ctl);
+ }
+
+ /* this bit wakes up the NIC */
+ _iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ ret = _iwl3945_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+ if (ret < 0) {
+ IWL_ERROR("MAC is in deep sleep!\n");
+ return -EIO;
+ }
+
+#ifdef CONFIG_IWL3945_DEBUG
+ atomic_inc(&priv->restrict_refcnt);
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_IWL3945_DEBUG
+static inline int __iwl3945_grab_nic_access(const char *f, u32 l,
+ struct iwl3945_priv *priv)
+{
+ if (atomic_read(&priv->restrict_refcnt))
+ IWL_DEBUG_INFO("Grabbing access while already held at "
+ "line %d.\n", l);
+
+ IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
+ return _iwl3945_grab_nic_access(priv);
+}
+#define iwl3945_grab_nic_access(priv) \
+ __iwl3945_grab_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl3945_grab_nic_access(priv) \
+ _iwl3945_grab_nic_access(priv)
+#endif
+
+static inline void _iwl3945_release_nic_access(struct iwl3945_priv *priv)
+{
+#ifdef CONFIG_IWL3945_DEBUG
+ if (atomic_dec_and_test(&priv->restrict_refcnt))
+#endif
+ _iwl3945_clear_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_release_nic_access(const char *f, u32 l,
+ struct iwl3945_priv *priv)
+{
+ if (atomic_read(&priv->restrict_refcnt) <= 0)
+ IWL_ERROR("Release unheld nic access at line %d.\n", l);
+
+ IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
+ _iwl3945_release_nic_access(priv);
+}
+#define iwl3945_release_nic_access(priv) \
+ __iwl3945_release_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl3945_release_nic_access(priv) \
+ _iwl3945_release_nic_access(priv)
+#endif
+
+static inline u32 _iwl3945_read_direct32(struct iwl3945_priv *priv, u32 reg)
+{
+ return _iwl3945_read32(priv, reg);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline u32 __iwl3945_read_direct32(const char *f, u32 l,
+ struct iwl3945_priv *priv, u32 reg)
+{
+ u32 value = _iwl3945_read_direct32(priv, reg);
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from %s %d\n", f, l);
+ IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
+ f, l);
+ return value;
+}
+#define iwl3945_read_direct32(priv, reg) \
+ __iwl3945_read_direct32(__FILE__, __LINE__, priv, reg)
+#else
+#define iwl3945_read_direct32 _iwl3945_read_direct32
+#endif
+
+static inline void _iwl3945_write_direct32(struct iwl3945_priv *priv,
+ u32 reg, u32 value)
+{
+ _iwl3945_write32(priv, reg, value);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static void __iwl3945_write_direct32(u32 line,
+ struct iwl3945_priv *priv, u32 reg, u32 value)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ _iwl3945_write_direct32(priv, reg, value);
+}
+#define iwl3945_write_direct32(priv, reg, value) \
+ __iwl3945_write_direct32(__LINE__, priv, reg, value)
+#else
+#define iwl3945_write_direct32 _iwl3945_write_direct32
+#endif
+
+static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv,
+ u32 reg, u32 len, u32 *values)
+{
+ u32 count = sizeof(u32);
+
+ if ((priv != NULL) && (values != NULL)) {
+ for (; 0 < len; len -= count, reg += count, values++)
+ _iwl3945_write_direct32(priv, reg, *values);
+ }
+}
+
+static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv,
+ u32 addr, u32 mask, int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((_iwl3945_read_direct32(priv, addr) & mask) == mask)
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIMEDOUT;
+}
+
+#ifdef CONFIG_IWL3945_DEBUG
+static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
+ struct iwl3945_priv *priv,
+ u32 addr, u32 mask, int timeout)
+{
+ int ret = _iwl3945_poll_direct_bit(priv, addr, mask, timeout);
+
+ if (unlikely(ret == -ETIMEDOUT))
+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
+ "timedout - %s %d\n", addr, mask, f, l);
+ else
+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+ "- %s %d\n", addr, mask, ret, f, l);
+ return ret;
+}
+#define iwl3945_poll_direct_bit(iwl, addr, mask, timeout) \
+ __iwl3945_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
+#else
+#define iwl3945_poll_direct_bit _iwl3945_poll_direct_bit
+#endif
+
+static inline u32 _iwl3945_read_prph(struct iwl3945_priv *priv, u32 reg)
+{
+ _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ return _iwl3945_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline u32 __iwl3945_read_prph(u32 line, struct iwl3945_priv *priv, u32 reg)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ return _iwl3945_read_prph(priv, reg);
+}
+
+#define iwl3945_read_prph(priv, reg) \
+ __iwl3945_read_prph(__LINE__, priv, reg)
+#else
+#define iwl3945_read_prph _iwl3945_read_prph
+#endif
+
+static inline void _iwl3945_write_prph(struct iwl3945_priv *priv,
+ u32 addr, u32 val)
+{
+ _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+ ((addr & 0x0000FFFF) | (3 << 24)));
+ _iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+}
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_write_prph(u32 line, struct iwl3945_priv *priv,
+ u32 addr, u32 val)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access from line %d\n", line);
+ _iwl3945_write_prph(priv, addr, val);
+}
+
+#define iwl3945_write_prph(priv, addr, val) \
+ __iwl3945_write_prph(__LINE__, priv, addr, val);
+#else
+#define iwl3945_write_prph _iwl3945_write_prph
+#endif
+
+#define _iwl3945_set_bits_prph(priv, reg, mask) \
+ _iwl3945_write_prph(priv, reg, (_iwl3945_read_prph(priv, reg) | mask))
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_set_bits_prph(u32 line, struct iwl3945_priv *priv,
+ u32 reg, u32 mask)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+
+ _iwl3945_set_bits_prph(priv, reg, mask);
+}
+#define iwl3945_set_bits_prph(priv, reg, mask) \
+ __iwl3945_set_bits_prph(__LINE__, priv, reg, mask)
+#else
+#define iwl3945_set_bits_prph _iwl3945_set_bits_prph
+#endif
+
+#define _iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \
+ _iwl3945_write_prph(priv, reg, ((_iwl3945_read_prph(priv, reg) & mask) | bits))
+
+#ifdef CONFIG_IWL3945_DEBUG
+static inline void __iwl3945_set_bits_mask_prph(u32 line,
+ struct iwl3945_priv *priv, u32 reg, u32 bits, u32 mask)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ _iwl3945_set_bits_mask_prph(priv, reg, bits, mask);
+}
+#define iwl3945_set_bits_mask_prph(priv, reg, bits, mask) \
+ __iwl3945_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
+#else
+#define iwl3945_set_bits_mask_prph _iwl3945_set_bits_mask_prph
+#endif
+
+static inline void iwl3945_clear_bits_prph(struct iwl3945_priv
+ *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl3945_read_prph(priv, reg);
+ _iwl3945_write_prph(priv, reg, (val & ~mask));
+}
+
+static inline u32 iwl3945_read_targ_mem(struct iwl3945_priv *priv, u32 addr)
+{
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+ return iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+}
+
+static inline void iwl3945_write_targ_mem(struct iwl3945_priv *priv, u32 addr, u32 val)
+{
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+}
+
+static inline void iwl3945_write_targ_mem_buf(struct iwl3945_priv *priv, u32 addr,
+ u32 len, u32 *values)
+{
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ for (; 0 < len; len -= sizeof(u32), values++)
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+}
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index c48b1b537d2b..80d31ae51e77 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -37,15 +37,13 @@
#include <linux/workqueue.h>
-#define IWL 3945
-
#include "../net/mac80211/ieee80211_rate.h"
-#include "iwlwifi.h"
+#include "iwl-3945.h"
#define RS_NAME "iwl-3945-rs"
-struct iwl_rate_scale_data {
+struct iwl3945_rate_scale_data {
u64 data;
s32 success_counter;
s32 success_ratio;
@@ -54,7 +52,7 @@ struct iwl_rate_scale_data {
unsigned long stamp;
};
-struct iwl_rate_scale_priv {
+struct iwl3945_rs_sta {
spinlock_t lock;
s32 *expected_tpt;
unsigned long last_partial_flush;
@@ -67,31 +65,31 @@ struct iwl_rate_scale_priv {
u8 start_rate;
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
- struct iwl_rate_scale_data win[IWL_RATE_COUNT];
+ struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
};
-static s32 iwl_expected_tpt_g[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT] = {
7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
};
-static s32 iwl_expected_tpt_g_prot[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT] = {
7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
};
-static s32 iwl_expected_tpt_a[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT] = {
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
};
-static s32 iwl_expected_tpt_b[IWL_RATE_COUNT] = {
+static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT] = {
7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
};
-struct iwl_tpt_entry {
+struct iwl3945_tpt_entry {
s8 min_rssi;
u8 index;
};
-static struct iwl_tpt_entry iwl_tpt_table_a[] = {
+static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
{-60, IWL_RATE_54M_INDEX},
{-64, IWL_RATE_48M_INDEX},
{-72, IWL_RATE_36M_INDEX},
@@ -102,7 +100,7 @@ static struct iwl_tpt_entry iwl_tpt_table_a[] = {
{-89, IWL_RATE_6M_INDEX}
};
-static struct iwl_tpt_entry iwl_tpt_table_b[] = {
+static struct iwl3945_tpt_entry iwl3945_tpt_table_b[] = {
{-86, IWL_RATE_11M_INDEX},
{-88, IWL_RATE_5M_INDEX},
{-90, IWL_RATE_2M_INDEX},
@@ -110,7 +108,7 @@ static struct iwl_tpt_entry iwl_tpt_table_b[] = {
};
-static struct iwl_tpt_entry iwl_tpt_table_g[] = {
+static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
{-60, IWL_RATE_54M_INDEX},
{-64, IWL_RATE_48M_INDEX},
{-68, IWL_RATE_36M_INDEX},
@@ -131,30 +129,30 @@ static struct iwl_tpt_entry iwl_tpt_table_g[] = {
#define IWL_RATE_MIN_SUCCESS_TH 8
#define IWL_RATE_DECREASE_TH 1920
-static u8 iwl_get_rate_index_by_rssi(s32 rssi, u8 mode)
+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, u8 mode)
{
u32 index = 0;
u32 table_size = 0;
- struct iwl_tpt_entry *tpt_table = NULL;
+ struct iwl3945_tpt_entry *tpt_table = NULL;
if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
rssi = IWL_MIN_RSSI_VAL;
switch (mode) {
case MODE_IEEE80211G:
- tpt_table = iwl_tpt_table_g;
- table_size = ARRAY_SIZE(iwl_tpt_table_g);
+ tpt_table = iwl3945_tpt_table_g;
+ table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
break;
case MODE_IEEE80211A:
- tpt_table = iwl_tpt_table_a;
- table_size = ARRAY_SIZE(iwl_tpt_table_a);
+ tpt_table = iwl3945_tpt_table_a;
+ table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
break;
default:
case MODE_IEEE80211B:
- tpt_table = iwl_tpt_table_b;
- table_size = ARRAY_SIZE(iwl_tpt_table_b);
+ tpt_table = iwl3945_tpt_table_b;
+ table_size = ARRAY_SIZE(iwl3945_tpt_table_b);
break;
}
@@ -166,7 +164,7 @@ static u8 iwl_get_rate_index_by_rssi(s32 rssi, u8 mode)
return tpt_table[index].index;
}
-static void iwl_clear_window(struct iwl_rate_scale_data *window)
+static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
{
window->data = 0;
window->success_counter = 0;
@@ -177,13 +175,13 @@ static void iwl_clear_window(struct iwl_rate_scale_data *window)
}
/**
- * iwl_rate_scale_flush_windows - flush out the rate scale windows
+ * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
*
* Returns the number of windows that have gathered data but were
* not flushed. If there were any that were not flushed, then
* reschedule the rate flushing routine.
*/
-static int iwl_rate_scale_flush_windows(struct iwl_rate_scale_priv *rs_priv)
+static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
{
int unflushed = 0;
int i;
@@ -195,19 +193,19 @@ static int iwl_rate_scale_flush_windows(struct iwl_rate_scale_priv *rs_priv)
* since we flushed, clear out the gathered statistics
*/
for (i = 0; i < IWL_RATE_COUNT; i++) {
- if (!rs_priv->win[i].counter)
+ if (!rs_sta->win[i].counter)
continue;
- spin_lock_irqsave(&rs_priv->lock, flags);
- if (time_after(jiffies, rs_priv->win[i].stamp +
+ spin_lock_irqsave(&rs_sta->lock, flags);
+ if (time_after(jiffies, rs_sta->win[i].stamp +
IWL_RATE_WIN_FLUSH)) {
IWL_DEBUG_RATE("flushing %d samples of rate "
"index %d\n",
- rs_priv->win[i].counter, i);
- iwl_clear_window(&rs_priv->win[i]);
+ rs_sta->win[i].counter, i);
+ iwl3945_clear_window(&rs_sta->win[i]);
} else
unflushed++;
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
}
return unflushed;
@@ -216,30 +214,30 @@ static int iwl_rate_scale_flush_windows(struct iwl_rate_scale_priv *rs_priv)
#define IWL_RATE_FLUSH_MAX 5000 /* msec */
#define IWL_RATE_FLUSH_MIN 50 /* msec */
-static void iwl_bg_rate_scale_flush(unsigned long data)
+static void iwl3945_bg_rate_scale_flush(unsigned long data)
{
- struct iwl_rate_scale_priv *rs_priv = (void *)data;
+ struct iwl3945_rs_sta *rs_sta = (void *)data;
int unflushed = 0;
unsigned long flags;
u32 packet_count, duration, pps;
IWL_DEBUG_RATE("enter\n");
- unflushed = iwl_rate_scale_flush_windows(rs_priv);
+ unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
- spin_lock_irqsave(&rs_priv->lock, flags);
+ spin_lock_irqsave(&rs_sta->lock, flags);
- rs_priv->flush_pending = 0;
+ rs_sta->flush_pending = 0;
/* Number of packets Rx'd since last time this timer ran */
- packet_count = (rs_priv->tx_packets - rs_priv->last_tx_packets) + 1;
+ packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
- rs_priv->last_tx_packets = rs_priv->tx_packets + 1;
+ rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
if (unflushed) {
duration =
- jiffies_to_msecs(jiffies - rs_priv->last_partial_flush);
-/* duration = jiffies_to_msecs(rs_priv->flush_time); */
+ jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
+/* duration = jiffies_to_msecs(rs_sta->flush_time); */
IWL_DEBUG_RATE("Tx'd %d packets in %dms\n",
packet_count, duration);
@@ -257,36 +255,36 @@ static void iwl_bg_rate_scale_flush(unsigned long data)
} else
duration = IWL_RATE_FLUSH_MAX;
- rs_priv->flush_time = msecs_to_jiffies(duration);
+ rs_sta->flush_time = msecs_to_jiffies(duration);
IWL_DEBUG_RATE("new flush period: %d msec ave %d\n",
duration, packet_count);
- mod_timer(&rs_priv->rate_scale_flush, jiffies +
- rs_priv->flush_time);
+ mod_timer(&rs_sta->rate_scale_flush, jiffies +
+ rs_sta->flush_time);
- rs_priv->last_partial_flush = jiffies;
+ rs_sta->last_partial_flush = jiffies;
}
/* If there weren't any unflushed entries, we don't schedule the timer
* to run again */
- rs_priv->last_flush = jiffies;
+ rs_sta->last_flush = jiffies;
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
IWL_DEBUG_RATE("leave\n");
}
/**
- * iwl_collect_tx_data - Update the success/failure sliding window
+ * iwl3945_collect_tx_data - Update the success/failure sliding window
*
* We keep a sliding window of the last 64 packets transmitted
* at this rate. window->data contains the bitmask of successful
* packets.
*/
-static void iwl_collect_tx_data(struct iwl_rate_scale_priv *rs_priv,
- struct iwl_rate_scale_data *window,
+static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
+ struct iwl3945_rate_scale_data *window,
int success, int retries)
{
unsigned long flags;
@@ -297,7 +295,7 @@ static void iwl_collect_tx_data(struct iwl_rate_scale_priv *rs_priv,
}
while (retries--) {
- spin_lock_irqsave(&rs_priv->lock, flags);
+ spin_lock_irqsave(&rs_sta->lock, flags);
/* If we have filled up the window then subtract one from the
* success counter if the high-bit is counting toward
@@ -325,7 +323,7 @@ static void iwl_collect_tx_data(struct iwl_rate_scale_priv *rs_priv,
/* Tag this window as having been updated */
window->stamp = jiffies;
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
}
}
@@ -362,7 +360,7 @@ static void *rs_alloc(struct ieee80211_local *local)
return local->hw.priv;
}
-/* rate scale requires free function to be implmented */
+/* rate scale requires free function to be implemented */
static void rs_free(void *priv)
{
return;
@@ -375,49 +373,49 @@ static void rs_clear(void *priv)
static void *rs_alloc_sta(void *priv, gfp_t gfp)
{
- struct iwl_rate_scale_priv *rs_priv;
+ struct iwl3945_rs_sta *rs_sta;
int i;
IWL_DEBUG_RATE("enter\n");
- rs_priv = kzalloc(sizeof(struct iwl_rate_scale_priv), gfp);
- if (!rs_priv) {
+ rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp);
+ if (!rs_sta) {
IWL_DEBUG_RATE("leave: ENOMEM\n");
return NULL;
}
- spin_lock_init(&rs_priv->lock);
+ spin_lock_init(&rs_sta->lock);
- rs_priv->start_rate = IWL_RATE_INVALID;
+ rs_sta->start_rate = IWL_RATE_INVALID;
/* default to just 802.11b */
- rs_priv->expected_tpt = iwl_expected_tpt_b;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_b;
- rs_priv->last_partial_flush = jiffies;
- rs_priv->last_flush = jiffies;
- rs_priv->flush_time = IWL_RATE_FLUSH;
- rs_priv->last_tx_packets = 0;
- rs_priv->ibss_sta_added = 0;
+ 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_priv->rate_scale_flush);
- rs_priv->rate_scale_flush.data = (unsigned long)rs_priv;
- rs_priv->rate_scale_flush.function = &iwl_bg_rate_scale_flush;
+ 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; i++)
- iwl_clear_window(&rs_priv->win[i]);
+ iwl3945_clear_window(&rs_sta->win[i]);
IWL_DEBUG_RATE("leave\n");
- return rs_priv;
+ return rs_sta;
}
static void rs_free_sta(void *priv, void *priv_sta)
{
- struct iwl_rate_scale_priv *rs_priv = priv_sta;
+ struct iwl3945_rs_sta *rs_sta = priv_sta;
IWL_DEBUG_RATE("enter\n");
- del_timer_sync(&rs_priv->rate_scale_flush);
- kfree(rs_priv);
+ del_timer_sync(&rs_sta->rate_scale_flush);
+ kfree(rs_sta);
IWL_DEBUG_RATE("leave\n");
}
@@ -427,9 +425,9 @@ static void rs_free_sta(void *priv, void *priv_sta)
* for A and B mode we need to overright prev
* value
*/
-static int rs_adjust_next_rate(struct iwl_priv *priv, int rate)
+static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
{
- int next_rate = iwl_get_prev_ieee_rate(rate);
+ int next_rate = iwl3945_get_prev_ieee_rate(rate);
switch (priv->phymode) {
case MODE_IEEE80211A:
@@ -451,7 +449,7 @@ static int rs_adjust_next_rate(struct iwl_priv *priv, int rate)
/**
* rs_tx_status - Update rate control values based on Tx results
*
- * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
+ * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by
* the hardware for each rate.
*/
static void rs_tx_status(void *priv_rate,
@@ -464,9 +462,9 @@ static void rs_tx_status(void *priv_rate,
unsigned long flags;
struct sta_info *sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iwl_rate_scale_priv *rs_priv;
+ struct iwl3945_rs_sta *rs_sta;
IWL_DEBUG_RATE("enter\n");
@@ -487,9 +485,9 @@ static void rs_tx_status(void *priv_rate,
return;
}
- rs_priv = (void *)sta->rate_ctrl_priv;
+ rs_sta = (void *)sta->rate_ctrl_priv;
- rs_priv->tx_packets++;
+ rs_sta->tx_packets++;
scale_rate_index = first_index;
last_index = first_index;
@@ -516,8 +514,8 @@ static void rs_tx_status(void *priv_rate,
/* Update this rate accounting for as many retries
* as was used for it (per current_count) */
- iwl_collect_tx_data(rs_priv,
- &rs_priv->win[scale_rate_index],
+ iwl3945_collect_tx_data(rs_sta,
+ &rs_sta->win[scale_rate_index],
0, current_count);
IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
scale_rate_index, current_count);
@@ -535,25 +533,25 @@ static void rs_tx_status(void *priv_rate,
last_index,
(tx_resp->flags & IEEE80211_TX_STATUS_ACK) ?
"success" : "failure");
- iwl_collect_tx_data(rs_priv,
- &rs_priv->win[last_index],
+ iwl3945_collect_tx_data(rs_sta,
+ &rs_sta->win[last_index],
tx_resp->flags & IEEE80211_TX_STATUS_ACK, 1);
/* We updated the rate scale window -- if its been more than
* flush_time since the last run, schedule the flush
* again */
- spin_lock_irqsave(&rs_priv->lock, flags);
+ spin_lock_irqsave(&rs_sta->lock, flags);
- if (!rs_priv->flush_pending &&
- time_after(jiffies, rs_priv->last_partial_flush +
- rs_priv->flush_time)) {
+ if (!rs_sta->flush_pending &&
+ time_after(jiffies, rs_sta->last_partial_flush +
+ rs_sta->flush_time)) {
- rs_priv->flush_pending = 1;
- mod_timer(&rs_priv->rate_scale_flush,
- jiffies + rs_priv->flush_time);
+ rs_sta->flush_pending = 1;
+ mod_timer(&rs_sta->rate_scale_flush,
+ jiffies + rs_sta->flush_time);
}
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
sta_info_put(sta);
@@ -562,29 +560,13 @@ static void rs_tx_status(void *priv_rate,
return;
}
-static struct ieee80211_rate *iwl_get_lowest_rate(struct ieee80211_local
- *local)
-{
- struct ieee80211_hw_mode *mode = local->oper_hw_mode;
- int i;
-
- for (i = 0; i < mode->num_rates; i++) {
- struct ieee80211_rate *rate = &mode->rates[i];
-
- if (rate->flags & IEEE80211_RATE_SUPPORTED)
- return rate;
- }
-
- return &mode->rates[0];
-}
-
-static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv,
+static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
u8 index, u16 rate_mask, int phymode)
{
u8 high = IWL_RATE_INVALID;
u8 low = IWL_RATE_INVALID;
- /* 802.11A walks to the next literal adjascent rate in
+ /* 802.11A walks to the next literal adjacent rate in
* the rate table */
if (unlikely(phymode == MODE_IEEE80211A)) {
int i;
@@ -613,10 +595,10 @@ static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv,
low = index;
while (low != IWL_RATE_INVALID) {
- if (rs_priv->tgg)
- low = iwl_rates[low].prev_rs_tgg;
+ if (rs_sta->tgg)
+ low = iwl3945_rates[low].prev_rs_tgg;
else
- low = iwl_rates[low].prev_rs;
+ low = iwl3945_rates[low].prev_rs;
if (low == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << low))
@@ -626,10 +608,10 @@ static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv,
high = index;
while (high != IWL_RATE_INVALID) {
- if (rs_priv->tgg)
- high = iwl_rates[high].next_rs_tgg;
+ if (rs_sta->tgg)
+ high = iwl3945_rates[high].next_rs_tgg;
else
- high = iwl_rates[high].next_rs;
+ high = iwl3945_rates[high].next_rs;
if (high == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << high))
@@ -656,17 +638,16 @@ static u16 iwl_get_adjacent_rate(struct iwl_rate_scale_priv *rs_priv,
* rate table and must reference the driver allocated rate table
*
*/
-static struct ieee80211_rate *rs_get_rate(void *priv_rate,
- struct net_device *dev,
- struct sk_buff *skb,
- struct rate_control_extra *extra)
+static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+ struct rate_selection *sel)
{
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
int index;
- struct iwl_rate_scale_priv *rs_priv;
- struct iwl_rate_scale_data *window = NULL;
+ struct iwl3945_rs_sta *rs_sta;
+ struct iwl3945_rate_scale_data *window = NULL;
int current_tpt = IWL_INVALID_VALUE;
int low_tpt = IWL_INVALID_VALUE;
int high_tpt = IWL_INVALID_VALUE;
@@ -677,31 +658,24 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
u16 fc, rate_mask;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RATE("enter\n");
- memset(extra, 0, sizeof(*extra));
+ sta = sta_info_get(local, hdr->addr1);
+ /* Send management frames and broadcast/multicast data using lowest
+ * rate. */
fc = le16_to_cpu(hdr->frame_control);
- if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
- (is_multicast_ether_addr(hdr->addr1))) {
- /* Send management frames and broadcast/multicast data using
- * lowest rate. */
- /* TODO: this could probably be improved.. */
- IWL_DEBUG_RATE("leave: lowest rate (not data or is "
- "multicast)\n");
-
- return iwl_get_lowest_rate(local);
- }
-
- sta = sta_info_get(local, hdr->addr1);
- if (!sta || !sta->rate_ctrl_priv) {
+ if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA ||
+ is_multicast_ether_addr(hdr->addr1) ||
+ !sta || !sta->rate_ctrl_priv) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
+ sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
if (sta)
sta_info_put(sta);
- return NULL;
+ return;
}
rate_mask = sta->supp_rates;
@@ -710,37 +684,37 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
if (priv->phymode == (u8) MODE_IEEE80211A)
rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
- rs_priv = (void *)sta->rate_ctrl_priv;
+ rs_sta = (void *)sta->rate_ctrl_priv;
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
- !rs_priv->ibss_sta_added) {
- u8 sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ !rs_sta->ibss_sta_added) {
+ u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, hdr->addr1));
- sta_id = iwl_add_station(priv,
+ sta_id = iwl3945_add_station(priv,
hdr->addr1, 0, CMD_ASYNC);
}
if (sta_id != IWL_INVALID_STATION)
- rs_priv->ibss_sta_added = 1;
+ rs_sta->ibss_sta_added = 1;
}
- spin_lock_irqsave(&rs_priv->lock, flags);
+ spin_lock_irqsave(&rs_sta->lock, flags);
- if (rs_priv->start_rate != IWL_RATE_INVALID) {
- index = rs_priv->start_rate;
- rs_priv->start_rate = IWL_RATE_INVALID;
+ if (rs_sta->start_rate != IWL_RATE_INVALID) {
+ index = rs_sta->start_rate;
+ rs_sta->start_rate = IWL_RATE_INVALID;
}
- window = &(rs_priv->win[index]);
+ window = &(rs_sta->win[index]);
fail_count = window->counter - window->success_counter;
if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
window->average_tpt = IWL_INVALID_VALUE;
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
"counter: %d, success_counter: %d, "
@@ -748,27 +722,27 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
index,
window->counter,
window->success_counter,
- rs_priv->expected_tpt ? "not " : "");
+ rs_sta->expected_tpt ? "not " : "");
goto out;
}
window->average_tpt = ((window->success_ratio *
- rs_priv->expected_tpt[index] + 64) / 128);
+ rs_sta->expected_tpt[index] + 64) / 128);
current_tpt = window->average_tpt;
- high_low = iwl_get_adjacent_rate(rs_priv, index, rate_mask,
+ high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
local->hw.conf.phymode);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
if (low != IWL_RATE_INVALID)
- low_tpt = rs_priv->win[low].average_tpt;
+ low_tpt = rs_sta->win[low].average_tpt;
if (high != IWL_RATE_INVALID)
- high_tpt = rs_priv->win[high].average_tpt;
+ high_tpt = rs_sta->win[high].average_tpt;
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
scale_action = 1;
@@ -846,7 +820,7 @@ static struct ieee80211_rate *rs_get_rate(void *priv_rate,
IWL_DEBUG_RATE("leave: %d\n", index);
- return &priv->ieee_rates[index];
+ sel->rate = &priv->ieee_rates[index];
}
static struct rate_control_ops rs_ops = {
@@ -862,11 +836,11 @@ static struct rate_control_ops rs_ops = {
.free_sta = rs_free_sta,
};
-int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+int iwl3945_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct iwl_priv *priv = hw->priv;
- struct iwl_rate_scale_priv *rs_priv;
+ struct iwl3945_priv *priv = hw->priv;
+ struct iwl3945_rs_sta *rs_sta;
struct sta_info *sta;
unsigned long flags;
int count = 0, i;
@@ -884,28 +858,29 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
return sprintf(buf, "station %d not found\n", sta_id);
}
- rs_priv = (void *)sta->rate_ctrl_priv;
- spin_lock_irqsave(&rs_priv->lock, flags);
+ rs_sta = (void *)sta->rate_ctrl_priv;
+ spin_lock_irqsave(&rs_sta->lock, flags);
i = IWL_RATE_54M_INDEX;
while (1) {
u64 mask;
int j;
count +=
- sprintf(&buf[count], " %2dMbs: ", iwl_rates[i].ieee / 2);
+ sprintf(&buf[count], " %2dMbs: ", iwl3945_rates[i].ieee / 2);
mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
buf[count++] =
- (rs_priv->win[i].data & mask) ? '1' : '0';
+ (rs_sta->win[i].data & mask) ? '1' : '0';
- samples += rs_priv->win[i].counter;
- good += rs_priv->win[i].success_counter;
- success += rs_priv->win[i].success_counter * iwl_rates[i].ieee;
+ samples += rs_sta->win[i].counter;
+ good += rs_sta->win[i].success_counter;
+ success += rs_sta->win[i].success_counter *
+ iwl3945_rates[i].ieee;
- if (rs_priv->win[i].stamp) {
+ if (rs_sta->win[i].stamp) {
int delta =
- jiffies_to_msecs(now - rs_priv->win[i].stamp);
+ jiffies_to_msecs(now - rs_sta->win[i].stamp);
if (delta > max_time)
max_time = delta;
@@ -914,18 +889,18 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
} else
buf[count++] = '\n';
- j = iwl_get_prev_ieee_rate(i);
+ j = iwl3945_get_prev_ieee_rate(i);
if (j == i)
break;
i = j;
}
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
sta_info_put(sta);
/* Display the average rate of all samples taken.
*
* NOTE: We multiple # of samples by 2 since the IEEE measurement
- * added from iwl_rates is actually 2X the rate */
+ * added from iwl3945_rates is actually 2X the rate */
if (samples)
count += sprintf(
&buf[count],
@@ -939,13 +914,13 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
return count;
}
-void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
s32 rssi = 0;
unsigned long flags;
struct ieee80211_local *local = hw_to_local(hw);
- struct iwl_rate_scale_priv *rs_priv;
+ struct iwl3945_rs_sta *rs_sta;
struct sta_info *sta;
IWL_DEBUG_RATE("enter\n");
@@ -965,33 +940,33 @@ void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
return;
}
- rs_priv = (void *)sta->rate_ctrl_priv;
+ rs_sta = (void *)sta->rate_ctrl_priv;
- spin_lock_irqsave(&rs_priv->lock, flags);
+ spin_lock_irqsave(&rs_sta->lock, flags);
- rs_priv->tgg = 0;
+ rs_sta->tgg = 0;
switch (priv->phymode) {
case MODE_IEEE80211G:
if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) {
- rs_priv->tgg = 1;
- rs_priv->expected_tpt = iwl_expected_tpt_g_prot;
+ rs_sta->tgg = 1;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
} else
- rs_priv->expected_tpt = iwl_expected_tpt_g;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_g;
break;
case MODE_IEEE80211A:
- rs_priv->expected_tpt = iwl_expected_tpt_a;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_a;
break;
default:
IWL_WARNING("Invalid phymode. Defaulting to 802.11b\n");
case MODE_IEEE80211B:
- rs_priv->expected_tpt = iwl_expected_tpt_b;
+ rs_sta->expected_tpt = iwl3945_expected_tpt_b;
break;
}
sta_info_put(sta);
- spin_unlock_irqrestore(&rs_priv->lock, flags);
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
rssi = priv->last_rx_rssi;
if (rssi == 0)
@@ -999,19 +974,20 @@ void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_RATE, "Network RSSI: %d\n", rssi);
- rs_priv->start_rate = iwl_get_rate_index_by_rssi(rssi, priv->phymode);
+ rs_sta->start_rate =
+ iwl3945_get_rate_index_by_rssi(rssi, priv->phymode);
IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
- "%d (plcp 0x%x)\n", rssi, rs_priv->start_rate,
- iwl_rates[rs_priv->start_rate].plcp);
+ "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
+ iwl3945_rates[rs_sta->start_rate].plcp);
}
-void iwl_rate_control_register(struct ieee80211_hw *hw)
+void iwl3945_rate_control_register(struct ieee80211_hw *hw)
{
ieee80211_rate_control_register(&rs_ops);
}
-void iwl_rate_control_unregister(struct ieee80211_hw *hw)
+void iwl3945_rate_control_unregister(struct ieee80211_hw *hw)
{
ieee80211_rate_control_unregister(&rs_ops);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
index bec4d3ffca1d..d5e9220f871d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
@@ -27,9 +27,9 @@
#ifndef __iwl_3945_rs_h__
#define __iwl_3945_rs_h__
-struct iwl_rate_info {
- u8 plcp;
- u8 ieee;
+struct iwl3945_rate_info {
+ u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
+ u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */
u8 prev_ieee; /* previous rate in IEEE speeds */
u8 next_ieee; /* next rate in IEEE speeds */
u8 prev_rs; /* previous rate used in rs algo */
@@ -38,9 +38,12 @@ struct iwl_rate_info {
u8 next_rs_tgg; /* next rate used in TGG rs algo */
u8 table_rs_index; /* index in rate scale table cmd */
u8 prev_table_rs; /* prev in rate table cmd */
-
};
+/*
+ * These serve as indexes into
+ * struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT];
+ */
enum {
IWL_RATE_1M_INDEX = 0,
IWL_RATE_2M_INDEX,
@@ -83,19 +86,20 @@ enum {
};
/* #define vs. enum to keep from defaulting to 'large integer' */
-#define IWL_RATE_6M_MASK (1<<IWL_RATE_6M_INDEX)
-#define IWL_RATE_9M_MASK (1<<IWL_RATE_9M_INDEX)
-#define IWL_RATE_12M_MASK (1<<IWL_RATE_12M_INDEX)
-#define IWL_RATE_18M_MASK (1<<IWL_RATE_18M_INDEX)
-#define IWL_RATE_24M_MASK (1<<IWL_RATE_24M_INDEX)
-#define IWL_RATE_36M_MASK (1<<IWL_RATE_36M_INDEX)
-#define IWL_RATE_48M_MASK (1<<IWL_RATE_48M_INDEX)
-#define IWL_RATE_54M_MASK (1<<IWL_RATE_54M_INDEX)
-#define IWL_RATE_1M_MASK (1<<IWL_RATE_1M_INDEX)
-#define IWL_RATE_2M_MASK (1<<IWL_RATE_2M_INDEX)
-#define IWL_RATE_5M_MASK (1<<IWL_RATE_5M_INDEX)
-#define IWL_RATE_11M_MASK (1<<IWL_RATE_11M_INDEX)
-
+#define IWL_RATE_6M_MASK (1 << IWL_RATE_6M_INDEX)
+#define IWL_RATE_9M_MASK (1 << IWL_RATE_9M_INDEX)
+#define IWL_RATE_12M_MASK (1 << IWL_RATE_12M_INDEX)
+#define IWL_RATE_18M_MASK (1 << IWL_RATE_18M_INDEX)
+#define IWL_RATE_24M_MASK (1 << IWL_RATE_24M_INDEX)
+#define IWL_RATE_36M_MASK (1 << IWL_RATE_36M_INDEX)
+#define IWL_RATE_48M_MASK (1 << IWL_RATE_48M_INDEX)
+#define IWL_RATE_54M_MASK (1 << IWL_RATE_54M_INDEX)
+#define IWL_RATE_1M_MASK (1 << IWL_RATE_1M_INDEX)
+#define IWL_RATE_2M_MASK (1 << IWL_RATE_2M_INDEX)
+#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX)
+#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
+
+/* 3945 uCode API values for (legacy) bit rates, both OFDM and CCK */
enum {
IWL_RATE_6M_PLCP = 13,
IWL_RATE_9M_PLCP = 15,
@@ -111,6 +115,7 @@ enum {
IWL_RATE_11M_PLCP = 110,
};
+/* MAC header values for bit rates */
enum {
IWL_RATE_6M_IEEE = 12,
IWL_RATE_9M_IEEE = 18,
@@ -152,18 +157,18 @@ enum {
(IWL_OFDM_BASIC_RATES_MASK | \
IWL_CCK_BASIC_RATES_MASK)
-#define IWL_RATES_MASK ((1<<IWL_RATE_COUNT)-1)
+#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
#define IWL_INVALID_VALUE -1
#define IWL_MIN_RSSI_VAL -100
#define IWL_MAX_RSSI_VAL 0
-extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
+extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT];
-static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
+static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
{
- u8 rate = iwl_rates[rate_index].prev_ieee;
+ u8 rate = iwl3945_rates[rate_index].prev_ieee;
if (rate == IWL_RATE_INVALID)
rate = rate_index;
@@ -171,40 +176,40 @@ static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
}
/**
- * iwl_fill_rs_info - Fill an output text buffer with the rate representation
+ * iwl3945_fill_rs_info - Fill an output text buffer with the rate representation
*
* NOTE: This is provided as a quick mechanism for a user to visualize
- * the performance of the rate control alogirthm and is not meant to be
+ * the performance of the rate control algorithm and is not meant to be
* parsed software.
*/
-extern int iwl_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
+extern int iwl3945_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
/**
- * iwl_rate_scale_init - Initialize the rate scale table based on assoc info
+ * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
*
- * The specific througput table used is based on the type of network
+ * The specific throughput table used is based on the type of network
* the associated with, including A, B, G, and G w/ TGG protection
*/
-extern void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
/**
- * iwl_rate_control_register - Register the rate control algorithm callbacks
+ * iwl3945_rate_control_register - Register the rate control algorithm callbacks
*
* Since the rate control algorithm is hardware specific, there is no need
* or reason to place it as a stand alone module. The driver can call
- * iwl_rate_control_register in order to register the rate control callbacks
+ * iwl3945_rate_control_register in order to register the rate control callbacks
* with the mac80211 subsystem. This should be performed prior to calling
* ieee80211_register_hw
*
*/
-extern void iwl_rate_control_register(struct ieee80211_hw *hw);
+extern void iwl3945_rate_control_register(struct ieee80211_hw *hw);
/**
- * iwl_rate_control_unregister - Unregister the rate control callbacks
+ * iwl3945_rate_control_unregister - Unregister the rate control callbacks
*
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
-extern void iwl_rate_control_unregister(struct ieee80211_hw *hw);
+extern void iwl3945_rate_control_unregister(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 3a45fe99a83e..76c4ed1135f2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -35,15 +35,12 @@
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/firmware.h>
-#include <net/mac80211.h>
-
#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+#include <net/mac80211.h>
-#define IWL 3945
-
-#include "iwlwifi.h"
-#include "iwl-helpers.h"
#include "iwl-3945.h"
+#include "iwl-helpers.h"
#include "iwl-3945-rs.h"
#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \
@@ -66,7 +63,7 @@
* maps to IWL_RATE_INVALID
*
*/
-const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */
IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */
IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */
@@ -81,12 +78,12 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
};
-/* 1 = enable the iwl_disable_events() function */
+/* 1 = enable the iwl3945_disable_events() function */
#define IWL_EVT_DISABLE (0)
#define IWL_EVT_DISABLE_SIZE (1532/32)
/**
- * iwl_disable_events - Disable selected events in uCode event log
+ * iwl3945_disable_events - Disable selected events in uCode event log
*
* Disable an event by writing "1"s into "disable"
* bitmap in SRAM. Bit position corresponds to Event # (id/type).
@@ -94,9 +91,9 @@ const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
* Use for only special debugging. This function is just a placeholder as-is,
* you'll need to provide the special bits! ...
* ... and set IWL_EVT_DISABLE to 1. */
-void iwl_disable_events(struct iwl_priv *priv)
+void iwl3945_disable_events(struct iwl3945_priv *priv)
{
- int rc;
+ int ret;
int i;
u32 base; /* SRAM address of event log header */
u32 disable_ptr; /* SRAM address of event-disable bitmap array */
@@ -152,32 +149,31 @@ void iwl_disable_events(struct iwl_priv *priv)
};
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl_hw_valid_rtc_data_addr(base)) {
+ if (!iwl3945_hw_valid_rtc_data_addr(base)) {
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
return;
}
- rc = iwl_grab_restricted_access(priv);
- if (rc) {
+ ret = iwl3945_grab_nic_access(priv);
+ if (ret) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
- disable_ptr = iwl_read_restricted_mem(priv, base + (4 * sizeof(u32)));
- array_size = iwl_read_restricted_mem(priv, base + (5 * sizeof(u32)));
- iwl_release_restricted_access(priv);
+ disable_ptr = iwl3945_read_targ_mem(priv, base + (4 * sizeof(u32)));
+ array_size = iwl3945_read_targ_mem(priv, base + (5 * sizeof(u32)));
+ iwl3945_release_nic_access(priv);
if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
IWL_DEBUG_INFO("Disabling selected uCode log events at 0x%x\n",
disable_ptr);
- rc = iwl_grab_restricted_access(priv);
+ ret = iwl3945_grab_nic_access(priv);
for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
- iwl_write_restricted_mem(priv,
- disable_ptr +
- (i * sizeof(u32)),
- evt_disable[i]);
+ iwl3945_write_targ_mem(priv,
+ disable_ptr + (i * sizeof(u32)),
+ evt_disable[i]);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
} else {
IWL_DEBUG_INFO("Selected uCode log events may be disabled\n");
IWL_DEBUG_INFO(" by writing \"1\"s into disable bitmap\n");
@@ -198,7 +194,7 @@ void iwl_disable_events(struct iwl_priv *priv)
* IWL_ANTENNA_MAIN - Force MAIN antenna
* IWL_ANTENNA_AUX - Force AUX antenna
*/
-__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
+__le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv)
{
switch (priv->antenna) {
case IWL_ANTENNA_DIVERSITY:
@@ -230,11 +226,11 @@ __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
*
*****************************************************************************/
-void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RX("Statistics notification received (%d vs %d).\n",
- (int)sizeof(struct iwl_notif_statistics),
+ (int)sizeof(struct iwl3945_notif_statistics),
le32_to_cpu(pkt->len));
memcpy(&priv->statistics, pkt->u.raw, sizeof(priv->statistics));
@@ -242,15 +238,107 @@ void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
priv->last_statistics_time = jiffies;
}
-static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
- struct iwl_rx_mem_buffer *rxb,
- struct ieee80211_rx_status *stats,
- u16 phy_flags)
+void iwl3945_add_radiotap(struct iwl3945_priv *priv, struct sk_buff *skb,
+ struct iwl3945_rx_frame_hdr *rx_hdr,
+ struct ieee80211_rx_status *stats)
+{
+ /* First cache any information we need before we overwrite
+ * the information provided in the skb from the hardware */
+ s8 signal = stats->ssi;
+ s8 noise = 0;
+ int rate = stats->rate;
+ u64 tsf = stats->mactime;
+ __le16 phy_flags_hw = rx_hdr->phy_flags;
+
+ struct iwl3945_rt_rx_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+ __le64 rt_tsf; /* TSF */
+ u8 rt_flags; /* radiotap packet flags */
+ u8 rt_rate; /* rate in 500kb/s */
+ __le16 rt_channelMHz; /* channel in MHz */
+ __le16 rt_chbitmask; /* channel bitfield */
+ s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
+ s8 rt_dbmnoise;
+ u8 rt_antenna; /* antenna number */
+ } __attribute__ ((packed)) *iwl3945_rt;
+
+ if (skb_headroom(skb) < sizeof(*iwl3945_rt)) {
+ if (net_ratelimit())
+ printk(KERN_ERR "not enough headroom [%d] for "
+ "radiotap head [%zd]\n",
+ skb_headroom(skb), sizeof(*iwl3945_rt));
+ return;
+ }
+
+ /* put radiotap header in front of 802.11 header and data */
+ iwl3945_rt = (void *)skb_push(skb, sizeof(*iwl3945_rt));
+
+ /* initialise radiotap header */
+ iwl3945_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+ iwl3945_rt->rt_hdr.it_pad = 0;
+
+ /* total header + data */
+ put_unaligned(cpu_to_le16(sizeof(*iwl3945_rt)),
+ &iwl3945_rt->rt_hdr.it_len);
+
+ /* Indicate all the fields we add to the radiotap header */
+ put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+ (1 << IEEE80211_RADIOTAP_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_CHANNEL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+ (1 << IEEE80211_RADIOTAP_ANTENNA)),
+ &iwl3945_rt->rt_hdr.it_present);
+
+ /* Zero the flags, we'll add to them as we go */
+ iwl3945_rt->rt_flags = 0;
+
+ put_unaligned(cpu_to_le64(tsf), &iwl3945_rt->rt_tsf);
+
+ iwl3945_rt->rt_dbmsignal = signal;
+ iwl3945_rt->rt_dbmnoise = noise;
+
+ /* Convert the channel frequency and set the flags */
+ put_unaligned(cpu_to_le16(stats->freq), &iwl3945_rt->rt_channelMHz);
+ if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_5GHZ),
+ &iwl3945_rt->rt_chbitmask);
+ else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
+ IEEE80211_CHAN_2GHZ),
+ &iwl3945_rt->rt_chbitmask);
+ else /* 802.11g */
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_2GHZ),
+ &iwl3945_rt->rt_chbitmask);
+
+ rate = iwl3945_rate_index_from_plcp(rate);
+ if (rate == -1)
+ iwl3945_rt->rt_rate = 0;
+ else
+ iwl3945_rt->rt_rate = iwl3945_rates[rate].ieee;
+
+ /* antenna number */
+ iwl3945_rt->rt_antenna =
+ le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+ /* set the preamble flag if we have it */
+ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+ iwl3945_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ stats->flag |= RX_FLAG_RADIOTAP;
+}
+
+static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+ struct iwl3945_rx_mem_buffer *rxb,
+ struct ieee80211_rx_status *stats)
{
struct ieee80211_hdr *hdr;
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
+ struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
+ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
short len = le16_to_cpu(rx_hdr->len);
/* We received data from the HW, so stop the watchdog */
@@ -265,15 +353,6 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
("Dropping packet while interface is not open.\n");
return;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- if (iwl_param_hwcrypto)
- iwl_set_decrypted_flag(priv, rxb->skb,
- le32_to_cpu(rx_end->status),
- stats);
- iwl_handle_data_packet_monitor(priv, rxb, IWL_RX_DATA(pkt),
- len, stats, phy_flags);
- return;
- }
skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
/* Set the size of the skb to the size of the frame */
@@ -281,23 +360,27 @@ static void iwl3945_handle_data_packet(struct iwl_priv *priv, int is_data,
hdr = (void *)rxb->skb->data;
- if (iwl_param_hwcrypto)
- iwl_set_decrypted_flag(priv, rxb->skb,
+ if (iwl3945_param_hwcrypto)
+ iwl3945_set_decrypted_flag(priv, rxb->skb,
le32_to_cpu(rx_end->status), stats);
+ if (priv->add_radiotap)
+ iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
+
ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
rxb->skb = NULL;
}
-static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
+static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
struct ieee80211_hdr *header;
- u16 phy_flags = le16_to_cpu(rx_hdr->phy_flags);
u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg);
u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff);
struct ieee80211_rx_status stats = {
@@ -327,7 +410,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
}
if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- iwl3945_handle_data_packet(priv, 1, rxb, &stats, phy_flags);
+ iwl3945_handle_data_packet(priv, 1, rxb, &stats);
return;
}
@@ -351,14 +434,14 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
* Calculate stats.signal (quality indicator in %) based on SNR. */
if (rx_stats_noise_diff) {
snr = rx_stats_sig_avg / rx_stats_noise_diff;
- stats.noise = stats.ssi - iwl_calc_db_from_ratio(snr);
- stats.signal = iwl_calc_sig_qual(stats.ssi, stats.noise);
+ stats.noise = stats.ssi - iwl3945_calc_db_from_ratio(snr);
+ stats.signal = iwl3945_calc_sig_qual(stats.ssi, stats.noise);
/* If noise info not available, calculate signal quality indicator (%)
* using just the dBm signal level. */
} else {
stats.noise = priv->last_rx_noise;
- stats.signal = iwl_calc_sig_qual(stats.ssi, 0);
+ stats.signal = iwl3945_calc_sig_qual(stats.ssi, 0);
}
@@ -368,24 +451,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
stats.freq = ieee80211chan2mhz(stats.channel);
- /* can be covered by iwl_report_frame() in most cases */
+ /* can be covered by iwl3945_report_frame() in most cases */
/* IWL_DEBUG_RX("RX status: 0x%08X\n", rx_end->status); */
header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
- network_packet = iwl_is_network_packet(priv, header);
+ network_packet = iwl3945_is_network_packet(priv, header);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_STATS && net_ratelimit())
+#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & IWL_DL_STATS && net_ratelimit())
IWL_DEBUG_STATS
("[%c] %d RSSI: %d Signal: %u, Noise: %u, Rate: %u\n",
network_packet ? '*' : ' ',
stats.channel, stats.ssi, stats.ssi,
stats.ssi, stats.rate);
- if (iwl_debug_level & (IWL_DL_RX))
+ if (iwl3945_debug_level & (IWL_DL_RX))
/* Set "1" to report good data frames in groups of 100 */
- iwl_report_frame(priv, pkt, header, 1);
+ iwl3945_report_frame(priv, pkt, header, 1);
#endif
if (network_packet) {
@@ -437,15 +520,20 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
break;
/*
- * TODO: There is no callback function from upper
- * stack to inform us when associated status. this
- * work around to sniff assoc_resp management frame
- * and finish the association process.
+ * TODO: Use the new callback function from
+ * mac80211 instead of sniffing these packets.
*/
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:{
struct ieee80211_mgmt *mgnt =
(struct ieee80211_mgmt *)header;
+
+ /* We have just associated, give some
+ * time for the 4-way handshake if
+ * any. Don't start scan too early. */
+ priv->next_scan_jiffies = jiffies +
+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+
priv->assoc_id = (~((1 << 15) | (1 << 14)) &
le16_to_cpu(mgnt->u.
assoc_resp.aid));
@@ -474,7 +562,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
}
}
- iwl3945_handle_data_packet(priv, 0, rxb, &stats, phy_flags);
+ iwl3945_handle_data_packet(priv, 0, rxb, &stats);
break;
case IEEE80211_FTYPE_CTL:
@@ -485,25 +573,24 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
DECLARE_MAC_BUF(mac2);
DECLARE_MAC_BUF(mac3);
- if (unlikely(is_duplicate_packet(priv, header)))
+ if (unlikely(iwl3945_is_duplicate_packet(priv, header)))
IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
print_mac(mac1, header->addr1),
print_mac(mac2, header->addr2),
print_mac(mac3, header->addr3));
else
- iwl3945_handle_data_packet(priv, 1, rxb, &stats,
- phy_flags);
+ iwl3945_handle_data_packet(priv, 1, rxb, &stats);
break;
}
}
}
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr,
dma_addr_t addr, u16 len)
{
int count;
u32 pad;
- struct iwl_tfd_frame *tfd = (struct iwl_tfd_frame *)ptr;
+ struct iwl3945_tfd_frame *tfd = (struct iwl3945_tfd_frame *)ptr;
count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
pad = TFD_CTL_PAD_GET(le32_to_cpu(tfd->control_flags));
@@ -526,14 +613,14 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
}
/**
- * iwl_hw_txq_free_tfd - Free one TFD, those at index [txq->q.last_used]
+ * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
*
* Does NOT advance any indexes
*/
-int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
{
- struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
- struct iwl_tfd_frame *bd = &bd_tmp[txq->q.last_used];
+ struct iwl3945_tfd_frame *bd_tmp = (struct iwl3945_tfd_frame *)&txq->bd[0];
+ struct iwl3945_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
struct pci_dev *dev = priv->pci_dev;
int i;
int counter;
@@ -556,19 +643,19 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
for (i = 1; i < counter; i++) {
pci_unmap_single(dev, le32_to_cpu(bd->pa[i].addr),
le32_to_cpu(bd->pa[i].len), PCI_DMA_TODEVICE);
- if (txq->txb[txq->q.last_used].skb[0]) {
- struct sk_buff *skb = txq->txb[txq->q.last_used].skb[0];
- if (txq->txb[txq->q.last_used].skb[0]) {
+ if (txq->txb[txq->q.read_ptr].skb[0]) {
+ struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0];
+ if (txq->txb[txq->q.read_ptr].skb[0]) {
/* Can be called from interrupt context */
dev_kfree_skb_any(skb);
- txq->txb[txq->q.last_used].skb[0] = NULL;
+ txq->txb[txq->q.read_ptr].skb[0] = NULL;
}
}
}
return 0;
}
-u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
+u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
{
int i;
int ret = IWL_INVALID_STATION;
@@ -592,11 +679,11 @@ u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
}
/**
- * iwl_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
+ * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
*
*/
-void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd,
struct ieee80211_tx_control *ctrl,
struct ieee80211_hdr *hdr, int sta_id, int tx_id)
{
@@ -609,7 +696,7 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
__le32 tx_flags;
u16 fc = le16_to_cpu(hdr->frame_control);
- rate = iwl_rates[rate_index].plcp;
+ rate = iwl3945_rates[rate_index].plcp;
tx_flags = cmd->cmd.tx.tx_flags;
/* We need to figure out how to get the sta->supp_rates while
@@ -676,10 +763,10 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
cmd->cmd.tx.supp_rates[1], cmd->cmd.tx.supp_rates[0]);
}
-u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
+u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id, u16 tx_rate, u8 flags)
{
unsigned long flags_spin;
- struct iwl_station_entry *station;
+ struct iwl3945_station_entry *station;
if (sta_id == IWL_INVALID_STATION)
return IWL_INVALID_STATION;
@@ -694,34 +781,19 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- iwl_send_add_station(priv, &station->sta, flags);
+ iwl3945_send_add_station(priv, &station->sta, flags);
IWL_DEBUG_RATE("SCALE sync station %d to rate %d\n",
sta_id, tx_rate);
return sta_id;
}
-void iwl_hw_card_show_info(struct iwl_priv *priv)
-{
- IWL_DEBUG_INFO("3945ABG HW Version %u.%u.%u\n",
- ((priv->eeprom.board_revision >> 8) & 0x0F),
- ((priv->eeprom.board_revision >> 8) >> 4),
- (priv->eeprom.board_revision & 0x00FF));
-
- IWL_DEBUG_INFO("3945ABG PBA Number %.*s\n",
- (int)sizeof(priv->eeprom.board_pba_number),
- priv->eeprom.board_pba_number);
-
- IWL_DEBUG_INFO("EEPROM_ANTENNA_SWITCH_TYPE is 0x%02X\n",
- priv->eeprom.antenna_switch_type);
-}
-
-static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+static int iwl3945_nic_set_pwr_src(struct iwl3945_priv *priv, int pwr_max)
{
int rc;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
@@ -733,23 +805,23 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
rc = pci_read_config_dword(priv->pci_dev,
PCI_POWER_SOURCE, &val);
if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT) {
- iwl_set_bits_mask_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
~APMG_PS_CTRL_MSK_PWR_SRC);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
- iwl_poll_bit(priv, CSR_GPIO_IN,
+ iwl3945_poll_bit(priv, CSR_GPIO_IN,
CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
CSR_GPIO_IN_BIT_AUX_POWER, 5000);
} else
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
} else {
- iwl_set_bits_mask_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl3945_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
~APMG_PS_CTRL_MSK_PWR_SRC);
- iwl_release_restricted_access(priv);
- iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+ iwl3945_release_nic_access(priv);
+ iwl3945_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -757,24 +829,24 @@ static int iwl3945_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
return rc;
}
-static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+static int iwl3945_rx_init(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
{
int rc;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted(priv, FH_RCSR_RBD_BASE(0), rxq->dma_addr);
- iwl_write_restricted(priv, FH_RCSR_RPTR_ADDR(0),
+ iwl3945_write_direct32(priv, FH_RCSR_RBD_BASE(0), rxq->dma_addr);
+ iwl3945_write_direct32(priv, FH_RCSR_RPTR_ADDR(0),
priv->hw_setting.shared_phys +
- offsetof(struct iwl_shared, rx_read_ptr[0]));
- iwl_write_restricted(priv, FH_RCSR_WPTR(0), 0);
- iwl_write_restricted(priv, FH_RCSR_CONFIG(0),
+ offsetof(struct iwl3945_shared, rx_read_ptr[0]));
+ iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), 0);
+ iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0),
ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
@@ -785,44 +857,44 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
/* fake read to flush all prev I/O */
- iwl_read_restricted(priv, FH_RSSR_CTRL);
+ iwl3945_read_direct32(priv, FH_RSSR_CTRL);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-static int iwl3945_tx_reset(struct iwl_priv *priv)
+static int iwl3945_tx_reset(struct iwl3945_priv *priv)
{
int rc;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
/* bypass mode */
- iwl_write_restricted_reg(priv, SCD_MODE_REG, 0x2);
+ iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
/* RA 0 is active */
- iwl_write_restricted_reg(priv, SCD_ARASTAT_REG, 0x01);
+ iwl3945_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
/* all 6 fifo are active */
- iwl_write_restricted_reg(priv, SCD_TXFACT_REG, 0x3f);
+ iwl3945_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
- iwl_write_restricted_reg(priv, SCD_SBYP_MODE_1_REG, 0x010000);
- iwl_write_restricted_reg(priv, SCD_SBYP_MODE_2_REG, 0x030002);
- iwl_write_restricted_reg(priv, SCD_TXF4MF_REG, 0x000004);
- iwl_write_restricted_reg(priv, SCD_TXF5MF_REG, 0x000005);
+ iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
+ iwl3945_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
+ iwl3945_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
+ iwl3945_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
- iwl_write_restricted(priv, FH_TSSR_CBB_BASE,
+ iwl3945_write_direct32(priv, FH_TSSR_CBB_BASE,
priv->hw_setting.shared_phys);
- iwl_write_restricted(priv, FH_TSSR_MSG_CONFIG,
+ iwl3945_write_direct32(priv, FH_TSSR_MSG_CONFIG,
ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
@@ -831,7 +903,7 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
@@ -842,12 +914,12 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
*
* Destroys all DMA structures and initialize them again
*/
-static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
+static int iwl3945_txq_ctx_reset(struct iwl3945_priv *priv)
{
int rc;
int txq_id, slots_num;
- iwl_hw_txq_ctx_free(priv);
+ iwl3945_hw_txq_ctx_free(priv);
/* Tx CMD queue */
rc = iwl3945_tx_reset(priv);
@@ -858,7 +930,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++) {
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+ rc = iwl3945_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id);
if (rc) {
IWL_ERROR("Tx %d queue init failed\n", txq_id);
@@ -869,26 +941,26 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
return rc;
error:
- iwl_hw_txq_ctx_free(priv);
+ iwl3945_hw_txq_ctx_free(priv);
return rc;
}
-int iwl_hw_nic_init(struct iwl_priv *priv)
+int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
{
u8 rev_id;
int rc;
unsigned long flags;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl3945_rx_queue *rxq = &priv->rxq;
- iwl_power_init_handle(priv);
+ iwl3945_power_init_handle(priv);
spin_lock_irqsave(&priv->lock, flags);
- iwl_set_bit(priv, CSR_ANA_PLL_CFG, (1 << 24));
- iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ iwl3945_set_bit(priv, CSR_ANA_PLL_CFG, (1 << 24));
+ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (rc < 0) {
@@ -897,18 +969,18 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
return rc;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
+ iwl3945_write_prph(priv, APMG_CLK_EN_REG,
APMG_CLK_VAL_DMA_CLK_RQT |
APMG_CLK_VAL_BSM_CLK_RQT);
udelay(20);
- iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
+ iwl3945_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
/* Determine HW type */
@@ -924,25 +996,17 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
IWL_DEBUG_INFO("RTP type \n");
else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) {
IWL_DEBUG_INFO("ALM-MB type\n");
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB);
} else {
IWL_DEBUG_INFO("ALM-MM type\n");
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM);
}
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Initialize the EEPROM */
- rc = iwl_eeprom_init(priv);
- if (rc)
- return rc;
-
- spin_lock_irqsave(&priv->lock, flags);
if (EEPROM_SKU_CAP_OP_MODE_MRC == priv->eeprom.sku_cap) {
IWL_DEBUG_INFO("SKU OP mode is mrc\n");
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC);
} else
IWL_DEBUG_INFO("SKU OP mode is basic\n");
@@ -950,24 +1014,24 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
if ((priv->eeprom.board_revision & 0xF0) == 0xD0) {
IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
priv->eeprom.board_revision);
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
} else {
IWL_DEBUG_INFO("3945ABG revision is 0x%X\n",
priv->eeprom.board_revision);
- iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
}
if (priv->eeprom.almgor_m_version <= 1) {
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
IWL_DEBUG_INFO("Card M type A version is 0x%X\n",
priv->eeprom.almgor_m_version);
} else {
IWL_DEBUG_INFO("Card M type B version is 0x%X\n",
priv->eeprom.almgor_m_version);
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl3945_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
}
spin_unlock_irqrestore(&priv->lock, flags);
@@ -980,15 +1044,15 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
/* Allocate the RX queue, or reset if it is already allocated */
if (!rxq->bd) {
- rc = iwl_rx_queue_alloc(priv);
+ rc = iwl3945_rx_queue_alloc(priv);
if (rc) {
IWL_ERROR("Unable to initialize Rx queue\n");
return -ENOMEM;
}
} else
- iwl_rx_queue_reset(priv, rxq);
+ iwl3945_rx_queue_reset(priv, rxq);
- iwl_rx_replenish(priv);
+ iwl3945_rx_replenish(priv);
iwl3945_rx_init(priv, rxq);
@@ -996,16 +1060,16 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
/* Look at using this instead:
rxq->need_update = 1;
- iwl_rx_queue_update_write_ptr(priv, rxq);
+ iwl3945_rx_queue_update_write_ptr(priv, rxq);
*/
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted(priv, FH_RCSR_WPTR(0), rxq->write & ~7);
- iwl_release_restricted_access(priv);
+ iwl3945_write_direct32(priv, FH_RCSR_WPTR(0), rxq->write & ~7);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1019,49 +1083,49 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
}
/**
- * iwl_hw_txq_ctx_free - Free TXQ Context
+ * iwl3945_hw_txq_ctx_free - Free TXQ Context
*
* Destroy all TX DMA queues and structures
*/
-void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
+void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv)
{
int txq_id;
/* Tx queues */
for (txq_id = 0; txq_id < TFD_QUEUE_MAX; txq_id++)
- iwl_tx_queue_free(priv, &priv->txq[txq_id]);
+ iwl3945_tx_queue_free(priv, &priv->txq[txq_id]);
}
-void iwl_hw_txq_ctx_stop(struct iwl_priv *priv)
+void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv)
{
int queue;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- if (iwl_grab_restricted_access(priv)) {
+ if (iwl3945_grab_nic_access(priv)) {
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_hw_txq_ctx_free(priv);
+ iwl3945_hw_txq_ctx_free(priv);
return;
}
/* stop SCD */
- iwl_write_restricted_reg(priv, SCD_MODE_REG, 0);
+ iwl3945_write_prph(priv, ALM_SCD_MODE_REG, 0);
/* reset TFD queues */
for (queue = TFD_QUEUE_MIN; queue < TFD_QUEUE_MAX; queue++) {
- iwl_write_restricted(priv, FH_TCSR_CONFIG(queue), 0x0);
- iwl_poll_restricted_bit(priv, FH_TSSR_TX_STATUS,
+ iwl3945_write_direct32(priv, FH_TCSR_CONFIG(queue), 0x0);
+ iwl3945_poll_direct_bit(priv, FH_TSSR_TX_STATUS,
ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(queue),
1000);
}
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_hw_txq_ctx_free(priv);
+ iwl3945_hw_txq_ctx_free(priv);
}
-int iwl_hw_nic_stop_master(struct iwl_priv *priv)
+int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv)
{
int rc = 0;
u32 reg_val;
@@ -1070,16 +1134,16 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
/* set stop master bit */
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+ iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- reg_val = iwl_read32(priv, CSR_GP_CNTRL);
+ reg_val = iwl3945_read32(priv, CSR_GP_CNTRL);
if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
(reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
IWL_DEBUG_INFO("Card in power save, master is already "
"stopped\n");
else {
- rc = iwl_poll_bit(priv, CSR_RESET,
+ rc = iwl3945_poll_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (rc < 0) {
@@ -1094,47 +1158,47 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
return rc;
}
-int iwl_hw_nic_reset(struct iwl_priv *priv)
+int iwl3945_hw_nic_reset(struct iwl3945_priv *priv)
{
int rc;
unsigned long flags;
- iwl_hw_nic_stop_master(priv);
+ iwl3945_hw_nic_stop_master(priv);
spin_lock_irqsave(&priv->lock, flags);
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (!rc) {
- iwl_write_restricted_reg(priv, APMG_CLK_CTRL_REG,
+ iwl3945_write_prph(priv, APMG_CLK_CTRL_REG,
APMG_CLK_VAL_BSM_CLK_RQT);
udelay(10);
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl3945_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- iwl_write_restricted_reg(priv, APMG_RTC_INT_MSK_REG, 0x0);
- iwl_write_restricted_reg(priv, APMG_RTC_INT_STT_REG,
+ iwl3945_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
+ iwl3945_write_prph(priv, APMG_RTC_INT_STT_REG,
0xFFFFFFFF);
/* enable DMA */
- iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
+ iwl3945_write_prph(priv, APMG_CLK_EN_REG,
APMG_CLK_VAL_DMA_CLK_RQT |
APMG_CLK_VAL_BSM_CLK_RQT);
udelay(10);
- iwl_set_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl3945_set_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
- iwl_clear_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl3945_clear_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
}
/* Clear the 'host command active' bit... */
@@ -1147,41 +1211,43 @@ int iwl_hw_nic_reset(struct iwl_priv *priv)
}
/**
- * iwl_hw_reg_adjust_power_by_temp - return index delta into power gain settings table
- */
-static int iwl_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
+ * iwl3945_hw_reg_adjust_power_by_temp
+ * return index delta into power gain settings table
+*/
+static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
{
return (new_reading - old_reading) * (-11) / 100;
}
/**
- * iwl_hw_reg_temp_out_of_range - Keep temperature in sane range
+ * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
*/
-static inline int iwl_hw_reg_temp_out_of_range(int temperature)
+static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
{
return (((temperature < -260) || (temperature > 25)) ? 1 : 0);
}
-int iwl_hw_get_temperature(struct iwl_priv *priv)
+int iwl3945_hw_get_temperature(struct iwl3945_priv *priv)
{
- return iwl_read32(priv, CSR_UCODE_DRV_GP2);
+ return iwl3945_read32(priv, CSR_UCODE_DRV_GP2);
}
/**
- * iwl_hw_reg_txpower_get_temperature - get current temperature by reading from NIC
- */
-static int iwl_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
+ * iwl3945_hw_reg_txpower_get_temperature
+ * get the current temperature by reading from NIC
+*/
+static int iwl3945_hw_reg_txpower_get_temperature(struct iwl3945_priv *priv)
{
int temperature;
- temperature = iwl_hw_get_temperature(priv);
+ temperature = iwl3945_hw_get_temperature(priv);
/* driver's okay range is -260 to +25.
* human readable okay range is 0 to +285 */
IWL_DEBUG_INFO("Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
/* handle insane temp reading */
- if (iwl_hw_reg_temp_out_of_range(temperature)) {
+ if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
IWL_ERROR("Error bad temperature value %d\n", temperature);
/* if really really hot(?),
@@ -1206,11 +1272,11 @@ static int iwl_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
* records new temperature in tx_mgr->temperature.
* replaces tx_mgr->last_temperature *only* if calib needed
* (assumes caller will actually do the calibration!). */
-static int is_temp_calib_needed(struct iwl_priv *priv)
+static int is_temp_calib_needed(struct iwl3945_priv *priv)
{
int temp_diff;
- priv->temperature = iwl_hw_reg_txpower_get_temperature(priv);
+ priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
temp_diff = priv->temperature - priv->last_temperature;
/* get absolute value */
@@ -1242,7 +1308,7 @@ static int is_temp_calib_needed(struct iwl_priv *priv)
/* radio and DSP power table, each step is 1/2 dB.
* 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
-static struct iwl_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
+static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
{
{251, 127}, /* 2.4 GHz, highest power */
{251, 127},
@@ -1403,7 +1469,7 @@ static struct iwl_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
{3, 120} } /* 5.x GHz, lowest power */
};
-static inline u8 iwl_hw_reg_fix_power_index(int index)
+static inline u8 iwl3945_hw_reg_fix_power_index(int index)
{
if (index < 0)
return 0;
@@ -1416,17 +1482,17 @@ static inline u8 iwl_hw_reg_fix_power_index(int index)
#define REG_RECALIB_PERIOD (60)
/**
- * iwl_hw_reg_set_scan_power - Set Tx power for scan probe requests
+ * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
*
* Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
* or 6 Mbit (OFDM) rates.
*/
-static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
+static void iwl3945_hw_reg_set_scan_power(struct iwl3945_priv *priv, u32 scan_tbl_index,
s32 rate_index, const s8 *clip_pwrs,
- struct iwl_channel_info *ch_info,
+ struct iwl3945_channel_info *ch_info,
int band_index)
{
- struct iwl_scan_power_info *scan_power_info;
+ struct iwl3945_scan_power_info *scan_power_info;
s8 power;
u8 power_index;
@@ -1462,7 +1528,7 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
* of the table. */
/* don't exceed table bounds for "real" setting */
- power_index = iwl_hw_reg_fix_power_index(power_index);
+ power_index = iwl3945_hw_reg_fix_power_index(power_index);
scan_power_info->power_table_index = power_index;
scan_power_info->tpc.tx_gain =
@@ -1472,21 +1538,21 @@ static void iwl_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
}
/**
- * iwl_hw_reg_send_txpower - fill in Tx Power command with gain settings
+ * iwl3945_hw_reg_send_txpower - fill in Tx Power command with gain settings
*
* Configures power settings for all rates for the current channel,
* using values from channel info struct, and send to NIC
*/
-int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv)
{
int rate_idx, i;
- const struct iwl_channel_info *ch_info = NULL;
- struct iwl_txpowertable_cmd txpower = {
+ const struct iwl3945_channel_info *ch_info = NULL;
+ struct iwl3945_txpowertable_cmd txpower = {
.channel = priv->active_rxon.channel,
};
txpower.band = (priv->phymode == MODE_IEEE80211A) ? 0 : 1;
- ch_info = iwl_get_channel_info(priv,
+ ch_info = iwl3945_get_channel_info(priv,
priv->phymode,
le16_to_cpu(priv->active_rxon.channel));
if (!ch_info) {
@@ -1508,7 +1574,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
rate_idx <= IWL_LAST_OFDM_RATE; rate_idx++, i++) {
txpower.power[i].tpc = ch_info->power_info[i].tpc;
- txpower.power[i].rate = iwl_rates[rate_idx].plcp;
+ txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
le16_to_cpu(txpower.channel),
@@ -1521,7 +1587,7 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
for (rate_idx = IWL_FIRST_CCK_RATE;
rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
txpower.power[i].tpc = ch_info->power_info[i].tpc;
- txpower.power[i].rate = iwl_rates[rate_idx].plcp;
+ txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
IWL_DEBUG_POWER("ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
le16_to_cpu(txpower.channel),
@@ -1531,13 +1597,13 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
txpower.power[i].rate);
}
- return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
- sizeof(struct iwl_txpowertable_cmd), &txpower);
+ return iwl3945_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
+ sizeof(struct iwl3945_txpowertable_cmd), &txpower);
}
/**
- * iwl_hw_reg_set_new_power - Configures power tables at new levels
+ * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
* @ch_info: Channel to update. Uses power_info.requested_power.
*
* Replace requested_power and base_power_index ch_info fields for
@@ -1552,10 +1618,10 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
* properly fill out the scan powers, and actual h/w gain settings,
* and send changes to NIC
*/
-static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
- struct iwl_channel_info *ch_info)
+static int iwl3945_hw_reg_set_new_power(struct iwl3945_priv *priv,
+ struct iwl3945_channel_info *ch_info)
{
- struct iwl_channel_power_info *power_info;
+ struct iwl3945_channel_power_info *power_info;
int power_changed = 0;
int i;
const s8 *clip_pwrs;
@@ -1595,7 +1661,7 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
- /* do all CCK rates' iwl_channel_power_info structures */
+ /* do all CCK rates' iwl3945_channel_power_info structures */
for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
power_info->requested_power = power;
power_info->base_power_index =
@@ -1609,13 +1675,13 @@ static int iwl_hw_reg_set_new_power(struct iwl_priv *priv,
}
/**
- * iwl_hw_reg_get_ch_txpower_limit - returns new power limit for channel
+ * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
*
* NOTE: Returned power limit may be less (but not more) than requested,
* based strictly on regulatory (eeprom and spectrum mgt) limitations
* (no consideration for h/w clipping limitations).
*/
-static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
+static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl3945_channel_info *ch_info)
{
s8 max_power;
@@ -1634,7 +1700,7 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
}
/**
- * iwl_hw_reg_comp_txpower_temp - Compensate for temperature
+ * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
*
* Compensate txpower settings of *all* channels for temperature.
* This only accounts for the difference between current temperature
@@ -1643,9 +1709,9 @@ static int iwl_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
*
* If RxOn is "associated", this sends the new Txpower to NIC!
*/
-static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
{
- struct iwl_channel_info *ch_info = NULL;
+ struct iwl3945_channel_info *ch_info = NULL;
int delta_index;
const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
u8 a_band;
@@ -1666,7 +1732,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
/* get power index adjustment based on curr and factory
* temps */
- delta_index = iwl_hw_reg_adjust_power_by_temp(temperature,
+ delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
ref_temp);
/* set tx power value for all rates, OFDM and CCK */
@@ -1679,7 +1745,7 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
power_idx += delta_index;
/* stay within table range */
- power_idx = iwl_hw_reg_fix_power_index(power_idx);
+ power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
ch_info->power_info[rate_index].
power_table_index = (u8) power_idx;
ch_info->power_info[rate_index].tpc =
@@ -1694,19 +1760,19 @@ static int iwl_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
- iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
+ iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs,
ch_info, a_band);
}
}
/* send Txpower command for current channel to ucode */
- return iwl_hw_reg_send_txpower(priv);
+ return iwl3945_hw_reg_send_txpower(priv);
}
-int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power)
{
- struct iwl_channel_info *ch_info;
+ struct iwl3945_channel_info *ch_info;
s8 max_power;
u8 a_band;
u8 i;
@@ -1728,26 +1794,26 @@ int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
/* find minimum power of all user and regulatory constraints
* (does not consider h/w clipping limitations) */
- max_power = iwl_hw_reg_get_ch_txpower_limit(ch_info);
+ max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
max_power = min(power, max_power);
if (max_power != ch_info->curr_txpow) {
ch_info->curr_txpow = max_power;
/* this considers the h/w clipping limitations */
- iwl_hw_reg_set_new_power(priv, ch_info);
+ iwl3945_hw_reg_set_new_power(priv, ch_info);
}
}
/* update txpower settings for all channels,
* send to NIC if associated. */
is_temp_calib_needed(priv);
- iwl_hw_reg_comp_txpower_temp(priv);
+ iwl3945_hw_reg_comp_txpower_temp(priv);
return 0;
}
/* will add 3945 channel switch cmd handling later */
-int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel)
{
return 0;
}
@@ -1762,26 +1828,26 @@ int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
* -- send new set of gain settings to NIC
* NOTE: This should continue working, even when we're not associated,
* so we can keep our internal table of scan powers current. */
-void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
+void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv)
{
/* This will kick in the "brute force"
- * iwl_hw_reg_comp_txpower_temp() below */
+ * iwl3945_hw_reg_comp_txpower_temp() below */
if (!is_temp_calib_needed(priv))
goto reschedule;
/* Set up a new set of temp-adjusted TxPowers, send to NIC.
* This is based *only* on current temperature,
* ignoring any previous power measurements */
- iwl_hw_reg_comp_txpower_temp(priv);
+ iwl3945_hw_reg_comp_txpower_temp(priv);
reschedule:
queue_delayed_work(priv->workqueue,
&priv->thermal_periodic, REG_RECALIB_PERIOD * HZ);
}
-void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
+static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv,
thermal_periodic.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -1793,7 +1859,7 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
}
/**
- * iwl_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
+ * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
* for the channel.
*
* This function is used when initializing channel-info structs.
@@ -1803,10 +1869,10 @@ void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
* on A-band, EEPROM's "group frequency" entries represent the top
* channel in each group 1-4. Group 5 All B/G channels are in group 0.
*/
-static u16 iwl_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
- const struct iwl_channel_info *ch_info)
+static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl3945_priv *priv,
+ const struct iwl3945_channel_info *ch_info)
{
- struct iwl_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0];
+ struct iwl3945_eeprom_txpower_group *ch_grp = &priv->eeprom.groups[0];
u8 group;
u16 group_index = 0; /* based on factory calib frequencies */
u8 grp_channel;
@@ -1832,20 +1898,20 @@ static u16 iwl_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
}
/**
- * iwl_hw_reg_get_matched_power_index - Interpolate to get nominal index
+ * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
*
* Interpolate to get nominal (i.e. at factory calibration temperature) index
* into radio/DSP gain settings table for requested power.
*/
-static int iwl_hw_reg_get_matched_power_index(struct iwl_priv *priv,
+static int iwl3945_hw_reg_get_matched_power_index(struct iwl3945_priv *priv,
s8 requested_power,
s32 setting_index, s32 *new_index)
{
- const struct iwl_eeprom_txpower_group *chnl_grp = NULL;
+ const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
s32 index0, index1;
s32 power = 2 * requested_power;
s32 i;
- const struct iwl_eeprom_txpower_sample *samples;
+ const struct iwl3945_eeprom_txpower_sample *samples;
s32 gains0, gains1;
s32 res;
s32 denominator;
@@ -1885,11 +1951,11 @@ static int iwl_hw_reg_get_matched_power_index(struct iwl_priv *priv,
return 0;
}
-static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
+static void iwl3945_hw_reg_init_channel_groups(struct iwl3945_priv *priv)
{
u32 i;
s32 rate_index;
- const struct iwl_eeprom_txpower_group *group;
+ const struct iwl3945_eeprom_txpower_group *group;
IWL_DEBUG_POWER("Initializing factory calib info from EEPROM\n");
@@ -1965,10 +2031,10 @@ static void iwl_hw_reg_init_channel_groups(struct iwl_priv *priv)
*
* This does *not* write values to NIC, just sets up our internal table.
*/
-int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv)
{
- struct iwl_channel_info *ch_info = NULL;
- struct iwl_channel_power_info *pwr_info;
+ struct iwl3945_channel_info *ch_info = NULL;
+ struct iwl3945_channel_power_info *pwr_info;
int delta_index;
u8 rate_index;
u8 scan_tbl_index;
@@ -1981,10 +2047,10 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
/* save temperature reference,
* so we can determine next time to calibrate */
- temperature = iwl_hw_reg_txpower_get_temperature(priv);
+ temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
priv->last_temperature = temperature;
- iwl_hw_reg_init_channel_groups(priv);
+ iwl3945_hw_reg_init_channel_groups(priv);
/* initialize Tx power info for each and every channel, 2.4 and 5.x */
for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
@@ -1995,14 +2061,14 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
/* find this channel's channel group (*not* "band") index */
ch_info->group_index =
- iwl_hw_reg_get_ch_grp_index(priv, ch_info);
+ iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
/* Get this chnlgrp's rate->max/clip-powers table */
clip_pwrs = priv->clip_groups[ch_info->group_index].clip_powers;
/* calculate power index *adjustment* value according to
* diff between current temperature and factory temperature */
- delta_index = iwl_hw_reg_adjust_power_by_temp(temperature,
+ delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
priv->eeprom.groups[ch_info->group_index].
temperature);
@@ -2025,7 +2091,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
/* get base (i.e. at factory-measured temperature)
* power table index for this rate's power */
- rc = iwl_hw_reg_get_matched_power_index(priv, pwr,
+ rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
ch_info->group_index,
&power_idx);
if (rc) {
@@ -2038,9 +2104,9 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
power_idx += delta_index;
/* stay within range of gain table */
- power_idx = iwl_hw_reg_fix_power_index(power_idx);
+ power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
- /* fill 1 OFDM rate's iwl_channel_power_info struct */
+ /* fill 1 OFDM rate's iwl3945_channel_power_info struct */
pwr_info->requested_power = pwr;
pwr_info->power_table_index = (u8) power_idx;
pwr_info->tpc.tx_gain =
@@ -2059,11 +2125,11 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
IWL_CCK_FROM_OFDM_INDEX_DIFF;
/* stay within table range */
- pwr_index = iwl_hw_reg_fix_power_index(pwr_index);
+ pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
gain = power_gain_table[a_band][pwr_index].tx_gain;
dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
- /* fill each CCK rate's iwl_channel_power_info structure
+ /* fill each CCK rate's iwl3945_channel_power_info structure
* NOTE: All CCK-rate Txpwrs are the same for a given chnl!
* NOTE: CCK rates start at end of OFDM rates! */
for (rate_index = 0;
@@ -2081,7 +2147,7 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
s32 actual_index = (scan_tbl_index == 0) ?
IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
- iwl_hw_reg_set_scan_power(priv, scan_tbl_index,
+ iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
actual_index, clip_pwrs, ch_info, a_band);
}
}
@@ -2089,66 +2155,66 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
return 0;
}
-int iwl_hw_rxq_stop(struct iwl_priv *priv)
+int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv)
{
int rc;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted(priv, FH_RCSR_CONFIG(0), 0);
- rc = iwl_poll_restricted_bit(priv, FH_RSSR_STATUS, (1 << 24), 1000);
+ iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), 0);
+ rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS, (1 << 24), 1000);
if (rc < 0)
IWL_ERROR("Can't stop Rx DMA.\n");
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
{
int rc;
unsigned long flags;
int txq_id = txq->q.id;
- struct iwl_shared *shared_data = priv->hw_setting.shared_virt;
+ struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt;
shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted(priv, FH_CBCC_CTRL(txq_id), 0);
- iwl_write_restricted(priv, FH_CBCC_BASE(txq_id), 0);
+ iwl3945_write_direct32(priv, FH_CBCC_CTRL(txq_id), 0);
+ iwl3945_write_direct32(priv, FH_CBCC_BASE(txq_id), 0);
- iwl_write_restricted(priv, FH_TCSR_CONFIG(txq_id),
+ iwl3945_write_direct32(priv, FH_TCSR_CONFIG(txq_id),
ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
/* fake read to flush all prev. writes */
- iwl_read32(priv, FH_TSSR_CBB_BASE);
+ iwl3945_read32(priv, FH_TSSR_CBB_BASE);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-int iwl_hw_get_rx_read(struct iwl_priv *priv)
+int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv)
{
- struct iwl_shared *shared_data = priv->hw_setting.shared_virt;
+ struct iwl3945_shared *shared_data = priv->hw_setting.shared_virt;
return le32_to_cpu(shared_data->rx_read_ptr[0]);
}
@@ -2156,22 +2222,22 @@ int iwl_hw_get_rx_read(struct iwl_priv *priv)
/**
* iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
*/
-int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
{
int rc, i, index, prev_index;
- struct iwl_rate_scaling_cmd rate_cmd = {
+ struct iwl3945_rate_scaling_cmd rate_cmd = {
.reserved = {0, 0, 0},
};
- struct iwl_rate_scaling_info *table = rate_cmd.table;
+ struct iwl3945_rate_scaling_info *table = rate_cmd.table;
- for (i = 0; i < ARRAY_SIZE(iwl_rates); i++) {
- index = iwl_rates[i].table_rs_index;
+ for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
+ index = iwl3945_rates[i].table_rs_index;
table[index].rate_n_flags =
- iwl_hw_set_rate_n_flags(iwl_rates[i].plcp, 0);
+ iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
table[index].try_cnt = priv->retry_rate;
- prev_index = iwl_get_prev_ieee_rate(i);
- table[index].next_rate_index = iwl_rates[prev_index].table_rs_index;
+ prev_index = iwl3945_get_prev_ieee_rate(i);
+ table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
}
switch (priv->phymode) {
@@ -2180,14 +2246,14 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
- table[i].next_rate_index = iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+ table[i].next_rate_index = iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
/* Don't fall back to CCK rates */
table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;
/* Don't drop out of OFDM rates */
table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
- iwl_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+ iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
break;
case MODE_IEEE80211B:
@@ -2195,7 +2261,7 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
- table[i].next_rate_index = iwl_rates[IWL_FIRST_CCK_RATE].table_rs_index;
+ table[i].next_rate_index = iwl3945_rates[IWL_FIRST_CCK_RATE].table_rs_index;
/* CCK shouldn't fall back to OFDM... */
table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
@@ -2208,25 +2274,26 @@ int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
/* Update the rate scaling for control frame Tx */
rate_cmd.table_id = 0;
- rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
&rate_cmd);
if (rc)
return rc;
/* Update the rate scaling for data frame Tx */
rate_cmd.table_id = 1;
- return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+ return iwl3945_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
&rate_cmd);
}
-int iwl_hw_set_hw_setting(struct iwl_priv *priv)
+/* Called when initializing driver */
+int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv)
{
memset((void *)&priv->hw_setting, 0,
- sizeof(struct iwl_driver_hw_info));
+ sizeof(struct iwl3945_driver_hw_info));
priv->hw_setting.shared_virt =
pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl_shared),
+ sizeof(struct iwl3945_shared),
&priv->hw_setting.shared_phys);
if (!priv->hw_setting.shared_virt) {
@@ -2236,31 +2303,31 @@ int iwl_hw_set_hw_setting(struct iwl_priv *priv)
}
priv->hw_setting.ac_queue_count = AC_NUM;
- priv->hw_setting.rx_buffer_size = IWL_RX_BUF_SIZE;
- priv->hw_setting.tx_cmd_len = sizeof(struct iwl_tx_cmd);
+ priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE;
+ priv->hw_setting.max_pkt_size = 2342;
+ priv->hw_setting.tx_cmd_len = sizeof(struct iwl3945_tx_cmd);
priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
- priv->hw_setting.cck_flag = 0;
priv->hw_setting.max_stations = IWL3945_STATION_COUNT;
priv->hw_setting.bcast_sta_id = IWL3945_BROADCAST_ID;
return 0;
}
-unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl_frame *frame, u8 rate)
+unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+ struct iwl3945_frame *frame, u8 rate)
{
- struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+ struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
unsigned int frame_size;
- tx_beacon_cmd = (struct iwl_tx_beacon_cmd *)&frame->u;
+ tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
tx_beacon_cmd->tx.sta_id = IWL3945_BROADCAST_ID;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
- frame_size = iwl_fill_beacon_frame(priv,
+ frame_size = iwl3945_fill_beacon_frame(priv,
tx_beacon_cmd->frame,
- BROADCAST_ADDR,
+ iwl3945_broadcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
BUG_ON(frame_size > MAX_MPDU_SIZE);
@@ -2277,35 +2344,43 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd->tx.supp_rates[1] =
(IWL_CCK_BASIC_RATES_MASK & 0xF);
- return (sizeof(struct iwl_tx_beacon_cmd) + frame_size);
+ return (sizeof(struct iwl3945_tx_beacon_cmd) + frame_size);
}
-void iwl_hw_rx_handler_setup(struct iwl_priv *priv)
+void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv)
{
priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
}
-void iwl_hw_setup_deferred_work(struct iwl_priv *priv)
+void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv)
{
INIT_DELAYED_WORK(&priv->thermal_periodic,
iwl3945_bg_reg_txpower_periodic);
}
-void iwl_hw_cancel_deferred_work(struct iwl_priv *priv)
+void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
{
cancel_delayed_work(&priv->thermal_periodic);
}
-struct pci_device_id iwl_hw_card_ids[] = {
- {0x8086, 0x4222, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x8086, 0x4227, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+struct pci_device_id iwl3945_hw_card_ids[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4222)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4227)},
{0}
};
-inline int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv)
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism. Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+inline int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv)
{
- _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+ _iwl3945_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
return 0;
}
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 813902e9f8c2..20b925f57e35 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -23,19 +23,955 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
+/*
+ * Please use this file (iwl-3945.h) for driver implementation definitions.
+ * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-3945-hw.h for hardware-related definitions.
+ */
#ifndef __iwl_3945_h__
#define __iwl_3945_h__
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <net/ieee80211_radiotap.h>
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+extern struct pci_device_id iwl3945_hw_card_ids[];
+
+#define DRV_NAME "iwl3945"
+#include "iwl-3945-hw.h"
+#include "iwl-prph.h"
+#include "iwl-3945-debug.h"
+
+/* Default noise level to report when noise measurement is not available.
+ * This may be because we're:
+ * 1) Not associated (4965, no beacon statistics being sent to driver)
+ * 2) Scanning (noise measurement does not apply to associated channel)
+ * 3) Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ * Also, -127 works better than 0 when averaging frames with/without
+ * noise info (e.g. averaging might be done in app); measured dBm values are
+ * always negative ... using a negative value as the default keeps all
+ * averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/* Module parameters accessible from iwl-*.c */
+extern int iwl3945_param_hwcrypto;
+extern int iwl3945_param_queues_num;
+
+enum iwl3945_antenna {
+ IWL_ANTENNA_DIVERSITY,
+ IWL_ANTENNA_MAIN,
+ IWL_ANTENNA_AUX
+};
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ * a value of 0 means RTS on all data/management packets
+ * a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ * than RTS value.
+ */
+#define IWL_RX_BUF_SIZE 3000U
+#define DEFAULT_RTS_THRESHOLD 2347U
+#define MIN_RTS_THRESHOLD 0U
+#define MAX_RTS_THRESHOLD 2347U
+#define MAX_MSDU_SIZE 2304U
+#define MAX_MPDU_SIZE 2346U
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+struct iwl3945_rx_mem_buffer {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb;
+ struct list_head list;
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct iwl3945_queue {
+ int n_bd; /* number of BDs in this queue */
+ int write_ptr; /* 1-st empty entry (index) host_w*/
+ int read_ptr; /* last used entry (index) host_r*/
+ dma_addr_t dma_addr; /* physical addr for BD's */
+ int n_window; /* safe queue window */
+ u32 id;
+ int low_mark; /* low watermark, resume queue if free
+ * space more than this */
+ int high_mark; /* high watermark, stop queue if free
+ * space less than this */
+} __attribute__ ((packed));
+
+#define MAX_NUM_OF_TBS (20)
+
+/* One for each TFD */
+struct iwl3945_tx_info {
+ struct ieee80211_tx_status status;
+ struct sk_buff *skb[MAX_NUM_OF_TBS];
+};
+
+/**
+ * struct iwl3945_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/Tx buffers
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @need_update: indicates need to update read/write index
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+struct iwl3945_tx_queue {
+ struct iwl3945_queue q;
+ struct iwl3945_tfd_frame *bd;
+ struct iwl3945_cmd *cmd;
+ dma_addr_t dma_addr_cmd;
+ struct iwl3945_tx_info *txb;
+ int need_update;
+ int active;
+};
+
+#define IWL_NUM_SCAN_RATES (2)
+
+struct iwl3945_channel_tgd_info {
+ u8 type;
+ s8 max_power;
+};
+
+struct iwl3945_channel_tgh_info {
+ s64 last_radar_time;
+};
+
+/* current Tx power values to use, one for each rate for each channel.
+ * requested power is limited by:
+ * -- regulatory EEPROM limits for this channel
+ * -- hardware capabilities (clip-powers)
+ * -- spectrum management
+ * -- user preference (e.g. iwconfig)
+ * when requested power is set, base power index must also be set. */
+struct iwl3945_channel_power_info {
+ struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */
+ s8 power_table_index; /* actual (compenst'd) index into gain table */
+ s8 base_power_index; /* gain index for power at factory temp. */
+ s8 requested_power; /* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct iwl3945_scan_power_info {
+ struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */
+ s8 power_table_index; /* actual (compenst'd) index into gain table */
+ s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */
+};
+
+/*
+ * One for each channel, holds all channel setup data
+ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
+ * with one another!
+ */
+#define IWL4965_MAX_RATE (33)
+
+struct iwl3945_channel_info {
+ struct iwl3945_channel_tgd_info tgd;
+ struct iwl3945_channel_tgh_info tgh;
+ struct iwl3945_eeprom_channel eeprom; /* EEPROM regulatory limit */
+ struct iwl3945_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for
+ * FAT channel */
+
+ u8 channel; /* channel number */
+ u8 flags; /* flags copied from EEPROM */
+ s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+ s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
+ s8 min_power; /* always 0 */
+ s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */
+
+ u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
+ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
+ u8 phymode; /* MODE_IEEE80211{A,B,G} */
+
+ /* Radio/DSP gain settings for each "normal" data Tx rate.
+ * These include, in addition to RF and DSP gain, a few fields for
+ * remembering/modifying gain settings (indexes). */
+ struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
+
+ /* Radio/DSP gain settings for each scan rate, for directed scans. */
+ struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
+};
+
+struct iwl3945_clip_group {
+ /* maximum power level to prevent clipping for each rate, derived by
+ * us from this band's saturation power in EEPROM */
+ const s8 clip_powers[IWL_MAX_RATES];
+};
+
+#include "iwl-3945-rs.h"
+
+#define IWL_TX_FIFO_AC0 0
+#define IWL_TX_FIFO_AC1 1
+#define IWL_TX_FIFO_AC2 2
+#define IWL_TX_FIFO_AC3 3
+#define IWL_TX_FIFO_HCCA_1 5
+#define IWL_TX_FIFO_HCCA_2 6
+#define IWL_TX_FIFO_NONE 7
+
+/* Minimum number of queues. MAX_NUM is defined in hw specific files */
+#define IWL_MIN_NUM_QUEUES 4
+
+/* Power management (not Tx power) structures */
+
+struct iwl3945_power_vec_entry {
+ struct iwl3945_powertable_cmd cmd;
+ u8 no_dtim;
+};
+#define IWL_POWER_RANGE_0 (0)
+#define IWL_POWER_RANGE_1 (1)
+
+#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */
+#define IWL_POWER_INDEX_3 0x03
+#define IWL_POWER_INDEX_5 0x05
+#define IWL_POWER_AC 0x06
+#define IWL_POWER_BATTERY 0x07
+#define IWL_POWER_LIMIT 0x07
+#define IWL_POWER_MASK 0x0F
+#define IWL_POWER_ENABLED 0x10
+#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK)
+
+struct iwl3945_power_mgr {
+ spinlock_t lock;
+ struct iwl3945_power_vec_entry pwr_range_0[IWL_POWER_AC];
+ struct iwl3945_power_vec_entry pwr_range_1[IWL_POWER_AC];
+ u8 active_index;
+ u32 dtim_val;
+};
+
+#define IEEE80211_DATA_LEN 2304
+#define IEEE80211_4ADDR_LEN 30
+#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl3945_frame {
+ union {
+ struct ieee80211_hdr frame;
+ struct iwl3945_tx_beacon_cmd beacon;
+ u8 raw[IEEE80211_FRAME_LEN];
+ u8 cmd[360];
+ } u;
+ struct list_head list;
+};
+
+#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
+#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
+#define SEQ_TO_INDEX(x) (x & 0xff)
+#define INDEX_TO_SEQ(x) (x & 0xff)
+#define SEQ_HUGE_FRAME (0x4000)
+#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+ /* CMD_SIZE_NORMAL = 0, */
+ CMD_SIZE_HUGE = (1 << 0),
+ /* CMD_SYNC = 0, */
+ CMD_ASYNC = (1 << 1),
+ /* CMD_NO_SKB = 0, */
+ CMD_WANT_SKB = (1 << 2),
+};
+
+struct iwl3945_cmd;
+struct iwl3945_priv;
+
+struct iwl3945_cmd_meta {
+ struct iwl3945_cmd_meta *source;
+ union {
+ struct sk_buff *skb;
+ int (*callback)(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd, struct sk_buff *skb);
+ } __attribute__ ((packed)) u;
+
+ /* The CMD_SIZE_HUGE flag bit indicates that the command
+ * structure is stored at the end of the shared queue memory. */
+ u32 flags;
+
+} __attribute__ ((packed));
+
+/**
+ * struct iwl3945_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+struct iwl3945_cmd {
+ struct iwl3945_cmd_meta meta;
+ struct iwl3945_cmd_header hdr;
+ union {
+ struct iwl3945_addsta_cmd addsta;
+ struct iwl3945_led_cmd led;
+ u32 flags;
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ struct iwl3945_bt_cmd bt;
+ struct iwl3945_rxon_time_cmd rxon_time;
+ struct iwl3945_powertable_cmd powertable;
+ struct iwl3945_qosparam_cmd qosparam;
+ struct iwl3945_tx_cmd tx;
+ struct iwl3945_tx_beacon_cmd tx_beacon;
+ struct iwl3945_rxon_assoc_cmd rxon_assoc;
+ u8 *indirect;
+ u8 payload[360];
+ } __attribute__ ((packed)) cmd;
+} __attribute__ ((packed));
+
+struct iwl3945_host_cmd {
+ u8 id;
+ u16 len;
+ struct iwl3945_cmd_meta meta;
+ const void *data;
+};
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl3945_cmd) - \
+ sizeof(struct iwl3945_cmd_meta))
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
+
+/**
+ * struct iwl3945_rx_queue - Rx queue
+ * @processed: Internal index to last handled Rx packet
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ *
+ * NOTE: rx_free and rx_used are used as a FIFO for iwl3945_rx_mem_buffers
+ */
+struct iwl3945_rx_queue {
+ __le32 *bd;
+ dma_addr_t dma_addr;
+ struct iwl3945_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct iwl3945_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ u32 processed;
+ u32 read;
+ u32 write;
+ u32 free_count;
+ struct list_head rx_free;
+ struct list_head rx_used;
+ int need_update;
+ spinlock_t lock;
+};
+
+#define IWL_SUPPORTED_RATES_IE_LEN 8
+
+#define SCAN_INTERVAL 100
+
+#define MAX_A_CHANNELS 252
+#define MIN_A_CHANNELS 7
+
+#define MAX_B_CHANNELS 14
+#define MIN_B_CHANNELS 1
+
+#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+#define STATUS_INT_ENABLED 1
+#define STATUS_RF_KILL_HW 2
+#define STATUS_RF_KILL_SW 3
+#define STATUS_INIT 4
+#define STATUS_ALIVE 5
+#define STATUS_READY 6
+#define STATUS_TEMPERATURE 7
+#define STATUS_GEO_CONFIGURED 8
+#define STATUS_EXIT_PENDING 9
+#define STATUS_IN_SUSPEND 10
+#define STATUS_STATISTICS 11
+#define STATUS_SCANNING 12
+#define STATUS_SCAN_ABORTING 13
+#define STATUS_SCAN_HW 14
+#define STATUS_POWER_PMI 15
+#define STATUS_FW_ERROR 16
+#define STATUS_CONF_PENDING 17
+
+#define MAX_TID_COUNT 9
+
+#define IWL_INVALID_RATE 0xFF
+#define IWL_INVALID_VALUE -1
+
+struct iwl3945_tid_data {
+ u16 seq_number;
+};
+
+struct iwl3945_hw_key {
+ enum ieee80211_key_alg alg;
+ int keylen;
+ u8 key[32];
+};
+
+union iwl3945_ht_rate_supp {
+ u16 rates;
+ struct {
+ u8 siso_rate;
+ u8 mimo_rate;
+ };
+};
+
+#ifdef CONFIG_IWL3945_QOS
+
+union iwl3945_qos_capabity {
+ struct {
+ u8 edca_count:4; /* bit 0-3 */
+ u8 q_ack:1; /* bit 4 */
+ u8 queue_request:1; /* bit 5 */
+ u8 txop_request:1; /* bit 6 */
+ u8 reserved:1; /* bit 7 */
+ } q_AP;
+ struct {
+ u8 acvo_APSD:1; /* bit 0 */
+ u8 acvi_APSD:1; /* bit 1 */
+ u8 ac_bk_APSD:1; /* bit 2 */
+ u8 ac_be_APSD:1; /* bit 3 */
+ u8 q_ack:1; /* bit 4 */
+ u8 max_len:2; /* bit 5-6 */
+ u8 more_data_ack:1; /* bit 7 */
+ } q_STA;
+ u8 val;
+};
+
+/* QoS structures */
+struct iwl3945_qos_info {
+ int qos_enable;
+ int qos_active;
+ union iwl3945_qos_capabity qos_cap;
+ struct iwl3945_qosparam_cmd def_qos_parm;
+};
+#endif /*CONFIG_IWL3945_QOS */
+
+#define STA_PS_STATUS_WAKE 0
+#define STA_PS_STATUS_SLEEP 1
+
+struct iwl3945_station_entry {
+ struct iwl3945_addsta_cmd sta;
+ struct iwl3945_tid_data tid[MAX_TID_COUNT];
+ union {
+ struct {
+ u8 rate;
+ u8 flags;
+ } s;
+ u16 rate_n_flags;
+ } current_rate;
+ u8 used;
+ u8 ps_status;
+ struct iwl3945_hw_key keyinfo;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+ void *v_addr; /* access by driver */
+ dma_addr_t p_addr; /* access by card's busmaster DMA */
+ u32 len; /* bytes */
+};
+
+/* uCode file layout */
+struct iwl3945_ucode {
+ __le32 ver; /* major/minor/subminor */
+ __le32 inst_size; /* bytes of runtime instructions */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of initialization instructions */
+ __le32 init_data_size; /* bytes of initialization data */
+ __le32 boot_size; /* bytes of bootstrap instructions */
+ u8 data[0]; /* data in same order as "size" elements */
+};
+
+#define IWL_IBSS_MAC_HASH_SIZE 32
+
+struct iwl3945_ibss_seq {
+ u8 mac[ETH_ALEN];
+ u16 seq_num;
+ u16 frag_num;
+ unsigned long packet_time;
+ struct list_head list;
+};
+
+/**
+ * struct iwl3945_driver_hw_info
+ * @max_txq_num: Max # Tx queues supported
+ * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+ * @tx_cmd_len: Size of Tx command (but not including frame itself)
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @rx_buf_size:
+ * @max_pkt_size:
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @max_stations:
+ * @bcast_sta_id:
+ * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
+ * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
+ */
+struct iwl3945_driver_hw_info {
+ u16 max_txq_num;
+ u16 ac_queue_count;
+ u16 tx_cmd_len;
+ u16 max_rxq_size;
+ u32 rx_buf_size;
+ u32 max_pkt_size;
+ u16 max_rxq_log;
+ u8 max_stations;
+ u8 bcast_sta_id;
+ void *shared_virt;
+ dma_addr_t shared_phys;
+};
+
+#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
+ x->u.rx_frame.stats.payload + \
+ x->u.rx_frame.stats.phy_count))
+#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
+ IWL_RX_HDR(x)->payload + \
+ le16_to_cpu(IWL_RX_HDR(x)->len)))
+#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
+#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
+
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-base.c which are forward declared here
+ * for use by iwl-*.c
+ *
+ *****************************************************************************/
+struct iwl3945_addsta_cmd;
+extern int iwl3945_send_add_station(struct iwl3945_priv *priv,
+ struct iwl3945_addsta_cmd *sta, u8 flags);
+extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid,
+ int is_ap, u8 flags);
+extern int iwl3945_is_network_packet(struct iwl3945_priv *priv,
+ struct ieee80211_hdr *header);
+extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
+extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
+#ifdef CONFIG_IWL3945_DEBUG
+extern void iwl3945_report_frame(struct iwl3945_priv *priv,
+ struct iwl3945_rx_packet *pkt,
+ struct ieee80211_hdr *header, int group100);
+#else
+static inline void iwl3945_report_frame(struct iwl3945_priv *priv,
+ struct iwl3945_rx_packet *pkt,
+ struct ieee80211_hdr *header,
+ int group100) {}
+#endif
+extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb,
+ void *data, short len,
+ struct ieee80211_rx_status *stats,
+ u16 phy_flags);
+extern int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv,
+ struct ieee80211_hdr *header);
+extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv);
+extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv,
+ struct iwl3945_rx_queue *rxq);
+extern int iwl3945_calc_db_from_ratio(int sig_ratio);
+extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm);
+extern int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq, int count, u32 id);
+extern void iwl3945_rx_replenish(void *data);
+extern void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq);
+extern int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len,
+ const void *data);
+extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv,
+ struct iwl3945_host_cmd *cmd);
+extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
+ struct ieee80211_hdr *hdr,
+ const u8 *dest, int left);
+extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv,
+ struct iwl3945_rx_queue *q);
+extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv);
+extern void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
+ u32 decrypt_res,
+ struct ieee80211_rx_status *stats);
+extern const u8 iwl3945_broadcast_addr[ETH_ALEN];
+
+/*
+ * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
+ * call this... todo... fix that.
+*/
+extern u8 iwl3945_sync_station(struct iwl3945_priv *priv, int sta_id,
+ u16 tx_rate, u8 flags);
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-[34]*.c which are forward declared here
+ * for use by iwl-base.c
+ *
+ * NOTE: The implementation of these functions are hardware specific
+ * which is why they are in the hardware specific files (vs. iwl-base.c)
+ *
+ * Naming convention --
+ * iwl3945_ <-- Its part of iwlwifi (should be changed to iwl3945_)
+ * iwl3945_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl3945_bg_ <-- Called from work queue context
+ * iwl3945_mac_ <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl3945_hw_rx_handler_setup(struct iwl3945_priv *priv);
+extern void iwl3945_hw_setup_deferred_work(struct iwl3945_priv *priv);
+extern void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv);
+extern int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv);
+extern int iwl3945_hw_set_hw_setting(struct iwl3945_priv *priv);
+extern int iwl3945_hw_nic_init(struct iwl3945_priv *priv);
+extern int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv);
+extern void iwl3945_hw_txq_ctx_free(struct iwl3945_priv *priv);
+extern void iwl3945_hw_txq_ctx_stop(struct iwl3945_priv *priv);
+extern int iwl3945_hw_nic_reset(struct iwl3945_priv *priv);
+extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *tfd,
+ dma_addr_t addr, u16 len);
+extern int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq);
+extern int iwl3945_hw_get_temperature(struct iwl3945_priv *priv);
+extern int iwl3945_hw_tx_queue_init(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq);
+extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
+ struct iwl3945_frame *frame, u8 rate);
+extern int iwl3945_hw_get_rx_read(struct iwl3945_priv *priv);
+extern void iwl3945_hw_build_tx_cmd_rate(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id);
+extern int iwl3945_hw_reg_send_txpower(struct iwl3945_priv *priv);
+extern int iwl3945_hw_reg_set_txpower(struct iwl3945_priv *priv, s8 power);
+extern void iwl3945_hw_rx_statistics(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb);
+extern void iwl3945_disable_events(struct iwl3945_priv *priv);
+extern int iwl4965_get_temperature(const struct iwl3945_priv *priv);
+
+/**
+ * iwl3945_hw_find_station - Find station id for a given BSSID
+ * @bssid: MAC address of station ID to find
+ *
+ * NOTE: This should not be hardware specific but the code has
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+extern u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *bssid);
+
+extern int iwl3945_hw_channel_switch(struct iwl3945_priv *priv, u16 channel);
+
/*
* Forward declare iwl-3945.c functions for iwl-base.c
*/
-extern int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv);
-extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
-extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
-extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
-extern void iwl3945_bg_reg_txpower_periodic(struct work_struct *work);
-extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
-extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id,
+extern int iwl3945_eeprom_acquire_semaphore(struct iwl3945_priv *priv);
+extern __le32 iwl3945_get_antenna_flags(const struct iwl3945_priv *priv);
+extern int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv);
+extern void iwl3945_reg_txpower_periodic(struct iwl3945_priv *priv);
+extern int iwl3945_txpower_set_from_eeprom(struct iwl3945_priv *priv);
+extern u8 iwl3945_sync_sta(struct iwl3945_priv *priv, int sta_id,
u16 tx_rate, u8 flags);
+
+
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+
+enum {
+ MEASUREMENT_READY = (1 << 0),
+ MEASUREMENT_ACTIVE = (1 << 1),
+};
+
+#endif
+
+struct iwl3945_priv {
+
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_hw *hw;
+ struct ieee80211_channel *ieee_channels;
+ struct ieee80211_rate *ieee_rates;
+
+ /* temporary frame storage list */
+ struct list_head free_frames;
+ int frames_count;
+
+ u8 phymode;
+ int alloc_rxb_skb;
+ bool add_radiotap;
+
+ void (*rx_handlers[REPLY_MAX])(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb);
+
+ const struct ieee80211_hw_mode *modes;
+
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+ /* spectrum measurement report caching */
+ struct iwl3945_spectrum_notification measure_report;
+ u8 measurement_status;
+#endif
+ /* ucode beacon time */
+ u32 ucode_beacon_time;
+
+ /* we allocate array of iwl3945_channel_info for NIC's valid channels.
+ * Access via channel # using indirect index array */
+ struct iwl3945_channel_info *channel_info; /* channel info array */
+ u8 channel_count; /* # of channels */
+
+ /* each calibration channel group in the EEPROM has a derived
+ * clip setting for each rate. */
+ const struct iwl3945_clip_group clip_groups[5];
+
+ /* thermal calibration */
+ s32 temperature; /* degrees Kelvin */
+ s32 last_temperature;
+
+ /* Scan related variables */
+ unsigned long last_scan_jiffies;
+ unsigned long next_scan_jiffies;
+ unsigned long scan_start;
+ unsigned long scan_pass_start;
+ unsigned long scan_start_tsf;
+ int scan_bands;
+ int one_direct_scan;
+ u8 direct_ssid_len;
+ u8 direct_ssid[IW_ESSID_MAX_SIZE];
+ struct iwl3945_scan_cmd *scan;
+ u8 only_active_channel;
+
+ /* spinlock */
+ spinlock_t lock; /* protect general shared data */
+ spinlock_t hcmd_lock; /* protect hcmd */
+ struct mutex mutex;
+
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+
+ /* uCode images, save to reload in case of failure */
+ struct fw_desc ucode_code; /* runtime inst */
+ struct fw_desc ucode_data; /* runtime data original */
+ struct fw_desc ucode_data_backup; /* runtime data save/restore */
+ struct fw_desc ucode_init; /* initialization inst */
+ struct fw_desc ucode_init_data; /* initialization data */
+ struct fw_desc ucode_boot; /* bootstrap inst */
+
+
+ struct iwl3945_rxon_time_cmd rxon_timing;
+
+ /* We declare this const so it can only be
+ * changed via explicit cast within the
+ * routines that actually update the physical
+ * hardware */
+ const struct iwl3945_rxon_cmd active_rxon;
+ struct iwl3945_rxon_cmd staging_rxon;
+
+ int error_recovering;
+ struct iwl3945_rxon_cmd recovery_rxon;
+
+ /* 1st responses from initialize and runtime uCode images.
+ * 4965's initialize alive response contains some calibration data. */
+ struct iwl3945_init_alive_resp card_alive_init;
+ struct iwl3945_alive_resp card_alive;
+
+#ifdef LED
+ /* LED related variables */
+ struct iwl3945_activity_blink activity;
+ unsigned long led_packets;
+ int led_state;
+#endif
+
+ u16 active_rate;
+ u16 active_rate_basic;
+
+ u8 call_post_assoc_from_beacon;
+ u8 assoc_station_added;
+ /* Rate scaling data */
+ s8 data_retry_limit;
+ u8 retry_rate;
+
+ wait_queue_head_t wait_command_queue;
+
+ int activity_timer_active;
+
+ /* Rx and Tx DMA processing queues */
+ struct iwl3945_rx_queue rxq;
+ struct iwl3945_tx_queue txq[IWL_MAX_NUM_QUEUES];
+
+ unsigned long status;
+ u32 config;
+
+ int last_rx_rssi; /* From Rx packet statisitics */
+ int last_rx_noise; /* From beacon statistics */
+
+ struct iwl3945_power_mgr power_data;
+
+ struct iwl3945_notif_statistics statistics;
+ unsigned long last_statistics_time;
+
+ /* context information */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u16 rates_mask;
+
+ u32 power_mode;
+ u32 antenna;
+ u8 bssid[ETH_ALEN];
+ u16 rts_threshold;
+ u8 mac_addr[ETH_ALEN];
+
+ /*station table variables */
+ spinlock_t sta_lock;
+ int num_stations;
+ struct iwl3945_station_entry stations[IWL_STATION_COUNT];
+
+ /* Indication if ieee80211_ops->open has been called */
+ int is_open;
+
+ u8 mac80211_registered;
+ int is_abg;
+
+ u32 notif_missed_beacons;
+
+ /* Rx'd packet timing information */
+ u32 last_beacon_time;
+ u64 last_tsf;
+
+ /* Duplicate packet detection */
+ u16 last_seq_num;
+ u16 last_frag_num;
+ unsigned long last_packet_time;
+
+ /* Hash table for finding stations in IBSS network */
+ struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
+
+ /* eeprom */
+ struct iwl3945_eeprom eeprom;
+
+ int iw_mode;
+
+ struct sk_buff *ibss_beacon;
+
+ /* Last Rx'd beacon timestamp */
+ u32 timestamp0;
+ u32 timestamp1;
+ u16 beacon_int;
+ struct iwl3945_driver_hw_info hw_setting;
+ struct ieee80211_vif *vif;
+
+ /* Current association information needed to configure the
+ * hardware */
+ u16 assoc_id;
+ u16 assoc_capability;
+ u8 ps_mode;
+
+#ifdef CONFIG_IWL3945_QOS
+ struct iwl3945_qos_info qos_data;
+#endif /*CONFIG_IWL3945_QOS */
+
+ struct workqueue_struct *workqueue;
+
+ struct work_struct up;
+ struct work_struct restart;
+ struct work_struct calibrated_work;
+ struct work_struct scan_completed;
+ struct work_struct rx_replenish;
+ struct work_struct rf_kill;
+ struct work_struct abort_scan;
+ struct work_struct update_link_led;
+ struct work_struct auth_work;
+ struct work_struct report_work;
+ struct work_struct request_scan;
+ struct work_struct beacon_update;
+
+ struct tasklet_struct irq_tasklet;
+
+ struct delayed_work init_alive_start;
+ struct delayed_work alive_start;
+ struct delayed_work activity_timer;
+ struct delayed_work thermal_periodic;
+ struct delayed_work gather_stats;
+ struct delayed_work scan_check;
+ struct delayed_work post_associate;
+
+#define IWL_DEFAULT_TX_POWER 0x0F
+ s8 user_txpower_limit;
+ s8 max_channel_txpower_limit;
+
+#ifdef CONFIG_PM
+ u32 pm_state[16];
+#endif
+
+#ifdef CONFIG_IWL3945_DEBUG
+ /* debugging info */
+ u32 framecnt_to_us;
+ atomic_t restrict_refcnt;
+#endif
+}; /*iwl3945_priv */
+
+static inline int iwl3945_is_associated(struct iwl3945_priv *priv)
+{
+ return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int is_channel_valid(const struct iwl3945_channel_info *ch_info)
+{
+ if (ch_info == NULL)
+ return 0;
+ return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+}
+
+static inline int is_channel_narrow(const struct iwl3945_channel_info *ch_info)
+{
+ return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
+}
+
+static inline int is_channel_radar(const struct iwl3945_channel_info *ch_info)
+{
+ return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+}
+
+static inline u8 is_channel_a_band(const struct iwl3945_channel_info *ch_info)
+{
+ return ch_info->phymode == MODE_IEEE80211A;
+}
+
+static inline u8 is_channel_bg_band(const struct iwl3945_channel_info *ch_info)
+{
+ return ((ch_info->phymode == MODE_IEEE80211B) ||
+ (ch_info->phymode == MODE_IEEE80211G));
+}
+
+static inline int is_channel_passive(const struct iwl3945_channel_info *ch)
+{
+ return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+}
+
+static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
+{
+ return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+}
+
+static inline int iwl3945_rate_index_from_plcp(int plcp)
+{
+ int i;
+
+ for (i = 0; i < IWL_RATE_COUNT; i++)
+ if (iwl3945_rates[i].plcp == plcp)
+ return i;
+ return -1;
+}
+
+extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
+ const struct iwl3945_priv *priv, int phymode, u16 channel);
+
+/* Requires full declaration of iwl3945_priv before including */
+#include "iwl-3945-io.h"
+
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
new file mode 100644
index 000000000000..f3470c896d9a
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
@@ -0,0 +1,2651 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-4965-commands.h) only for uCode API definitions.
+ * Please use iwl-4965-hw.h for hardware-related definitions.
+ * Please use iwl-4965.h for driver implementation definitions.
+ */
+
+#ifndef __iwl4965_commands_h__
+#define __iwl4965_commands_h__
+
+enum {
+ REPLY_ALIVE = 0x1,
+ REPLY_ERROR = 0x2,
+
+ /* RXON and QOS commands */
+ REPLY_RXON = 0x10,
+ REPLY_RXON_ASSOC = 0x11,
+ REPLY_QOS_PARAM = 0x13,
+ REPLY_RXON_TIMING = 0x14,
+
+ /* Multi-Station support */
+ REPLY_ADD_STA = 0x18,
+ REPLY_REMOVE_STA = 0x19, /* not used */
+ REPLY_REMOVE_ALL_STA = 0x1a, /* not used */
+
+ /* RX, TX, LEDs */
+ REPLY_TX = 0x1c,
+ REPLY_RATE_SCALE = 0x47, /* 3945 only */
+ REPLY_LEDS_CMD = 0x48,
+ REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */
+
+ /* 802.11h related */
+ RADAR_NOTIFICATION = 0x70, /* not used */
+ REPLY_QUIET_CMD = 0x71, /* not used */
+ REPLY_CHANNEL_SWITCH = 0x72,
+ CHANNEL_SWITCH_NOTIFICATION = 0x73,
+ REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
+ SPECTRUM_MEASURE_NOTIFICATION = 0x75,
+
+ /* Power Management */
+ POWER_TABLE_CMD = 0x77,
+ PM_SLEEP_NOTIFICATION = 0x7A,
+ PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
+
+ /* Scan commands and notifications */
+ REPLY_SCAN_CMD = 0x80,
+ REPLY_SCAN_ABORT_CMD = 0x81,
+ SCAN_START_NOTIFICATION = 0x82,
+ SCAN_RESULTS_NOTIFICATION = 0x83,
+ SCAN_COMPLETE_NOTIFICATION = 0x84,
+
+ /* IBSS/AP commands */
+ BEACON_NOTIFICATION = 0x90,
+ REPLY_TX_BEACON = 0x91,
+ WHO_IS_AWAKE_NOTIFICATION = 0x94, /* not used */
+
+ /* Miscellaneous commands */
+ QUIET_NOTIFICATION = 0x96, /* not used */
+ REPLY_TX_PWR_TABLE_CMD = 0x97,
+ MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */
+
+ /* Bluetooth device coexistance config command */
+ REPLY_BT_CONFIG = 0x9b,
+
+ /* Statistics */
+ REPLY_STATISTICS_CMD = 0x9c,
+ STATISTICS_NOTIFICATION = 0x9d,
+
+ /* RF-KILL commands and notifications */
+ REPLY_CARD_STATE_CMD = 0xa0,
+ CARD_STATE_NOTIFICATION = 0xa1,
+
+ /* Missed beacons notification */
+ MISSED_BEACONS_NOTIFICATION = 0xa2,
+
+ REPLY_CT_KILL_CONFIG_CMD = 0xa4,
+ SENSITIVITY_CMD = 0xa8,
+ REPLY_PHY_CALIBRATION_CMD = 0xb0,
+ REPLY_RX_PHY_CMD = 0xc0,
+ REPLY_RX_MPDU_CMD = 0xc1,
+ REPLY_4965_RX = 0xc3,
+ REPLY_COMPRESSED_BA = 0xc5,
+ REPLY_MAX = 0xff
+};
+
+/******************************************************************************
+ * (0)
+ * Commonly used structures and definitions:
+ * Command header, rate_n_flags, txpower
+ *
+ *****************************************************************************/
+
+/* iwl4965_cmd_header flags value */
+#define IWL_CMD_FAILED_MSK 0x40
+
+/**
+ * struct iwl4965_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl4965_cmd_header {
+ u8 cmd; /* Command ID: REPLY_RXON, etc. */
+ u8 flags; /* IWL_CMD_* */
+ /*
+ * The driver sets up the sequence number to values of its chosing.
+ * uCode does not use this value, but passes it back to the driver
+ * when sending the response to each driver-originated command, so
+ * the driver can match the response to the command. Since the values
+ * don't get used by uCode, the driver may set up an arbitrary format.
+ *
+ * There is one exception: uCode sets bit 15 when it originates
+ * the response/notification, i.e. when the response/notification
+ * is not a direct response to a command sent by the driver. For
+ * example, uCode issues REPLY_3945_RX when it sends a received frame
+ * to the driver; it is not a direct response to any driver command.
+ *
+ * The Linux driver uses the following format:
+ *
+ * 0:7 index/position within Tx queue
+ * 8:13 Tx queue selection
+ * 14:14 driver sets this to indicate command is in the 'huge'
+ * storage at the end of the command buffers, i.e. scan cmd
+ * 15:15 uCode sets this in uCode-originated response/notification
+ */
+ __le16 sequence;
+
+ /* command or response/notification data follows immediately */
+ u8 data[0];
+} __attribute__ ((packed));
+
+/**
+ * 4965 rate_n_flags bit fields
+ *
+ * rate_n_flags format is used in following 4965 commands:
+ * REPLY_4965_RX (response only)
+ * REPLY_TX (both command and response)
+ * REPLY_TX_LINK_QUALITY_CMD
+ *
+ * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"):
+ * 2-0: 0) 6 Mbps
+ * 1) 12 Mbps
+ * 2) 18 Mbps
+ * 3) 24 Mbps
+ * 4) 36 Mbps
+ * 5) 48 Mbps
+ * 6) 54 Mbps
+ * 7) 60 Mbps
+ *
+ * 3: 0) Single stream (SISO)
+ * 1) Dual stream (MIMO)
+ *
+ * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data
+ *
+ * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
+ * 3-0: 0xD) 6 Mbps
+ * 0xF) 9 Mbps
+ * 0x5) 12 Mbps
+ * 0x7) 18 Mbps
+ * 0x9) 24 Mbps
+ * 0xB) 36 Mbps
+ * 0x1) 48 Mbps
+ * 0x3) 54 Mbps
+ *
+ * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"):
+ * 3-0: 10) 1 Mbps
+ * 20) 2 Mbps
+ * 55) 5.5 Mbps
+ * 110) 11 Mbps
+ */
+#define RATE_MCS_CODE_MSK 0x7
+#define RATE_MCS_MIMO_POS 3
+#define RATE_MCS_MIMO_MSK 0x8
+#define RATE_MCS_HT_DUP_POS 5
+#define RATE_MCS_HT_DUP_MSK 0x20
+
+/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */
+#define RATE_MCS_FLAGS_POS 8
+#define RATE_MCS_HT_POS 8
+#define RATE_MCS_HT_MSK 0x100
+
+/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */
+#define RATE_MCS_CCK_POS 9
+#define RATE_MCS_CCK_MSK 0x200
+
+/* Bit 10: (1) Use Green Field preamble */
+#define RATE_MCS_GF_POS 10
+#define RATE_MCS_GF_MSK 0x400
+
+/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */
+#define RATE_MCS_FAT_POS 11
+#define RATE_MCS_FAT_MSK 0x800
+
+/* Bit 12: (1) Duplicate data on both 20MHz chnls. FAT (bit 11) must be set. */
+#define RATE_MCS_DUP_POS 12
+#define RATE_MCS_DUP_MSK 0x1000
+
+/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
+#define RATE_MCS_SGI_POS 13
+#define RATE_MCS_SGI_MSK 0x2000
+
+/**
+ * rate_n_flags Tx antenna masks (4965 has 2 transmitters):
+ * bit14:15 01 B inactive, A active
+ * 10 B active, A inactive
+ * 11 Both active
+ */
+#define RATE_MCS_ANT_A_POS 14
+#define RATE_MCS_ANT_B_POS 15
+#define RATE_MCS_ANT_A_MSK 0x4000
+#define RATE_MCS_ANT_B_MSK 0x8000
+#define RATE_MCS_ANT_AB_MSK 0xc000
+
+
+/**
+ * struct iwl4965_tx_power - txpower format used in REPLY_SCAN_CMD
+ *
+ * Scan uses only one transmitter, so only one analog/dsp gain pair is needed.
+ */
+struct iwl4965_tx_power {
+ u8 tx_gain; /* gain for analog radio */
+ u8 dsp_atten; /* gain for DSP */
+} __attribute__ ((packed));
+
+#define POWER_TABLE_NUM_ENTRIES 33
+#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
+#define POWER_TABLE_CCK_ENTRY 32
+
+/**
+ * union iwl4965_tx_power_dual_stream
+ *
+ * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Use __le32 version (struct tx_power_dual_stream) when building command.
+ *
+ * Driver provides radio gain and DSP attenuation settings to device in pairs,
+ * one value for each transmitter chain. The first value is for transmitter A,
+ * second for transmitter B.
+ *
+ * For SISO bit rates, both values in a pair should be identical.
+ * For MIMO rates, one value may be different from the other,
+ * in order to balance the Tx output between the two transmitters.
+ *
+ * See more details in doc for TXPOWER in iwl-4965-hw.h.
+ */
+union iwl4965_tx_power_dual_stream {
+ struct {
+ u8 radio_tx_gain[2];
+ u8 dsp_predis_atten[2];
+ } s;
+ u32 dw;
+};
+
+/**
+ * struct tx_power_dual_stream
+ *
+ * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Same format as iwl_tx_power_dual_stream, but __le32
+ */
+struct tx_power_dual_stream {
+ __le32 dw;
+} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_tx_power_db
+ *
+ * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl4965_tx_power_db {
+ struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
+} __attribute__ ((packed));
+
+
+/******************************************************************************
+ * (0a)
+ * Alive and Error Commands & Responses:
+ *
+ *****************************************************************************/
+
+#define UCODE_VALID_OK __constant_cpu_to_le32(0x1)
+#define INITIALIZE_SUBTYPE (9)
+
+/*
+ * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "initialize alive" notification once the initialization
+ * uCode image has completed its work, and is ready to load the runtime image.
+ * This is the *first* "alive" notification that the driver will receive after
+ * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * For 4965, this notification contains important calibration data for
+ * calculating txpower settings:
+ *
+ * 1) Power supply voltage indication. The voltage sensor outputs higher
+ * values for lower voltage, and vice versa.
+ *
+ * 2) Temperature measurement parameters, for each of two channel widths
+ * (20 MHz and 40 MHz) supported by the radios. Temperature sensing
+ * is done via one of the receiver chains, and channel width influences
+ * the results.
+ *
+ * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
+ * for each of 5 frequency ranges.
+ */
+struct iwl4965_init_alive_resp {
+ u8 ucode_minor;
+ u8 ucode_major;
+ __le16 reserved1;
+ u8 sw_rev[8];
+ u8 ver_type;
+ u8 ver_subtype; /* "9" for initialize alive */
+ __le16 reserved2;
+ __le32 log_event_table_ptr;
+ __le32 error_event_table_ptr;
+ __le32 timestamp;
+ __le32 is_valid;
+
+ /* calibration values from "initialize" uCode */
+ __le32 voltage; /* signed, higher value is lower voltage */
+ __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for FAT channel*/
+ __le32 therm_r2[2]; /* signed */
+ __le32 therm_r3[2]; /* signed */
+ __le32 therm_r4[2]; /* signed */
+ __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups,
+ * 2 Tx chains */
+} __attribute__ ((packed));
+
+
+/**
+ * REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver. This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * This response includes two pointers to structures within the device's
+ * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
+ *
+ * 1) log_event_table_ptr indicates base of the event log. This traces
+ * a 256-entry history of uCode execution within a circular buffer.
+ * Its header format is:
+ *
+ * __le32 log_size; log capacity (in number of entries)
+ * __le32 type; (1) timestamp with each entry, (0) no timestamp
+ * __le32 wraps; # times uCode has wrapped to top of circular buffer
+ * __le32 write_index; next circular buffer entry that uCode would fill
+ *
+ * The header is followed by the circular buffer of log entries. Entries
+ * with timestamps have the following format:
+ *
+ * __le32 event_id; range 0 - 1500
+ * __le32 timestamp; low 32 bits of TSF (of network, if associated)
+ * __le32 data; event_id-specific data value
+ *
+ * Entries without timestamps contain only event_id and data.
+ *
+ * 2) error_event_table_ptr indicates base of the error log. This contains
+ * information about any uCode error that occurs. For 4965, the format
+ * of the error log is:
+ *
+ * __le32 valid; (nonzero) valid, (0) log is empty
+ * __le32 error_id; type of error
+ * __le32 pc; program counter
+ * __le32 blink1; branch link
+ * __le32 blink2; branch link
+ * __le32 ilink1; interrupt link
+ * __le32 ilink2; interrupt link
+ * __le32 data1; error-specific data
+ * __le32 data2; error-specific data
+ * __le32 line; source code line of error
+ * __le32 bcon_time; beacon timer
+ * __le32 tsf_low; network timestamp function timer
+ * __le32 tsf_hi; network timestamp function timer
+ *
+ * The Linux driver can print both logs to the system log when a uCode error
+ * occurs.
+ */
+struct iwl4965_alive_resp {
+ u8 ucode_minor;
+ u8 ucode_major;
+ __le16 reserved1;
+ u8 sw_rev[8];
+ u8 ver_type;
+ u8 ver_subtype; /* not "9" for runtime alive */
+ __le16 reserved2;
+ __le32 log_event_table_ptr; /* SRAM address for event log */
+ __le32 error_event_table_ptr; /* SRAM address for error log */
+ __le32 timestamp;
+ __le32 is_valid;
+} __attribute__ ((packed));
+
+
+union tsf {
+ u8 byte[8];
+ __le16 word[4];
+ __le32 dw[2];
+};
+
+/*
+ * REPLY_ERROR = 0x2 (response only, not a command)
+ */
+struct iwl4965_error_resp {
+ __le32 error_type;
+ u8 cmd_id;
+ u8 reserved1;
+ __le16 bad_cmd_seq_num;
+ __le32 error_info;
+ union tsf timestamp;
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (1)
+ * RXON Commands & Responses:
+ *
+ *****************************************************************************/
+
+/*
+ * Rx config defines & structure
+ */
+/* rx_config device types */
+enum {
+ RXON_DEV_TYPE_AP = 1,
+ RXON_DEV_TYPE_ESS = 3,
+ RXON_DEV_TYPE_IBSS = 4,
+ RXON_DEV_TYPE_SNIFFER = 6,
+};
+
+
+#define RXON_RX_CHAIN_DRIVER_FORCE_MSK __constant_cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_VALID_MSK __constant_cpu_to_le16(0x7 << 1)
+#define RXON_RX_CHAIN_VALID_POS (1)
+#define RXON_RX_CHAIN_FORCE_SEL_MSK __constant_cpu_to_le16(0x7 << 4)
+#define RXON_RX_CHAIN_FORCE_SEL_POS (4)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK __constant_cpu_to_le16(0x7 << 7)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7)
+#define RXON_RX_CHAIN_CNT_MSK __constant_cpu_to_le16(0x3 << 10)
+#define RXON_RX_CHAIN_CNT_POS (10)
+#define RXON_RX_CHAIN_MIMO_CNT_MSK __constant_cpu_to_le16(0x3 << 12)
+#define RXON_RX_CHAIN_MIMO_CNT_POS (12)
+#define RXON_RX_CHAIN_MIMO_FORCE_MSK __constant_cpu_to_le16(0x1 << 14)
+#define RXON_RX_CHAIN_MIMO_FORCE_POS (14)
+
+/* rx_config flags */
+/* band & modulation selection */
+#define RXON_FLG_BAND_24G_MSK __constant_cpu_to_le32(1 << 0)
+#define RXON_FLG_CCK_MSK __constant_cpu_to_le32(1 << 1)
+/* auto detection enable */
+#define RXON_FLG_AUTO_DETECT_MSK __constant_cpu_to_le32(1 << 2)
+/* TGg protection when tx */
+#define RXON_FLG_TGG_PROTECT_MSK __constant_cpu_to_le32(1 << 3)
+/* cck short slot & preamble */
+#define RXON_FLG_SHORT_SLOT_MSK __constant_cpu_to_le32(1 << 4)
+#define RXON_FLG_SHORT_PREAMBLE_MSK __constant_cpu_to_le32(1 << 5)
+/* antenna selection */
+#define RXON_FLG_DIS_DIV_MSK __constant_cpu_to_le32(1 << 7)
+#define RXON_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0x0f00)
+#define RXON_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
+#define RXON_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+/* radar detection enable */
+#define RXON_FLG_RADAR_DETECT_MSK __constant_cpu_to_le32(1 << 12)
+#define RXON_FLG_TGJ_NARROW_BAND_MSK __constant_cpu_to_le32(1 << 13)
+/* rx response to host with 8-byte TSF
+* (according to ON_AIR deassertion) */
+#define RXON_FLG_TSF2HOST_MSK __constant_cpu_to_le32(1 << 15)
+
+
+/* HT flags */
+#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22)
+#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK __constant_cpu_to_le32(0x1 << 22)
+
+#define RXON_FLG_HT_OPERATING_MODE_POS (23)
+
+#define RXON_FLG_HT_PROT_MSK __constant_cpu_to_le32(0x1 << 23)
+#define RXON_FLG_FAT_PROT_MSK __constant_cpu_to_le32(0x2 << 23)
+
+#define RXON_FLG_CHANNEL_MODE_POS (25)
+#define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25)
+#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25)
+#define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25)
+
+/* rx_config filter flags */
+/* accept all data frames */
+#define RXON_FILTER_PROMISC_MSK __constant_cpu_to_le32(1 << 0)
+/* pass control & management to host */
+#define RXON_FILTER_CTL2HOST_MSK __constant_cpu_to_le32(1 << 1)
+/* accept multi-cast */
+#define RXON_FILTER_ACCEPT_GRP_MSK __constant_cpu_to_le32(1 << 2)
+/* don't decrypt uni-cast frames */
+#define RXON_FILTER_DIS_DECRYPT_MSK __constant_cpu_to_le32(1 << 3)
+/* don't decrypt multi-cast frames */
+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK __constant_cpu_to_le32(1 << 4)
+/* STA is associated */
+#define RXON_FILTER_ASSOC_MSK __constant_cpu_to_le32(1 << 5)
+/* transfer to host non bssid beacons in associated state */
+#define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6)
+
+/**
+ * REPLY_RXON = 0x10 (command, has simple generic response)
+ *
+ * RXON tunes the radio tuner to a service channel, and sets up a number
+ * of parameters that are used primarily for Rx, but also for Tx operations.
+ *
+ * NOTE: When tuning to a new channel, driver must set the
+ * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent
+ * info within the device, including the station tables, tx retry
+ * rate tables, and txpower tables. Driver must build a new station
+ * table and txpower table before transmitting anything on the RXON
+ * channel.
+ *
+ * NOTE: All RXONs wipe clean the internal txpower table. Driver must
+ * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ * regardless of whether RXON_FILTER_ASSOC_MSK is set.
+ */
+struct iwl4965_rxon_cmd {
+ u8 node_addr[6];
+ __le16 reserved1;
+ u8 bssid_addr[6];
+ __le16 reserved2;
+ u8 wlap_bssid_addr[6];
+ __le16 reserved3;
+ u8 dev_type;
+ u8 air_propagation;
+ __le16 rx_chain;
+ u8 ofdm_basic_rates;
+ u8 cck_basic_rates;
+ __le16 assoc_id;
+ __le32 flags;
+ __le32 filter_flags;
+ __le16 channel;
+ u8 ofdm_ht_single_stream_basic_rates;
+ u8 ofdm_ht_dual_stream_basic_rates;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
+ */
+struct iwl4965_rxon_assoc_cmd {
+ __le32 flags;
+ __le32 filter_flags;
+ u8 ofdm_basic_rates;
+ u8 cck_basic_rates;
+ u8 ofdm_ht_single_stream_basic_rates;
+ u8 ofdm_ht_dual_stream_basic_rates;
+ __le16 rx_chain_select_flags;
+ __le16 reserved;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
+ */
+struct iwl4965_rxon_time_cmd {
+ union tsf timestamp;
+ __le16 beacon_interval;
+ __le16 atim_window;
+ __le32 beacon_init_val;
+ __le16 listen_interval;
+ __le16 reserved;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
+ */
+struct iwl4965_channel_switch_cmd {
+ u8 band;
+ u8 expect_beacon;
+ __le16 channel;
+ __le32 rxon_flags;
+ __le32 rxon_filter_flags;
+ __le32 switch_time;
+ struct iwl4965_tx_power_db tx_power;
+} __attribute__ ((packed));
+
+/*
+ * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
+ */
+struct iwl4965_csa_notification {
+ __le16 band;
+ __le16 channel;
+ __le32 status; /* 0 - OK, 1 - fail */
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (2)
+ * Quality-of-Service (QOS) Commands & Responses:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ *
+ * @cw_min: Contention window, start value in numbers of slots.
+ * Should be a power-of-2, minus 1. Device's default is 0x0f.
+ * @cw_max: Contention window, max value in numbers of slots.
+ * Should be a power-of-2, minus 1. Device's default is 0x3f.
+ * @aifsn: Number of slots in Arbitration Interframe Space (before
+ * performing random backoff timing prior to Tx). Device default 1.
+ * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0.
+ *
+ * Device will automatically increase contention window by (2*CW) + 1 for each
+ * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
+ * value, to cap the CW value.
+ */
+struct iwl4965_ac_qos {
+ __le16 cw_min;
+ __le16 cw_max;
+ u8 aifsn;
+ u8 reserved1;
+ __le16 edca_txop;
+} __attribute__ ((packed));
+
+/* QoS flags defines */
+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK __constant_cpu_to_le32(0x01)
+#define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02)
+#define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10)
+
+/* Number of Access Categories (AC) (EDCA), queues 0..3 */
+#define AC_NUM 4
+
+/*
+ * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ *
+ * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
+ * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
+ */
+struct iwl4965_qosparam_cmd {
+ __le32 qos_flags;
+ struct iwl4965_ac_qos ac[AC_NUM];
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (3)
+ * Add/Modify Stations Commands & Responses:
+ *
+ *****************************************************************************/
+/*
+ * Multi station support
+ */
+
+/* Special, dedicated locations within device's station table */
+#define IWL_AP_ID 0
+#define IWL_MULTICAST_ID 1
+#define IWL_STA_ID 2
+#define IWL4965_BROADCAST_ID 31
+#define IWL4965_STATION_COUNT 32
+
+#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/
+#define IWL_INVALID_STATION 255
+
+#define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1 << 8);
+#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17)
+#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18)
+#define STA_FLG_MAX_AGG_SIZE_POS (19)
+#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19)
+#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21)
+#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22)
+#define STA_FLG_AGG_MPDU_DENSITY_POS (23)
+#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23)
+
+/* Use in mode field. 1: modify existing entry, 0: add new station entry */
+#define STA_CONTROL_MODIFY_MSK 0x01
+
+/* key flags __le16*/
+#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x7)
+#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0)
+#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x1)
+#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x2)
+#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x3)
+
+#define STA_KEY_FLG_KEYID_POS 8
+#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
+
+/* Flags indicate whether to modify vs. don't change various station params */
+#define STA_MODIFY_KEY_MASK 0x01
+#define STA_MODIFY_TID_DISABLE_TX 0x02
+#define STA_MODIFY_TX_RATE_MSK 0x04
+#define STA_MODIFY_ADDBA_TID_MSK 0x08
+#define STA_MODIFY_DELBA_TID_MSK 0x10
+
+/* Receiver address (actually, Rx station's index into station table),
+ * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
+#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid))
+
+struct iwl4965_keyinfo {
+ __le16 key_flags;
+ u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */
+ u8 reserved1;
+ __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */
+ __le16 reserved2;
+ u8 key[16]; /* 16-byte unicast decryption key */
+} __attribute__ ((packed));
+
+/**
+ * struct sta_id_modify
+ * @addr[ETH_ALEN]: station's MAC address
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
+ *
+ * Driver selects unused table index when adding new station,
+ * or the index to a pre-existing station entry when modifying that station.
+ * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ *
+ * modify_mask flags select which parameters to modify vs. leave alone.
+ */
+struct sta_id_modify {
+ u8 addr[ETH_ALEN];
+ __le16 reserved1;
+ u8 sta_id;
+ u8 modify_mask;
+ __le16 reserved2;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_ADD_STA = 0x18 (command)
+ *
+ * The device contains an internal table of per-station information,
+ * with info on security keys, aggregation parameters, and Tx rates for
+ * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD,
+ * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ *
+ * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * a new entry, or modifying a pre-existing one.
+ *
+ * NOTE: RXON command (without "associated" bit set) wipes the station table
+ * clean. Moving into RF_KILL state does this also. Driver must set up
+ * new station table before transmitting anything on the RXON channel
+ * (except active scans or active measurements; those commands carry
+ * their own txpower/rate setup data).
+ *
+ * When getting started on a new channel, driver must set up the
+ * IWL_BROADCAST_ID entry (last entry in the table). For a client
+ * station in a BSS, once an AP is selected, driver sets up the AP STA
+ * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP
+ * are all that are needed for a BSS client station. If the device is
+ * used as AP, or in an IBSS network, driver must set up station table
+ * entries for all STAs in network, starting with index IWL_STA_ID.
+ */
+struct iwl4965_addsta_cmd {
+ u8 mode; /* 1: modify existing, 0: add new station */
+ u8 reserved[3];
+ struct sta_id_modify sta;
+ struct iwl4965_keyinfo key;
+ __le32 station_flags; /* STA_FLG_* */
+ __le32 station_flags_msk; /* STA_FLG_* */
+
+ /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+ * corresponding to bit (e.g. bit 5 controls TID 5).
+ * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+ __le16 tid_disable_tx;
+
+ __le16 reserved1;
+
+ /* TID for which to add block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+ u8 add_immediate_ba_tid;
+
+ /* TID for which to remove block-ack support.
+ * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+ u8 remove_immediate_ba_tid;
+
+ /* Starting Sequence Number for added block-ack support.
+ * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+ __le16 add_immediate_ba_ssn;
+
+ __le32 reserved2;
+} __attribute__ ((packed));
+
+#define ADD_STA_SUCCESS_MSK 0x1
+#define ADD_STA_NO_ROOM_IN_TABLE 0x2
+#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4
+#define ADD_STA_MODIFY_NON_EXIST_STA 0x8
+/*
+ * REPLY_ADD_STA = 0x18 (response)
+ */
+struct iwl4965_add_sta_resp {
+ u8 status; /* ADD_STA_* */
+} __attribute__ ((packed));
+
+
+/******************************************************************************
+ * (4)
+ * Rx Responses:
+ *
+ *****************************************************************************/
+
+struct iwl4965_rx_frame_stats {
+ u8 phy_count;
+ u8 id;
+ u8 rssi;
+ u8 agc;
+ __le16 sig_avg;
+ __le16 noise_diff;
+ u8 payload[0];
+} __attribute__ ((packed));
+
+struct iwl4965_rx_frame_hdr {
+ __le16 channel;
+ __le16 phy_flags;
+ u8 reserved1;
+ u8 rate;
+ __le16 len;
+ u8 payload[0];
+} __attribute__ ((packed));
+
+#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
+
+#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
+
+#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
+#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
+#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8)
+#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8)
+#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8)
+
+#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11)
+#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11)
+#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11)
+#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11)
+#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11)
+
+struct iwl4965_rx_frame_end {
+ __le32 status;
+ __le64 timestamp;
+ __le32 beacon_timestamp;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_3945_RX = 0x1b (response only, not a command)
+ *
+ * NOTE: DO NOT dereference from casts to this structure
+ * It is provided only for calculating minimum data set size.
+ * The actual offsets of the hdr and end are dynamic based on
+ * stats.phy_count
+ */
+struct iwl4965_rx_frame {
+ struct iwl4965_rx_frame_stats stats;
+ struct iwl4965_rx_frame_hdr hdr;
+ struct iwl4965_rx_frame_end end;
+} __attribute__ ((packed));
+
+/* Fixed (non-configurable) rx data from phy */
+#define RX_PHY_FLAGS_ANTENNAE_OFFSET (4)
+#define RX_PHY_FLAGS_ANTENNAE_MASK (0x70)
+#define IWL_AGC_DB_MASK (0x3f80) /* MASK(7,13) */
+#define IWL_AGC_DB_POS (7)
+struct iwl4965_rx_non_cfg_phy {
+ __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */
+ __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */
+ u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */
+ u8 pad[0];
+} __attribute__ ((packed));
+
+/*
+ * REPLY_4965_RX = 0xc3 (response only, not a command)
+ * Used only for legacy (non 11n) frames.
+ */
+#define RX_RES_PHY_CNT 14
+struct iwl4965_rx_phy_res {
+ u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */
+ u8 cfg_phy_cnt; /* configurable DSP phy data byte count */
+ u8 stat_id; /* configurable DSP phy data set ID */
+ u8 reserved1;
+ __le64 timestamp; /* TSF at on air rise */
+ __le32 beacon_time_stamp; /* beacon at on-air rise */
+ __le16 phy_flags; /* general phy flags: band, modulation, ... */
+ __le16 channel; /* channel number */
+ __le16 non_cfg_phy[RX_RES_PHY_CNT]; /* upto 14 phy entries */
+ __le32 reserved2;
+ __le32 rate_n_flags; /* RATE_MCS_* */
+ __le16 byte_count; /* frame's byte-count */
+ __le16 reserved3;
+} __attribute__ ((packed));
+
+struct iwl4965_rx_mpdu_res_start {
+ __le16 byte_count;
+ __le16 reserved;
+} __attribute__ ((packed));
+
+
+/******************************************************************************
+ * (5)
+ * Tx Commands & Responses:
+ *
+ * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * queues in host DRAM, shared between driver and device (see comments for
+ * SCD registers and Tx/Rx Queues). When the device's Tx scheduler and uCode
+ * are preparing to transmit, the device pulls the Tx command over the PCI
+ * bus via one of the device's Tx DMA channels, to fill an internal FIFO
+ * from which data will be transmitted.
+ *
+ * uCode handles all timing and protocol related to control frames
+ * (RTS/CTS/ACK), based on flags in the Tx command. uCode and Tx scheduler
+ * handle reception of block-acks; uCode updates the host driver via
+ * REPLY_COMPRESSED_BA (4965).
+ *
+ * uCode handles retrying Tx when an ACK is expected but not received.
+ * This includes trying lower data rates than the one requested in the Tx
+ * command, as set up by the REPLY_RATE_SCALE (for 3945) or
+ * REPLY_TX_LINK_QUALITY_CMD (4965).
+ *
+ * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * This command must be executed after every RXON command, before Tx can occur.
+ *****************************************************************************/
+
+/* REPLY_TX Tx flags field */
+
+/* 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
+#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
+
+/* 1: Transmit Clear-To-Send to self before this frame.
+ * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
+#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
+
+/* 1: Expect ACK from receiving station
+ * 0: Don't expect ACK (MAC header's duration field s/b 0)
+ * Set this for unicast frames, but not broadcast/multicast. */
+#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
+
+/* For 4965:
+ * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
+ * Tx command's initial_rate_index indicates first rate to try;
+ * uCode walks through table for additional Tx attempts.
+ * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
+ * This rate will be used for all Tx attempts; it will not be scaled. */
+#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
+
+/* 1: Expect immediate block-ack.
+ * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
+#define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6)
+
+/* 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set. */
+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
+
+/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
+ * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
+#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
+#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
+#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+
+/* 1: Ignore Bluetooth priority for this frame.
+ * 0: Delay Tx until Bluetooth device is done (normal usage). */
+#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
+
+/* 1: uCode overrides sequence control field in MAC header.
+ * 0: Driver provides sequence control field in MAC header.
+ * Set this for management frames, non-QOS data frames, non-unicast frames,
+ * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
+#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
+
+/* 1: This frame is non-last MPDU; more fragments are coming.
+ * 0: Last fragment, or not using fragmentation. */
+#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
+
+/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
+ * 0: No TSF required in outgoing frame.
+ * Set this for transmitting beacons and probe responses. */
+#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
+
+/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
+ * alignment of frame's payload data field.
+ * 0: No pad
+ * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
+ * field (but not both). Driver must align frame data (i.e. data following
+ * MAC header) to DWORD boundary. */
+#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
+
+/* HCCA-AP - disable duration overwriting. */
+#define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
+
+
+/*
+ * TX command security control
+ */
+#define TX_CMD_SEC_WEP 0x01
+#define TX_CMD_SEC_CCM 0x02
+#define TX_CMD_SEC_TKIP 0x03
+#define TX_CMD_SEC_MSK 0x03
+#define TX_CMD_SEC_SHIFT 6
+#define TX_CMD_SEC_KEY128 0x08
+
+/*
+ * 4965 uCode updates these Tx attempt count values in host DRAM.
+ * Used for managing Tx retries when expecting block-acks.
+ * Driver should set these fields to 0.
+ */
+struct iwl4965_dram_scratch {
+ u8 try_cnt; /* Tx attempts */
+ u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */
+ __le16 reserved;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_TX = 0x1c (command)
+ */
+struct iwl4965_tx_cmd {
+ /*
+ * MPDU byte count:
+ * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+ * + 8 byte IV for CCM or TKIP (not used for WEP)
+ * + Data payload
+ * + 8-byte MIC (not used for CCM/WEP)
+ * NOTE: Does not include Tx command bytes, post-MAC pad bytes,
+ * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+ * Range: 14-2342 bytes.
+ */
+ __le16 len;
+
+ /*
+ * MPDU or MSDU byte count for next frame.
+ * Used for fragmentation and bursting, but not 11n aggregation.
+ * Same as "len", but for next frame. Set to 0 if not applicable.
+ */
+ __le16 next_frame_len;
+
+ __le32 tx_flags; /* TX_CMD_FLG_* */
+
+ /* 4965's uCode may modify this field of the Tx command (in host DRAM!).
+ * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
+ struct iwl4965_dram_scratch scratch;
+
+ /* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
+ __le32 rate_n_flags; /* RATE_MCS_* */
+
+ /* Index of destination station in uCode's station table */
+ u8 sta_id;
+
+ /* Type of security encryption: CCM or TKIP */
+ u8 sec_ctl; /* TX_CMD_SEC_* */
+
+ /*
+ * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial
+ * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set. Normally "0" for
+ * data frames, this field may be used to selectively reduce initial
+ * rate (via non-0 value) for special frames (e.g. management), while
+ * still supporting rate scaling for all frames.
+ */
+ u8 initial_rate_index;
+ u8 reserved;
+ u8 key[16];
+ __le16 next_frame_flags;
+ __le16 reserved2;
+ union {
+ __le32 life_time;
+ __le32 attempt;
+ } stop_time;
+
+ /* Host DRAM physical address pointer to "scratch" in this command.
+ * Must be dword aligned. "0" in dram_lsb_ptr disables usage. */
+ __le32 dram_lsb_ptr;
+ u8 dram_msb_ptr;
+
+ u8 rts_retry_limit; /*byte 50 */
+ u8 data_retry_limit; /*byte 51 */
+ u8 tid_tspec;
+ union {
+ __le16 pm_frame_timeout;
+ __le16 attempt_duration;
+ } timeout;
+
+ /*
+ * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+ * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+ */
+ __le16 driver_txop;
+
+ /*
+ * MAC header goes here, followed by 2 bytes padding if MAC header
+ * length is 26 or 30 bytes, followed by payload data
+ */
+ u8 payload[0];
+ struct ieee80211_hdr hdr[0];
+} __attribute__ ((packed));
+
+/* TX command response is sent after *all* transmission attempts.
+ *
+ * NOTES:
+ *
+ * TX_STATUS_FAIL_NEXT_FRAG
+ *
+ * If the fragment flag in the MAC header for the frame being transmitted
+ * is set and there is insufficient time to transmit the next frame, the
+ * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
+ *
+ * TX_STATUS_FIFO_UNDERRUN
+ *
+ * Indicates the host did not provide bytes to the FIFO fast enough while
+ * a TX was in progress.
+ *
+ * TX_STATUS_FAIL_MGMNT_ABORT
+ *
+ * This status is only possible if the ABORT ON MGMT RX parameter was
+ * set to true with the TX command.
+ *
+ * If the MSB of the status parameter is set then an abort sequence is
+ * required. This sequence consists of the host activating the TX Abort
+ * control line, and then waiting for the TX Abort command response. This
+ * indicates that a the device is no longer in a transmit state, and that the
+ * command FIFO has been cleared. The host must then deactivate the TX Abort
+ * control line. Receiving is still allowed in this case.
+ */
+enum {
+ TX_STATUS_SUCCESS = 0x01,
+ TX_STATUS_DIRECT_DONE = 0x02,
+ TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
+ TX_STATUS_FAIL_LONG_LIMIT = 0x83,
+ TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
+ TX_STATUS_FAIL_MGMNT_ABORT = 0x85,
+ TX_STATUS_FAIL_NEXT_FRAG = 0x86,
+ TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
+ TX_STATUS_FAIL_DEST_PS = 0x88,
+ TX_STATUS_FAIL_ABORTED = 0x89,
+ TX_STATUS_FAIL_BT_RETRY = 0x8a,
+ TX_STATUS_FAIL_STA_INVALID = 0x8b,
+ TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
+ TX_STATUS_FAIL_TID_DISABLE = 0x8d,
+ TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
+ TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
+ TX_STATUS_FAIL_TX_LOCKED = 0x90,
+ TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
+};
+
+#define TX_PACKET_MODE_REGULAR 0x0000
+#define TX_PACKET_MODE_BURST_SEQ 0x0100
+#define TX_PACKET_MODE_BURST_FIRST 0x0200
+
+enum {
+ TX_POWER_PA_NOT_ACTIVE = 0x0,
+};
+
+enum {
+ TX_STATUS_MSK = 0x000000ff, /* bits 0:7 */
+ TX_STATUS_DELAY_MSK = 0x00000040,
+ TX_STATUS_ABORT_MSK = 0x00000080,
+ TX_PACKET_MODE_MSK = 0x0000ff00, /* bits 8:15 */
+ TX_FIFO_NUMBER_MSK = 0x00070000, /* bits 16:18 */
+ TX_RESERVED = 0x00780000, /* bits 19:22 */
+ TX_POWER_PA_DETECT_MSK = 0x7f800000, /* bits 23:30 */
+ TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */
+};
+
+/* *******************************
+ * TX aggregation status
+ ******************************* */
+
+enum {
+ AGG_TX_STATE_TRANSMITTED = 0x00,
+ AGG_TX_STATE_UNDERRUN_MSK = 0x01,
+ AGG_TX_STATE_BT_PRIO_MSK = 0x02,
+ AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
+ AGG_TX_STATE_ABORT_MSK = 0x08,
+ AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40,
+ AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
+ AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
+ AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
+ AGG_TX_STATE_DUMP_TX_MSK = 0x200,
+ AGG_TX_STATE_DELAY_TX_MSK = 0x400
+};
+
+#define AGG_TX_STATE_LAST_SENT_MSK \
+(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
+
+/* # tx attempts for first frame in aggregation */
+#define AGG_TX_STATE_TRY_CNT_POS 12
+#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
+
+/* Command ID and sequence number of Tx command for this frame */
+#define AGG_TX_STATE_SEQ_NUM_POS 16
+#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
+
+/*
+ * REPLY_TX = 0x1c (response)
+ *
+ * This response may be in one of two slightly different formats, indicated
+ * by the frame_count field:
+ *
+ * 1) No aggregation (frame_count == 1). This reports Tx results for
+ * a single frame. Multiple attempts, at various bit rates, may have
+ * been made for this frame.
+ *
+ * 2) Aggregation (frame_count > 1). This reports Tx results for
+ * 2 or more frames that used block-acknowledge. All frames were
+ * transmitted at same rate. Rate scaling may have been used if first
+ * frame in this new agg block failed in previous agg block(s).
+ *
+ * Note that, for aggregation, ACK (block-ack) status is not delivered here;
+ * block-ack has not been received by the time the 4965 records this status.
+ * This status relates to reasons the tx might have been blocked or aborted
+ * within the sending station (this 4965), rather than whether it was
+ * received successfully by the destination station.
+ */
+struct iwl4965_tx_resp {
+ u8 frame_count; /* 1 no aggregation, >1 aggregation */
+ u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */
+ u8 failure_rts; /* # failures due to unsuccessful RTS */
+ u8 failure_frame; /* # failures due to no ACK (unused for agg) */
+
+ /* For non-agg: Rate at which frame was successful.
+ * For agg: Rate at which all frames were transmitted. */
+ __le32 rate_n_flags; /* RATE_MCS_* */
+
+ /* For non-agg: RTS + CTS + frame tx attempts time + ACK.
+ * For agg: RTS + CTS + aggregation tx time + block-ack time. */
+ __le16 wireless_media_time; /* uSecs */
+
+ __le16 reserved;
+ __le32 pa_power1; /* RF power amplifier measurement (not used) */
+ __le32 pa_power2;
+
+ /*
+ * For non-agg: frame status TX_STATUS_*
+ * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status
+ * fields follow this one, up to frame_count.
+ * Bit fields:
+ * 11- 0: AGG_TX_STATE_* status code
+ * 15-12: Retry count for 1st frame in aggregation (retries
+ * occur if tx failed for this frame when it was a
+ * member of a previous aggregation block). If rate
+ * scaling is used, retry count indicates the rate
+ * table entry used for all frames in the new agg.
+ * 31-16: Sequence # for this frame's Tx cmd (not SSN!)
+ */
+ __le32 status; /* TX status (for aggregation status of 1st frame) */
+} __attribute__ ((packed));
+
+/*
+ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ *
+ * Reports Block-Acknowledge from recipient station
+ */
+struct iwl4965_compressed_ba_resp {
+ __le32 sta_addr_lo32;
+ __le16 sta_addr_hi16;
+ __le16 reserved;
+
+ /* Index of recipient (BA-sending) station in uCode's station table */
+ u8 sta_id;
+ u8 tid;
+ __le16 ba_seq_ctl;
+ __le32 ba_bitmap0;
+ __le32 ba_bitmap1;
+ __le16 scd_flow;
+ __le16 scd_ssn;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
+ *
+ * See details under "TXPOWER" in iwl-4965-hw.h.
+ */
+struct iwl4965_txpowertable_cmd {
+ u8 band; /* 0: 5 GHz, 1: 2.4 GHz */
+ u8 reserved;
+ __le16 channel;
+ struct iwl4965_tx_power_db tx_power;
+} __attribute__ ((packed));
+
+/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
+#define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0)
+
+/* # of EDCA prioritized tx fifos */
+#define LINK_QUAL_AC_NUM AC_NUM
+
+/* # entries in rate scale table to support Tx retries */
+#define LINK_QUAL_MAX_RETRY_NUM 16
+
+/* Tx antenna selection values */
+#define LINK_QUAL_ANT_A_MSK (1 << 0)
+#define LINK_QUAL_ANT_B_MSK (1 << 1)
+#define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
+
+
+/**
+ * struct iwl4965_link_qual_general_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl4965_link_qual_general_params {
+ u8 flags;
+
+ /* No entries at or above this (driver chosen) index contain MIMO */
+ u8 mimo_delimiter;
+
+ /* Best single antenna to use for single stream (legacy, SISO). */
+ u8 single_stream_ant_msk; /* LINK_QUAL_ANT_* */
+
+ /* Best antennas to use for MIMO (unused for 4965, assumes both). */
+ u8 dual_stream_ant_msk; /* LINK_QUAL_ANT_* */
+
+ /*
+ * If driver needs to use different initial rates for different
+ * EDCA QOS access categories (as implemented by tx fifos 0-3),
+ * this table will set that up, by indicating the indexes in the
+ * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start.
+ * Otherwise, driver should set all entries to 0.
+ *
+ * Entry usage:
+ * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice
+ * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3.
+ */
+ u8 start_rate_index[LINK_QUAL_AC_NUM];
+} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_link_qual_agg_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl4965_link_qual_agg_params {
+
+ /* Maximum number of uSec in aggregation.
+ * Driver should set this to 4000 (4 milliseconds). */
+ __le16 agg_time_limit;
+
+ /*
+ * Number of Tx retries allowed for a frame, before that frame will
+ * no longer be considered for the start of an aggregation sequence
+ * (scheduler will then try to tx it as single frame).
+ * Driver should set this to 3.
+ */
+ u8 agg_dis_start_th;
+
+ /*
+ * Maximum number of frames in aggregation.
+ * 0 = no limit (default). 1 = no aggregation.
+ * Other values = max # frames in aggregation.
+ */
+ u8 agg_frame_cnt_limit;
+
+ __le32 reserved;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
+ *
+ * For 4965 only; 3945 uses REPLY_RATE_SCALE.
+ *
+ * Each station in the 4965's internal station table has its own table of 16
+ * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when
+ * an ACK is not received. This command replaces the entire table for
+ * one station.
+ *
+ * NOTE: Station must already be in 4965's station table. Use REPLY_ADD_STA.
+ *
+ * The rate scaling procedures described below work well. Of course, other
+ * procedures are possible, and may work better for particular environments.
+ *
+ *
+ * FILLING THE RATE TABLE
+ *
+ * Given a particular initial rate and mode, as determined by the rate
+ * scaling algorithm described below, the Linux driver uses the following
+ * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the
+ * Link Quality command:
+ *
+ *
+ * 1) If using High-throughput (HT) (SISO or MIMO) initial rate:
+ * a) Use this same initial rate for first 3 entries.
+ * b) Find next lower available rate using same mode (SISO or MIMO),
+ * use for next 3 entries. If no lower rate available, switch to
+ * legacy mode (no FAT channel, no MIMO, no short guard interval).
+ * c) If using MIMO, set command's mimo_delimiter to number of entries
+ * using MIMO (3 or 6).
+ * d) After trying 2 HT rates, switch to legacy mode (no FAT channel,
+ * no MIMO, no short guard interval), at the next lower bit rate
+ * (e.g. if second HT bit rate was 54, try 48 legacy), and follow
+ * legacy procedure for remaining table entries.
+ *
+ * 2) If using legacy initial rate:
+ * a) Use the initial rate for only one entry.
+ * b) For each following entry, reduce the rate to next lower available
+ * rate, until reaching the lowest available rate.
+ * c) When reducing rate, also switch antenna selection.
+ * d) Once lowest available rate is reached, repeat this rate until
+ * rate table is filled (16 entries), switching antenna each entry.
+ *
+ *
+ * ACCUMULATING HISTORY
+ *
+ * The rate scaling algorithm for 4965, as implemented in Linux driver, uses
+ * two sets of frame Tx success history: One for the current/active modulation
+ * mode, and one for a speculative/search mode that is being attempted. If the
+ * speculative mode turns out to be more effective (i.e. actual transfer
+ * rate is better), then the driver continues to use the speculative mode
+ * as the new current active mode.
+ *
+ * Each history set contains, separately for each possible rate, data for a
+ * sliding window of the 62 most recent tx attempts at that rate. The data
+ * includes a shifting bitmap of success(1)/failure(0), and sums of successful
+ * and attempted frames, from which the driver can additionally calculate a
+ * success ratio (success / attempted) and number of failures
+ * (attempted - success), and control the size of the window (attempted).
+ * The driver uses the bit map to remove successes from the success sum, as
+ * the oldest tx attempts fall out of the window.
+ *
+ * When the 4965 makes multiple tx attempts for a given frame, each attempt
+ * might be at a different rate, and have different modulation characteristics
+ * (e.g. antenna, fat channel, short guard interval), as set up in the rate
+ * scaling table in the Link Quality command. The driver must determine
+ * which rate table entry was used for each tx attempt, to determine which
+ * rate-specific history to update, and record only those attempts that
+ * match the modulation characteristics of the history set.
+ *
+ * When using block-ack (aggregation), all frames are transmitted at the same
+ * rate, since there is no per-attempt acknowledgement from the destination
+ * station. The Tx response struct iwl_tx_resp indicates the Tx rate in
+ * rate_n_flags field. After receiving a block-ack, the driver can update
+ * history for the entire block all at once.
+ *
+ *
+ * FINDING BEST STARTING RATE:
+ *
+ * When working with a selected initial modulation mode (see below), the
+ * driver attempts to find a best initial rate. The initial rate is the
+ * first entry in the Link Quality command's rate table.
+ *
+ * 1) Calculate actual throughput (success ratio * expected throughput, see
+ * table below) for current initial rate. Do this only if enough frames
+ * have been attempted to make the value meaningful: at least 6 failed
+ * tx attempts, or at least 8 successes. If not enough, don't try rate
+ * scaling yet.
+ *
+ * 2) Find available rates adjacent to current initial rate. Available means:
+ * a) supported by hardware &&
+ * b) supported by association &&
+ * c) within any constraints selected by user
+ *
+ * 3) Gather measured throughputs for adjacent rates. These might not have
+ * enough history to calculate a throughput. That's okay, we might try
+ * using one of them anyway!
+ *
+ * 4) Try decreasing rate if, for current rate:
+ * a) success ratio is < 15% ||
+ * b) lower adjacent rate has better measured throughput ||
+ * c) higher adjacent rate has worse throughput, and lower is unmeasured
+ *
+ * As a sanity check, if decrease was determined above, leave rate
+ * unchanged if:
+ * a) lower rate unavailable
+ * b) success ratio at current rate > 85% (very good)
+ * c) current measured throughput is better than expected throughput
+ * of lower rate (under perfect 100% tx conditions, see table below)
+ *
+ * 5) Try increasing rate if, for current rate:
+ * a) success ratio is < 15% ||
+ * b) both adjacent rates' throughputs are unmeasured (try it!) ||
+ * b) higher adjacent rate has better measured throughput ||
+ * c) lower adjacent rate has worse throughput, and higher is unmeasured
+ *
+ * As a sanity check, if increase was determined above, leave rate
+ * unchanged if:
+ * a) success ratio at current rate < 70%. This is not particularly
+ * good performance; higher rate is sure to have poorer success.
+ *
+ * 6) Re-evaluate the rate after each tx frame. If working with block-
+ * acknowledge, history and statistics may be calculated for the entire
+ * block (including prior history that fits within the history windows),
+ * before re-evaluation.
+ *
+ * FINDING BEST STARTING MODULATION MODE:
+ *
+ * After working with a modulation mode for a "while" (and doing rate scaling),
+ * the driver searches for a new initial mode in an attempt to improve
+ * throughput. The "while" is measured by numbers of attempted frames:
+ *
+ * For legacy mode, search for new mode after:
+ * 480 successful frames, or 160 failed frames
+ * For high-throughput modes (SISO or MIMO), search for new mode after:
+ * 4500 successful frames, or 400 failed frames
+ *
+ * Mode switch possibilities are (3 for each mode):
+ *
+ * For legacy:
+ * Change antenna, try SISO (if HT association), try MIMO (if HT association)
+ * For SISO:
+ * Change antenna, try MIMO, try shortened guard interval (SGI)
+ * For MIMO:
+ * Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI)
+ *
+ * When trying a new mode, use the same bit rate as the old/current mode when
+ * trying antenna switches and shortened guard interval. When switching to
+ * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate
+ * for which the expected throughput (under perfect conditions) is about the
+ * same or slightly better than the actual measured throughput delivered by
+ * the old/current mode.
+ *
+ * Actual throughput can be estimated by multiplying the expected throughput
+ * by the success ratio (successful / attempted tx frames). Frame size is
+ * not considered in this calculation; it assumes that frame size will average
+ * out to be fairly consistent over several samples. The following are
+ * metric values for expected throughput assuming 100% success ratio.
+ * Only G band has support for CCK rates:
+ *
+ * RATE: 1 2 5 11 6 9 12 18 24 36 48 54 60
+ *
+ * G: 7 13 35 58 40 57 72 98 121 154 177 186 186
+ * A: 0 0 0 0 40 57 72 98 121 154 177 186 186
+ * SISO 20MHz: 0 0 0 0 42 42 76 102 124 159 183 193 202
+ * SGI SISO 20MHz: 0 0 0 0 46 46 82 110 132 168 192 202 211
+ * MIMO 20MHz: 0 0 0 0 74 74 123 155 179 214 236 244 251
+ * SGI MIMO 20MHz: 0 0 0 0 81 81 131 164 188 222 243 251 257
+ * SISO 40MHz: 0 0 0 0 77 77 127 160 184 220 242 250 257
+ * SGI SISO 40MHz: 0 0 0 0 83 83 135 169 193 229 250 257 264
+ * MIMO 40MHz: 0 0 0 0 123 123 182 214 235 264 279 285 289
+ * SGI MIMO 40MHz: 0 0 0 0 131 131 191 222 242 270 284 289 293
+ *
+ * After the new mode has been tried for a short while (minimum of 6 failed
+ * frames or 8 successful frames), compare success ratio and actual throughput
+ * estimate of the new mode with the old. If either is better with the new
+ * mode, continue to use the new mode.
+ *
+ * Continue comparing modes until all 3 possibilities have been tried.
+ * If moving from legacy to HT, try all 3 possibilities from the new HT
+ * mode. After trying all 3, a best mode is found. Continue to use this mode
+ * for the longer "while" described above (e.g. 480 successful frames for
+ * legacy), and then repeat the search process.
+ *
+ */
+struct iwl4965_link_quality_cmd {
+
+ /* Index of destination/recipient station in uCode's station table */
+ u8 sta_id;
+ u8 reserved1;
+ __le16 control; /* not used */
+ struct iwl4965_link_qual_general_params general_params;
+ struct iwl4965_link_qual_agg_params agg_params;
+
+ /*
+ * Rate info; when using rate-scaling, Tx command's initial_rate_index
+ * specifies 1st Tx rate attempted, via index into this table.
+ * 4965 works its way through table when retrying Tx.
+ */
+ struct {
+ __le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */
+ } rs_table[LINK_QUAL_MAX_RETRY_NUM];
+ __le32 reserved2;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ *
+ * 3945 and 4965 support hardware handshake with Bluetooth device on
+ * same platform. Bluetooth device alerts wireless device when it will Tx;
+ * wireless device can delay or kill its own Tx to accomodate.
+ */
+struct iwl4965_bt_cmd {
+ u8 flags;
+ u8 lead_time;
+ u8 max_kill;
+ u8 reserved;
+ __le32 kill_ack_mask;
+ __le32 kill_cts_mask;
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (6)
+ * Spectrum Management (802.11h) Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/*
+ * Spectrum Management
+ */
+#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK | \
+ RXON_FILTER_CTL2HOST_MSK | \
+ RXON_FILTER_ACCEPT_GRP_MSK | \
+ RXON_FILTER_DIS_DECRYPT_MSK | \
+ RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
+ RXON_FILTER_ASSOC_MSK | \
+ RXON_FILTER_BCON_AWARE_MSK)
+
+struct iwl4965_measure_channel {
+ __le32 duration; /* measurement duration in extended beacon
+ * format */
+ u8 channel; /* channel to measure */
+ u8 type; /* see enum iwl4965_measure_type */
+ __le16 reserved;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
+ */
+struct iwl4965_spectrum_cmd {
+ __le16 len; /* number of bytes starting from token */
+ u8 token; /* token id */
+ u8 id; /* measurement id -- 0 or 1 */
+ u8 origin; /* 0 = TGh, 1 = other, 2 = TGk */
+ u8 periodic; /* 1 = periodic */
+ __le16 path_loss_timeout;
+ __le32 start_time; /* start time in extended beacon format */
+ __le32 reserved2;
+ __le32 flags; /* rxon flags */
+ __le32 filter_flags; /* rxon filter flags */
+ __le16 channel_count; /* minimum 1, maximum 10 */
+ __le16 reserved3;
+ struct iwl4965_measure_channel channels[10];
+} __attribute__ ((packed));
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
+ */
+struct iwl4965_spectrum_resp {
+ u8 token;
+ u8 id; /* id of the prior command replaced, or 0xff */
+ __le16 status; /* 0 - command will be handled
+ * 1 - cannot handle (conflicts with another
+ * measurement) */
+} __attribute__ ((packed));
+
+enum iwl4965_measurement_state {
+ IWL_MEASUREMENT_START = 0,
+ IWL_MEASUREMENT_STOP = 1,
+};
+
+enum iwl4965_measurement_status {
+ IWL_MEASUREMENT_OK = 0,
+ IWL_MEASUREMENT_CONCURRENT = 1,
+ IWL_MEASUREMENT_CSA_CONFLICT = 2,
+ IWL_MEASUREMENT_TGH_CONFLICT = 3,
+ /* 4-5 reserved */
+ IWL_MEASUREMENT_STOPPED = 6,
+ IWL_MEASUREMENT_TIMEOUT = 7,
+ IWL_MEASUREMENT_PERIODIC_FAILED = 8,
+};
+
+#define NUM_ELEMENTS_IN_HISTOGRAM 8
+
+struct iwl4965_measurement_histogram {
+ __le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */
+ __le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */
+} __attribute__ ((packed));
+
+/* clear channel availability counters */
+struct iwl4965_measurement_cca_counters {
+ __le32 ofdm;
+ __le32 cck;
+} __attribute__ ((packed));
+
+enum iwl4965_measure_type {
+ IWL_MEASURE_BASIC = (1 << 0),
+ IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
+ IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
+ IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
+ IWL_MEASURE_FRAME = (1 << 4),
+ /* bits 5:6 are reserved */
+ IWL_MEASURE_IDLE = (1 << 7),
+};
+
+/*
+ * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
+ */
+struct iwl4965_spectrum_notification {
+ u8 id; /* measurement id -- 0 or 1 */
+ u8 token;
+ u8 channel_index; /* index in measurement channel list */
+ u8 state; /* 0 - start, 1 - stop */
+ __le32 start_time; /* lower 32-bits of TSF */
+ u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */
+ u8 channel;
+ u8 type; /* see enum iwl4965_measurement_type */
+ u8 reserved1;
+ /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
+ * valid if applicable for measurement type requested. */
+ __le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */
+ __le32 cca_cck; /* cca fraction time in 44Mhz clock periods */
+ __le32 cca_time; /* channel load time in usecs */
+ u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 -
+ * unidentified */
+ u8 reserved2[3];
+ struct iwl4965_measurement_histogram histogram;
+ __le32 stop_time; /* lower 32-bits of TSF */
+ __le32 status; /* see iwl4965_measurement_status */
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (7)
+ * Power Management Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl4965_powertable_cmd - Power Table Command
+ * @flags: See below:
+ *
+ * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
+ *
+ * PM allow:
+ * bit 0 - '0' Driver not allow power management
+ * '1' Driver allow PM (use rest of parameters)
+ * uCode send sleep notifications:
+ * bit 1 - '0' Don't send sleep notification
+ * '1' send sleep notification (SEND_PM_NOTIFICATION)
+ * Sleep over DTIM
+ * bit 2 - '0' PM have to walk up every DTIM
+ * '1' PM could sleep over DTIM till listen Interval.
+ * PCI power managed
+ * bit 3 - '0' (PCI_LINK_CTRL & 0x1)
+ * '1' !(PCI_LINK_CTRL & 0x1)
+ * Force sleep Modes
+ * bit 31/30- '00' use both mac/xtal sleeps
+ * '01' force Mac sleep
+ * '10' force xtal sleep
+ * '11' Illegal set
+ *
+ * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
+ * ucode assume sleep over DTIM is allowed and we don't need to wakeup
+ * for every DTIM.
+ */
+#define IWL_POWER_VEC_SIZE 5
+
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le16(1 << 0)
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le16(1 << 2)
+#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1 << 3)
+
+struct iwl4965_powertable_cmd {
+ __le16 flags;
+ u8 keep_alive_seconds;
+ u8 debug_flags;
+ __le32 rx_data_timeout;
+ __le32 tx_data_timeout;
+ __le32 sleep_interval[IWL_POWER_VEC_SIZE];
+ __le32 keep_alive_beacons;
+} __attribute__ ((packed));
+
+/*
+ * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
+ * 3945 and 4965 identical.
+ */
+struct iwl4965_sleep_notification {
+ u8 pm_sleep_mode;
+ u8 pm_wakeup_src;
+ __le16 reserved;
+ __le32 sleep_time;
+ __le32 tsf_low;
+ __le32 bcon_timer;
+} __attribute__ ((packed));
+
+/* Sleep states. 3945 and 4965 identical. */
+enum {
+ IWL_PM_NO_SLEEP = 0,
+ IWL_PM_SLP_MAC = 1,
+ IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
+ IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
+ IWL_PM_SLP_PHY = 4,
+ IWL_PM_SLP_REPENT = 5,
+ IWL_PM_WAKEUP_BY_TIMER = 6,
+ IWL_PM_WAKEUP_BY_DRIVER = 7,
+ IWL_PM_WAKEUP_BY_RFKILL = 8,
+ /* 3 reserved */
+ IWL_PM_NUM_OF_MODES = 12,
+};
+
+/*
+ * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response)
+ */
+#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */
+#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */
+#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */
+struct iwl4965_card_state_cmd {
+ __le32 status; /* CARD_STATE_CMD_* request new power state */
+} __attribute__ ((packed));
+
+/*
+ * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
+ */
+struct iwl4965_card_state_notif {
+ __le32 flags;
+} __attribute__ ((packed));
+
+#define HW_CARD_DISABLED 0x01
+#define SW_CARD_DISABLED 0x02
+#define RF_CARD_DISABLED 0x04
+#define RXON_CARD_DISABLED 0x10
+
+struct iwl4965_ct_kill_config {
+ __le32 reserved;
+ __le32 critical_temperature_M;
+ __le32 critical_temperature_R;
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (8)
+ * Scan Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl4965_scan_channel - entry in REPLY_SCAN_CMD channel table
+ *
+ * One for each channel in the scan list.
+ * Each channel can independently select:
+ * 1) SSID for directed active scans
+ * 2) Txpower setting (for rate specified within Tx command)
+ * 3) How long to stay on-channel (behavior may be modified by quiet_time,
+ * quiet_plcp_th, good_CRC_th)
+ *
+ * To avoid uCode errors, make sure the following are true (see comments
+ * under struct iwl4965_scan_cmd about max_out_time and quiet_time):
+ * 1) If using passive_dwell (i.e. passive_dwell != 0):
+ * active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
+ * 2) quiet_time <= active_dwell
+ * 3) If restricting off-channel time (i.e. max_out_time !=0):
+ * passive_dwell < max_out_time
+ * active_dwell < max_out_time
+ */
+struct iwl4965_scan_channel {
+ /*
+ * type is defined as:
+ * 0:0 1 = active, 0 = passive
+ * 1:4 SSID direct bit map; if a bit is set, then corresponding
+ * SSID IE is transmitted in probe request.
+ * 5:7 reserved
+ */
+ u8 type;
+ u8 channel; /* band is selected by iwl4965_scan_cmd "flags" field */
+ struct iwl4965_tx_power tpc;
+ __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */
+ __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */
+} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_ssid_ie - directed scan network information element
+ *
+ * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
+ * in struct iwl4965_scan_channel; each channel may select different ssids from
+ * among the 4 entries. SSID IEs get transmitted in reverse order of entry.
+ */
+struct iwl4965_ssid_ie {
+ u8 id;
+ u8 len;
+ u8 ssid[32];
+} __attribute__ ((packed));
+
+#define PROBE_OPTION_MAX 0x4
+#define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF)
+#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1)
+#define IWL_MAX_SCAN_SIZE 1024
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (command)
+ *
+ * The hardware scan command is very powerful; the driver can set it up to
+ * maintain (relatively) normal network traffic while doing a scan in the
+ * background. The max_out_time and suspend_time control the ratio of how
+ * long the device stays on an associated network channel ("service channel")
+ * vs. how long it's away from the service channel, i.e. tuned to other channels
+ * for scanning.
+ *
+ * max_out_time is the max time off-channel (in usec), and suspend_time
+ * is how long (in "extended beacon" format) that the scan is "suspended"
+ * after returning to the service channel. That is, suspend_time is the
+ * time that we stay on the service channel, doing normal work, between
+ * scan segments. The driver may set these parameters differently to support
+ * scanning when associated vs. not associated, and light vs. heavy traffic
+ * loads when associated.
+ *
+ * After receiving this command, the device's scan engine does the following;
+ *
+ * 1) Sends SCAN_START notification to driver
+ * 2) Checks to see if it has time to do scan for one channel
+ * 3) Sends NULL packet, with power-save (PS) bit set to 1,
+ * to tell AP that we're going off-channel
+ * 4) Tunes to first channel in scan list, does active or passive scan
+ * 5) Sends SCAN_RESULT notification to driver
+ * 6) Checks to see if it has time to do scan on *next* channel in list
+ * 7) Repeats 4-6 until it no longer has time to scan the next channel
+ * before max_out_time expires
+ * 8) Returns to service channel
+ * 9) Sends NULL packet with PS=0 to tell AP that we're back
+ * 10) Stays on service channel until suspend_time expires
+ * 11) Repeats entire process 2-10 until list is complete
+ * 12) Sends SCAN_COMPLETE notification
+ *
+ * For fast, efficient scans, the scan command also has support for staying on
+ * a channel for just a short time, if doing active scanning and getting no
+ * responses to the transmitted probe request. This time is controlled by
+ * quiet_time, and the number of received packets below which a channel is
+ * considered "quiet" is controlled by quiet_plcp_threshold.
+ *
+ * For active scanning on channels that have regulatory restrictions against
+ * blindly transmitting, the scan can listen before transmitting, to make sure
+ * that there is already legitimate activity on the channel. If enough
+ * packets are cleanly received on the channel (controlled by good_CRC_th,
+ * typical value 1), the scan engine starts transmitting probe requests.
+ *
+ * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
+ *
+ * To avoid uCode errors, see timing restrictions described under
+ * struct iwl4965_scan_channel.
+ */
+struct iwl4965_scan_cmd {
+ __le16 len;
+ u8 reserved0;
+ u8 channel_count; /* # channels in channel list */
+ __le16 quiet_time; /* dwell only this # millisecs on quiet channel
+ * (only for active scan) */
+ __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */
+ __le16 good_CRC_th; /* passive -> active promotion threshold */
+ __le16 rx_chain; /* RXON_RX_CHAIN_* */
+ __le32 max_out_time; /* max usec to be away from associated (service)
+ * channel */
+ __le32 suspend_time; /* pause scan this long (in "extended beacon
+ * format") when returning to service chnl:
+ * 3945; 31:24 # beacons, 19:0 additional usec,
+ * 4965; 31:22 # beacons, 21:0 additional usec.
+ */
+ __le32 flags; /* RXON_FLG_* */
+ __le32 filter_flags; /* RXON_FILTER_* */
+
+ /* For active scans (set to all-0s for passive scans).
+ * Does not include payload. Must specify Tx rate; no rate scaling. */
+ struct iwl4965_tx_cmd tx_cmd;
+
+ /* For directed active scans (set to all-0s otherwise) */
+ struct iwl4965_ssid_ie direct_scan[PROBE_OPTION_MAX];
+
+ /*
+ * Probe request frame, followed by channel list.
+ *
+ * Size of probe request frame is specified by byte count in tx_cmd.
+ * Channel list follows immediately after probe request frame.
+ * Number of channels in list is specified by channel_count.
+ * Each channel in list is of type:
+ *
+ * struct iwl4965_scan_channel channels[0];
+ *
+ * NOTE: Only one band of channels can be scanned per pass. You
+ * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+ * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+ * before requesting another scan.
+ */
+ u8 data[0];
+} __attribute__ ((packed));
+
+/* Can abort will notify by complete notification with abort status. */
+#define CAN_ABORT_STATUS __constant_cpu_to_le32(0x1)
+/* complete notification statuses */
+#define ABORT_STATUS 0x2
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (response)
+ */
+struct iwl4965_scanreq_notification {
+ __le32 status; /* 1: okay, 2: cannot fulfill request */
+} __attribute__ ((packed));
+
+/*
+ * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
+ */
+struct iwl4965_scanstart_notification {
+ __le32 tsf_low;
+ __le32 tsf_high;
+ __le32 beacon_timer;
+ u8 channel;
+ u8 band;
+ u8 reserved[2];
+ __le32 status;
+} __attribute__ ((packed));
+
+#define SCAN_OWNER_STATUS 0x1;
+#define MEASURE_OWNER_STATUS 0x2;
+
+#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */
+/*
+ * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
+ */
+struct iwl4965_scanresults_notification {
+ u8 channel;
+ u8 band;
+ u8 reserved[2];
+ __le32 tsf_low;
+ __le32 tsf_high;
+ __le32 statistics[NUMBER_OF_STATISTICS];
+} __attribute__ ((packed));
+
+/*
+ * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
+ */
+struct iwl4965_scancomplete_notification {
+ u8 scanned_channels;
+ u8 status;
+ u8 reserved;
+ u8 last_channel;
+ __le32 tsf_low;
+ __le32 tsf_high;
+} __attribute__ ((packed));
+
+
+/******************************************************************************
+ * (9)
+ * IBSS/AP Commands and Notifications:
+ *
+ *****************************************************************************/
+
+/*
+ * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
+ */
+struct iwl4965_beacon_notif {
+ struct iwl4965_tx_resp beacon_notify_hdr;
+ __le32 low_tsf;
+ __le32 high_tsf;
+ __le32 ibss_mgr_status;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
+ */
+struct iwl4965_tx_beacon_cmd {
+ struct iwl4965_tx_cmd tx;
+ __le16 tim_idx;
+ u8 tim_size;
+ u8 reserved1;
+ struct ieee80211_hdr frame[0]; /* beacon frame */
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (10)
+ * Statistics Commands and Notifications:
+ *
+ *****************************************************************************/
+
+#define IWL_TEMP_CONVERT 260
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
+
+/* Used for passing to driver number of successes and failures per rate */
+struct rate_histogram {
+ union {
+ __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } success;
+ union {
+ __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+ __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+ __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+ } failed;
+} __attribute__ ((packed));
+
+/* statistics command response */
+
+struct statistics_rx_phy {
+ __le32 ina_cnt;
+ __le32 fina_cnt;
+ __le32 plcp_err;
+ __le32 crc32_err;
+ __le32 overrun_err;
+ __le32 early_overrun_err;
+ __le32 crc32_good;
+ __le32 false_alarm_cnt;
+ __le32 fina_sync_err_cnt;
+ __le32 sfd_timeout;
+ __le32 fina_timeout;
+ __le32 unresponded_rts;
+ __le32 rxe_frame_limit_overrun;
+ __le32 sent_ack_cnt;
+ __le32 sent_cts_cnt;
+ __le32 sent_ba_rsp_cnt;
+ __le32 dsp_self_kill;
+ __le32 mh_format_err;
+ __le32 re_acq_main_rssi_sum;
+ __le32 reserved3;
+} __attribute__ ((packed));
+
+struct statistics_rx_ht_phy {
+ __le32 plcp_err;
+ __le32 overrun_err;
+ __le32 early_overrun_err;
+ __le32 crc32_good;
+ __le32 crc32_err;
+ __le32 mh_format_err;
+ __le32 agg_crc32_good;
+ __le32 agg_mpdu_cnt;
+ __le32 agg_cnt;
+ __le32 reserved2;
+} __attribute__ ((packed));
+
+struct statistics_rx_non_phy {
+ __le32 bogus_cts; /* CTS received when not expecting CTS */
+ __le32 bogus_ack; /* ACK received when not expecting ACK */
+ __le32 non_bssid_frames; /* number of frames with BSSID that
+ * doesn't belong to the STA BSSID */
+ __le32 filtered_frames; /* count frames that were dumped in the
+ * filtering process */
+ __le32 non_channel_beacons; /* beacons with our bss id but not on
+ * our serving channel */
+ __le32 channel_beacons; /* beacons with our bss id and in our
+ * serving channel */
+ __le32 num_missed_bcon; /* number of missed beacons */
+ __le32 adc_rx_saturation_time; /* count in 0.8us units the time the
+ * ADC was in saturation */
+ __le32 ina_detection_search_time;/* total time (in 0.8us) searched
+ * for INA */
+ __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */
+ __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */
+ __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */
+ __le32 interference_data_flag; /* flag for interference data
+ * availability. 1 when data is
+ * available. */
+ __le32 channel_load; /* counts RX Enable time in uSec */
+ __le32 dsp_false_alarms; /* DSP false alarm (both OFDM
+ * and CCK) counter */
+ __le32 beacon_rssi_a;
+ __le32 beacon_rssi_b;
+ __le32 beacon_rssi_c;
+ __le32 beacon_energy_a;
+ __le32 beacon_energy_b;
+ __le32 beacon_energy_c;
+} __attribute__ ((packed));
+
+struct statistics_rx {
+ struct statistics_rx_phy ofdm;
+ struct statistics_rx_phy cck;
+ struct statistics_rx_non_phy general;
+ struct statistics_rx_ht_phy ofdm_ht;
+} __attribute__ ((packed));
+
+struct statistics_tx_non_phy_agg {
+ __le32 ba_timeout;
+ __le32 ba_reschedule_frames;
+ __le32 scd_query_agg_frame_cnt;
+ __le32 scd_query_no_agg;
+ __le32 scd_query_agg;
+ __le32 scd_query_mismatch;
+ __le32 frame_not_ready;
+ __le32 underrun;
+ __le32 bt_prio_kill;
+ __le32 rx_ba_rsp_cnt;
+ __le32 reserved2;
+ __le32 reserved3;
+} __attribute__ ((packed));
+
+struct statistics_tx {
+ __le32 preamble_cnt;
+ __le32 rx_detected_cnt;
+ __le32 bt_prio_defer_cnt;
+ __le32 bt_prio_kill_cnt;
+ __le32 few_bytes_cnt;
+ __le32 cts_timeout;
+ __le32 ack_timeout;
+ __le32 expected_ack_cnt;
+ __le32 actual_ack_cnt;
+ __le32 dump_msdu_cnt;
+ __le32 burst_abort_next_frame_mismatch_cnt;
+ __le32 burst_abort_missing_next_frame_cnt;
+ __le32 cts_timeout_collision;
+ __le32 ack_or_ba_timeout_collision;
+ struct statistics_tx_non_phy_agg agg;
+} __attribute__ ((packed));
+
+struct statistics_dbg {
+ __le32 burst_check;
+ __le32 burst_count;
+ __le32 reserved[4];
+} __attribute__ ((packed));
+
+struct statistics_div {
+ __le32 tx_on_a;
+ __le32 tx_on_b;
+ __le32 exec_time;
+ __le32 probe_time;
+ __le32 reserved1;
+ __le32 reserved2;
+} __attribute__ ((packed));
+
+struct statistics_general {
+ __le32 temperature;
+ __le32 temperature_m;
+ struct statistics_dbg dbg;
+ __le32 sleep_time;
+ __le32 slots_out;
+ __le32 slots_idle;
+ __le32 ttl_timestamp;
+ struct statistics_div div;
+ __le32 rx_enable_counter;
+ __le32 reserved1;
+ __le32 reserved2;
+ __le32 reserved3;
+} __attribute__ ((packed));
+
+/*
+ * REPLY_STATISTICS_CMD = 0x9c,
+ * 3945 and 4965 identical.
+ *
+ * This command triggers an immediate response containing uCode statistics.
+ * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
+ *
+ * If the CLEAR_STATS configuration flag is set, uCode will clear its
+ * internal copy of the statistics (counters) after issuing the response.
+ * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
+ *
+ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
+ * STATISTICS_NOTIFICATIONs after received beacons (see below). This flag
+ * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
+ */
+#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
+#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
+struct iwl4965_statistics_cmd {
+ __le32 configuration_flags; /* IWL_STATS_CONF_* */
+} __attribute__ ((packed));
+
+/*
+ * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
+ *
+ * By default, uCode issues this notification after receiving a beacon
+ * while associated. To disable this behavior, set DISABLE_NOTIF flag in the
+ * REPLY_STATISTICS_CMD 0x9c, above.
+ *
+ * Statistics counters continue to increment beacon after beacon, but are
+ * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
+ * 0x9c with CLEAR_STATS bit set (see above).
+ *
+ * uCode also issues this notification during scans. uCode clears statistics
+ * appropriately so that each notification contains statistics for only the
+ * one channel that has just been scanned.
+ */
+#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
+#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
+struct iwl4965_notif_statistics {
+ __le32 flag;
+ struct statistics_rx rx;
+ struct statistics_tx tx;
+ struct statistics_general general;
+} __attribute__ ((packed));
+
+
+/*
+ * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
+ */
+/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row,
+ * then this notification will be sent. */
+#define CONSECUTIVE_MISSED_BCONS_TH 20
+
+struct iwl4965_missed_beacon_notif {
+ __le32 consequtive_missed_beacons;
+ __le32 total_missed_becons;
+ __le32 num_expected_beacons;
+ __le32 num_recvd_beacons;
+} __attribute__ ((packed));
+
+
+/******************************************************************************
+ * (11)
+ * Rx Calibration Commands:
+ *
+ * With the uCode used for open source drivers, most Tx calibration (except
+ * for Tx Power) and most Rx calibration is done by uCode during the
+ * "initialize" phase of uCode boot. Driver must calibrate only:
+ *
+ * 1) Tx power (depends on temperature), described elsewhere
+ * 2) Receiver gain balance (optimize MIMO, and detect disconnected antennas)
+ * 3) Receiver sensitivity (to optimize signal detection)
+ *
+ *****************************************************************************/
+
+/**
+ * SENSITIVITY_CMD = 0xa8 (command, has simple generic response)
+ *
+ * This command sets up the Rx signal detector for a sensitivity level that
+ * is high enough to lock onto all signals within the associated network,
+ * but low enough to ignore signals that are below a certain threshold, so as
+ * not to have too many "false alarms". False alarms are signals that the
+ * Rx DSP tries to lock onto, but then discards after determining that they
+ * are noise.
+ *
+ * The optimum number of false alarms is between 5 and 50 per 200 TUs
+ * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e.
+ * time listening, not transmitting). Driver must adjust sensitivity so that
+ * the ratio of actual false alarms to actual Rx time falls within this range.
+ *
+ * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each
+ * received beacon. These provide information to the driver to analyze the
+ * sensitivity. Don't analyze statistics that come in from scanning, or any
+ * other non-associated-network source. Pertinent statistics include:
+ *
+ * From "general" statistics (struct statistics_rx_non_phy):
+ *
+ * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level)
+ * Measure of energy of desired signal. Used for establishing a level
+ * below which the device does not detect signals.
+ *
+ * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB)
+ * Measure of background noise in silent period after beacon.
+ *
+ * channel_load
+ * uSecs of actual Rx time during beacon period (varies according to
+ * how much time was spent transmitting).
+ *
+ * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately:
+ *
+ * false_alarm_cnt
+ * Signal locks abandoned early (before phy-level header).
+ *
+ * plcp_err
+ * Signal locks abandoned late (during phy-level header).
+ *
+ * NOTE: Both false_alarm_cnt and plcp_err increment monotonically from
+ * beacon to beacon, i.e. each value is an accumulation of all errors
+ * before and including the latest beacon. Values will wrap around to 0
+ * after counting up to 2^32 - 1. Driver must differentiate vs.
+ * previous beacon's values to determine # false alarms in the current
+ * beacon period.
+ *
+ * Total number of false alarms = false_alarms + plcp_errs
+ *
+ * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for OFDM are at or close to settings for
+ * maximum sensitivity):
+ *
+ * START / MIN / MAX
+ * HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX 90 / 85 / 120
+ * HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX 170 / 170 / 210
+ * HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX 105 / 105 / 140
+ * HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX 220 / 220 / 270
+ *
+ * If actual rate of OFDM false alarms (+ plcp_errors) is too high
+ * (greater than 50 for each 204.8 msecs listening), reduce sensitivity
+ * by *adding* 1 to all 4 of the table entries above, up to the max for
+ * each entry. Conversely, if false alarm rate is too low (less than 5
+ * for each 204.8 msecs listening), *subtract* 1 from each entry to
+ * increase sensitivity.
+ *
+ * For CCK sensitivity, keep track of the following:
+ *
+ * 1). 20-beacon history of maximum background noise, indicated by
+ * (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the
+ * 3 receivers. For any given beacon, the "silence reference" is
+ * the maximum of last 60 samples (20 beacons * 3 receivers).
+ *
+ * 2). 10-beacon history of strongest signal level, as indicated
+ * by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers,
+ * i.e. the strength of the signal through the best receiver at the
+ * moment. These measurements are "upside down", with lower values
+ * for stronger signals, so max energy will be *minimum* value.
+ *
+ * Then for any given beacon, the driver must determine the *weakest*
+ * of the strongest signals; this is the minimum level that needs to be
+ * successfully detected, when using the best receiver at the moment.
+ * "Max cck energy" is the maximum (higher value means lower energy!)
+ * of the last 10 minima. Once this is determined, driver must add
+ * a little margin by adding "6" to it.
+ *
+ * 3). Number of consecutive beacon periods with too few false alarms.
+ * Reset this to 0 at the first beacon period that falls within the
+ * "good" range (5 to 50 false alarms per 204.8 milliseconds rx).
+ *
+ * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for CCK are at maximum sensitivity):
+ *
+ * START / MIN / MAX
+ * HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX 125 / 125 / 200
+ * HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX 200 / 200 / 400
+ * HD_MIN_ENERGY_CCK_DET_INDEX 100 / 0 / 100
+ *
+ * If actual rate of CCK false alarms (+ plcp_errors) is too high
+ * (greater than 50 for each 204.8 msecs listening), method for reducing
+ * sensitivity is:
+ *
+ * 1) *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ * up to max 400.
+ *
+ * 2) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160,
+ * sensitivity has been reduced a significant amount; bring it up to
+ * a moderate 161. Otherwise, *add* 3, up to max 200.
+ *
+ * 3) a) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160,
+ * sensitivity has been reduced only a moderate or small amount;
+ * *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX,
+ * down to min 0. Otherwise (if gain has been significantly reduced),
+ * don't change the HD_MIN_ENERGY_CCK_DET_INDEX value.
+ *
+ * b) Save a snapshot of the "silence reference".
+ *
+ * If actual rate of CCK false alarms (+ plcp_errors) is too low
+ * (less than 5 for each 204.8 msecs listening), method for increasing
+ * sensitivity is used only if:
+ *
+ * 1a) Previous beacon did not have too many false alarms
+ * 1b) AND difference between previous "silence reference" and current
+ * "silence reference" (prev - current) is 2 or more,
+ * OR 2) 100 or more consecutive beacon periods have had rate of
+ * less than 5 false alarms per 204.8 milliseconds rx time.
+ *
+ * Method for increasing sensitivity:
+ *
+ * 1) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX,
+ * down to min 125.
+ *
+ * 2) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ * down to min 200.
+ *
+ * 3) *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100.
+ *
+ * If actual rate of CCK false alarms (+ plcp_errors) is within good range
+ * (between 5 and 50 for each 204.8 msecs listening):
+ *
+ * 1) Save a snapshot of the silence reference.
+ *
+ * 2) If previous beacon had too many CCK false alarms (+ plcp_errors),
+ * give some extra margin to energy threshold by *subtracting* 8
+ * from value in HD_MIN_ENERGY_CCK_DET_INDEX.
+ *
+ * For all cases (too few, too many, good range), make sure that the CCK
+ * detection threshold (energy) is below the energy level for robust
+ * detection over the past 10 beacon periods, the "Max cck energy".
+ * Lower values mean higher energy; this means making sure that the value
+ * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
+ *
+ * Driver should set the following entries to fixed values:
+ *
+ * HD_MIN_ENERGY_OFDM_DET_INDEX 100
+ * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190
+ * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390
+ * HD_OFDM_ENERGY_TH_IN_INDEX 62
+ */
+
+/*
+ * Table entries in SENSITIVITY_CMD (struct iwl4965_sensitivity_cmd)
+ */
+#define HD_TABLE_SIZE (11) /* number of entries */
+#define HD_MIN_ENERGY_CCK_DET_INDEX (0) /* table indexes */
+#define HD_MIN_ENERGY_OFDM_DET_INDEX (1)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX (2)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX (3)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX (4)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX (5)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX (6)
+#define HD_BARKER_CORR_TH_ADD_MIN_INDEX (7)
+#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX (8)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9)
+#define HD_OFDM_ENERGY_TH_IN_INDEX (10)
+
+/* Control field in struct iwl4965_sensitivity_cmd */
+#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0)
+#define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1)
+
+/**
+ * struct iwl4965_sensitivity_cmd
+ * @control: (1) updates working table, (0) updates default table
+ * @table: energy threshold values, use HD_* as index into table
+ *
+ * Always use "1" in "control" to update uCode's working table and DSP.
+ */
+struct iwl4965_sensitivity_cmd {
+ __le16 control; /* always use "1" */
+ __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */
+} __attribute__ ((packed));
+
+
+/**
+ * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
+ *
+ * This command sets the relative gains of 4965's 3 radio receiver chains.
+ *
+ * After the first association, driver should accumulate signal and noise
+ * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
+ * beacons from the associated network (don't collect statistics that come
+ * in from scanning, or any other non-network source).
+ *
+ * DISCONNECTED ANTENNA:
+ *
+ * Driver should determine which antennas are actually connected, by comparing
+ * average beacon signal levels for the 3 Rx chains. Accumulate (add) the
+ * following values over 20 beacons, one accumulator for each of the chains
+ * a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the strongest signal from among a/b/c. Compare the other two to the
+ * strongest. If any signal is more than 15 dB (times 20, unless you
+ * divide the accumulated values by 20) below the strongest, the driver
+ * considers that antenna to be disconnected, and should not try to use that
+ * antenna/chain for Rx or Tx. If both A and B seem to be disconnected,
+ * driver should declare the stronger one as connected, and attempt to use it
+ * (A and B are the only 2 Tx chains!).
+ *
+ *
+ * RX BALANCE:
+ *
+ * Driver should balance the 3 receivers (but just the ones that are connected
+ * to antennas, see above) for gain, by comparing the average signal levels
+ * detected during the silence after each beacon (background noise).
+ * Accumulate (add) the following values over 20 beacons, one accumulator for
+ * each of the chains a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the weakest background noise level from among a/b/c. This Rx chain
+ * will be the reference, with 0 gain adjustment. Attenuate other channels by
+ * finding noise difference:
+ *
+ * (accum_noise[i] - accum_noise[reference]) / 30
+ *
+ * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB.
+ * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the
+ * driver should limit the difference results to a range of 0-3 (0-4.5 dB),
+ * and set bit 2 to indicate "reduce gain". The value for the reference
+ * (weakest) chain should be "0".
+ *
+ * diff_gain_[abc] bit fields:
+ * 2: (1) reduce gain, (0) increase gain
+ * 1-0: amount of gain, units of 1.5 dB
+ */
+
+/* "Differential Gain" opcode used in REPLY_PHY_CALIBRATION_CMD. */
+#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
+
+struct iwl4965_calibration_cmd {
+ u8 opCode; /* PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+ u8 flags; /* not used */
+ __le16 reserved;
+ s8 diff_gain_a; /* see above */
+ s8 diff_gain_b;
+ s8 diff_gain_c;
+ u8 reserved1;
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (12)
+ * Miscellaneous Commands:
+ *
+ *****************************************************************************/
+
+/*
+ * LEDs Command & Response
+ * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
+ *
+ * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
+ * this command turns it on or off, or sets up a periodic blinking cycle.
+ */
+struct iwl4965_led_cmd {
+ __le32 interval; /* "interval" in uSec */
+ u8 id; /* 1: Activity, 2: Link, 3: Tech */
+ u8 off; /* # intervals off while blinking;
+ * "0", with >0 "on" value, turns LED on */
+ u8 on; /* # intervals on while blinking;
+ * "0", regardless of "off", turns LED off */
+ u8 reserved;
+} __attribute__ ((packed));
+
+/******************************************************************************
+ * (13)
+ * Union of all expected notifications/responses:
+ *
+ *****************************************************************************/
+
+struct iwl4965_rx_packet {
+ __le32 len;
+ struct iwl4965_cmd_header hdr;
+ union {
+ struct iwl4965_alive_resp alive_frame;
+ struct iwl4965_rx_frame rx_frame;
+ struct iwl4965_tx_resp tx_resp;
+ struct iwl4965_spectrum_notification spectrum_notif;
+ struct iwl4965_csa_notification csa_notif;
+ struct iwl4965_error_resp err_resp;
+ struct iwl4965_card_state_notif card_state_notif;
+ struct iwl4965_beacon_notif beacon_status;
+ struct iwl4965_add_sta_resp add_sta;
+ struct iwl4965_sleep_notification sleep_notif;
+ struct iwl4965_spectrum_resp spectrum;
+ struct iwl4965_notif_statistics stats;
+ struct iwl4965_compressed_ba_resp compressed_ba;
+ struct iwl4965_missed_beacon_notif missed_beacon;
+ __le32 status;
+ u8 raw[0];
+ } u;
+} __attribute__ ((packed));
+
+#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl4965_rx_frame))
+
+#endif /* __iwl4965_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-debug.h b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
new file mode 100644
index 000000000000..36696bbf170c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-debug.h
@@ -0,0 +1,152 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl4965_debug_h__
+#define __iwl4965_debug_h__
+
+#ifdef CONFIG_IWL4965_DEBUG
+extern u32 iwl4965_debug_level;
+#define IWL_DEBUG(level, fmt, args...) \
+do { if (iwl4965_debug_level & (level)) \
+ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+
+#define IWL_DEBUG_LIMIT(level, fmt, args...) \
+do { if ((iwl4965_debug_level & (level)) && net_ratelimit()) \
+ printk(KERN_ERR DRV_NAME": %c %s " fmt, \
+ in_interrupt() ? 'I' : 'U', __FUNCTION__ , ## args); } while (0)
+#else
+static inline void IWL_DEBUG(int level, const char *fmt, ...)
+{
+}
+static inline void IWL_DEBUG_LIMIT(int level, const char *fmt, ...)
+{
+}
+#endif /* CONFIG_IWL4965_DEBUG */
+
+/*
+ * To use the debug system;
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of:
+ *
+ * #define IWL_DL_xxxx VALUE
+ *
+ * shifting value to the left one bit from the previous entry. xxxx should be
+ * the name of the classification (for example, WEP)
+ *
+ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
+ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * To add your debug level to the list of levels seen when you perform
+ *
+ * % cat /proc/net/iwl/debug_level
+ *
+ * you simply need to add your entry to the iwl4965_debug_levels array.
+ *
+ * If you do not see debug_level in /proc/net/iwl then you do not have
+ * CONFIG_IWL4965_DEBUG defined in your kernel configuration
+ *
+ */
+
+#define IWL_DL_INFO (1 << 0)
+#define IWL_DL_MAC80211 (1 << 1)
+#define IWL_DL_HOST_COMMAND (1 << 2)
+#define IWL_DL_STATE (1 << 3)
+
+#define IWL_DL_RADIO (1 << 7)
+#define IWL_DL_POWER (1 << 8)
+#define IWL_DL_TEMP (1 << 9)
+
+#define IWL_DL_NOTIF (1 << 10)
+#define IWL_DL_SCAN (1 << 11)
+#define IWL_DL_ASSOC (1 << 12)
+#define IWL_DL_DROP (1 << 13)
+
+#define IWL_DL_TXPOWER (1 << 14)
+
+#define IWL_DL_AP (1 << 15)
+
+#define IWL_DL_FW (1 << 16)
+#define IWL_DL_RF_KILL (1 << 17)
+#define IWL_DL_FW_ERRORS (1 << 18)
+
+#define IWL_DL_LED (1 << 19)
+
+#define IWL_DL_RATE (1 << 20)
+
+#define IWL_DL_CALIB (1 << 21)
+#define IWL_DL_WEP (1 << 22)
+#define IWL_DL_TX (1 << 23)
+#define IWL_DL_RX (1 << 24)
+#define IWL_DL_ISR (1 << 25)
+#define IWL_DL_HT (1 << 26)
+#define IWL_DL_IO (1 << 27)
+#define IWL_DL_11H (1 << 28)
+
+#define IWL_DL_STATS (1 << 29)
+#define IWL_DL_TX_REPLY (1 << 30)
+#define IWL_DL_QOS (1 << 31)
+
+#define IWL_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a)
+#define IWL_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a)
+#define IWL_DEBUG_INFO(f, a...) IWL_DEBUG(IWL_DL_INFO, f, ## a)
+
+#define IWL_DEBUG_MAC80211(f, a...) IWL_DEBUG(IWL_DL_MAC80211, f, ## a)
+#define IWL_DEBUG_TEMP(f, a...) IWL_DEBUG(IWL_DL_TEMP, f, ## a)
+#define IWL_DEBUG_SCAN(f, a...) IWL_DEBUG(IWL_DL_SCAN, f, ## a)
+#define IWL_DEBUG_RX(f, a...) IWL_DEBUG(IWL_DL_RX, f, ## a)
+#define IWL_DEBUG_TX(f, a...) IWL_DEBUG(IWL_DL_TX, f, ## a)
+#define IWL_DEBUG_ISR(f, a...) IWL_DEBUG(IWL_DL_ISR, f, ## a)
+#define IWL_DEBUG_LED(f, a...) IWL_DEBUG(IWL_DL_LED, f, ## a)
+#define IWL_DEBUG_WEP(f, a...) IWL_DEBUG(IWL_DL_WEP, f, ## a)
+#define IWL_DEBUG_HC(f, a...) IWL_DEBUG(IWL_DL_HOST_COMMAND, f, ## a)
+#define IWL_DEBUG_CALIB(f, a...) IWL_DEBUG(IWL_DL_CALIB, f, ## a)
+#define IWL_DEBUG_FW(f, a...) IWL_DEBUG(IWL_DL_FW, f, ## a)
+#define IWL_DEBUG_RF_KILL(f, a...) IWL_DEBUG(IWL_DL_RF_KILL, f, ## a)
+#define IWL_DEBUG_DROP(f, a...) IWL_DEBUG(IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_DROP_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_AP(f, a...) IWL_DEBUG(IWL_DL_AP, f, ## a)
+#define IWL_DEBUG_TXPOWER(f, a...) IWL_DEBUG(IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_IO(f, a...) IWL_DEBUG(IWL_DL_IO, f, ## a)
+#define IWL_DEBUG_RATE(f, a...) IWL_DEBUG(IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_RATE_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_NOTIF(f, a...) IWL_DEBUG(IWL_DL_NOTIF, f, ## a)
+#define IWL_DEBUG_ASSOC(f, a...) IWL_DEBUG(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_ASSOC_LIMIT(f, a...) \
+ IWL_DEBUG_LIMIT(IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_HT(f, a...) IWL_DEBUG(IWL_DL_HT, f, ## a)
+#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
+#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
+#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
+#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
+#define IWL_DEBUG_11H(f, a...) IWL_DEBUG(IWL_DL_11H, f, ## a)
+
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index 99a19ef4c743..ff71c09ab1a7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
+ * it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
@@ -60,48 +60,618 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+/*
+ * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
+ * Use iwl-4965-commands.h for uCode API definitions.
+ * Use iwl-4965.h for driver implementation definitions.
+ */
#ifndef __iwl_4965_hw_h__
#define __iwl_4965_hw_h__
-#define IWL_RX_BUF_SIZE (4 * 1024)
-#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
+/*
+ * uCode queue management definitions ...
+ * Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4.
+ * The first queue used for block-ack aggregation is #7 (4965 only).
+ * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
+ */
+#define IWL_CMD_QUEUE_NUM 4
+#define IWL_CMD_FIFO_NUM 4
+#define IWL_BACK_QUEUE_FIRST_ID 7
+
+/* Tx rates */
+#define IWL_CCK_RATES 4
+#define IWL_OFDM_RATES 8
+#define IWL_HT_RATES 16
+#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
+
+/* Time constants */
+#define SHORT_SLOT_TIME 9
+#define LONG_SLOT_TIME 20
+
+/* RSSI to dBm */
+#define IWL_RSSI_OFFSET 44
+
+/*
+ * EEPROM related constants, enums, and structures.
+ */
+
+/*
+ * EEPROM access time values:
+ *
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
+ * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
+ * CSR_EEPROM_REG_BIT_CMD (0x2).
+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+ */
+#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
+#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
+
+/*
+ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
+ *
+ * IBSS and/or AP operation is allowed *only* on those channels with
+ * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because
+ * RADAR detection is not supported by the 4965 driver, but is a
+ * requirement for establishing a new network for legal operation on channels
+ * requiring RADAR detection or restricting ACTIVE scanning.
+ *
+ * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels.
+ * It only indicates that 20 MHz channel use is supported; FAT channel
+ * usage is indicated by a separate set of regulatory flags for each
+ * FAT channel pair.
+ *
+ * NOTE: Using a channel inappropriately will result in a uCode error!
+ */
+enum {
+ EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
+ EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
+ /* Bit 2 Reserved */
+ EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
+ EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
+ EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */
+ EEPROM_CHANNEL_NARROW = (1 << 6), /* 10 MHz channel (not used) */
+ EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
+};
+
+/* SKU Capabilities */
+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
+
+/* *regulatory* channel data format in eeprom, one for each channel.
+ * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */
+struct iwl4965_eeprom_channel {
+ u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
+ s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
+} __attribute__ ((packed));
+
+/* 4965 has two radio transmitters (and 3 radio receivers) */
+#define EEPROM_TX_POWER_TX_CHAINS (2)
+
+/* 4965 has room for up to 8 sets of txpower calibration data */
+#define EEPROM_TX_POWER_BANDS (8)
+
+/* 4965 factory calibration measures txpower gain settings for
+ * each of 3 target output levels */
+#define EEPROM_TX_POWER_MEASUREMENTS (3)
+
+/* 4965 driver does not work with txpower calibration version < 5.
+ * Look for this in calib_version member of struct iwl4965_eeprom. */
+#define EEPROM_TX_POWER_VERSION_NEW (5)
+
+
+/*
+ * 4965 factory calibration data for one txpower level, on one channel,
+ * measured on one of the 2 tx chains (radio transmitter and associated
+ * antenna). EEPROM contains:
+ *
+ * 1) Temperature (degrees Celsius) of device when measurement was made.
+ *
+ * 2) Gain table index used to achieve the target measurement power.
+ * This refers to the "well-known" gain tables (see iwl-4965-hw.h).
+ *
+ * 3) Actual measured output power, in half-dBm ("34" = 17 dBm).
+ *
+ * 4) RF power amplifier detector level measurement (not used).
+ */
+struct iwl4965_eeprom_calib_measure {
+ u8 temperature; /* Device temperature (Celsius) */
+ u8 gain_idx; /* Index into gain table */
+ u8 actual_pow; /* Measured RF output power, half-dBm */
+ s8 pa_det; /* Power amp detector level (not used) */
+} __attribute__ ((packed));
+
+
+/*
+ * 4965 measurement set for one channel. EEPROM contains:
+ *
+ * 1) Channel number measured
+ *
+ * 2) Measurements for each of 3 power levels for each of 2 radio transmitters
+ * (a.k.a. "tx chains") (6 measurements altogether)
+ */
+struct iwl4965_eeprom_calib_ch_info {
+ u8 ch_num;
+ struct iwl4965_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
+ [EEPROM_TX_POWER_MEASUREMENTS];
+} __attribute__ ((packed));
+
+/*
+ * 4965 txpower subband info.
+ *
+ * For each frequency subband, EEPROM contains the following:
+ *
+ * 1) First and last channels within range of the subband. "0" values
+ * indicate that this sample set is not being used.
+ *
+ * 2) Sample measurement sets for 2 channels close to the range endpoints.
+ */
+struct iwl4965_eeprom_calib_subband_info {
+ u8 ch_from; /* channel number of lowest channel in subband */
+ u8 ch_to; /* channel number of highest channel in subband */
+ struct iwl4965_eeprom_calib_ch_info ch1;
+ struct iwl4965_eeprom_calib_ch_info ch2;
+} __attribute__ ((packed));
+
+
+/*
+ * 4965 txpower calibration info. EEPROM contains:
+ *
+ * 1) Factory-measured saturation power levels (maximum levels at which
+ * tx power amplifier can output a signal without too much distortion).
+ * There is one level for 2.4 GHz band and one for 5 GHz band. These
+ * values apply to all channels within each of the bands.
+ *
+ * 2) Factory-measured power supply voltage level. This is assumed to be
+ * constant (i.e. same value applies to all channels/bands) while the
+ * factory measurements are being made.
+ *
+ * 3) Up to 8 sets of factory-measured txpower calibration values.
+ * These are for different frequency ranges, since txpower gain
+ * characteristics of the analog radio circuitry vary with frequency.
+ *
+ * Not all sets need to be filled with data;
+ * struct iwl4965_eeprom_calib_subband_info contains range of channels
+ * (0 if unused) for each set of data.
+ */
+struct iwl4965_eeprom_calib_info {
+ u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */
+ u8 saturation_power52; /* half-dBm */
+ s16 voltage; /* signed */
+ struct iwl4965_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
+} __attribute__ ((packed));
+
+
+/*
+ * 4965 EEPROM map
+ */
+struct iwl4965_eeprom {
+ u8 reserved0[16];
+#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
+ u16 device_id; /* abs.ofs: 16 */
+ u8 reserved1[2];
+#define EEPROM_PMC (2*0x0A) /* 2 bytes */
+ u16 pmc; /* abs.ofs: 20 */
+ u8 reserved2[20];
+#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
+ u8 mac_address[6]; /* abs.ofs: 42 */
+ u8 reserved3[58];
+#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
+ u16 board_revision; /* abs.ofs: 106 */
+ u8 reserved4[11];
+#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
+ u8 board_pba_number[9]; /* abs.ofs: 119 */
+ u8 reserved5[8];
+#define EEPROM_VERSION (2*0x44) /* 2 bytes */
+ u16 version; /* abs.ofs: 136 */
+#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
+ u8 sku_cap; /* abs.ofs: 138 */
+#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
+ u8 leds_mode; /* abs.ofs: 139 */
+#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
+ u16 oem_mode;
+#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
+ u16 wowlan_mode; /* abs.ofs: 142 */
+#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
+ u16 leds_time_interval; /* abs.ofs: 144 */
+#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
+ u8 leds_off_time; /* abs.ofs: 146 */
+#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
+ u8 leds_on_time; /* abs.ofs: 147 */
+#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
+ u8 almgor_m_version; /* abs.ofs: 148 */
+#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
+ u8 antenna_switch_type; /* abs.ofs: 149 */
+ u8 reserved6[8];
+#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */
+ u16 board_revision_4965; /* abs.ofs: 158 */
+ u8 reserved7[13];
+#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */
+ u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
+ u8 reserved8[10];
+#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
+ u8 sku_id[4]; /* abs.ofs: 192 */
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by 3945 or 4965 has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width. FAT (40 MHz)
+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
+ u16 band_1_count; /* abs.ofs: 196 */
+#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
+ struct iwl4965_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
+ u16 band_2_count; /* abs.ofs: 226 */
+#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
+ struct iwl4965_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
+ u16 band_3_count; /* abs.ofs: 254 */
+#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
+ struct iwl4965_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
+ u16 band_4_count; /* abs.ofs: 280 */
+#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
+ struct iwl4965_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
+ u16 band_5_count; /* abs.ofs: 304 */
+#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
+ struct iwl4965_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
+
+ u8 reserved10[2];
+
+
+/*
+ * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ *
+ * The channel listed is the center of the lower 20 MHz half of the channel.
+ * The overall center frequency is actually 2 channels (10 MHz) above that,
+ * and the upper half of each FAT channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of FAT channel 1 is channel 5,
+ * and the overall FAT channel width centers on channel 3.
+ *
+ * NOTE: The RXON command uses 20 MHz channel numbers to specify the
+ * control channel to which to tune. RXON also specifies whether the
+ * control channel is the upper or lower half of a FAT channel.
+ *
+ * NOTE: 4965 does not support FAT channels on 2.4 GHz.
+ */
+#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */
+ struct iwl4965_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
+ u8 reserved11[2];
+
+/*
+ * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+ */
+#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */
+ struct iwl4965_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
+ u8 reserved12[6];
+
+/*
+ * 4965 driver requires txpower calibration format version 5 or greater.
+ * Driver does not work with txpower calibration version < 5.
+ * This value is simply a 16-bit number, no major/minor versions here.
+ */
+#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */
+ u16 calib_version; /* abs.ofs: 364 */
+ u8 reserved13[2];
+ u8 reserved14[96]; /* abs.ofs: 368 */
+
+/*
+ * 4965 Txpower calibration data.
+ */
+#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */
+ struct iwl4965_eeprom_calib_info calib_info; /* abs.ofs: 464 */
+
+ u8 reserved16[140]; /* fill out to full 1024 byte block */
+
+
+} __attribute__ ((packed));
+
+#define IWL_EEPROM_IMAGE_SIZE 1024
+
+/* End of EEPROM */
+
+#include "iwl-4965-commands.h"
+
+#define PCI_LINK_CTRL 0x0F0
+#define PCI_POWER_SOURCE 0x0C8
+#define PCI_REG_WUM8 0x0E8
+#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
+
+/*=== CSR (control and status registers) ===*/
+#define CSR_BASE (0x000)
+
+#define CSR_SW_VER (CSR_BASE+0x000)
+#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
+#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
+#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
+#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
+#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
+#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
+#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+#define CSR_GP_CNTRL (CSR_BASE+0x024)
+
+/*
+ * Hardware revision info
+ * Bit fields:
+ * 31-8: Reserved
+ * 7-4: Type of device: 0x0 = 4965, 0xd = 3945
+ * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D
+ * 1-0: "Dash" value, as in A-1, etc.
+ *
+ * NOTE: Revision step affects calculation of CCK txpower for 4965.
+ */
+#define CSR_HW_REV (CSR_BASE+0x028)
+
+/* EEPROM reads */
+#define CSR_EEPROM_REG (CSR_BASE+0x02c)
+#define CSR_EEPROM_GP (CSR_BASE+0x030)
+#define CSR_GP_UCODE (CSR_BASE+0x044)
+#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
+#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
+#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
+#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
+#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
+
+/*
+ * Indicates hardware rev, to determine CCK backoff for txpower calculation.
+ * Bit fields:
+ * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step
+ */
+#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
+
+/* Hardware interface configuration bits */
+#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010)
+#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
+#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
+#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
+#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
+
+/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
+ * acknowledged (reset) by host writing "1" to flagged bits. */
+#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
+#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
+#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */
+#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
+#define CSR_INT_BIT_MAC_CLK_ACTV (1 << 26) /* NIC controller's clock toggled on/off */
+#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
+#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */
+#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */
+#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */
+#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */
+#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */
+
+#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
+ CSR_INT_BIT_HW_ERR | \
+ CSR_INT_BIT_FH_TX | \
+ CSR_INT_BIT_SW_ERR | \
+ CSR_INT_BIT_RF_KILL | \
+ CSR_INT_BIT_SW_RX | \
+ CSR_INT_BIT_WAKEUP | \
+ CSR_INT_BIT_ALIVE)
+
+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */
+#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */
+#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */
+#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */
+#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */
+#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */
+
+#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
+ CSR_FH_INT_BIT_RX_CHNL1 | \
+ CSR_FH_INT_BIT_RX_CHNL0)
+
+#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \
+ CSR_FH_INT_BIT_TX_CHNL0)
+
+
+/* RESET */
+#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
+#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
+#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
+#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
+#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
+
+/* GP (general purpose) CONTROL */
+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
+
+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
+
+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
+
+
+/* EEPROM REG */
+#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
+#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
+
+/* EEPROM GP */
+#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
+#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
+#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
+
+/* UCODE DRV GP */
+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
+#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
+
+/* GPIO */
+#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
+
+/* GI Chicken Bits */
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
+
+/*=== HBUS (Host-side Bus) ===*/
+#define HBUS_BASE (0x400)
+
+/*
+ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+ * structures, error log, event log, verifying uCode load).
+ * First write to address register, then read from or write to data register
+ * to complete the job. Once the address register is set up, accesses to
+ * data registers auto-increment the address by one dword.
+ * Bit usage for address registers (read or write):
+ * 0-31: memory address within device
+ */
+#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
+#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
+#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
+#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
+
+/*
+ * Registers for accessing device's internal peripheral registers
+ * (e.g. SCD, BSM, etc.). First write to address register,
+ * then read from or write to data register to complete the job.
+ * Bit usage for address registers (read or write):
+ * 0-15: register address (offset) within device
+ * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword)
+ */
+#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
+#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
+#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
+#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
+
+/*
+ * Per-Tx-queue write pointer (index, really!) (3945 and 4965).
+ * Driver sets this to indicate index to next TFD that driver will fill
+ * (1 past latest filled).
+ * Bit usage:
+ * 0-7: queue write index (0-255)
+ * 11-8: queue selector (0-15)
+ */
+#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
+
+#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
+
+#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
+
+#define TFD_QUEUE_SIZE_MAX (256)
+
+#define IWL_NUM_SCAN_RATES (2)
+
+#define IWL_DEFAULT_TX_RETRY 15
+
+#define RX_QUEUE_SIZE 256
+#define RX_QUEUE_MASK 255
+#define RX_QUEUE_SIZE_LOG 8
+
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+ sizeof(struct iwl4965_cmd_meta))
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+/* Size of one Rx buffer in host DRAM */
+#define IWL_RX_BUF_SIZE_4K (4 * 1024)
+#define IWL_RX_BUF_SIZE_8K (8 * 1024)
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */
+#define RTC_INST_LOWER_BOUND (0x000000)
#define KDR_RTC_INST_UPPER_BOUND (0x018000)
+
+#define RTC_DATA_LOWER_BOUND (0x800000)
#define KDR_RTC_DATA_UPPER_BOUND (0x80A000)
+
#define KDR_RTC_INST_SIZE (KDR_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
#define KDR_RTC_DATA_SIZE (KDR_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
#define IWL_MAX_INST_SIZE KDR_RTC_INST_SIZE
#define IWL_MAX_DATA_SIZE KDR_RTC_DATA_SIZE
-static inline int iwl_hw_valid_rtc_data_addr(u32 addr)
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL_MAX_BSM_SIZE BSM_SRAM_SIZE
+
+static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
{
return (addr >= RTC_DATA_LOWER_BOUND) &&
(addr < KDR_RTC_DATA_UPPER_BOUND);
}
-/********************* START TXPOWER *****************************************/
-enum {
- HT_IE_EXT_CHANNEL_NONE = 0,
- HT_IE_EXT_CHANNEL_ABOVE,
- HT_IE_EXT_CHANNEL_INVALID,
- HT_IE_EXT_CHANNEL_BELOW,
- HT_IE_EXT_CHANNEL_MAX
-};
-
-enum {
- CALIB_CH_GROUP_1 = 0,
- CALIB_CH_GROUP_2 = 1,
- CALIB_CH_GROUP_3 = 2,
- CALIB_CH_GROUP_4 = 3,
- CALIB_CH_GROUP_5 = 4,
- CALIB_CH_GROUP_MAX
-};
+/********************* START TEMPERATURE *************************************/
-/* Temperature calibration offset is 3% 0C in Kelvin */
+/**
+ * 4965 temperature calculation.
+ *
+ * The driver must calculate the device temperature before calculating
+ * a txpower setting (amplifier gain is temperature dependent). The
+ * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
+ * values used for the life of the driver, and one of which (R4) is the
+ * real-time temperature indicator.
+ *
+ * uCode provides all 4 values to the driver via the "initialize alive"
+ * notification (see struct iwl4965_init_alive_resp). After the runtime uCode
+ * image loads, uCode updates the R4 value via statistics notifications
+ * (see STATISTICS_NOTIFICATION), which occur after each received beacon
+ * when associated, or can be requested via REPLY_STATISTICS_CMD.
+ *
+ * NOTE: uCode provides the R4 value as a 23-bit signed value. Driver
+ * must sign-extend to 32 bits before applying formula below.
+ *
+ * Formula:
+ *
+ * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
+ *
+ * NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is
+ * an additional correction, which should be centered around 0 degrees
+ * Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for
+ * centering the 97/100 correction around 0 degrees K.
+ *
+ * Add 273 to Kelvin value to find degrees Celsius, for comparing current
+ * temperature with factory-measured temperatures when calculating txpower
+ * settings.
+ */
#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
#define TEMPERATURE_CALIB_A_VAL 259
+/* Limit range of calculated temperature to be between these Kelvin values */
#define IWL_TX_POWER_TEMPERATURE_MIN (263)
#define IWL_TX_POWER_TEMPERATURE_MAX (410)
@@ -109,228 +679,875 @@ enum {
(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
((t) > IWL_TX_POWER_TEMPERATURE_MAX))
-#define IWL_TX_POWER_ILLEGAL_TEMPERATURE (300)
+/********************* END TEMPERATURE ***************************************/
-#define IWL_TX_POWER_TEMPERATURE_DIFFERENCE (2)
+/********************* START TXPOWER *****************************************/
-#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
+/**
+ * 4965 txpower calculations rely on information from three sources:
+ *
+ * 1) EEPROM
+ * 2) "initialize" alive notification
+ * 3) statistics notifications
+ *
+ * EEPROM data consists of:
+ *
+ * 1) Regulatory information (max txpower and channel usage flags) is provided
+ * separately for each channel that can possibly supported by 4965.
+ * 40 MHz wide (.11n fat) channels are listed separately from 20 MHz
+ * (legacy) channels.
+ *
+ * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
+ * for locations in EEPROM.
+ *
+ * 2) Factory txpower calibration information is provided separately for
+ * sub-bands of contiguous channels. 2.4GHz has just one sub-band,
+ * but 5 GHz has several sub-bands.
+ *
+ * In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
+ *
+ * See struct iwl4965_eeprom_calib_info (and the tree of structures
+ * contained within it) for format, and struct iwl4965_eeprom for
+ * locations in EEPROM.
+ *
+ * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
+ * consists of:
+ *
+ * 1) Temperature calculation parameters.
+ *
+ * 2) Power supply voltage measurement.
+ *
+ * 3) Tx gain compensation to balance 2 transmitters for MIMO use.
+ *
+ * Statistics notifications deliver:
+ *
+ * 1) Current values for temperature param R4.
+ */
+
+/**
+ * To calculate a txpower setting for a given desired target txpower, channel,
+ * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
+ * support MIMO and transmit diversity), driver must do the following:
+ *
+ * 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
+ * Do not exceed regulatory limit; reduce target txpower if necessary.
+ *
+ * If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ * 2 transmitters will be used simultaneously; driver must reduce the
+ * regulatory limit by 3 dB (half-power) for each transmitter, so the
+ * combined total output of the 2 transmitters is within regulatory limits.
+ *
+ *
+ * 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by
+ * backoff for this bit rate*. Do not exceed (saturation - backoff[rate]);
+ * reduce target txpower if necessary.
+ *
+ * Backoff values below are in 1/2 dB units (equivalent to steps in
+ * txpower gain tables):
+ *
+ * OFDM 6 - 36 MBit: 10 steps (5 dB)
+ * OFDM 48 MBit: 15 steps (7.5 dB)
+ * OFDM 54 MBit: 17 steps (8.5 dB)
+ * OFDM 60 MBit: 20 steps (10 dB)
+ * CCK all rates: 10 steps (5 dB)
+ *
+ * Backoff values apply to saturation txpower on a per-transmitter basis;
+ * when using MIMO (2 transmitters), each transmitter uses the same
+ * saturation level provided in EEPROM, and the same backoff values;
+ * no reduction (such as with regulatory txpower limits) is required.
+ *
+ * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
+ * widths and 40 Mhz (.11n fat) channel widths; there is no separate
+ * factory measurement for fat channels.
+ *
+ * The result of this step is the final target txpower. The rest of
+ * the steps figure out the proper settings for the device to achieve
+ * that target txpower.
+ *
+ *
+ * 3) Determine (EEPROM) calibration subband for the target channel, by
+ * comparing against first and last channels in each subband
+ * (see struct iwl4965_eeprom_calib_subband_info).
+ *
+ *
+ * 4) Linearly interpolate (EEPROM) factory calibration measurement sets,
+ * referencing the 2 factory-measured (sample) channels within the subband.
+ *
+ * Interpolation is based on difference between target channel's frequency
+ * and the sample channels' frequencies. Since channel numbers are based
+ * on frequency (5 MHz between each channel number), this is equivalent
+ * to interpolating based on channel number differences.
+ *
+ * Note that the sample channels may or may not be the channels at the
+ * edges of the subband. The target channel may be "outside" of the
+ * span of the sampled channels.
+ *
+ * Driver may choose the pair (for 2 Tx chains) of measurements (see
+ * struct iwl4965_eeprom_calib_ch_info) for which the actual measured
+ * txpower comes closest to the desired txpower. Usually, though,
+ * the middle set of measurements is closest to the regulatory limits,
+ * and is therefore a good choice for all txpower calculations (this
+ * assumes that high accuracy is needed for maximizing legal txpower,
+ * while lower txpower configurations do not need as much accuracy).
+ *
+ * Driver should interpolate both members of the chosen measurement pair,
+ * i.e. for both Tx chains (radio transmitters), unless the driver knows
+ * that only one of the chains will be used (e.g. only one tx antenna
+ * connected, but this should be unusual). The rate scaling algorithm
+ * switches antennas to find best performance, so both Tx chains will
+ * be used (although only one at a time) even for non-MIMO transmissions.
+ *
+ * Driver should interpolate factory values for temperature, gain table
+ * index, and actual power. The power amplifier detector values are
+ * not used by the driver.
+ *
+ * Sanity check: If the target channel happens to be one of the sample
+ * channels, the results should agree with the sample channel's
+ * measurements!
+ *
+ *
+ * 5) Find difference between desired txpower and (interpolated)
+ * factory-measured txpower. Using (interpolated) factory gain table index
+ * (shown elsewhere) as a starting point, adjust this index lower to
+ * increase txpower, or higher to decrease txpower, until the target
+ * txpower is reached. Each step in the gain table is 1/2 dB.
+ *
+ * For example, if factory measured txpower is 16 dBm, and target txpower
+ * is 13 dBm, add 6 steps to the factory gain index to reduce txpower
+ * by 3 dB.
+ *
+ *
+ * 6) Find difference between current device temperature and (interpolated)
+ * factory-measured temperature for sub-band. Factory values are in
+ * degrees Celsius. To calculate current temperature, see comments for
+ * "4965 temperature calculation".
+ *
+ * If current temperature is higher than factory temperature, driver must
+ * increase gain (lower gain table index), and vice versa.
+ *
+ * Temperature affects gain differently for different channels:
+ *
+ * 2.4 GHz all channels: 3.5 degrees per half-dB step
+ * 5 GHz channels 34-43: 4.5 degrees per half-dB step
+ * 5 GHz channels >= 44: 4.0 degrees per half-dB step
+ *
+ * NOTE: Temperature can increase rapidly when transmitting, especially
+ * with heavy traffic at high txpowers. Driver should update
+ * temperature calculations often under these conditions to
+ * maintain strong txpower in the face of rising temperature.
+ *
+ *
+ * 7) Find difference between current power supply voltage indicator
+ * (from "initialize alive") and factory-measured power supply voltage
+ * indicator (EEPROM).
+ *
+ * If the current voltage is higher (indicator is lower) than factory
+ * voltage, gain should be reduced (gain table index increased) by:
+ *
+ * (eeprom - current) / 7
+ *
+ * If the current voltage is lower (indicator is higher) than factory
+ * voltage, gain should be increased (gain table index decreased) by:
+ *
+ * 2 * (current - eeprom) / 7
+ *
+ * If number of index steps in either direction turns out to be > 2,
+ * something is wrong ... just use 0.
+ *
+ * NOTE: Voltage compensation is independent of band/channel.
+ *
+ * NOTE: "Initialize" uCode measures current voltage, which is assumed
+ * to be constant after this initial measurement. Voltage
+ * compensation for txpower (number of steps in gain table)
+ * may be calculated once and used until the next uCode bootload.
+ *
+ *
+ * 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ * adjust txpower for each transmitter chain, so txpower is balanced
+ * between the two chains. There are 5 pairs of tx_atten[group][chain]
+ * values in "initialize alive", one pair for each of 5 channel ranges:
+ *
+ * Group 0: 5 GHz channel 34-43
+ * Group 1: 5 GHz channel 44-70
+ * Group 2: 5 GHz channel 71-124
+ * Group 3: 5 GHz channel 125-200
+ * Group 4: 2.4 GHz all channels
+ *
+ * Add the tx_atten[group][chain] value to the index for the target chain.
+ * The values are signed, but are in pairs of 0 and a non-negative number,
+ * so as to reduce gain (if necessary) of the "hotter" channel. This
+ * avoids any need to double-check for regulatory compliance after
+ * this step.
+ *
+ *
+ * 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation
+ * value to the index:
+ *
+ * Hardware rev B: 9 steps (4.5 dB)
+ * Hardware rev C: 5 steps (2.5 dB)
+ *
+ * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ * bits [3:2], 1 = B, 2 = C.
+ *
+ * NOTE: This compensation is in addition to any saturation backoff that
+ * might have been applied in an earlier step.
+ *
+ *
+ * 10) Select the gain table, based on band (2.4 vs 5 GHz).
+ *
+ * Limit the adjusted index to stay within the table!
+ *
+ *
+ * 11) Read gain table entries for DSP and radio gain, place into appropriate
+ * location(s) in command (struct iwl4965_txpowertable_cmd).
+ */
+/* Limit range of txpower output target to be between these values */
#define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */
#define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */
-/* timeout equivalent to 3 minutes */
-#define IWL_TX_POWER_TIMELIMIT_NOCALIB 1800000000
-
-#define IWL_TX_POWER_CCK_COMPENSATION (9)
-
-#define MIN_TX_GAIN_INDEX (0)
-#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9)
-#define MAX_TX_GAIN_INDEX_52GHZ (98)
-#define MIN_TX_GAIN_52GHZ (98)
-#define MAX_TX_GAIN_INDEX_24GHZ (98)
-#define MIN_TX_GAIN_24GHZ (98)
-#define MAX_TX_GAIN (0)
-#define MAX_TX_GAIN_52GHZ_EXT (-9)
+/**
+ * When MIMO is used (2 transmitters operating simultaneously), driver should
+ * limit each transmitter to deliver a max of 3 dB below the regulatory limit
+ * for the device. That is, use half power for each transmitter, so total
+ * txpower is within regulatory limits.
+ *
+ * The value "6" represents number of steps in gain table to reduce power 3 dB.
+ * Each step is 1/2 dB.
+ */
+#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
+/**
+ * CCK gain compensation.
+ *
+ * When calculating txpowers for CCK, after making sure that the target power
+ * is within regulatory and saturation limits, driver must additionally
+ * back off gain by adding these values to the gain table index.
+ *
+ * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ * bits [3:2], 1 = B, 2 = C.
+ */
+#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
+#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
+
+/*
+ * 4965 power supply voltage compensation for txpower
+ */
+#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V (7)
+
+/**
+ * Gain tables.
+ *
+ * The following tables contain pair of values for setting txpower, i.e.
+ * gain settings for the output of the device's digital signal processor (DSP),
+ * and for the analog gain structure of the transmitter.
+ *
+ * Each entry in the gain tables represents a step of 1/2 dB. Note that these
+ * are *relative* steps, not indications of absolute output power. Output
+ * power varies with temperature, voltage, and channel frequency, and also
+ * requires consideration of average power (to satisfy regulatory constraints),
+ * and peak power (to avoid distortion of the output signal).
+ *
+ * Each entry contains two values:
+ * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained
+ * linear value that multiplies the output of the digital signal processor,
+ * before being sent to the analog radio.
+ * 2) Radio gain. This sets the analog gain of the radio Tx path.
+ * It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * EEPROM contains factory calibration data for txpower. This maps actual
+ * measured txpower levels to gain settings in the "well known" tables
+ * below ("well-known" means here that both factory calibration *and* the
+ * driver work with the same table).
+ *
+ * There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table
+ * has an extension (into negative indexes), in case the driver needs to
+ * boost power setting for high device temperatures (higher than would be
+ * present during factory calibration). A 5 Ghz EEPROM index of "40"
+ * corresponds to the 49th entry in the table used by the driver.
+ */
+#define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */
+#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */
+
+/**
+ * 2.4 GHz gain table
+ *
+ * Index Dsp gain Radio gain
+ * 0 110 0x3f (highest gain)
+ * 1 104 0x3f
+ * 2 98 0x3f
+ * 3 110 0x3e
+ * 4 104 0x3e
+ * 5 98 0x3e
+ * 6 110 0x3d
+ * 7 104 0x3d
+ * 8 98 0x3d
+ * 9 110 0x3c
+ * 10 104 0x3c
+ * 11 98 0x3c
+ * 12 110 0x3b
+ * 13 104 0x3b
+ * 14 98 0x3b
+ * 15 110 0x3a
+ * 16 104 0x3a
+ * 17 98 0x3a
+ * 18 110 0x39
+ * 19 104 0x39
+ * 20 98 0x39
+ * 21 110 0x38
+ * 22 104 0x38
+ * 23 98 0x38
+ * 24 110 0x37
+ * 25 104 0x37
+ * 26 98 0x37
+ * 27 110 0x36
+ * 28 104 0x36
+ * 29 98 0x36
+ * 30 110 0x35
+ * 31 104 0x35
+ * 32 98 0x35
+ * 33 110 0x34
+ * 34 104 0x34
+ * 35 98 0x34
+ * 36 110 0x33
+ * 37 104 0x33
+ * 38 98 0x33
+ * 39 110 0x32
+ * 40 104 0x32
+ * 41 98 0x32
+ * 42 110 0x31
+ * 43 104 0x31
+ * 44 98 0x31
+ * 45 110 0x30
+ * 46 104 0x30
+ * 47 98 0x30
+ * 48 110 0x6
+ * 49 104 0x6
+ * 50 98 0x6
+ * 51 110 0x5
+ * 52 104 0x5
+ * 53 98 0x5
+ * 54 110 0x4
+ * 55 104 0x4
+ * 56 98 0x4
+ * 57 110 0x3
+ * 58 104 0x3
+ * 59 98 0x3
+ * 60 110 0x2
+ * 61 104 0x2
+ * 62 98 0x2
+ * 63 110 0x1
+ * 64 104 0x1
+ * 65 98 0x1
+ * 66 110 0x0
+ * 67 104 0x0
+ * 68 98 0x0
+ * 69 97 0
+ * 70 96 0
+ * 71 95 0
+ * 72 94 0
+ * 73 93 0
+ * 74 92 0
+ * 75 91 0
+ * 76 90 0
+ * 77 89 0
+ * 78 88 0
+ * 79 87 0
+ * 80 86 0
+ * 81 85 0
+ * 82 84 0
+ * 83 83 0
+ * 84 82 0
+ * 85 81 0
+ * 86 80 0
+ * 87 79 0
+ * 88 78 0
+ * 89 77 0
+ * 90 76 0
+ * 91 75 0
+ * 92 74 0
+ * 93 73 0
+ * 94 72 0
+ * 95 71 0
+ * 96 70 0
+ * 97 69 0
+ * 98 68 0
+ */
+
+/**
+ * 5 GHz gain table
+ *
+ * Index Dsp gain Radio gain
+ * -9 123 0x3F (highest gain)
+ * -8 117 0x3F
+ * -7 110 0x3F
+ * -6 104 0x3F
+ * -5 98 0x3F
+ * -4 110 0x3E
+ * -3 104 0x3E
+ * -2 98 0x3E
+ * -1 110 0x3D
+ * 0 104 0x3D
+ * 1 98 0x3D
+ * 2 110 0x3C
+ * 3 104 0x3C
+ * 4 98 0x3C
+ * 5 110 0x3B
+ * 6 104 0x3B
+ * 7 98 0x3B
+ * 8 110 0x3A
+ * 9 104 0x3A
+ * 10 98 0x3A
+ * 11 110 0x39
+ * 12 104 0x39
+ * 13 98 0x39
+ * 14 110 0x38
+ * 15 104 0x38
+ * 16 98 0x38
+ * 17 110 0x37
+ * 18 104 0x37
+ * 19 98 0x37
+ * 20 110 0x36
+ * 21 104 0x36
+ * 22 98 0x36
+ * 23 110 0x35
+ * 24 104 0x35
+ * 25 98 0x35
+ * 26 110 0x34
+ * 27 104 0x34
+ * 28 98 0x34
+ * 29 110 0x33
+ * 30 104 0x33
+ * 31 98 0x33
+ * 32 110 0x32
+ * 33 104 0x32
+ * 34 98 0x32
+ * 35 110 0x31
+ * 36 104 0x31
+ * 37 98 0x31
+ * 38 110 0x30
+ * 39 104 0x30
+ * 40 98 0x30
+ * 41 110 0x25
+ * 42 104 0x25
+ * 43 98 0x25
+ * 44 110 0x24
+ * 45 104 0x24
+ * 46 98 0x24
+ * 47 110 0x23
+ * 48 104 0x23
+ * 49 98 0x23
+ * 50 110 0x22
+ * 51 104 0x18
+ * 52 98 0x18
+ * 53 110 0x17
+ * 54 104 0x17
+ * 55 98 0x17
+ * 56 110 0x16
+ * 57 104 0x16
+ * 58 98 0x16
+ * 59 110 0x15
+ * 60 104 0x15
+ * 61 98 0x15
+ * 62 110 0x14
+ * 63 104 0x14
+ * 64 98 0x14
+ * 65 110 0x13
+ * 66 104 0x13
+ * 67 98 0x13
+ * 68 110 0x12
+ * 69 104 0x08
+ * 70 98 0x08
+ * 71 110 0x07
+ * 72 104 0x07
+ * 73 98 0x07
+ * 74 110 0x06
+ * 75 104 0x06
+ * 76 98 0x06
+ * 77 110 0x05
+ * 78 104 0x05
+ * 79 98 0x05
+ * 80 110 0x04
+ * 81 104 0x04
+ * 82 98 0x04
+ * 83 110 0x03
+ * 84 104 0x03
+ * 85 98 0x03
+ * 86 110 0x02
+ * 87 104 0x02
+ * 88 98 0x02
+ * 89 110 0x01
+ * 90 104 0x01
+ * 91 98 0x01
+ * 92 110 0x00
+ * 93 104 0x00
+ * 94 98 0x00
+ * 95 93 0x00
+ * 96 88 0x00
+ * 97 83 0x00
+ * 98 78 0x00
+ */
+
+
+/**
+ * Sanity checks and default values for EEPROM regulatory levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Regulatory limits refer to the maximum average txpower allowed by
+ * regulatory agencies in the geographies in which the device is meant
+ * to be operated. These limits are SKU-specific (i.e. geography-specific),
+ * and channel-specific; each channel has an individual regulatory limit
+ * listed in the EEPROM.
+ *
+ * Units are in half-dBm (i.e. "34" means 17 dBm).
+ */
#define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34)
#define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34)
#define IWL_TX_POWER_REGULATORY_MIN (0)
#define IWL_TX_POWER_REGULATORY_MAX (34)
+
+/**
+ * Sanity checks and default values for EEPROM saturation levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Saturation is the highest level that the output power amplifier can produce
+ * without significant clipping distortion. This is a "peak" power level.
+ * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
+ * require differing amounts of backoff, relative to their average power output,
+ * in order to avoid clipping distortion.
+ *
+ * Driver must make sure that it is violating neither the saturation limit,
+ * nor the regulatory limit, when calculating Tx power settings for various
+ * rates.
+ *
+ * Units are in half-dBm (i.e. "38" means 19 dBm).
+ */
#define IWL_TX_POWER_DEFAULT_SATURATION_24 (38)
#define IWL_TX_POWER_DEFAULT_SATURATION_52 (38)
#define IWL_TX_POWER_SATURATION_MIN (20)
#define IWL_TX_POWER_SATURATION_MAX (50)
-/* dv *0.4 = dt; so that 5 degrees temperature diff equals
- * 12.5 in voltage diff */
-#define IWL_TX_TEMPERATURE_UPDATE_LIMIT 9
-
-#define IWL_INVALID_CHANNEL (0xffffffff)
-#define IWL_TX_POWER_REGITRY_BIT (2)
-
-#define MIN_IWL_TX_POWER_CALIB_DUR (100)
-#define IWL_CCK_FROM_OFDM_POWER_DIFF (-5)
-#define IWL_CCK_FROM_OFDM_INDEX_DIFF (9)
-
-/* Number of entries in the gain table */
-#define POWER_GAIN_NUM_ENTRIES 78
-#define TX_POW_MAX_SESSION_NUM 5
-/* timeout equivalent to 3 minutes */
-#define TX_IWL_TIMELIMIT_NOCALIB 1800000000
-
-/* Kedron TX_CALIB_STATES */
-#define IWL_TX_CALIB_STATE_SEND_TX 0x00000001
-#define IWL_TX_CALIB_WAIT_TX_RESPONSE 0x00000002
-#define IWL_TX_CALIB_ENABLED 0x00000004
-#define IWL_TX_CALIB_XVT_ON 0x00000008
-#define IWL_TX_CALIB_TEMPERATURE_CORRECT 0x00000010
-#define IWL_TX_CALIB_WORKING_WITH_XVT 0x00000020
-#define IWL_TX_CALIB_XVT_PERIODICAL 0x00000040
-
-#define NUM_IWL_TX_CALIB_SETTINS 5 /* Number of tx correction groups */
-
-#define IWL_MIN_POWER_IN_VP_TABLE 1 /* 0.5dBm multiplied by 2 */
-#define IWL_MAX_POWER_IN_VP_TABLE 40 /* 20dBm - multiplied by 2 (because
- * entries are for each 0.5dBm) */
-#define IWL_STEP_IN_VP_TABLE 1 /* 0.5dB - multiplied by 2 */
-#define IWL_NUM_POINTS_IN_VPTABLE \
- (1 + IWL_MAX_POWER_IN_VP_TABLE - IWL_MIN_POWER_IN_VP_TABLE)
-
-#define MIN_TX_GAIN_INDEX (0)
-#define MAX_TX_GAIN_INDEX_52GHZ (98)
-#define MIN_TX_GAIN_52GHZ (98)
-#define MAX_TX_GAIN_INDEX_24GHZ (98)
-#define MIN_TX_GAIN_24GHZ (98)
-#define MAX_TX_GAIN (0)
-
-/* First and last channels of all groups */
+/**
+ * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
+ * and thermal Txpower calibration.
+ *
+ * When calculating txpower, driver must compensate for current device
+ * temperature; higher temperature requires higher gain. Driver must calculate
+ * current temperature (see "4965 temperature calculation"), then compare vs.
+ * factory calibration temperature in EEPROM; if current temperature is higher
+ * than factory temperature, driver must *increase* gain by proportions shown
+ * in table below. If current temperature is lower than factory, driver must
+ * *decrease* gain.
+ *
+ * Different frequency ranges require different compensation, as shown below.
+ */
+/* Group 0, 5.2 GHz ch 34-43: 4.5 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
+
+/* Group 1, 5.3 GHz ch 44-70: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
+
+/* Group 2, 5.5 GHz ch 71-124: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
+
+/* Group 3, 5.7 GHz ch 125-200: 4.0 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
+
+/* Group 4, 2.4 GHz all channels: 3.5 degrees per 1/2 dB. */
#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
-
-union iwl_tx_power_dual_stream {
- struct {
- u8 radio_tx_gain[2];
- u8 dsp_predis_atten[2];
- } s;
- u32 dw;
+enum {
+ CALIB_CH_GROUP_1 = 0,
+ CALIB_CH_GROUP_2 = 1,
+ CALIB_CH_GROUP_3 = 2,
+ CALIB_CH_GROUP_4 = 3,
+ CALIB_CH_GROUP_5 = 4,
+ CALIB_CH_GROUP_MAX
};
/********************* END TXPOWER *****************************************/
-/* HT flags */
-#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22)
-#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK __constant_cpu_to_le32(0x1<<22)
-
-#define RXON_FLG_HT_OPERATING_MODE_POS (23)
-
-#define RXON_FLG_HT_PROT_MSK __constant_cpu_to_le32(0x1<<23)
-#define RXON_FLG_FAT_PROT_MSK __constant_cpu_to_le32(0x2<<23)
-
-#define RXON_FLG_CHANNEL_MODE_POS (25)
-#define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3<<25)
-#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1<<25)
-#define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2<<25)
-
-#define RXON_RX_CHAIN_DRIVER_FORCE_MSK __constant_cpu_to_le16(0x1<<0)
-#define RXON_RX_CHAIN_VALID_MSK __constant_cpu_to_le16(0x7<<1)
-#define RXON_RX_CHAIN_VALID_POS (1)
-#define RXON_RX_CHAIN_FORCE_SEL_MSK __constant_cpu_to_le16(0x7<<4)
-#define RXON_RX_CHAIN_FORCE_SEL_POS (4)
-#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK __constant_cpu_to_le16(0x7<<7)
-#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7)
-#define RXON_RX_CHAIN_CNT_MSK __constant_cpu_to_le16(0x3<<10)
-#define RXON_RX_CHAIN_CNT_POS (10)
-#define RXON_RX_CHAIN_MIMO_CNT_MSK __constant_cpu_to_le16(0x3<<12)
-#define RXON_RX_CHAIN_MIMO_CNT_POS (12)
-#define RXON_RX_CHAIN_MIMO_FORCE_MSK __constant_cpu_to_le16(0x1<<14)
-#define RXON_RX_CHAIN_MIMO_FORCE_POS (14)
-
-
-#define MCS_DUP_6M_PLCP 0x20
-
-/* OFDM HT rate masks */
-/* ***************************************** */
-#define R_MCS_6M_MSK 0x1
-#define R_MCS_12M_MSK 0x2
-#define R_MCS_18M_MSK 0x4
-#define R_MCS_24M_MSK 0x8
-#define R_MCS_36M_MSK 0x10
-#define R_MCS_48M_MSK 0x20
-#define R_MCS_54M_MSK 0x40
-#define R_MCS_60M_MSK 0x80
-#define R_MCS_12M_DUAL_MSK 0x100
-#define R_MCS_24M_DUAL_MSK 0x200
-#define R_MCS_36M_DUAL_MSK 0x400
-#define R_MCS_48M_DUAL_MSK 0x800
-
-#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
-#define is_siso(tbl) (((tbl) == LQ_SISO))
-#define is_mimo(tbl) (((tbl) == LQ_MIMO))
-#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
-#define is_a_band(tbl) (((tbl) == LQ_A))
-#define is_g_and(tbl) (((tbl) == LQ_G))
-
+/****************************/
/* Flow Handler Definitions */
+/****************************/
-/**********************/
-/* Addresses */
-/**********************/
-
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
#define FH_MEM_LOWER_BOUND (0x1000)
#define FH_MEM_UPPER_BOUND (0x1EF0)
-#define IWL_FH_REGS_LOWER_BOUND (0x1000)
-#define IWL_FH_REGS_UPPER_BOUND (0x2000)
-
+/**
+ * Keep-Warm (KW) buffer base address.
+ *
+ * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
+ * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
+ * DRAM access when 4965 is Txing or Rxing. The dummy accesses prevent host
+ * from going into a power-savings mode that would cause higher DRAM latency,
+ * and possible data over/under-runs, before all Tx/Rx is complete.
+ *
+ * Driver loads IWL_FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
+ * of the buffer, which must be 4K aligned. Once this is set up, the 4965
+ * automatically invokes keep-warm accesses when normal accesses might not
+ * be sufficient to maintain fast DRAM response.
+ *
+ * Bit fields:
+ * 31-0: Keep-warm buffer physical base address [35:4], must be 4K aligned
+ */
#define IWL_FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C)
-/* CBBC Area - Circular buffers base address cache pointers table */
+
+/**
+ * TFD Circular Buffers Base (CBBC) addresses
+ *
+ * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
+ * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
+ * (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04
+ * bytes from one another. Each TFD circular buffer in DRAM must be 256-byte
+ * aligned (address bits 0-7 must be 0).
+ *
+ * Bit fields in each pointer register:
+ * 27-0: TFD CB physical base address [35:8], must be 256-byte aligned
+ */
#define FH_MEM_CBBC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_MEM_CBBC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10)
-/* queues 0 - 15 */
+
+/* Find TFD CB base pointer for given queue (range 0-15). */
#define FH_MEM_CBBC_QUEUE(x) (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
-/* RSCSR Area */
+
+/**
+ * Rx SRAM Control and Status Registers (RSCSR)
+ *
+ * These registers provide handshake between driver and 4965 for the Rx queue
+ * (this queue handles *all* command responses, notifications, Rx data, etc.
+ * sent from 4965 uCode to host driver). Unlike Tx, there is only one Rx
+ * queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can
+ * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
+ * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
+ * mapping between RBDs and RBs.
+ *
+ * Driver must allocate host DRAM memory for the following, and set the
+ * physical address of each into 4965 registers:
+ *
+ * 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
+ * entries (although any power of 2, up to 4096, is selectable by driver).
+ * Each entry (1 dword) points to a receive buffer (RB) of consistent size
+ * (typically 4K, although 8K or 16K are also selectable by driver).
+ * Driver sets up RB size and number of RBDs in the CB via Rx config
+ * register FH_MEM_RCSR_CHNL0_CONFIG_REG.
+ *
+ * Bit fields within one RBD:
+ * 27-0: Receive Buffer physical address bits [35:8], 256-byte aligned
+ *
+ * Driver sets physical address [35:8] of base of RBD circular buffer
+ * into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
+ *
+ * 2) Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
+ * (RBs) have been filled, via a "write pointer", actually the index of
+ * the RB's corresponding RBD within the circular buffer. Driver sets
+ * physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
+ *
+ * Bit fields in lower dword of Rx status buffer (upper dword not used
+ * by driver; see struct iwl4965_shared, val0):
+ * 31-12: Not used by driver
+ * 11- 0: Index of last filled Rx buffer descriptor
+ * (4965 writes, driver reads this value)
+ *
+ * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
+ * enter pointers to these RBs into contiguous RBD circular buffer entries,
+ * and update the 4965's "write" index register, FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
+ *
+ * This "write" index corresponds to the *next* RBD that the driver will make
+ * available, i.e. one RBD past the tail of the ready-to-fill RBDs within
+ * the circular buffer. This value should initially be 0 (before preparing any
+ * RBs), should be 8 after preparing the first 8 RBs (for example), and must
+ * wrap back to 0 at the end of the circular buffer (but don't wrap before
+ * "read" index has advanced past 1! See below).
+ * NOTE: 4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
+ *
+ * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
+ * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
+ * to tell the driver the index of the latest filled RBD. The driver must
+ * read this "read" index from DRAM after receiving an Rx interrupt from 4965.
+ *
+ * The driver must also internally keep track of a third index, which is the
+ * next RBD to process. When receiving an Rx interrupt, driver should process
+ * all filled but unprocessed RBs up to, but not including, the RB
+ * corresponding to the "read" index. For example, if "read" index becomes "1",
+ * driver may process the RB pointed to by RBD 0. Depending on volume of
+ * traffic, there may be many RBs to process.
+ *
+ * If read index == write index, 4965 thinks there is no room to put new data.
+ * Due to this, the maximum number of filled RBs is 255, instead of 256. To
+ * be safe, make sure that there is a gap of at least 2 RBDs between "write"
+ * and "read" indexes; that is, make sure that there are no more than 254
+ * buffers waiting to be filled.
+ */
#define FH_MEM_RSCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBC0)
#define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND)
+/**
+ * Physical base address of 8-byte Rx Status buffer.
+ * Bit fields:
+ * 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
+ */
#define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0)
+
+/**
+ * Physical base address of Rx Buffer Descriptor Circular Buffer.
+ * Bit fields:
+ * 27-0: RBD CD physical base address [35:8], must be 256-byte aligned.
+ */
#define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004)
+
+/**
+ * Rx write pointer (index, really!).
+ * Bit fields:
+ * 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1.
+ * NOTE: For 256-entry circular buffer, use only bits [7:0].
+ */
#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008)
+#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
+
-/* RCSR Area - Registers address map */
+/**
+ * Rx Config/Status Registers (RCSR)
+ * Rx Config Reg for channel 0 (only channel used)
+ *
+ * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
+ * normal operation (see bit fields).
+ *
+ * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
+ * Driver should poll FH_MEM_RSSR_RX_STATUS_REG for
+ * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
+ *
+ * Bit fields:
+ * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ * '10' operate normally
+ * 29-24: reserved
+ * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
+ * min "5" for 32 RBDs, max "12" for 4096 RBDs.
+ * 19-18: reserved
+ * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
+ * '10' 12K, '11' 16K.
+ * 15-14: reserved
+ * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
+ * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
+ * typical value 0x10 (about 1/2 msec)
+ * 3- 0: reserved
+ */
#define FH_MEM_RCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC00)
#define FH_MEM_RCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xCC0)
#define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND)
#define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0)
-/* RSSR Area - Rx shared ctrl & status registers */
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MASK (0x00000FF0) /* bit 4-11 */
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MASK (0x00001000) /* bit 12 */
+#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MASK (0x00008000) /* bit 15 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MASK (0x00030000) /* bits 16-17 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MASK (0x00F00000) /* bits 20-23 */
+#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK (0xC0000000) /* bits 30-31 */
+
+#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20)
+#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_BITSHIFT (4)
+#define RX_RB_TIMEOUT (0x10)
+
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000)
+
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K (0x00010000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000)
+
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
+
+
+/**
+ * Rx Shared Status Registers (RSSR)
+ *
+ * After stopping Rx DMA channel (writing 0 to FH_MEM_RCSR_CHNL0_CONFIG_REG),
+ * driver must poll FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
+ *
+ * Bit fields:
+ * 24: 1 = Channel 0 is idle
+ *
+ * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV contain
+ * default values that should not be altered by the driver.
+ */
#define FH_MEM_RSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC40)
#define FH_MEM_RSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
+
#define FH_MEM_RSSR_SHARED_CTRL_REG (FH_MEM_RSSR_LOWER_BOUND)
#define FH_MEM_RSSR_RX_STATUS_REG (FH_MEM_RSSR_LOWER_BOUND + 0x004)
#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV (FH_MEM_RSSR_LOWER_BOUND + 0x008)
-/* TCSR */
-#define IWL_FH_TCSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xD00)
-#define IWL_FH_TCSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xE60)
+#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
+
-#define IWL_FH_TCSR_CHNL_NUM (7)
+/**
+ * Transmit DMA Channel Control/Status Registers (TCSR)
+ *
+ * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
+ * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
+ * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
+ *
+ * To use a Tx DMA channel, driver must initialize its
+ * IWL_FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
+ *
+ * IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ * IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
+ *
+ * All other bits should be 0.
+ *
+ * Bit fields:
+ * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ * '10' operate normally
+ * 29- 4: Reserved, set to "0"
+ * 3: Enable internal DMA requests (1, normal operation), disable (0)
+ * 2- 0: Reserved, set to "0"
+ */
+#define IWL_FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00)
+#define IWL_FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
+
+/* Find Control/Status reg for given Tx DMA/FIFO channel */
#define IWL_FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
(IWL_FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
-/* TSSR Area - Tx shared status registers */
-/* TSSR */
-#define IWL_FH_TSSR_LOWER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEA0)
-#define IWL_FH_TSSR_UPPER_BOUND (IWL_FH_REGS_LOWER_BOUND + 0xEC0)
-
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG (IWL_FH_TSSR_LOWER_BOUND + 0x008)
-#define IWL_FH_TSSR_TX_STATUS_REG (IWL_FH_TSSR_LOWER_BOUND + 0x010)
-
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000)
+#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
+#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_64B (0x00000000)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_256B (0x00000800)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_512B (0x00000C00)
+#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
+#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
+#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080)
+/**
+ * Tx Shared Status Registers (TSSR)
+ *
+ * After stopping Tx DMA channel (writing 0 to
+ * IWL_FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
+ * IWL_FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
+ * (channel's buffers empty | no pending requests).
+ *
+ * Bit fields:
+ * 31-24: 1 = Channel buffers empty (channel 7:0)
+ * 23-16: 1 = No pending requests (channel 7:0)
+ */
+#define IWL_FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0)
+#define IWL_FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020)
-#define IWL_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005)
+#define IWL_FH_TSSR_TX_STATUS_REG (IWL_FH_TSSR_LOWER_BOUND + 0x010)
#define IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) \
((1 << (_chnl)) << 24)
@@ -341,147 +1558,347 @@ union iwl_tx_power_dual_stream {
(IWL_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \
IWL_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl))
-/* TCSR: tx_config register values */
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_ARC (0x00000002)
-
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
-
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
-
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
-#define IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
-
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000)
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000)
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003)
-
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001)
-
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
-#define IWL_FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
-
-/* RCSR: channel 0 rx_config register defines */
-#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MASK (0xC0000000) /* bits 30-31 */
-#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MASK (0x00F00000) /* bits 20-23 */
-#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MASK (0x00030000) /* bits 16-17 */
-#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MASK (0x00008000) /* bit 15 */
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MASK (0x00001000) /* bit 12 */
-#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MASK (0x00000FF0) /* bit 4-11 */
-
-#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT (20)
-#define FH_RCSR_RX_CONFIG_RB_SIZE_BITSHIFT (16)
-
-/* RCSR: rx_config register values */
-#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000)
-#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000)
-#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000)
-
-#define IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000)
-
-/* RCSR channel 0 config register values */
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
-#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
-
-/* RSCSR: defs used in normal mode */
-#define FH_RSCSR_CHNL0_RBDCB_WPTR_MASK (0x00000FFF) /* bits 0-11 */
+/********************* START TX SCHEDULER *************************************/
+/**
+ * 4965 Tx Scheduler
+ *
+ * The Tx Scheduler selects the next frame to be transmitted, chosing TFDs
+ * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
+ * host DRAM. It steers each frame's Tx command (which contains the frame
+ * data) into one of up to 7 prioritized Tx DMA FIFO channels within the
+ * device. A queue maps to only one (selectable by driver) Tx DMA channel,
+ * but one DMA channel may take input from several queues.
+ *
+ * Tx DMA channels have dedicated purposes. For 4965, they are used as follows:
+ *
+ * 0 -- EDCA BK (background) frames, lowest priority
+ * 1 -- EDCA BE (best effort) frames, normal priority
+ * 2 -- EDCA VI (video) frames, higher priority
+ * 3 -- EDCA VO (voice) and management frames, highest priority
+ * 4 -- Commands (e.g. RXON, etc.)
+ * 5 -- HCCA short frames
+ * 6 -- HCCA long frames
+ * 7 -- not used by driver (device-internal only)
+ *
+ * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
+ * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to
+ * support 11n aggregation via EDCA DMA channels.
+ *
+ * The driver sets up each queue to work in one of two modes:
+ *
+ * 1) Scheduler-Ack, in which the scheduler automatically supports a
+ * block-ack (BA) window of up to 64 TFDs. In this mode, each queue
+ * contains TFDs for a unique combination of Recipient Address (RA)
+ * and Traffic Identifier (TID), that is, traffic of a given
+ * Quality-Of-Service (QOS) priority, destined for a single station.
+ *
+ * In scheduler-ack mode, the scheduler keeps track of the Tx status of
+ * each frame within the BA window, including whether it's been transmitted,
+ * and whether it's been acknowledged by the receiving station. The device
+ * automatically processes block-acks received from the receiving STA,
+ * and reschedules un-acked frames to be retransmitted (successful
+ * Tx completion may end up being out-of-order).
+ *
+ * The driver must maintain the queue's Byte Count table in host DRAM
+ * (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode.
+ * This mode does not support fragmentation.
+ *
+ * 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
+ * The device may automatically retry Tx, but will retry only one frame
+ * at a time, until receiving ACK from receiving station, or reaching
+ * retry limit and giving up.
+ *
+ * The command queue (#4) must use this mode!
+ * This mode does not require use of the Byte Count table in host DRAM.
+ *
+ * Driver controls scheduler operation via 3 means:
+ * 1) Scheduler registers
+ * 2) Shared scheduler data base in internal 4956 SRAM
+ * 3) Shared data in host DRAM
+ *
+ * Initialization:
+ *
+ * When loading, driver should allocate memory for:
+ * 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs.
+ * 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory
+ * (1024 bytes for each queue).
+ *
+ * After receiving "Alive" response from uCode, driver must initialize
+ * the scheduler (especially for queue #4, the command queue, otherwise
+ * the driver can't issue commands!):
+ */
+
+/**
+ * Max Tx window size is the max number of contiguous TFDs that the scheduler
+ * can keep track of at one time when creating block-ack chains of frames.
+ * Note that "64" matches the number of ack bits in a block-ack packet.
+ * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize
+ * SCD_CONTEXT_QUEUE_OFFSET(x) values.
+ */
#define SCD_WIN_SIZE 64
#define SCD_FRAME_LIMIT 64
-/* memory mapped registers */
+/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */
#define SCD_START_OFFSET 0xa02c00
+/*
+ * 4965 tells driver SRAM address for internal scheduler structs via this reg.
+ * Value is valid only after "Alive" response from uCode.
+ */
#define SCD_SRAM_BASE_ADDR (SCD_START_OFFSET + 0x0)
+
+/*
+ * Driver may need to update queue-empty bits after changing queue's
+ * write and read pointers (indexes) during (re-)initialization (i.e. when
+ * scheduler is not tracking what's happening).
+ * Bit fields:
+ * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit
+ * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty
+ * NOTE: This register is not used by Linux driver.
+ */
#define SCD_EMPTY_BITS (SCD_START_OFFSET + 0x4)
+
+/*
+ * Physical base address of array of byte count (BC) circular buffers (CBs).
+ * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode.
+ * This register points to BC CB for queue 0, must be on 1024-byte boundary.
+ * Others are spaced by 1024 bytes.
+ * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad.
+ * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff).
+ * Bit fields:
+ * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned.
+ */
#define SCD_DRAM_BASE_ADDR (SCD_START_OFFSET + 0x10)
-#define SCD_AIT (SCD_START_OFFSET + 0x18)
+
+/*
+ * Enables any/all Tx DMA/FIFO channels.
+ * Scheduler generates requests for only the active channels.
+ * Set this to 0xff to enable all 8 channels (normal usage).
+ * Bit fields:
+ * 7- 0: Enable (1), disable (0), one bit for each channel 0-7
+ */
#define SCD_TXFACT (SCD_START_OFFSET + 0x1c)
+
+/* Mask to enable contiguous Tx DMA/FIFO channels between "lo" and "hi". */
+#define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \
+ ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+/*
+ * Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
+ * Initialized and updated by driver as new TFDs are added to queue.
+ * NOTE: If using Block Ack, index must correspond to frame's
+ * Start Sequence Number; index = (SSN & 0xff)
+ * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses?
+ */
#define SCD_QUEUE_WRPTR(x) (SCD_START_OFFSET + 0x24 + (x) * 4)
-#define SCD_QUEUE_RDPTR(x) (SCD_START_OFFSET + 0x64 + (x) * 4)
-#define SCD_SETQUEUENUM (SCD_START_OFFSET + 0xa4)
-#define SCD_SET_TXSTAT_TXED (SCD_START_OFFSET + 0xa8)
-#define SCD_SET_TXSTAT_DONE (SCD_START_OFFSET + 0xac)
-#define SCD_SET_TXSTAT_NOT_SCHD (SCD_START_OFFSET + 0xb0)
-#define SCD_DECREASE_CREDIT (SCD_START_OFFSET + 0xb4)
-#define SCD_DECREASE_SCREDIT (SCD_START_OFFSET + 0xb8)
-#define SCD_LOAD_CREDIT (SCD_START_OFFSET + 0xbc)
-#define SCD_LOAD_SCREDIT (SCD_START_OFFSET + 0xc0)
-#define SCD_BAR (SCD_START_OFFSET + 0xc4)
-#define SCD_BAR_DW0 (SCD_START_OFFSET + 0xc8)
-#define SCD_BAR_DW1 (SCD_START_OFFSET + 0xcc)
-#define SCD_QUEUECHAIN_SEL (SCD_START_OFFSET + 0xd0)
-#define SCD_QUERY_REQ (SCD_START_OFFSET + 0xd8)
-#define SCD_QUERY_RES (SCD_START_OFFSET + 0xdc)
-#define SCD_PENDING_FRAMES (SCD_START_OFFSET + 0xe0)
-#define SCD_INTERRUPT_MASK (SCD_START_OFFSET + 0xe4)
-#define SCD_INTERRUPT_THRESHOLD (SCD_START_OFFSET + 0xe8)
-#define SCD_QUERY_MIN_FRAME_SIZE (SCD_START_OFFSET + 0x100)
-#define SCD_QUEUE_STATUS_BITS(x) (SCD_START_OFFSET + 0x104 + (x) * 4)
-/* SRAM structures */
-#define SCD_CONTEXT_DATA_OFFSET 0x380
-#define SCD_TX_STTS_BITMAP_OFFSET 0x400
-#define SCD_TRANSLATE_TBL_OFFSET 0x500
-#define SCD_CONTEXT_QUEUE_OFFSET(x) (SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
-#define SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
- ((SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
+/*
+ * Queue (x) Read Pointers (indexes, really!), one for each Tx queue.
+ * For FIFO mode, index indicates next frame to transmit.
+ * For Scheduler-ACK mode, index indicates first frame in Tx window.
+ * Initialized by driver, updated by scheduler.
+ */
+#define SCD_QUEUE_RDPTR(x) (SCD_START_OFFSET + 0x64 + (x) * 4)
-#define SCD_TXFACT_REG_TXFIFO_MASK(lo, hi) \
- ((1<<(hi))|((1<<(hi))-(1<<(lo))))
+/*
+ * Select which queues work in chain mode (1) vs. not (0).
+ * Use chain mode to build chains of aggregated frames.
+ * Bit fields:
+ * 31-16: Reserved
+ * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time
+ * NOTE: If driver sets up queue for chain mode, it should be also set up
+ * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x).
+ */
+#define SCD_QUEUECHAIN_SEL (SCD_START_OFFSET + 0xd0)
+/*
+ * Select which queues interrupt driver when scheduler increments
+ * a queue's read pointer (index).
+ * Bit fields:
+ * 31-16: Reserved
+ * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled
+ * NOTE: This functionality is apparently a no-op; driver relies on interrupts
+ * from Rx queue to read Tx command responses and update Tx queues.
+ */
+#define SCD_INTERRUPT_MASK (SCD_START_OFFSET + 0xe4)
-#define SCD_MODE_REG_BIT_SEARCH_MODE (1<<0)
-#define SCD_MODE_REG_BIT_SBYP_MODE (1<<1)
+/*
+ * Queue search status registers. One for each queue.
+ * Sets up queue mode and assigns queue to Tx DMA channel.
+ * Bit fields:
+ * 19-10: Write mask/enable bits for bits 0-9
+ * 9: Driver should init to "0"
+ * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0).
+ * Driver should init to "1" for aggregation mode, or "0" otherwise.
+ * 7-6: Driver should init to "0"
+ * 5: Window Size Left; indicates whether scheduler can request
+ * another TFD, based on window size, etc. Driver should init
+ * this bit to "1" for aggregation mode, or "0" for non-agg.
+ * 4-1: Tx FIFO to use (range 0-7).
+ * 0: Queue is active (1), not active (0).
+ * Other bits should be written as "0"
+ *
+ * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled
+ * via SCD_QUEUECHAIN_SEL.
+ */
+#define SCD_QUEUE_STATUS_BITS(x) (SCD_START_OFFSET + 0x104 + (x) * 4)
-#define SCD_TXFIFO_POS_TID (0)
-#define SCD_TXFIFO_POS_RA (4)
+/* Bit field positions */
#define SCD_QUEUE_STTS_REG_POS_ACTIVE (0)
#define SCD_QUEUE_STTS_REG_POS_TXF (1)
#define SCD_QUEUE_STTS_REG_POS_WSL (5)
#define SCD_QUEUE_STTS_REG_POS_SCD_ACK (8)
+
+/* Write masks */
#define SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10)
#define SCD_QUEUE_STTS_REG_MSK (0x0007FC00)
-#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
+/**
+ * 4965 internal SRAM structures for scheduler, shared with driver ...
+ *
+ * Driver should clear and initialize the following areas after receiving
+ * "Alive" response from 4965 uCode, i.e. after initial
+ * uCode load, or after a uCode load done for error recovery:
+ *
+ * SCD_CONTEXT_DATA_OFFSET (size 128 bytes)
+ * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes)
+ * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes)
+ *
+ * Driver accesses SRAM via HBUS_TARG_MEM_* registers.
+ * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR.
+ * All OFFSET values must be added to this base address.
+ */
+
+/*
+ * Queue context. One 8-byte entry for each of 16 queues.
+ *
+ * Driver should clear this entire area (size 0x80) to 0 after receiving
+ * "Alive" notification from uCode. Additionally, driver should init
+ * each queue's entry as follows:
+ *
+ * LS Dword bit fields:
+ * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64.
+ *
+ * MS Dword bit fields:
+ * 16-22: Frame limit. Driver should init to 10 (0xa).
+ *
+ * Driver should init all other bits to 0.
+ *
+ * Init must be done after driver receives "Alive" response from 4965 uCode,
+ * and when setting up queue for aggregation.
+ */
+#define SCD_CONTEXT_DATA_OFFSET 0x380
+#define SCD_CONTEXT_QUEUE_OFFSET(x) (SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
#define SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0)
#define SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F)
-#define SCD_QUEUE_CTX_REG1_CREDIT_POS (8)
-#define SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00)
-#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24)
-#define SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000)
#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16)
#define SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000)
-#define CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R (0x00000010)
-#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00)
-#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100)
-#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200)
+/*
+ * Tx Status Bitmap
+ *
+ * Driver should clear this entire area (size 0x100) to 0 after receiving
+ * "Alive" notification from uCode. Area is used only by device itself;
+ * no other support (besides clearing) is required from driver.
+ */
+#define SCD_TX_STTS_BITMAP_OFFSET 0x400
-static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
+/*
+ * RAxTID to queue translation mapping.
+ *
+ * When queue is in Scheduler-ACK mode, frames placed in a that queue must be
+ * for only one combination of receiver address (RA) and traffic ID (TID), i.e.
+ * one QOS priority level destined for one station (for this wireless link,
+ * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit
+ * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK
+ * mode, the device ignores the mapping value.
+ *
+ * Bit fields, for each 16-bit map:
+ * 15-9: Reserved, set to 0
+ * 8-4: Index into device's station table for recipient station
+ * 3-0: Traffic ID (tid), range 0-15
+ *
+ * Driver should clear this entire area (size 32 bytes) to 0 after receiving
+ * "Alive" notification from uCode. To update a 16-bit map value, driver
+ * must read a dword-aligned value from device SRAM, replace the 16-bit map
+ * value of interest, and write the dword value back into device SRAM.
+ */
+#define SCD_TRANSLATE_TBL_OFFSET 0x500
+
+/* Find translation table dword to read/write for given queue */
+#define SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
+ ((SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
+
+#define SCD_TXFIFO_POS_TID (0)
+#define SCD_TXFIFO_POS_RA (4)
+#define SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF)
+
+/*********************** END TX SCHEDULER *************************************/
+
+static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags)
{
return le32_to_cpu(rate_n_flags) & 0xFF;
}
-static inline u16 iwl_hw_get_rate_n_flags(__le32 rate_n_flags)
+static inline u16 iwl4965_hw_get_rate_n_flags(__le32 rate_n_flags)
{
return le32_to_cpu(rate_n_flags) & 0xFFFF;
}
-static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u16 flags)
+static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u16 flags)
{
return cpu_to_le32(flags|(u16)rate);
}
-struct iwl_tfd_frame_data {
+
+/**
+ * Tx/Rx Queues
+ *
+ * Most communication between driver and 4965 is via queues of data buffers.
+ * For example, all commands that the driver issues to device's embedded
+ * controller (uCode) are via the command queue (one of the Tx queues). All
+ * uCode command responses/replies/notifications, including Rx frames, are
+ * conveyed from uCode to driver via the Rx queue.
+ *
+ * Most support for these queues, including handshake support, resides in
+ * structures in host DRAM, shared between the driver and the device. When
+ * allocating this memory, the driver must make sure that data written by
+ * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
+ * cache memory), so DRAM and cache are consistent, and the device can
+ * immediately see changes made by the driver.
+ *
+ * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
+ * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array
+ * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+ */
+#define IWL4965_MAX_WIN_SIZE 64
+#define IWL4965_QUEUE_SIZE 256
+#define IWL4965_NUM_FIFOS 7
+#define IWL_MAX_NUM_QUEUES 16
+
+
+/**
+ * struct iwl4965_tfd_frame_data
+ *
+ * Describes up to 2 buffers containing (contiguous) portions of a Tx frame.
+ * Each buffer must be on dword boundary.
+ * Up to 10 iwl_tfd_frame_data structures, describing up to 20 buffers,
+ * may be filled within a TFD (iwl_tfd_frame).
+ *
+ * Bit fields in tb1_addr:
+ * 31- 0: Tx buffer 1 address bits [31:0]
+ *
+ * Bit fields in val1:
+ * 31-16: Tx buffer 2 address bits [15:0]
+ * 15- 4: Tx buffer 1 length (bytes)
+ * 3- 0: Tx buffer 1 address bits [32:32]
+ *
+ * Bit fields in val2:
+ * 31-20: Tx buffer 2 length (bytes)
+ * 19- 0: Tx buffer 2 address bits [35:16]
+ */
+struct iwl4965_tfd_frame_data {
__le32 tb1_addr;
__le32 val1;
@@ -509,7 +1926,36 @@ struct iwl_tfd_frame_data {
#define IWL_tb2_len_SYM val2
} __attribute__ ((packed));
-struct iwl_tfd_frame {
+
+/**
+ * struct iwl4965_tfd_frame
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * 4965 supports up to 16 Tx queues resident in host DRAM.
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes for 4965.
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the 4965's FH_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM. These buffers collectively contain the (one) frame described
+ * by the TFD. Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM. Each buffer has max size
+ * of (4K - 4). The 4965 concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * Bit fields in the control dword (val0):
+ * 31-30: # dwords (0-3) of padding required at end of frame for 16-byte bound
+ * 29: reserved
+ * 28-24: # Transmit Buffer Descriptors in TFD
+ * 23- 0: reserved
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ */
+struct iwl4965_tfd_frame {
__le32 val0;
/* __le32 rsvd1:24; */
/* __le32 num_tbs:5; */
@@ -518,15 +1964,20 @@ struct iwl_tfd_frame {
#define IWL_num_tbs_SYM val0
/* __le32 rsvd2:1; */
/* __le32 padding:2; */
- struct iwl_tfd_frame_data pa[10];
+ struct iwl4965_tfd_frame_data pa[10];
__le32 reserved;
} __attribute__ ((packed));
-#define IWL4965_MAX_WIN_SIZE 64
-#define IWL4965_QUEUE_SIZE 256
-#define IWL4965_NUM_FIFOS 7
-#define IWL_MAX_NUM_QUEUES 16
+/**
+ * struct iwl4965_queue_byte_cnt_entry
+ *
+ * Byte Count Table Entry
+ *
+ * Bit fields:
+ * 15-12: reserved
+ * 11- 0: total to-be-transmitted byte count of frame (does not include command)
+ */
struct iwl4965_queue_byte_cnt_entry {
__le16 val;
/* __le16 byte_cnt:12; */
@@ -536,6 +1987,25 @@ struct iwl4965_queue_byte_cnt_entry {
/* __le16 rsvd:4; */
} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_sched_queue_byte_cnt_tbl
+ *
+ * Byte Count table
+ *
+ * Each Tx queue uses a byte-count table containing 320 entries:
+ * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
+ * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
+ * max Tx window is 64 TFDs).
+ *
+ * When driver sets up a new TFD, it must also enter the total byte count
+ * of the frame to be transmitted into the corresponding entry in the byte
+ * count table for the chosen Tx queue. If the TFD index is 0-63, the driver
+ * must duplicate the byte count entry in corresponding index 256-319.
+ *
+ * "dont_care" padding puts each byte count table on a 1024-byte boundary;
+ * 4965 assumes tables are separated by 1024 bytes.
+ */
struct iwl4965_sched_queue_byte_cnt_tbl {
struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL4965_QUEUE_SIZE +
IWL4965_MAX_WIN_SIZE];
@@ -544,9 +2014,31 @@ struct iwl4965_sched_queue_byte_cnt_tbl {
sizeof(__le16)];
} __attribute__ ((packed));
-/* Base physical address of iwl_shared is provided to SCD_DRAM_BASE_ADDR
- * and &iwl_shared.val0 is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG */
-struct iwl_shared {
+
+/**
+ * struct iwl4965_shared - handshake area for Tx and Rx
+ *
+ * For convenience in allocating memory, this structure combines 2 areas of
+ * DRAM which must be shared between driver and 4965. These do not need to
+ * be combined, if better allocation would result from keeping them separate:
+ *
+ * 1) The Tx byte count tables occupy 1024 bytes each (16 KBytes total for
+ * 16 queues). Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find
+ * the first of these tables. 4965 assumes tables are 1024 bytes apart.
+ *
+ * 2) The Rx status (val0 and val1) occupies only 8 bytes. Driver uses
+ * FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area.
+ * Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD)
+ * that has been filled by the 4965.
+ *
+ * Bit fields val0:
+ * 31-12: Not used
+ * 11- 0: Index of last filled Rx buffer descriptor (4965 writes, driver reads)
+ *
+ * Bit fields val1:
+ * 31- 0: Not used
+ */
+struct iwl4965_shared {
struct iwl4965_sched_queue_byte_cnt_tbl
queues_byte_cnt_tbls[IWL_MAX_NUM_QUEUES];
__le32 val0;
@@ -578,4 +2070,4 @@ struct iwl_shared {
__le32 padding2;
} __attribute__ ((packed));
-#endif /* __iwl_4965_hw_h__ */
+#endif /* __iwl4965_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-io.h b/drivers/net/wireless/iwlwifi/iwl-4965-io.h
new file mode 100644
index 000000000000..34a0b57eea0c
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-io.h
@@ -0,0 +1,431 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#ifndef __iwl4965_io_h__
+#define __iwl4965_io_h__
+
+#include <linux/io.h>
+
+#include "iwl-4965-debug.h"
+
+/*
+ * IO, register, and NIC memory access functions
+ *
+ * NOTE on naming convention and macro usage for these
+ *
+ * A single _ prefix before a an access function means that no state
+ * check or debug information is printed when that function is called.
+ *
+ * A double __ prefix before an access function means that state is checked
+ * and the current line number is printed in addition to any other debug output.
+ *
+ * The non-prefixed name is the #define that maps the caller into a
+ * #define that provides the caller's __LINE__ to the double prefix version.
+ *
+ * If you wish to call the function without any debug or state checking,
+ * you should use the single _ prefix version (as is used by dependent IO
+ * routines, for example _iwl4965_read_direct32 calls the non-check version of
+ * _iwl4965_read32.)
+ *
+ * These declarations are *extremely* useful in quickly isolating code deltas
+ * which result in misconfiguring of the hardware I/O. In combination with
+ * git-bisect and the IO debug level you can quickly determine the specific
+ * commit which breaks the IO sequence to the hardware.
+ *
+ */
+
+#define _iwl4965_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_write32(const char *f, u32 l, struct iwl4965_priv *iwl,
+ u32 ofs, u32 val)
+{
+ IWL_DEBUG_IO("write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+ _iwl4965_write32(iwl, ofs, val);
+}
+#define iwl4965_write32(iwl, ofs, val) \
+ __iwl4965_write32(__FILE__, __LINE__, iwl, ofs, val)
+#else
+#define iwl4965_write32(iwl, ofs, val) _iwl4965_write32(iwl, ofs, val)
+#endif
+
+#define _iwl4965_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
+#ifdef CONFIG_IWL4965_DEBUG
+static inline u32 __iwl4965_read32(char *f, u32 l, struct iwl4965_priv *iwl, u32 ofs)
+{
+ IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+ return _iwl4965_read32(iwl, ofs);
+}
+#define iwl4965_read32(iwl, ofs) __iwl4965_read32(__FILE__, __LINE__, iwl, ofs)
+#else
+#define iwl4965_read32(p, o) _iwl4965_read32(p, o)
+#endif
+
+static inline int _iwl4965_poll_bit(struct iwl4965_priv *priv, u32 addr,
+ u32 bits, u32 mask, int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((_iwl4965_read32(priv, addr) & mask) == (bits & mask))
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIMEDOUT;
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline int __iwl4965_poll_bit(const char *f, u32 l,
+ struct iwl4965_priv *priv, u32 addr,
+ u32 bits, u32 mask, int timeout)
+{
+ int ret = _iwl4965_poll_bit(priv, addr, bits, mask, timeout);
+ if (unlikely(ret == -ETIMEDOUT))
+ IWL_DEBUG_IO
+ ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
+ addr, bits, mask, f, l);
+ else
+ IWL_DEBUG_IO
+ ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
+ addr, bits, mask, ret, f, l);
+ return ret;
+}
+#define iwl4965_poll_bit(iwl, addr, bits, mask, timeout) \
+ __iwl4965_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
+#else
+#define iwl4965_poll_bit(p, a, b, m, t) _iwl4965_poll_bit(p, a, b, m, t)
+#endif
+
+static inline void _iwl4965_set_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+{
+ _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) | mask);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_set_bit(const char *f, u32 l,
+ struct iwl4965_priv *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl4965_read32(priv, reg) | mask;
+ IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+ _iwl4965_write32(priv, reg, val);
+}
+#define iwl4965_set_bit(p, r, m) __iwl4965_set_bit(__FILE__, __LINE__, p, r, m)
+#else
+#define iwl4965_set_bit(p, r, m) _iwl4965_set_bit(p, r, m)
+#endif
+
+static inline void _iwl4965_clear_bit(struct iwl4965_priv *priv, u32 reg, u32 mask)
+{
+ _iwl4965_write32(priv, reg, _iwl4965_read32(priv, reg) & ~mask);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_clear_bit(const char *f, u32 l,
+ struct iwl4965_priv *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl4965_read32(priv, reg) & ~mask;
+ IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+ _iwl4965_write32(priv, reg, val);
+}
+#define iwl4965_clear_bit(p, r, m) __iwl4965_clear_bit(__FILE__, __LINE__, p, r, m)
+#else
+#define iwl4965_clear_bit(p, r, m) _iwl4965_clear_bit(p, r, m)
+#endif
+
+static inline int _iwl4965_grab_nic_access(struct iwl4965_priv *priv)
+{
+ int ret;
+ u32 gp_ctl;
+
+#ifdef CONFIG_IWL4965_DEBUG
+ if (atomic_read(&priv->restrict_refcnt))
+ return 0;
+#endif
+ if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
+ test_bit(STATUS_RF_KILL_SW, &priv->status)) {
+ IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
+ "wakes up NIC\n");
+
+ /* 10 msec allows time for NIC to complete its data save */
+ gp_ctl = _iwl4965_read32(priv, CSR_GP_CNTRL);
+ if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
+ IWL_DEBUG_RF_KILL("Wait for complete power-down, "
+ "gpctl = 0x%08x\n", gp_ctl);
+ mdelay(10);
+ } else
+ IWL_DEBUG_RF_KILL("power-down complete, "
+ "gpctl = 0x%08x\n", gp_ctl);
+ }
+
+ /* this bit wakes up the NIC */
+ _iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ ret = _iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
+ if (ret < 0) {
+ IWL_ERROR("MAC is in deep sleep!\n");
+ return -EIO;
+ }
+
+#ifdef CONFIG_IWL4965_DEBUG
+ atomic_inc(&priv->restrict_refcnt);
+#endif
+ return 0;
+}
+
+#ifdef CONFIG_IWL4965_DEBUG
+static inline int __iwl4965_grab_nic_access(const char *f, u32 l,
+ struct iwl4965_priv *priv)
+{
+ if (atomic_read(&priv->restrict_refcnt))
+ IWL_DEBUG_INFO("Grabbing access while already held at "
+ "line %d.\n", l);
+
+ IWL_DEBUG_IO("grabbing nic access - %s %d\n", f, l);
+ return _iwl4965_grab_nic_access(priv);
+}
+#define iwl4965_grab_nic_access(priv) \
+ __iwl4965_grab_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl4965_grab_nic_access(priv) \
+ _iwl4965_grab_nic_access(priv)
+#endif
+
+static inline void _iwl4965_release_nic_access(struct iwl4965_priv *priv)
+{
+#ifdef CONFIG_IWL4965_DEBUG
+ if (atomic_dec_and_test(&priv->restrict_refcnt))
+#endif
+ _iwl4965_clear_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_release_nic_access(const char *f, u32 l,
+ struct iwl4965_priv *priv)
+{
+ if (atomic_read(&priv->restrict_refcnt) <= 0)
+ IWL_ERROR("Release unheld nic access at line %d.\n", l);
+
+ IWL_DEBUG_IO("releasing nic access - %s %d\n", f, l);
+ _iwl4965_release_nic_access(priv);
+}
+#define iwl4965_release_nic_access(priv) \
+ __iwl4965_release_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl4965_release_nic_access(priv) \
+ _iwl4965_release_nic_access(priv)
+#endif
+
+static inline u32 _iwl4965_read_direct32(struct iwl4965_priv *priv, u32 reg)
+{
+ return _iwl4965_read32(priv, reg);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline u32 __iwl4965_read_direct32(const char *f, u32 l,
+ struct iwl4965_priv *priv, u32 reg)
+{
+ u32 value = _iwl4965_read_direct32(priv, reg);
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from %s %d\n", f, l);
+ IWL_DEBUG_IO("read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
+ f, l);
+ return value;
+}
+#define iwl4965_read_direct32(priv, reg) \
+ __iwl4965_read_direct32(__FILE__, __LINE__, priv, reg)
+#else
+#define iwl4965_read_direct32 _iwl4965_read_direct32
+#endif
+
+static inline void _iwl4965_write_direct32(struct iwl4965_priv *priv,
+ u32 reg, u32 value)
+{
+ _iwl4965_write32(priv, reg, value);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static void __iwl4965_write_direct32(u32 line,
+ struct iwl4965_priv *priv, u32 reg, u32 value)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ _iwl4965_write_direct32(priv, reg, value);
+}
+#define iwl4965_write_direct32(priv, reg, value) \
+ __iwl4965_write_direct32(__LINE__, priv, reg, value)
+#else
+#define iwl4965_write_direct32 _iwl4965_write_direct32
+#endif
+
+static inline void iwl4965_write_reg_buf(struct iwl4965_priv *priv,
+ u32 reg, u32 len, u32 *values)
+{
+ u32 count = sizeof(u32);
+
+ if ((priv != NULL) && (values != NULL)) {
+ for (; 0 < len; len -= count, reg += count, values++)
+ _iwl4965_write_direct32(priv, reg, *values);
+ }
+}
+
+static inline int _iwl4965_poll_direct_bit(struct iwl4965_priv *priv,
+ u32 addr, u32 mask, int timeout)
+{
+ int i = 0;
+
+ do {
+ if ((_iwl4965_read_direct32(priv, addr) & mask) == mask)
+ return i;
+ mdelay(10);
+ i += 10;
+ } while (i < timeout);
+
+ return -ETIMEDOUT;
+}
+
+#ifdef CONFIG_IWL4965_DEBUG
+static inline int __iwl4965_poll_direct_bit(const char *f, u32 l,
+ struct iwl4965_priv *priv,
+ u32 addr, u32 mask, int timeout)
+{
+ int ret = _iwl4965_poll_direct_bit(priv, addr, mask, timeout);
+
+ if (unlikely(ret == -ETIMEDOUT))
+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) - "
+ "timedout - %s %d\n", addr, mask, f, l);
+ else
+ IWL_DEBUG_IO("poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+ "- %s %d\n", addr, mask, ret, f, l);
+ return ret;
+}
+#define iwl4965_poll_direct_bit(iwl, addr, mask, timeout) \
+ __iwl4965_poll_direct_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
+#else
+#define iwl4965_poll_direct_bit _iwl4965_poll_direct_bit
+#endif
+
+static inline u32 _iwl4965_read_prph(struct iwl4965_priv *priv, u32 reg)
+{
+ _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ return _iwl4965_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline u32 __iwl4965_read_prph(u32 line, struct iwl4965_priv *priv, u32 reg)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ return _iwl4965_read_prph(priv, reg);
+}
+
+#define iwl4965_read_prph(priv, reg) \
+ __iwl4965_read_prph(__LINE__, priv, reg)
+#else
+#define iwl4965_read_prph _iwl4965_read_prph
+#endif
+
+static inline void _iwl4965_write_prph(struct iwl4965_priv *priv,
+ u32 addr, u32 val)
+{
+ _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+ ((addr & 0x0000FFFF) | (3 << 24)));
+ _iwl4965_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+}
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_write_prph(u32 line, struct iwl4965_priv *priv,
+ u32 addr, u32 val)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access from line %d\n", line);
+ _iwl4965_write_prph(priv, addr, val);
+}
+
+#define iwl4965_write_prph(priv, addr, val) \
+ __iwl4965_write_prph(__LINE__, priv, addr, val);
+#else
+#define iwl4965_write_prph _iwl4965_write_prph
+#endif
+
+#define _iwl4965_set_bits_prph(priv, reg, mask) \
+ _iwl4965_write_prph(priv, reg, (_iwl4965_read_prph(priv, reg) | mask))
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_set_bits_prph(u32 line, struct iwl4965_priv *priv,
+ u32 reg, u32 mask)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+
+ _iwl4965_set_bits_prph(priv, reg, mask);
+}
+#define iwl4965_set_bits_prph(priv, reg, mask) \
+ __iwl4965_set_bits_prph(__LINE__, priv, reg, mask)
+#else
+#define iwl4965_set_bits_prph _iwl4965_set_bits_prph
+#endif
+
+#define _iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+ _iwl4965_write_prph(priv, reg, ((_iwl4965_read_prph(priv, reg) & mask) | bits))
+
+#ifdef CONFIG_IWL4965_DEBUG
+static inline void __iwl4965_set_bits_mask_prph(u32 line,
+ struct iwl4965_priv *priv, u32 reg, u32 bits, u32 mask)
+{
+ if (!atomic_read(&priv->restrict_refcnt))
+ IWL_ERROR("Nic access not held from line %d\n", line);
+ _iwl4965_set_bits_mask_prph(priv, reg, bits, mask);
+}
+#define iwl4965_set_bits_mask_prph(priv, reg, bits, mask) \
+ __iwl4965_set_bits_mask_prph(__LINE__, priv, reg, bits, mask)
+#else
+#define iwl4965_set_bits_mask_prph _iwl4965_set_bits_mask_prph
+#endif
+
+static inline void iwl4965_clear_bits_prph(struct iwl4965_priv
+ *priv, u32 reg, u32 mask)
+{
+ u32 val = _iwl4965_read_prph(priv, reg);
+ _iwl4965_write_prph(priv, reg, (val & ~mask));
+}
+
+static inline u32 iwl4965_read_targ_mem(struct iwl4965_priv *priv, u32 addr)
+{
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+ return iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+}
+
+static inline void iwl4965_write_targ_mem(struct iwl4965_priv *priv, u32 addr, u32 val)
+{
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
+}
+
+static inline void iwl4965_write_targ_mem_buf(struct iwl4965_priv *priv, u32 addr,
+ u32 len, u32 *values)
+{
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ for (; 0 < len; len -= sizeof(u32), values++)
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
+}
+#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
index 8dc78c0bf1ff..d06462264147 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c
@@ -36,11 +36,9 @@
#include <linux/workqueue.h>
-#define IWL 4965
-
#include "../net/mac80211/ieee80211_rate.h"
-#include "iwlwifi.h"
+#include "iwl-4965.h"
#include "iwl-helpers.h"
#define RS_NAME "iwl-4965-rs"
@@ -49,13 +47,12 @@
#define IWL_NUMBER_TRY 1
#define IWL_HT_NUMBER_TRY 3
-#define IWL_RATE_MAX_WINDOW 62
-#define IWL_RATE_HIGH_TH 10880
-#define IWL_RATE_MIN_FAILURE_TH 6
-#define IWL_RATE_MIN_SUCCESS_TH 8
-#define IWL_RATE_DECREASE_TH 1920
-#define IWL_RATE_INCREASE_TH 8960
-#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ) /*2 seconds */
+#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */
+#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */
+#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */
+
+/* max time to accum history 2 seconds */
+#define IWL_RATE_SCALE_FLUSH_INTVL (2*HZ)
static u8 rs_ht_to_legacy[] = {
IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
@@ -67,83 +64,109 @@ static u8 rs_ht_to_legacy[] = {
IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
};
-struct iwl_rate {
+struct iwl4965_rate {
u32 rate_n_flags;
} __attribute__ ((packed));
-struct iwl_rate_scale_data {
- u64 data;
- s32 success_counter;
- s32 success_ratio;
- s32 counter;
- s32 average_tpt;
+/**
+ * struct iwl4965_rate_scale_data -- tx success history for one rate
+ */
+struct iwl4965_rate_scale_data {
+ u64 data; /* bitmap of successful frames */
+ s32 success_counter; /* number of frames successful */
+ s32 success_ratio; /* per-cent * 128 */
+ s32 counter; /* number of frames attempted */
+ s32 average_tpt; /* success ratio * expected throughput */
unsigned long stamp;
};
-struct iwl_scale_tbl_info {
- enum iwl_table_type lq_type;
- enum iwl_antenna_type antenna_type;
- u8 is_SGI;
- u8 is_fat;
- u8 is_dup;
- u8 action;
- s32 *expected_tpt;
- struct iwl_rate current_rate;
- struct iwl_rate_scale_data win[IWL_RATE_COUNT];
+/**
+ * struct iwl4965_scale_tbl_info -- tx params and success history for all rates
+ *
+ * There are two of these in struct iwl_rate_scale_priv,
+ * one for "active", and one for "search".
+ */
+struct iwl4965_scale_tbl_info {
+ enum iwl4965_table_type lq_type;
+ enum iwl4965_antenna_type antenna_type;
+ u8 is_SGI; /* 1 = short guard interval */
+ u8 is_fat; /* 1 = 40 MHz channel width */
+ u8 is_dup; /* 1 = duplicated data streams */
+ u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
+ s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */
+ struct iwl4965_rate current_rate; /* rate_n_flags, uCode API format */
+ struct iwl4965_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */
};
-struct iwl_rate_scale_priv {
- u8 active_tbl;
- u8 enable_counter;
- u8 stay_in_tbl;
- u8 search_better_tbl;
+/**
+ * struct iwl_rate_scale_priv -- driver's rate scaling private structure
+ *
+ * Pointer to this gets passed back and forth between driver and mac80211.
+ */
+struct iwl4965_lq_sta {
+ u8 active_tbl; /* index of active table, range 0-1 */
+ u8 enable_counter; /* indicates HT mode */
+ u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */
+ u8 search_better_tbl; /* 1: currently trying alternate mode */
s32 last_tpt;
+
+ /* The following determine when to search for a new mode */
u32 table_count_limit;
- u32 max_failure_limit;
- u32 max_success_limit;
+ u32 max_failure_limit; /* # failed frames before new search */
+ u32 max_success_limit; /* # successful frames before new search */
u32 table_count;
- u32 total_failed;
- u32 total_success;
- u32 flush_timer;
- u8 action_counter;
+ u32 total_failed; /* total failed frames, any/all rates */
+ u32 total_success; /* total successful frames, any/all rates */
+ u32 flush_timer; /* time staying in mode before new search */
+
+ u8 action_counter; /* # mode-switch actions tried */
u8 antenna;
u8 valid_antenna;
u8 is_green;
u8 is_dup;
u8 phymode;
u8 ibss_sta_added;
+
+ /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
u32 supp_rates;
u16 active_rate;
u16 active_siso_rate;
u16 active_mimo_rate;
u16 active_rate_basic;
- struct iwl_link_quality_cmd lq;
- struct iwl_scale_tbl_info lq_info[LQ_SIZE];
+
+ struct iwl4965_link_quality_cmd lq;
+ struct iwl4965_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
#ifdef CONFIG_MAC80211_DEBUGFS
struct dentry *rs_sta_dbgfs_scale_table_file;
struct dentry *rs_sta_dbgfs_stats_table_file;
- struct iwl_rate dbg_fixed;
- struct iwl_priv *drv;
+ struct iwl4965_rate dbg_fixed;
+ struct iwl4965_priv *drv;
#endif
};
-static void rs_rate_scale_perform(struct iwl_priv *priv,
+static void rs_rate_scale_perform(struct iwl4965_priv *priv,
struct net_device *dev,
struct ieee80211_hdr *hdr,
struct sta_info *sta);
-static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
- struct iwl_rate *tx_mcs,
- struct iwl_link_quality_cmd *tbl);
+static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *tx_mcs,
+ struct iwl4965_link_quality_cmd *tbl);
#ifdef CONFIG_MAC80211_DEBUGFS
-static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
- struct iwl_rate *mcs, int index);
+static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *mcs, int index);
#else
-static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
- struct iwl_rate *mcs, int index)
+static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *mcs, int index)
{}
#endif
+
+/*
+ * Expected throughput metrics for following rates:
+ * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
+ * "G" is the only table that supports CCK (the first 4 rates).
+ */
static s32 expected_tpt_A[IWL_RATE_COUNT] = {
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
};
@@ -184,36 +207,34 @@ static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = {
0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
};
-static int iwl_lq_sync_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static int iwl4965_lq_sync_callback(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd, struct sk_buff *skb)
{
/*We didn't cache the SKB; let the caller free it */
return 1;
}
-static inline u8 iwl_rate_get_rate(u32 rate_n_flags)
+static inline u8 iwl4965_rate_get_rate(u32 rate_n_flags)
{
return (u8)(rate_n_flags & 0xFF);
}
-static int rs_send_lq_cmd(struct iwl_priv *priv,
- struct iwl_link_quality_cmd *lq, u8 flags)
+static int rs_send_lq_cmd(struct iwl4965_priv *priv,
+ struct iwl4965_link_quality_cmd *lq, u8 flags)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
int i;
#endif
- int rc = -1;
-
- struct iwl_host_cmd cmd = {
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_TX_LINK_QUALITY_CMD,
- .len = sizeof(struct iwl_link_quality_cmd),
+ .len = sizeof(struct iwl4965_link_quality_cmd),
.meta.flags = flags,
.data = lq,
};
if ((lq->sta_id == 0xFF) &&
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
- return rc;
+ return -EINVAL;
if (lq->sta_id == 0xFF)
lq->sta_id = IWL_AP_ID;
@@ -222,23 +243,23 @@ static int rs_send_lq_cmd(struct iwl_priv *priv,
IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
lq->general_params.single_stream_ant_msk,
lq->general_params.dual_stream_ant_msk);
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
IWL_DEBUG_RATE("lq index %d 0x%X\n",
i, lq->rs_table[i].rate_n_flags);
#endif
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_lq_sync_callback;
+ cmd.meta.u.callback = iwl4965_lq_sync_callback;
- if (iwl_is_associated(priv) && priv->assoc_station_added &&
+ if (iwl4965_is_associated(priv) && priv->assoc_station_added &&
priv->lq_mngr.lq_ready)
- rc = iwl_send_cmd(priv, &cmd);
+ return iwl4965_send_cmd(priv, &cmd);
- return rc;
+ return 0;
}
-static int rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
+static void rs_rate_scale_clear_window(struct iwl4965_rate_scale_data *window)
{
window->data = 0;
window->success_counter = 0;
@@ -246,29 +267,38 @@ static int rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
window->counter = 0;
window->average_tpt = IWL_INVALID_VALUE;
window->stamp = 0;
-
- return 0;
}
-static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
+/**
+ * rs_collect_tx_data - Update the success/failure sliding window
+ *
+ * We keep a sliding window of the last 62 packets transmitted
+ * at this rate. window->data contains the bitmask of successful
+ * packets.
+ */
+static int rs_collect_tx_data(struct iwl4965_rate_scale_data *windows,
int scale_index, s32 tpt, u32 status)
{
- int rc = 0;
- struct iwl_rate_scale_data *window = NULL;
+ struct iwl4965_rate_scale_data *window = NULL;
u64 mask;
u8 win_size = IWL_RATE_MAX_WINDOW;
s32 fail_count;
- if (scale_index < 0)
- return -1;
-
- if (scale_index >= IWL_RATE_COUNT)
- return -1;
+ if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
+ return -EINVAL;
+ /* Select data for current tx bit rate */
window = &(windows[scale_index]);
+ /*
+ * Keep track of only the latest 62 tx frame attempts in this rate's
+ * history window; anything older isn't really relevant any more.
+ * If we have filled up the sliding window, drop the oldest attempt;
+ * if the oldest attempt (highest bit in bitmap) shows "success",
+ * subtract "1" from the success counter (this is the main reason
+ * we keep these bitmaps!).
+ */
if (window->counter >= win_size) {
-
window->counter = win_size - 1;
mask = 1;
mask = (mask << (win_size - 1));
@@ -278,7 +308,11 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
}
}
+ /* Increment frames-attempted counter */
window->counter = window->counter + 1;
+
+ /* Shift bitmap by one frame (throw away oldest history),
+ * OR in "1", and increment "success" if this frame was successful. */
mask = window->data;
window->data = (mask << 1);
if (status != 0) {
@@ -286,6 +320,7 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
window->data |= 0x1;
}
+ /* Calculate current success ratio, avoid divide-by-0! */
if (window->counter > 0)
window->success_ratio = 128 * (100 * window->success_counter)
/ window->counter;
@@ -294,37 +329,40 @@ static int rs_collect_tx_data(struct iwl_rate_scale_data *windows,
fail_count = window->counter - window->success_counter;
+ /* Calculate average throughput, if we have enough history. */
if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
(window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
window->average_tpt = (window->success_ratio * tpt + 64) / 128;
else
window->average_tpt = IWL_INVALID_VALUE;
+ /* Tag this window as having been updated */
window->stamp = jiffies;
- return rc;
+ return 0;
}
-int static rs_mcs_from_tbl(struct iwl_rate *mcs_rate,
- struct iwl_scale_tbl_info *tbl,
+/*
+ * Fill uCode API rate_n_flags field, based on "search" or "active" table.
+ */
+static void rs_mcs_from_tbl(struct iwl4965_rate *mcs_rate,
+ struct iwl4965_scale_tbl_info *tbl,
int index, u8 use_green)
{
- int rc = 0;
-
if (is_legacy(tbl->lq_type)) {
- mcs_rate->rate_n_flags = iwl_rates[index].plcp;
+ mcs_rate->rate_n_flags = iwl4965_rates[index].plcp;
if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
mcs_rate->rate_n_flags |= RATE_MCS_CCK_MSK;
} else if (is_siso(tbl->lq_type)) {
if (index > IWL_LAST_OFDM_RATE)
index = IWL_LAST_OFDM_RATE;
- mcs_rate->rate_n_flags = iwl_rates[index].plcp_siso |
+ mcs_rate->rate_n_flags = iwl4965_rates[index].plcp_siso |
RATE_MCS_HT_MSK;
} else {
if (index > IWL_LAST_OFDM_RATE)
index = IWL_LAST_OFDM_RATE;
- mcs_rate->rate_n_flags = iwl_rates[index].plcp_mimo |
+ mcs_rate->rate_n_flags = iwl4965_rates[index].plcp_mimo |
RATE_MCS_HT_MSK;
}
@@ -343,7 +381,7 @@ int static rs_mcs_from_tbl(struct iwl_rate *mcs_rate,
}
if (is_legacy(tbl->lq_type))
- return rc;
+ return;
if (tbl->is_fat) {
if (tbl->is_dup)
@@ -359,27 +397,31 @@ int static rs_mcs_from_tbl(struct iwl_rate *mcs_rate,
if (is_siso(tbl->lq_type))
mcs_rate->rate_n_flags &= ~RATE_MCS_SGI_MSK;
}
- return rc;
}
-static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate,
- int phymode, struct iwl_scale_tbl_info *tbl,
+/*
+ * Interpret uCode API's rate_n_flags format,
+ * fill "search" or "active" tx mode table.
+ */
+static int rs_get_tbl_info_from_mcs(const struct iwl4965_rate *mcs_rate,
+ int phymode, struct iwl4965_scale_tbl_info *tbl,
int *rate_idx)
{
int index;
u32 ant_msk;
- index = iwl_rate_index_from_plcp(mcs_rate->rate_n_flags);
+ index = iwl4965_rate_index_from_plcp(mcs_rate->rate_n_flags);
if (index == IWL_RATE_INVALID) {
*rate_idx = -1;
- return -1;
+ return -EINVAL;
}
- tbl->is_SGI = 0;
+ tbl->is_SGI = 0; /* default legacy setup */
tbl->is_fat = 0;
tbl->is_dup = 0;
- tbl->antenna_type = ANT_BOTH;
+ tbl->antenna_type = ANT_BOTH; /* default MIMO setup */
+ /* legacy rate format */
if (!(mcs_rate->rate_n_flags & RATE_MCS_HT_MSK)) {
ant_msk = (mcs_rate->rate_n_flags & RATE_MCS_ANT_AB_MSK);
@@ -399,7 +441,8 @@ static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate,
}
*rate_idx = index;
- } else if (iwl_rate_get_rate(mcs_rate->rate_n_flags)
+ /* HT rate format, SISO (might be 20 MHz legacy or 40 MHz fat width) */
+ } else if (iwl4965_rate_get_rate(mcs_rate->rate_n_flags)
<= IWL_RATE_SISO_60M_PLCP) {
tbl->lq_type = LQ_SISO;
@@ -423,6 +466,8 @@ static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate,
tbl->is_dup = 1;
*rate_idx = index;
+
+ /* HT rate format, MIMO (might be 20 MHz legacy or 40 MHz fat width) */
} else {
tbl->lq_type = LQ_MIMO;
if (mcs_rate->rate_n_flags & RATE_MCS_SGI_MSK)
@@ -439,8 +484,8 @@ static int rs_get_tbl_info_from_mcs(const struct iwl_rate *mcs_rate,
return 0;
}
-static inline void rs_toggle_antenna(struct iwl_rate *new_rate,
- struct iwl_scale_tbl_info *tbl)
+static inline void rs_toggle_antenna(struct iwl4965_rate *new_rate,
+ struct iwl4965_scale_tbl_info *tbl)
{
if (tbl->antenna_type == ANT_AUX) {
tbl->antenna_type = ANT_MAIN;
@@ -453,18 +498,15 @@ static inline void rs_toggle_antenna(struct iwl_rate *new_rate,
}
}
-static inline s8 rs_use_green(struct iwl_priv *priv)
+static inline u8 rs_use_green(struct iwl4965_priv *priv,
+ struct ieee80211_conf *conf)
{
- s8 rc = 0;
-#ifdef CONFIG_IWLWIFI_HT
- if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht)
- return 0;
-
- if ((priv->current_assoc_ht.is_green_field) &&
- !(priv->current_assoc_ht.operating_mode & 0x4))
- rc = 1;
-#endif /*CONFIG_IWLWIFI_HT */
- return rc;
+#ifdef CONFIG_IWL4965_HT
+ return ((conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
+ priv->current_ht_config.is_green_field &&
+ !priv->current_ht_config.non_GF_STA_present);
+#endif /* CONFIG_IWL4965_HT */
+ return 0;
}
/**
@@ -474,23 +516,24 @@ static inline s8 rs_use_green(struct iwl_priv *priv)
* basic available rates.
*
*/
-static void rs_get_supported_rates(struct iwl_rate_scale_priv *lq_data,
+static void rs_get_supported_rates(struct iwl4965_lq_sta *lq_sta,
struct ieee80211_hdr *hdr,
- enum iwl_table_type rate_type,
+ enum iwl4965_table_type rate_type,
u16 *data_rate)
{
if (is_legacy(rate_type))
- *data_rate = lq_data->active_rate;
+ *data_rate = lq_sta->active_rate;
else {
if (is_siso(rate_type))
- *data_rate = lq_data->active_siso_rate;
+ *data_rate = lq_sta->active_siso_rate;
else
- *data_rate = lq_data->active_mimo_rate;
+ *data_rate = lq_sta->active_mimo_rate;
}
if (hdr && is_multicast_ether_addr(hdr->addr1) &&
- lq_data->active_rate_basic)
- *data_rate = lq_data->active_rate_basic;
+ lq_sta->active_rate_basic) {
+ *data_rate = lq_sta->active_rate_basic;
+ }
}
static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
@@ -498,7 +541,7 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
u8 high = IWL_RATE_INVALID;
u8 low = IWL_RATE_INVALID;
- /* 802.11A or ht walks to the next literal adjascent rate in
+ /* 802.11A or ht walks to the next literal adjacent rate in
* the rate table */
if (is_a_band(rate_type) || !is_legacy(rate_type)) {
int i;
@@ -527,7 +570,7 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
low = index;
while (low != IWL_RATE_INVALID) {
- low = iwl_rates[low].prev_rs;
+ low = iwl4965_rates[low].prev_rs;
if (low == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << low))
@@ -537,7 +580,7 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
high = index;
while (high != IWL_RATE_INVALID) {
- high = iwl_rates[high].next_rs;
+ high = iwl4965_rates[high].next_rs;
if (high == IWL_RATE_INVALID)
break;
if (rate_mask & (1 << high))
@@ -548,15 +591,15 @@ static u16 rs_get_adjacent_rate(u8 index, u16 rate_mask, int rate_type)
return (high << 8) | low;
}
-static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
- struct iwl_scale_tbl_info *tbl, u8 scale_index,
- u8 ht_possible, struct iwl_rate *mcs_rate)
+static void rs_get_lower_rate(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_scale_tbl_info *tbl, u8 scale_index,
+ u8 ht_possible, struct iwl4965_rate *mcs_rate)
{
s32 low;
u16 rate_mask;
u16 high_low;
u8 switch_to_legacy = 0;
- u8 is_green = lq_data->is_green;
+ u8 is_green = lq_sta->is_green;
/* check if we need to switch from HT to legacy rates.
* assumption is that mandatory rates (1Mbps or 6Mbps)
@@ -564,7 +607,7 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
switch_to_legacy = 1;
scale_index = rs_ht_to_legacy[scale_index];
- if (lq_data->phymode == MODE_IEEE80211A)
+ if (lq_sta->phymode == MODE_IEEE80211A)
tbl->lq_type = LQ_A;
else
tbl->lq_type = LQ_G;
@@ -577,22 +620,22 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
tbl->is_SGI = 0;
}
- rs_get_supported_rates(lq_data, NULL, tbl->lq_type, &rate_mask);
+ rs_get_supported_rates(lq_sta, NULL, tbl->lq_type, &rate_mask);
- /* mask with station rate restriction */
+ /* Mask with station rate restriction */
if (is_legacy(tbl->lq_type)) {
- if (lq_data->phymode == (u8) MODE_IEEE80211A)
+ /* supp_rates has no CCK bits in A mode */
+ if (lq_sta->phymode == (u8) MODE_IEEE80211A)
rate_mask = (u16)(rate_mask &
- (lq_data->supp_rates << IWL_FIRST_OFDM_RATE));
+ (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
else
- rate_mask = (u16)(rate_mask & lq_data->supp_rates);
+ rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
}
- /* if we did switched from HT to legacy check current rate */
- if ((switch_to_legacy) &&
- (rate_mask & (1 << scale_index))) {
+ /* If we switched from HT to legacy, check current rate */
+ if (switch_to_legacy && (rate_mask & (1 << scale_index))) {
rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green);
- return 0;
+ return;
}
high_low = rs_get_adjacent_rate(scale_index, rate_mask, tbl->lq_type);
@@ -602,29 +645,29 @@ static int rs_get_lower_rate(struct iwl_rate_scale_priv *lq_data,
rs_mcs_from_tbl(mcs_rate, tbl, low, is_green);
else
rs_mcs_from_tbl(mcs_rate, tbl, scale_index, is_green);
-
- return 0;
}
-static void rs_tx_status(void *priv_rate,
- struct net_device *dev,
+/*
+ * mac80211 sends us Tx status
+ */
+static void rs_tx_status(void *priv_rate, struct net_device *dev,
struct sk_buff *skb,
struct ieee80211_tx_status *tx_resp)
{
int status;
u8 retries;
int rs_index, index = 0;
- struct iwl_rate_scale_priv *lq;
- struct iwl_link_quality_cmd *table;
+ struct iwl4965_lq_sta *lq_sta;
+ struct iwl4965_link_quality_cmd *table;
struct sta_info *sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
- struct iwl_rate_scale_data *window = NULL;
- struct iwl_rate_scale_data *search_win = NULL;
- struct iwl_rate tx_mcs;
- struct iwl_scale_tbl_info tbl_type;
- struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
+ struct iwl4965_rate_scale_data *window = NULL;
+ struct iwl4965_rate_scale_data *search_win = NULL;
+ struct iwl4965_rate tx_mcs;
+ struct iwl4965_scale_tbl_info tbl_type;
+ struct iwl4965_scale_tbl_info *curr_tbl, *search_tbl;
u8 active_index = 0;
u16 fc = le16_to_cpu(hdr->frame_control);
s32 tpt = 0;
@@ -648,27 +691,32 @@ static void rs_tx_status(void *priv_rate,
return;
}
- lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
if (!priv->lq_mngr.lq_ready)
return;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq->ibss_sta_added)
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ !lq_sta->ibss_sta_added)
return;
- table = &lq->lq;
- active_index = lq->active_tbl;
+ table = &lq_sta->lq;
+ active_index = lq_sta->active_tbl;
- lq->antenna = (lq->valid_antenna & local->hw.conf.antenna_sel_tx);
- if (!lq->antenna)
- lq->antenna = lq->valid_antenna;
+ /* Get mac80211 antenna info */
+ lq_sta->antenna =
+ (lq_sta->valid_antenna & local->hw.conf.antenna_sel_tx);
+ if (!lq_sta->antenna)
+ lq_sta->antenna = lq_sta->valid_antenna;
- lq->antenna = lq->valid_antenna;
- curr_tbl = &(lq->lq_info[active_index]);
- search_tbl = &(lq->lq_info[(1 - active_index)]);
- window = (struct iwl_rate_scale_data *)
+ /* Ignore mac80211 antenna info for now */
+ lq_sta->antenna = lq_sta->valid_antenna;
+
+ curr_tbl = &(lq_sta->lq_info[active_index]);
+ search_tbl = &(lq_sta->lq_info[(1 - active_index)]);
+ window = (struct iwl4965_rate_scale_data *)
&(curr_tbl->win[0]);
- search_win = (struct iwl_rate_scale_data *)
+ search_win = (struct iwl4965_rate_scale_data *)
&(search_tbl->win[0]);
tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
@@ -682,6 +730,14 @@ static void rs_tx_status(void *priv_rate,
return;
}
+ /*
+ * Ignore this Tx frame response if its initial rate doesn't match
+ * that of latest Link Quality command. There may be stragglers
+ * from a previous Link Quality command, but we're no longer interested
+ * in those; they're either from the "active" mode while we're trying
+ * to check "search" mode, or a prior "search" mode after we've moved
+ * to a new "search" mode (which might become the new "active" mode).
+ */
if (retries &&
(tx_mcs.rate_n_flags !=
le32_to_cpu(table->rs_table[0].rate_n_flags))) {
@@ -692,12 +748,17 @@ static void rs_tx_status(void *priv_rate,
return;
}
+ /* Update frame history window with "failure" for each Tx retry. */
while (retries) {
+ /* Look up the rate and other info used for each tx attempt.
+ * Each tx attempt steps one entry deeper in the rate table. */
tx_mcs.rate_n_flags =
le32_to_cpu(table->rs_table[index].rate_n_flags);
rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
&tbl_type, &rs_index);
+ /* If type matches "search" table,
+ * add failure to "search" history */
if ((tbl_type.lq_type == search_tbl->lq_type) &&
(tbl_type.antenna_type == search_tbl->antenna_type) &&
(tbl_type.is_SGI == search_tbl->is_SGI)) {
@@ -705,8 +766,10 @@ static void rs_tx_status(void *priv_rate,
tpt = search_tbl->expected_tpt[rs_index];
else
tpt = 0;
- rs_collect_tx_data(search_win,
- rs_index, tpt, 0);
+ rs_collect_tx_data(search_win, rs_index, tpt, 0);
+
+ /* Else if type matches "current/active" table,
+ * add failure to "current/active" history */
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
(tbl_type.antenna_type == curr_tbl->antenna_type) &&
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
@@ -716,13 +779,21 @@ static void rs_tx_status(void *priv_rate,
tpt = 0;
rs_collect_tx_data(window, rs_index, tpt, 0);
}
- if (lq->stay_in_tbl)
- lq->total_failed++;
+
+ /* If not searching for a new mode, increment failed counter
+ * ... this helps determine when to start searching again */
+ if (lq_sta->stay_in_tbl)
+ lq_sta->total_failed++;
--retries;
index++;
}
+ /*
+ * Find (by rate) the history window to update with final Tx attempt;
+ * if Tx was successful first try, use original rate,
+ * else look up the rate that was, finally, successful.
+ */
if (!tx_resp->retry_count)
tx_mcs.rate_n_flags = tx_resp->control.tx_rate;
else
@@ -732,11 +803,14 @@ static void rs_tx_status(void *priv_rate,
rs_get_tbl_info_from_mcs(&tx_mcs, priv->phymode,
&tbl_type, &rs_index);
+ /* Update frame history window with "success" if Tx got ACKed ... */
if (tx_resp->flags & IEEE80211_TX_STATUS_ACK)
status = 1;
else
status = 0;
+ /* If type matches "search" table,
+ * add final tx status to "search" history */
if ((tbl_type.lq_type == search_tbl->lq_type) &&
(tbl_type.antenna_type == search_tbl->antenna_type) &&
(tbl_type.is_SGI == search_tbl->is_SGI)) {
@@ -746,6 +820,9 @@ static void rs_tx_status(void *priv_rate,
tpt = 0;
rs_collect_tx_data(search_win,
rs_index, tpt, status);
+
+ /* Else if type matches "current/active" table,
+ * add final tx status to "current/active" history */
} else if ((tbl_type.lq_type == curr_tbl->lq_type) &&
(tbl_type.antenna_type == curr_tbl->antenna_type) &&
(tbl_type.is_SGI == curr_tbl->is_SGI)) {
@@ -756,67 +833,77 @@ static void rs_tx_status(void *priv_rate,
rs_collect_tx_data(window, rs_index, tpt, status);
}
- if (lq->stay_in_tbl) {
+ /* If not searching for new mode, increment success/failed counter
+ * ... these help determine when to start searching again */
+ if (lq_sta->stay_in_tbl) {
if (status)
- lq->total_success++;
+ lq_sta->total_success++;
else
- lq->total_failed++;
+ lq_sta->total_failed++;
}
+ /* See if there's a better rate or modulation mode to try. */
rs_rate_scale_perform(priv, dev, hdr, sta);
sta_info_put(sta);
return;
}
static u8 rs_is_ant_connected(u8 valid_antenna,
- enum iwl_antenna_type antenna_type)
+ enum iwl4965_antenna_type antenna_type)
{
if (antenna_type == ANT_AUX)
return ((valid_antenna & 0x2) ? 1:0);
else if (antenna_type == ANT_MAIN)
return ((valid_antenna & 0x1) ? 1:0);
- else if (antenna_type == ANT_BOTH) {
- if ((valid_antenna & 0x3) == 0x3)
- return 1;
- else
- return 0;
- }
+ else if (antenna_type == ANT_BOTH)
+ return ((valid_antenna & 0x3) == 0x3);
return 1;
}
static u8 rs_is_other_ant_connected(u8 valid_antenna,
- enum iwl_antenna_type antenna_type)
+ enum iwl4965_antenna_type antenna_type)
{
if (antenna_type == ANT_AUX)
- return (rs_is_ant_connected(valid_antenna, ANT_MAIN));
+ return rs_is_ant_connected(valid_antenna, ANT_MAIN);
else
- return (rs_is_ant_connected(valid_antenna, ANT_AUX));
+ return rs_is_ant_connected(valid_antenna, ANT_AUX);
return 0;
}
+/*
+ * Begin a period of staying with a selected modulation mode.
+ * Set "stay_in_tbl" flag to prevent any mode switches.
+ * Set frame tx success limits according to legacy vs. high-throughput,
+ * and reset overall (spanning all rates) tx success history statistics.
+ * These control how long we stay using same modulation mode before
+ * searching for a new mode.
+ */
static void rs_set_stay_in_table(u8 is_legacy,
- struct iwl_rate_scale_priv *lq_data)
+ struct iwl4965_lq_sta *lq_sta)
{
IWL_DEBUG_HT("we are staying in the same table\n");
- lq_data->stay_in_tbl = 1;
+ lq_sta->stay_in_tbl = 1; /* only place this gets set */
if (is_legacy) {
- lq_data->table_count_limit = IWL_LEGACY_TABLE_COUNT;
- lq_data->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
- lq_data->max_success_limit = IWL_LEGACY_TABLE_COUNT;
+ lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT;
+ lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
+ lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT;
} else {
- lq_data->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;
- lq_data->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;
- lq_data->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;
+ lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;
+ lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;
+ lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;
}
- lq_data->table_count = 0;
- lq_data->total_failed = 0;
- lq_data->total_success = 0;
+ lq_sta->table_count = 0;
+ lq_sta->total_failed = 0;
+ lq_sta->total_success = 0;
}
-static void rs_get_expected_tpt_table(struct iwl_rate_scale_priv *lq_data,
- struct iwl_scale_tbl_info *tbl)
+/*
+ * Find correct throughput table for given mode of modulation
+ */
+static void rs_get_expected_tpt_table(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_scale_tbl_info *tbl)
{
if (is_legacy(tbl->lq_type)) {
if (!is_a_band(tbl->lq_type))
@@ -824,7 +911,7 @@ static void rs_get_expected_tpt_table(struct iwl_rate_scale_priv *lq_data,
else
tbl->expected_tpt = expected_tpt_A;
} else if (is_siso(tbl->lq_type)) {
- if (tbl->is_fat && !lq_data->is_dup)
+ if (tbl->is_fat && !lq_sta->is_dup)
if (tbl->is_SGI)
tbl->expected_tpt = expected_tpt_siso40MHzSGI;
else
@@ -835,7 +922,7 @@ static void rs_get_expected_tpt_table(struct iwl_rate_scale_priv *lq_data,
tbl->expected_tpt = expected_tpt_siso20MHz;
} else if (is_mimo(tbl->lq_type)) {
- if (tbl->is_fat && !lq_data->is_dup)
+ if (tbl->is_fat && !lq_sta->is_dup)
if (tbl->is_SGI)
tbl->expected_tpt = expected_tpt_mimo40MHzSGI;
else
@@ -848,18 +935,34 @@ static void rs_get_expected_tpt_table(struct iwl_rate_scale_priv *lq_data,
tbl->expected_tpt = expected_tpt_G;
}
-#ifdef CONFIG_IWLWIFI_HT
-static s32 rs_get_best_rate(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
- struct iwl_scale_tbl_info *tbl,
+#ifdef CONFIG_IWL4965_HT
+/*
+ * Find starting rate for new "search" high-throughput mode of modulation.
+ * Goal is to find lowest expected rate (under perfect conditions) that is
+ * above the current measured throughput of "active" mode, to give new mode
+ * a fair chance to prove itself without too many challenges.
+ *
+ * This gets called when transitioning to more aggressive modulation
+ * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
+ * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need
+ * to decrease to match "active" throughput. When moving from MIMO to SISO,
+ * bit rate will typically need to increase, but not if performance was bad.
+ */
+static s32 rs_get_best_rate(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_scale_tbl_info *tbl, /* "search" */
u16 rate_mask, s8 index, s8 rate)
{
- struct iwl_scale_tbl_info *active_tbl =
- &(lq_data->lq_info[lq_data->active_tbl]);
- s32 new_rate, high, low, start_hi;
+ /* "active" values */
+ struct iwl4965_scale_tbl_info *active_tbl =
+ &(lq_sta->lq_info[lq_sta->active_tbl]);
s32 active_sr = active_tbl->win[index].success_ratio;
- s32 *tpt_tbl = tbl->expected_tpt;
s32 active_tpt = active_tbl->expected_tpt[index];
+
+ /* expected "search" throughput */
+ s32 *tpt_tbl = tbl->expected_tpt;
+
+ s32 new_rate, high, low, start_hi;
u16 high_low;
new_rate = high = low = start_hi = IWL_RATE_INVALID;
@@ -870,28 +973,60 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
- if ((((100 * tpt_tbl[rate]) > lq_data->last_tpt) &&
+ /*
+ * Lower the "search" bit rate, to give new "search" mode
+ * approximately the same throughput as "active" if:
+ *
+ * 1) "Active" mode has been working modestly well (but not
+ * great), and expected "search" throughput (under perfect
+ * conditions) at candidate rate is above the actual
+ * measured "active" throughput (but less than expected
+ * "active" throughput under perfect conditions).
+ * OR
+ * 2) "Active" mode has been working perfectly or very well
+ * and expected "search" throughput (under perfect
+ * conditions) at candidate rate is above expected
+ * "active" throughput (under perfect conditions).
+ */
+ if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
((active_sr > IWL_RATE_DECREASE_TH) &&
(active_sr <= IWL_RATE_HIGH_TH) &&
(tpt_tbl[rate] <= active_tpt))) ||
((active_sr >= IWL_RATE_SCALE_SWITCH) &&
(tpt_tbl[rate] > active_tpt))) {
+ /* (2nd or later pass)
+ * If we've already tried to raise the rate, and are
+ * now trying to lower it, use the higher rate. */
if (start_hi != IWL_RATE_INVALID) {
new_rate = start_hi;
break;
}
+
new_rate = rate;
+
+ /* Loop again with lower rate */
if (low != IWL_RATE_INVALID)
rate = low;
+
+ /* Lower rate not available, use the original */
else
break;
+
+ /* Else try to raise the "search" rate to match "active" */
} else {
+ /* (2nd or later pass)
+ * If we've already tried to lower the rate, and are
+ * now trying to raise it, use the lower rate. */
if (new_rate != IWL_RATE_INVALID)
break;
+
+ /* Loop again with higher rate */
else if (high != IWL_RATE_INVALID) {
start_hi = high;
rate = high;
+
+ /* Higher rate not available, use the original */
} else {
new_rate = rate;
break;
@@ -901,58 +1036,64 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
return new_rate;
}
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT */
static inline u8 rs_is_both_ant_supp(u8 valid_antenna)
{
return (rs_is_ant_connected(valid_antenna, ANT_BOTH));
}
-static int rs_switch_to_mimo(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
- struct iwl_scale_tbl_info *tbl, int index)
+/*
+ * Set up search table for MIMO
+ */
+static int rs_switch_to_mimo(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+ struct iwl4965_scale_tbl_info *tbl, int index)
{
- int rc = -1;
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
u16 rate_mask;
s32 rate;
- s8 is_green = lq_data->is_green;
+ s8 is_green = lq_sta->is_green;
- if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht)
+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
+ !sta->ht_info.ht_supported)
return -1;
IWL_DEBUG_HT("LQ: try to switch to MIMO\n");
tbl->lq_type = LQ_MIMO;
- rs_get_supported_rates(lq_data, NULL, tbl->lq_type,
+ rs_get_supported_rates(lq_sta, NULL, tbl->lq_type,
&rate_mask);
- if (priv->current_assoc_ht.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)
+ if (priv->current_ht_config.tx_mimo_ps_mode == IWL_MIMO_PS_STATIC)
return -1;
- if (!rs_is_both_ant_supp(lq_data->antenna))
+ /* Need both Tx chains/antennas to support MIMO */
+ if (!rs_is_both_ant_supp(lq_sta->antenna))
return -1;
- rc = 0;
- tbl->is_dup = lq_data->is_dup;
+ tbl->is_dup = lq_sta->is_dup;
tbl->action = 0;
- if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ)
+ if (priv->current_ht_config.supported_chan_width
+ == IWL_CHANNEL_WIDTH_40MHZ)
tbl->is_fat = 1;
else
tbl->is_fat = 0;
if (tbl->is_fat) {
- if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY)
+ if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
tbl->is_SGI = 1;
else
tbl->is_SGI = 0;
- } else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY)
+ } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
tbl->is_SGI = 1;
else
tbl->is_SGI = 0;
- rs_get_expected_tpt_table(lq_data, tbl);
+ rs_get_expected_tpt_table(lq_sta, tbl);
- rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index);
+ rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index, index);
IWL_DEBUG_HT("LQ: MIMO best rate %d mask %X\n", rate, rate_mask);
if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask))
@@ -961,43 +1102,49 @@ static int rs_switch_to_mimo(struct iwl_priv *priv,
IWL_DEBUG_HT("LQ: Switch to new mcs %X index is green %X\n",
tbl->current_rate.rate_n_flags, is_green);
-
-#endif /*CONFIG_IWLWIFI_HT */
- return rc;
+ return 0;
+#else
+ return -1;
+#endif /*CONFIG_IWL4965_HT */
}
-static int rs_switch_to_siso(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
- struct iwl_scale_tbl_info *tbl, int index)
+/*
+ * Set up search table for SISO
+ */
+static int rs_switch_to_siso(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
+ struct iwl4965_scale_tbl_info *tbl, int index)
{
- int rc = -1;
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
u16 rate_mask;
- u8 is_green = lq_data->is_green;
+ u8 is_green = lq_sta->is_green;
s32 rate;
IWL_DEBUG_HT("LQ: try to switch to SISO\n");
- if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht)
+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
+ !sta->ht_info.ht_supported)
return -1;
- rc = 0;
- tbl->is_dup = lq_data->is_dup;
+ tbl->is_dup = lq_sta->is_dup;
tbl->lq_type = LQ_SISO;
tbl->action = 0;
- rs_get_supported_rates(lq_data, NULL, tbl->lq_type,
+ rs_get_supported_rates(lq_sta, NULL, tbl->lq_type,
&rate_mask);
- if (priv->current_channel_width == IWL_CHANNEL_WIDTH_40MHZ)
+ if (priv->current_ht_config.supported_chan_width
+ == IWL_CHANNEL_WIDTH_40MHZ)
tbl->is_fat = 1;
else
tbl->is_fat = 0;
if (tbl->is_fat) {
- if (priv->current_assoc_ht.sgf & HT_SHORT_GI_40MHZ_ONLY)
+ if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
tbl->is_SGI = 1;
else
tbl->is_SGI = 0;
- } else if (priv->current_assoc_ht.sgf & HT_SHORT_GI_20MHZ_ONLY)
+ } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
tbl->is_SGI = 1;
else
tbl->is_SGI = 0;
@@ -1005,8 +1152,8 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
if (is_green)
tbl->is_SGI = 0;
- rs_get_expected_tpt_table(lq_data, tbl);
- rate = rs_get_best_rate(priv, lq_data, tbl, rate_mask, index, index);
+ rs_get_expected_tpt_table(lq_sta, tbl);
+ rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index, index);
IWL_DEBUG_HT("LQ: get best rate %d mask %X\n", rate, rate_mask);
if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
@@ -1017,23 +1164,30 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
rs_mcs_from_tbl(&tbl->current_rate, tbl, rate, is_green);
IWL_DEBUG_HT("LQ: Switch to new mcs %X index is green %X\n",
tbl->current_rate.rate_n_flags, is_green);
+ return 0;
+#else
+ return -1;
-#endif /*CONFIG_IWLWIFI_HT */
- return rc;
+#endif /*CONFIG_IWL4965_HT */
}
-static int rs_move_legacy_other(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
+/*
+ * Try to switch to new modulation mode from legacy
+ */
+static int rs_move_legacy_other(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
int index)
{
- int rc = 0;
- struct iwl_scale_tbl_info *tbl =
- &(lq_data->lq_info[lq_data->active_tbl]);
- struct iwl_scale_tbl_info *search_tbl =
- &(lq_data->lq_info[(1 - lq_data->active_tbl)]);
- struct iwl_rate_scale_data *window = &(tbl->win[index]);
- u32 sz = (sizeof(struct iwl_scale_tbl_info) -
- (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+ int ret = 0;
+ struct iwl4965_scale_tbl_info *tbl =
+ &(lq_sta->lq_info[lq_sta->active_tbl]);
+ struct iwl4965_scale_tbl_info *search_tbl =
+ &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ struct iwl4965_rate_scale_data *window = &(tbl->win[index]);
+ u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
+ (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
for (; ;) {
@@ -1042,52 +1196,59 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
IWL_DEBUG_HT("LQ Legacy switch Antenna\n");
search_tbl->lq_type = LQ_NONE;
- lq_data->action_counter++;
+ lq_sta->action_counter++;
+
+ /* Don't change antenna if success has been great */
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break;
- if (!rs_is_other_ant_connected(lq_data->antenna,
+
+ /* Don't change antenna if other one is not connected */
+ if (!rs_is_other_ant_connected(lq_sta->antenna,
tbl->antenna_type))
break;
+ /* Set up search table to try other antenna */
memcpy(search_tbl, tbl, sz);
rs_toggle_antenna(&(search_tbl->current_rate),
search_tbl);
- rs_get_expected_tpt_table(lq_data, search_tbl);
- lq_data->search_better_tbl = 1;
+ rs_get_expected_tpt_table(lq_sta, search_tbl);
+ lq_sta->search_better_tbl = 1;
goto out;
case IWL_LEGACY_SWITCH_SISO:
IWL_DEBUG_HT("LQ: Legacy switch to SISO\n");
+
+ /* Set up search table to try SISO */
memcpy(search_tbl, tbl, sz);
search_tbl->lq_type = LQ_SISO;
search_tbl->is_SGI = 0;
search_tbl->is_fat = 0;
- rc = rs_switch_to_siso(priv, lq_data, search_tbl,
- index);
- if (!rc) {
- lq_data->search_better_tbl = 1;
- lq_data->action_counter = 0;
- }
- if (!rc)
+ ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
+ search_tbl, index);
+ if (!ret) {
+ lq_sta->search_better_tbl = 1;
+ lq_sta->action_counter = 0;
goto out;
+ }
break;
case IWL_LEGACY_SWITCH_MIMO:
IWL_DEBUG_HT("LQ: Legacy switch MIMO\n");
+
+ /* Set up search table to try MIMO */
memcpy(search_tbl, tbl, sz);
search_tbl->lq_type = LQ_MIMO;
search_tbl->is_SGI = 0;
search_tbl->is_fat = 0;
search_tbl->antenna_type = ANT_BOTH;
- rc = rs_switch_to_mimo(priv, lq_data, search_tbl,
- index);
- if (!rc) {
- lq_data->search_better_tbl = 1;
- lq_data->action_counter = 0;
- }
- if (!rc)
+ ret = rs_switch_to_mimo(priv, lq_sta, conf, sta,
+ search_tbl, index);
+ if (!ret) {
+ lq_sta->search_better_tbl = 1;
+ lq_sta->action_counter = 0;
goto out;
+ }
break;
}
tbl->action++;
@@ -1108,30 +1269,35 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
}
-static int rs_move_siso_to_other(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
+/*
+ * Try to switch to new modulation mode from SISO
+ */
+static int rs_move_siso_to_other(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
int index)
{
- int rc = -1;
- u8 is_green = lq_data->is_green;
- struct iwl_scale_tbl_info *tbl =
- &(lq_data->lq_info[lq_data->active_tbl]);
- struct iwl_scale_tbl_info *search_tbl =
- &(lq_data->lq_info[(1 - lq_data->active_tbl)]);
- struct iwl_rate_scale_data *window = &(tbl->win[index]);
- u32 sz = (sizeof(struct iwl_scale_tbl_info) -
- (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+ int ret;
+ u8 is_green = lq_sta->is_green;
+ struct iwl4965_scale_tbl_info *tbl =
+ &(lq_sta->lq_info[lq_sta->active_tbl]);
+ struct iwl4965_scale_tbl_info *search_tbl =
+ &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ struct iwl4965_rate_scale_data *window = &(tbl->win[index]);
+ u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
+ (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
for (;;) {
- lq_data->action_counter++;
+ lq_sta->action_counter++;
switch (tbl->action) {
case IWL_SISO_SWITCH_ANTENNA:
IWL_DEBUG_HT("LQ: SISO SWITCH ANTENNA SISO\n");
search_tbl->lq_type = LQ_NONE;
if (window->success_ratio >= IWL_RS_GOOD_RATIO)
break;
- if (!rs_is_other_ant_connected(lq_data->antenna,
+ if (!rs_is_other_ant_connected(lq_sta->antenna,
tbl->antenna_type))
break;
@@ -1139,7 +1305,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
search_tbl->action = IWL_SISO_SWITCH_MIMO;
rs_toggle_antenna(&(search_tbl->current_rate),
search_tbl);
- lq_data->search_better_tbl = 1;
+ lq_sta->search_better_tbl = 1;
goto out;
@@ -1150,13 +1316,12 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
search_tbl->is_SGI = 0;
search_tbl->is_fat = 0;
search_tbl->antenna_type = ANT_BOTH;
- rc = rs_switch_to_mimo(priv, lq_data, search_tbl,
- index);
- if (!rc)
- lq_data->search_better_tbl = 1;
-
- if (!rc)
+ ret = rs_switch_to_mimo(priv, lq_sta, conf, sta,
+ search_tbl, index);
+ if (!ret) {
+ lq_sta->search_better_tbl = 1;
goto out;
+ }
break;
case IWL_SISO_SWITCH_GI:
IWL_DEBUG_HT("LQ: SISO SWITCH TO GI\n");
@@ -1168,17 +1333,17 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
search_tbl->is_SGI = 1;
else
break;
- lq_data->search_better_tbl = 1;
+ lq_sta->search_better_tbl = 1;
if ((tbl->lq_type == LQ_SISO) &&
(tbl->is_SGI)) {
- s32 tpt = lq_data->last_tpt / 100;
+ s32 tpt = lq_sta->last_tpt / 100;
if (((!tbl->is_fat) &&
(tpt >= expected_tpt_siso20MHz[index])) ||
((tbl->is_fat) &&
(tpt >= expected_tpt_siso40MHz[index])))
- lq_data->search_better_tbl = 0;
+ lq_sta->search_better_tbl = 0;
}
- rs_get_expected_tpt_table(lq_data, search_tbl);
+ rs_get_expected_tpt_table(lq_sta, search_tbl);
rs_mcs_from_tbl(&search_tbl->current_rate,
search_tbl, index, is_green);
goto out;
@@ -1199,26 +1364,33 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
return 0;
}
-static int rs_move_mimo_to_other(struct iwl_priv *priv,
- struct iwl_rate_scale_priv *lq_data,
+/*
+ * Try to switch to new modulation mode from MIMO
+ */
+static int rs_move_mimo_to_other(struct iwl4965_priv *priv,
+ struct iwl4965_lq_sta *lq_sta,
+ struct ieee80211_conf *conf,
+ struct sta_info *sta,
int index)
{
- int rc = -1;
- s8 is_green = lq_data->is_green;
- struct iwl_scale_tbl_info *tbl =
- &(lq_data->lq_info[lq_data->active_tbl]);
- struct iwl_scale_tbl_info *search_tbl =
- &(lq_data->lq_info[(1 - lq_data->active_tbl)]);
- u32 sz = (sizeof(struct iwl_scale_tbl_info) -
- (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+ int ret;
+ s8 is_green = lq_sta->is_green;
+ struct iwl4965_scale_tbl_info *tbl =
+ &(lq_sta->lq_info[lq_sta->active_tbl]);
+ struct iwl4965_scale_tbl_info *search_tbl =
+ &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+ u32 sz = (sizeof(struct iwl4965_scale_tbl_info) -
+ (sizeof(struct iwl4965_rate_scale_data) * IWL_RATE_COUNT));
u8 start_action = tbl->action;
for (;;) {
- lq_data->action_counter++;
+ lq_sta->action_counter++;
switch (tbl->action) {
case IWL_MIMO_SWITCH_ANTENNA_A:
case IWL_MIMO_SWITCH_ANTENNA_B:
IWL_DEBUG_HT("LQ: MIMO SWITCH TO SISO\n");
+
+ /* Set up new search table for SISO */
memcpy(search_tbl, tbl, sz);
search_tbl->lq_type = LQ_SISO;
search_tbl->is_SGI = 0;
@@ -1228,16 +1400,18 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
else
search_tbl->antenna_type = ANT_AUX;
- rc = rs_switch_to_siso(priv, lq_data, search_tbl,
- index);
- if (!rc) {
- lq_data->search_better_tbl = 1;
+ ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
+ search_tbl, index);
+ if (!ret) {
+ lq_sta->search_better_tbl = 1;
goto out;
}
break;
case IWL_MIMO_SWITCH_GI:
IWL_DEBUG_HT("LQ: MIMO SWITCH TO GI\n");
+
+ /* Set up new search table for MIMO */
memcpy(search_tbl, tbl, sz);
search_tbl->lq_type = LQ_MIMO;
search_tbl->antenna_type = ANT_BOTH;
@@ -1246,17 +1420,24 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
search_tbl->is_SGI = 0;
else
search_tbl->is_SGI = 1;
- lq_data->search_better_tbl = 1;
+ lq_sta->search_better_tbl = 1;
+
+ /*
+ * If active table already uses the fastest possible
+ * modulation (dual stream with short guard interval),
+ * and it's working well, there's no need to look
+ * for a better type of modulation!
+ */
if ((tbl->lq_type == LQ_MIMO) &&
(tbl->is_SGI)) {
- s32 tpt = lq_data->last_tpt / 100;
+ s32 tpt = lq_sta->last_tpt / 100;
if (((!tbl->is_fat) &&
(tpt >= expected_tpt_mimo20MHz[index])) ||
((tbl->is_fat) &&
(tpt >= expected_tpt_mimo40MHz[index])))
- lq_data->search_better_tbl = 0;
+ lq_sta->search_better_tbl = 0;
}
- rs_get_expected_tpt_table(lq_data, search_tbl);
+ rs_get_expected_tpt_table(lq_sta, search_tbl);
rs_mcs_from_tbl(&search_tbl->current_rate,
search_tbl, index, is_green);
goto out;
@@ -1279,43 +1460,71 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
}
-static void rs_stay_in_table(struct iwl_rate_scale_priv *lq_data)
+/*
+ * Check whether we should continue using same modulation mode, or
+ * begin search for a new mode, based on:
+ * 1) # tx successes or failures while using this mode
+ * 2) # times calling this function
+ * 3) elapsed time in this mode (not used, for now)
+ */
+static void rs_stay_in_table(struct iwl4965_lq_sta *lq_sta)
{
- struct iwl_scale_tbl_info *tbl;
+ struct iwl4965_scale_tbl_info *tbl;
int i;
int active_tbl;
int flush_interval_passed = 0;
- active_tbl = lq_data->active_tbl;
+ active_tbl = lq_sta->active_tbl;
- tbl = &(lq_data->lq_info[active_tbl]);
+ tbl = &(lq_sta->lq_info[active_tbl]);
- if (lq_data->stay_in_tbl) {
+ /* If we've been disallowing search, see if we should now allow it */
+ if (lq_sta->stay_in_tbl) {
- if (lq_data->flush_timer)
+ /* Elapsed time using current modulation mode */
+ if (lq_sta->flush_timer)
flush_interval_passed =
time_after(jiffies,
- (unsigned long)(lq_data->flush_timer +
+ (unsigned long)(lq_sta->flush_timer +
IWL_RATE_SCALE_FLUSH_INTVL));
+ /* For now, disable the elapsed time criterion */
flush_interval_passed = 0;
- if ((lq_data->total_failed > lq_data->max_failure_limit) ||
- (lq_data->total_success > lq_data->max_success_limit) ||
- ((!lq_data->search_better_tbl) && (lq_data->flush_timer)
+
+ /*
+ * Check if we should allow search for new modulation mode.
+ * If many frames have failed or succeeded, or we've used
+ * this same modulation for a long time, allow search, and
+ * reset history stats that keep track of whether we should
+ * allow a new search. Also (below) reset all bitmaps and
+ * stats in active history.
+ */
+ if ((lq_sta->total_failed > lq_sta->max_failure_limit) ||
+ (lq_sta->total_success > lq_sta->max_success_limit) ||
+ ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
&& (flush_interval_passed))) {
IWL_DEBUG_HT("LQ: stay is expired %d %d %d\n:",
- lq_data->total_failed,
- lq_data->total_success,
+ lq_sta->total_failed,
+ lq_sta->total_success,
flush_interval_passed);
- lq_data->stay_in_tbl = 0;
- lq_data->total_failed = 0;
- lq_data->total_success = 0;
- lq_data->flush_timer = 0;
- } else if (lq_data->table_count > 0) {
- lq_data->table_count++;
- if (lq_data->table_count >=
- lq_data->table_count_limit) {
- lq_data->table_count = 0;
+
+ /* Allow search for new mode */
+ lq_sta->stay_in_tbl = 0; /* only place reset */
+ lq_sta->total_failed = 0;
+ lq_sta->total_success = 0;
+ lq_sta->flush_timer = 0;
+
+ /*
+ * Else if we've used this modulation mode enough repetitions
+ * (regardless of elapsed time or success/failure), reset
+ * history bitmaps and rate-specific stats for all rates in
+ * active table.
+ */
+ } else {
+ lq_sta->table_count++;
+ if (lq_sta->table_count >=
+ lq_sta->table_count_limit) {
+ lq_sta->table_count = 0;
IWL_DEBUG_HT("LQ: stay in table clear win\n");
for (i = 0; i < IWL_RATE_COUNT; i++)
@@ -1324,23 +1533,32 @@ static void rs_stay_in_table(struct iwl_rate_scale_priv *lq_data)
}
}
- if (!lq_data->stay_in_tbl) {
+ /* If transitioning to allow "search", reset all history
+ * bitmaps and stats in active table (this will become the new
+ * "search" table). */
+ if (!lq_sta->stay_in_tbl) {
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&(tbl->win[i]));
}
}
}
-static void rs_rate_scale_perform(struct iwl_priv *priv,
+/*
+ * Do rate scaling and search for new modulation mode.
+ */
+static void rs_rate_scale_perform(struct iwl4965_priv *priv,
struct net_device *dev,
struct ieee80211_hdr *hdr,
struct sta_info *sta)
{
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_hw *hw = local_to_hw(local);
+ struct ieee80211_conf *conf = &hw->conf;
int low = IWL_RATE_INVALID;
int high = IWL_RATE_INVALID;
int index;
int i;
- struct iwl_rate_scale_data *window = NULL;
+ struct iwl4965_rate_scale_data *window = NULL;
int current_tpt = IWL_INVALID_VALUE;
int low_tpt = IWL_INVALID_VALUE;
int high_tpt = IWL_INVALID_VALUE;
@@ -1348,10 +1566,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
s8 scale_action = 0;
u16 fc, rate_mask;
u8 update_lq = 0;
- struct iwl_rate_scale_priv *lq_data;
- struct iwl_scale_tbl_info *tbl, *tbl1;
+ struct iwl4965_lq_sta *lq_sta;
+ struct iwl4965_scale_tbl_info *tbl, *tbl1;
u16 rate_scale_index_msk = 0;
- struct iwl_rate mcs_rate;
+ struct iwl4965_rate mcs_rate;
u8 is_green = 0;
u8 active_tbl = 0;
u8 done_search = 0;
@@ -1374,34 +1592,42 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
IWL_DEBUG_RATE("still rate scaling not ready\n");
return;
}
- lq_data = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
- if (!lq_data->search_better_tbl)
- active_tbl = lq_data->active_tbl;
+ /*
+ * Select rate-scale / modulation-mode table to work with in
+ * the rest of this function: "search" if searching for better
+ * modulation mode, or "active" if doing rate scaling within a mode.
+ */
+ if (!lq_sta->search_better_tbl)
+ active_tbl = lq_sta->active_tbl;
else
- active_tbl = 1 - lq_data->active_tbl;
+ active_tbl = 1 - lq_sta->active_tbl;
- tbl = &(lq_data->lq_info[active_tbl]);
- is_green = lq_data->is_green;
+ tbl = &(lq_sta->lq_info[active_tbl]);
+ is_green = lq_sta->is_green;
+ /* current tx rate */
index = sta->last_txrate;
IWL_DEBUG_RATE("Rate scale index %d for type %d\n", index,
tbl->lq_type);
- rs_get_supported_rates(lq_data, hdr, tbl->lq_type,
+ /* rates available for this association, and for modulation mode */
+ rs_get_supported_rates(lq_sta, hdr, tbl->lq_type,
&rate_mask);
IWL_DEBUG_RATE("mask 0x%04X \n", rate_mask);
/* mask with station rate restriction */
if (is_legacy(tbl->lq_type)) {
- if (lq_data->phymode == (u8) MODE_IEEE80211A)
+ if (lq_sta->phymode == (u8) MODE_IEEE80211A)
+ /* supp_rates has no CCK bits in A mode */
rate_scale_index_msk = (u16) (rate_mask &
- (lq_data->supp_rates << IWL_FIRST_OFDM_RATE));
+ (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
else
rate_scale_index_msk = (u16) (rate_mask &
- lq_data->supp_rates);
+ lq_sta->supp_rates);
} else
rate_scale_index_msk = rate_mask;
@@ -1409,11 +1635,13 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
if (!rate_scale_index_msk)
rate_scale_index_msk = rate_mask;
+ /* If current rate is no longer supported on current association,
+ * or user changed preferences for rates, find a new supported rate. */
if (index < 0 || !((1 << index) & rate_scale_index_msk)) {
index = IWL_INVALID_VALUE;
update_lq = 1;
- /* get the lowest availabe rate */
+ /* get the highest available rate */
for (i = 0; i <= IWL_RATE_COUNT; i++) {
if ((1 << i) & rate_scale_index_msk)
index = i;
@@ -1425,11 +1653,19 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
}
}
+ /* Get expected throughput table and history window for current rate */
if (!tbl->expected_tpt)
- rs_get_expected_tpt_table(lq_data, tbl);
+ rs_get_expected_tpt_table(lq_sta, tbl);
window = &(tbl->win[index]);
+ /*
+ * If there is not enough history to calculate actual average
+ * throughput, keep analyzing results of more tx frames, without
+ * changing rate or mode (bypass most of the rest of this function).
+ * Set up new rate table in uCode only if old rate is not supported
+ * in current association (use new rate found above).
+ */
fail_count = window->counter - window->success_counter;
if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH))
@@ -1437,82 +1673,118 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
IWL_DEBUG_RATE("LQ: still below TH succ %d total %d "
"for index %d\n",
window->success_counter, window->counter, index);
+
+ /* Can't calculate this yet; not enough history */
window->average_tpt = IWL_INVALID_VALUE;
- rs_stay_in_table(lq_data);
+
+ /* Should we stay with this modulation mode,
+ * or search for a new one? */
+ rs_stay_in_table(lq_sta);
+
+ /* Set up new rate table in uCode, if needed */
if (update_lq) {
rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
- rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq);
- rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+ rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
}
goto out;
+ /* Else we have enough samples; calculate estimate of
+ * actual average throughput */
} else
window->average_tpt = ((window->success_ratio *
tbl->expected_tpt[index] + 64) / 128);
- if (lq_data->search_better_tbl) {
+ /* If we are searching for better modulation mode, check success. */
+ if (lq_sta->search_better_tbl) {
int success_limit = IWL_RATE_SCALE_SWITCH;
+ /* If good success, continue using the "search" mode;
+ * no need to send new link quality command, since we're
+ * continuing to use the setup that we've been trying. */
if ((window->success_ratio > success_limit) ||
- (window->average_tpt > lq_data->last_tpt)) {
+ (window->average_tpt > lq_sta->last_tpt)) {
if (!is_legacy(tbl->lq_type)) {
IWL_DEBUG_HT("LQ: we are switching to HT"
" rate suc %d current tpt %d"
" old tpt %d\n",
window->success_ratio,
window->average_tpt,
- lq_data->last_tpt);
- lq_data->enable_counter = 1;
+ lq_sta->last_tpt);
+ lq_sta->enable_counter = 1;
}
- lq_data->active_tbl = active_tbl;
+ /* Swap tables; "search" becomes "active" */
+ lq_sta->active_tbl = active_tbl;
current_tpt = window->average_tpt;
+
+ /* Else poor success; go back to mode in "active" table */
} else {
+ /* Nullify "search" table */
tbl->lq_type = LQ_NONE;
- active_tbl = lq_data->active_tbl;
- tbl = &(lq_data->lq_info[active_tbl]);
- index = iwl_rate_index_from_plcp(
+ /* Revert to "active" table */
+ active_tbl = lq_sta->active_tbl;
+ tbl = &(lq_sta->lq_info[active_tbl]);
+
+ /* Revert to "active" rate and throughput info */
+ index = iwl4965_rate_index_from_plcp(
tbl->current_rate.rate_n_flags);
+ current_tpt = lq_sta->last_tpt;
+ /* Need to set up a new rate table in uCode */
update_lq = 1;
- current_tpt = lq_data->last_tpt;
IWL_DEBUG_HT("XXY GO BACK TO OLD TABLE\n");
}
- lq_data->search_better_tbl = 0;
- done_search = 1;
+
+ /* Either way, we've made a decision; modulation mode
+ * search is done, allow rate adjustment next time. */
+ lq_sta->search_better_tbl = 0;
+ done_search = 1; /* Don't switch modes below! */
goto lq_update;
}
+ /* (Else) not in search of better modulation mode, try for better
+ * starting rate, while staying in this mode. */
high_low = rs_get_adjacent_rate(index, rate_scale_index_msk,
tbl->lq_type);
low = high_low & 0xff;
high = (high_low >> 8) & 0xff;
+ /* Collect measured throughputs for current and adjacent rates */
current_tpt = window->average_tpt;
-
if (low != IWL_RATE_INVALID)
low_tpt = tbl->win[low].average_tpt;
-
if (high != IWL_RATE_INVALID)
high_tpt = tbl->win[high].average_tpt;
-
+ /* Assume rate increase */
scale_action = 1;
+ /* Too many failures, decrease rate */
if ((window->success_ratio <= IWL_RATE_DECREASE_TH) ||
(current_tpt == 0)) {
IWL_DEBUG_RATE("decrease rate because of low success_ratio\n");
scale_action = -1;
+
+ /* No throughput measured yet for adjacent rates; try increase. */
} else if ((low_tpt == IWL_INVALID_VALUE) &&
(high_tpt == IWL_INVALID_VALUE))
scale_action = 1;
+
+ /* Both adjacent throughputs are measured, but neither one has better
+ * throughput; we're using the best rate, don't change it! */
else if ((low_tpt != IWL_INVALID_VALUE) &&
(high_tpt != IWL_INVALID_VALUE) &&
(low_tpt < current_tpt) &&
(high_tpt < current_tpt))
scale_action = 0;
+
+ /* At least one adjacent rate's throughput is measured,
+ * and may have better performance. */
else {
+ /* Higher adjacent rate's throughput is measured */
if (high_tpt != IWL_INVALID_VALUE) {
+ /* Higher rate has better throughput */
if (high_tpt > current_tpt)
scale_action = 1;
else {
@@ -1520,7 +1792,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
("decrease rate because of high tpt\n");
scale_action = -1;
}
+
+ /* Lower adjacent rate's throughput is measured */
} else if (low_tpt != IWL_INVALID_VALUE) {
+ /* Lower rate has better throughput */
if (low_tpt > current_tpt) {
IWL_DEBUG_RATE
("decrease rate because of low tpt\n");
@@ -1530,23 +1805,30 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
}
}
+ /* Sanity check; asked for decrease, but success rate or throughput
+ * has been good at old rate. Don't change it. */
if (scale_action == -1) {
if ((low != IWL_RATE_INVALID) &&
((window->success_ratio > IWL_RATE_HIGH_TH) ||
(current_tpt > (100 * tbl->expected_tpt[low]))))
scale_action = 0;
+
+ /* Sanity check; asked for increase, but success rate has not been great
+ * even at old rate, higher rate will be worse. Don't change it. */
} else if ((scale_action == 1) &&
(window->success_ratio < IWL_RATE_INCREASE_TH))
scale_action = 0;
switch (scale_action) {
case -1:
+ /* Decrease starting rate, update uCode's rate table */
if (low != IWL_RATE_INVALID) {
update_lq = 1;
index = low;
}
break;
case 1:
+ /* Increase starting rate, update uCode's rate table */
if (high != IWL_RATE_INVALID) {
update_lq = 1;
index = high;
@@ -1554,6 +1836,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
break;
case 0:
+ /* No change */
default:
break;
}
@@ -1563,65 +1846,97 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
index, scale_action, low, high, tbl->lq_type);
lq_update:
+ /* Replace uCode's rate table for the destination station. */
if (update_lq) {
rs_mcs_from_tbl(&mcs_rate, tbl, index, is_green);
- rs_fill_link_cmd(lq_data, &mcs_rate, &lq_data->lq);
- rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+ rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
}
- rs_stay_in_table(lq_data);
- if (!update_lq && !done_search && !lq_data->stay_in_tbl) {
- lq_data->last_tpt = current_tpt;
+ /* Should we stay with this modulation mode, or search for a new one? */
+ rs_stay_in_table(lq_sta);
+ /*
+ * Search for new modulation mode if we're:
+ * 1) Not changing rates right now
+ * 2) Not just finishing up a search
+ * 3) Allowing a new search
+ */
+ if (!update_lq && !done_search && !lq_sta->stay_in_tbl) {
+ /* Save current throughput to compare with "search" throughput*/
+ lq_sta->last_tpt = current_tpt;
+
+ /* Select a new "search" modulation mode to try.
+ * If one is found, set up the new "search" table. */
if (is_legacy(tbl->lq_type))
- rs_move_legacy_other(priv, lq_data, index);
+ rs_move_legacy_other(priv, lq_sta, conf, sta, index);
else if (is_siso(tbl->lq_type))
- rs_move_siso_to_other(priv, lq_data, index);
+ rs_move_siso_to_other(priv, lq_sta, conf, sta, index);
else
- rs_move_mimo_to_other(priv, lq_data, index);
+ rs_move_mimo_to_other(priv, lq_sta, conf, sta, index);
- if (lq_data->search_better_tbl) {
- tbl = &(lq_data->lq_info[(1 - lq_data->active_tbl)]);
+ /* If new "search" mode was selected, set up in uCode table */
+ if (lq_sta->search_better_tbl) {
+ /* Access the "search" table, clear its history. */
+ tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
for (i = 0; i < IWL_RATE_COUNT; i++)
rs_rate_scale_clear_window(&(tbl->win[i]));
- index = iwl_rate_index_from_plcp(
+ /* Use new "search" start rate */
+ index = iwl4965_rate_index_from_plcp(
tbl->current_rate.rate_n_flags);
IWL_DEBUG_HT("Switch current mcs: %X index: %d\n",
tbl->current_rate.rate_n_flags, index);
- rs_fill_link_cmd(lq_data, &tbl->current_rate,
- &lq_data->lq);
- rs_send_lq_cmd(priv, &lq_data->lq, CMD_ASYNC);
+ rs_fill_link_cmd(lq_sta, &tbl->current_rate,
+ &lq_sta->lq);
+ rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
}
- tbl1 = &(lq_data->lq_info[lq_data->active_tbl]);
+ /* If the "active" (non-search) mode was legacy,
+ * and we've tried switching antennas,
+ * but we haven't been able to try HT modes (not available),
+ * stay with best antenna legacy modulation for a while
+ * before next round of mode comparisons. */
+ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
if (is_legacy(tbl1->lq_type) &&
-#ifdef CONFIG_IWLWIFI_HT
- !priv->current_assoc_ht.is_ht &&
+#ifdef CONFIG_IWL4965_HT
+ (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) &&
#endif
- (lq_data->action_counter >= 1)) {
- lq_data->action_counter = 0;
+ (lq_sta->action_counter >= 1)) {
+ lq_sta->action_counter = 0;
IWL_DEBUG_HT("LQ: STAY in legacy table\n");
- rs_set_stay_in_table(1, lq_data);
+ rs_set_stay_in_table(1, lq_sta);
}
- if (lq_data->enable_counter &&
- (lq_data->action_counter >= IWL_ACTION_LIMIT)) {
-#ifdef CONFIG_IWLWIFI_HT_AGG
- if ((lq_data->last_tpt > TID_AGG_TPT_THREHOLD) &&
+ /* If we're in an HT mode, and all 3 mode switch actions
+ * have been tried and compared, stay in this best modulation
+ * mode for a while before next round of mode comparisons. */
+ if (lq_sta->enable_counter &&
+ (lq_sta->action_counter >= IWL_ACTION_LIMIT)) {
+#ifdef CONFIG_IWL4965_HT_AGG
+ /* If appropriate, set up aggregation! */
+ if ((lq_sta->last_tpt > TID_AGG_TPT_THREHOLD) &&
(priv->lq_mngr.agg_ctrl.auto_agg)) {
priv->lq_mngr.agg_ctrl.tid_retry =
TID_ALL_SPECIFIED;
schedule_work(&priv->agg_work);
}
-#endif /*CONFIG_IWLWIFI_HT_AGG */
- lq_data->action_counter = 0;
- rs_set_stay_in_table(0, lq_data);
+#endif /*CONFIG_IWL4965_HT_AGG */
+ lq_sta->action_counter = 0;
+ rs_set_stay_in_table(0, lq_sta);
}
+
+ /*
+ * Else, don't search for a new modulation mode.
+ * Put new timestamp in stay-in-modulation-mode flush timer if:
+ * 1) Not changing rates right now
+ * 2) Not just finishing up a search
+ * 3) flush timer is empty
+ */
} else {
- if ((!update_lq) && (!done_search) && (!lq_data->flush_timer))
- lq_data->flush_timer = jiffies;
+ if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer))
+ lq_sta->flush_timer = jiffies;
}
out:
@@ -1632,7 +1947,7 @@ out:
/* sta->txrate is an index to A mode rates which start
* at IWL_FIRST_OFDM_RATE
*/
- if (lq_data->phymode == (u8) MODE_IEEE80211A)
+ if (lq_sta->phymode == (u8) MODE_IEEE80211A)
sta->txrate = i - IWL_FIRST_OFDM_RATE;
else
sta->txrate = i;
@@ -1641,38 +1956,39 @@ out:
}
-static void rs_initialize_lq(struct iwl_priv *priv,
+static void rs_initialize_lq(struct iwl4965_priv *priv,
+ struct ieee80211_conf *conf,
struct sta_info *sta)
{
int i;
- struct iwl_rate_scale_priv *lq;
- struct iwl_scale_tbl_info *tbl;
+ struct iwl4965_lq_sta *lq_sta;
+ struct iwl4965_scale_tbl_info *tbl;
u8 active_tbl = 0;
int rate_idx;
- u8 use_green = rs_use_green(priv);
- struct iwl_rate mcs_rate;
+ u8 use_green = rs_use_green(priv, conf);
+ struct iwl4965_rate mcs_rate;
if (!sta || !sta->rate_ctrl_priv)
goto out;
- lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate;
- if ((lq->lq.sta_id == 0xff) &&
+ if ((lq_sta->lq.sta_id == 0xff) &&
(priv->iw_mode == IEEE80211_IF_TYPE_IBSS))
goto out;
- if (!lq->search_better_tbl)
- active_tbl = lq->active_tbl;
+ if (!lq_sta->search_better_tbl)
+ active_tbl = lq_sta->active_tbl;
else
- active_tbl = 1 - lq->active_tbl;
+ active_tbl = 1 - lq_sta->active_tbl;
- tbl = &(lq->lq_info[active_tbl]);
+ tbl = &(lq_sta->lq_info[active_tbl]);
if ((i < 0) || (i >= IWL_RATE_COUNT))
i = 0;
- mcs_rate.rate_n_flags = iwl_rates[i].plcp ;
+ mcs_rate.rate_n_flags = iwl4965_rates[i].plcp ;
mcs_rate.rate_n_flags |= RATE_MCS_ANT_B_MSK;
mcs_rate.rate_n_flags &= ~RATE_MCS_ANT_A_MSK;
@@ -1686,114 +2002,95 @@ static void rs_initialize_lq(struct iwl_priv *priv,
rs_mcs_from_tbl(&mcs_rate, tbl, rate_idx, use_green);
tbl->current_rate.rate_n_flags = mcs_rate.rate_n_flags;
- rs_get_expected_tpt_table(lq, tbl);
- rs_fill_link_cmd(lq, &mcs_rate, &lq->lq);
- rs_send_lq_cmd(priv, &lq->lq, CMD_ASYNC);
+ rs_get_expected_tpt_table(lq_sta, tbl);
+ rs_fill_link_cmd(lq_sta, &mcs_rate, &lq_sta->lq);
+ rs_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
out:
return;
}
-static struct ieee80211_rate *rs_get_lowest_rate(struct ieee80211_local
- *local)
-{
- struct ieee80211_hw_mode *mode = local->oper_hw_mode;
- int i;
-
- for (i = 0; i < mode->num_rates; i++) {
- struct ieee80211_rate *rate = &mode->rates[i];
-
- if (rate->flags & IEEE80211_RATE_SUPPORTED)
- return rate;
- }
-
- return &mode->rates[0];
-}
-
-static struct ieee80211_rate *rs_get_rate(void *priv_rate,
- struct net_device *dev,
- struct sk_buff *skb,
- struct rate_control_extra
- *extra)
+static void rs_get_rate(void *priv_rate, struct net_device *dev,
+ struct ieee80211_hw_mode *mode, struct sk_buff *skb,
+ struct rate_selection *sel)
{
int i;
struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct sta_info *sta;
u16 fc;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct iwl_rate_scale_priv *lq;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
+ struct iwl4965_lq_sta *lq_sta;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
- memset(extra, 0, sizeof(*extra));
-
- fc = le16_to_cpu(hdr->frame_control);
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
- /* Send management frames and broadcast/multicast data using
- * lowest rate. */
- /* TODO: this could probably be improved.. */
- return rs_get_lowest_rate(local);
- }
-
sta = sta_info_get(local, hdr->addr1);
- if (!sta || !sta->rate_ctrl_priv) {
+ /* Send management frames and broadcast/multicast data using lowest
+ * rate. */
+ fc = le16_to_cpu(hdr->frame_control);
+ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
+ !sta || !sta->rate_ctrl_priv) {
+ sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
if (sta)
sta_info_put(sta);
- return rs_get_lowest_rate(local);
+ return;
}
- lq = (struct iwl_rate_scale_priv *)sta->rate_ctrl_priv;
+ lq_sta = (struct iwl4965_lq_sta *)sta->rate_ctrl_priv;
i = sta->last_txrate;
- if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) && !lq->ibss_sta_added) {
- u8 sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
+ !lq_sta->ibss_sta_added) {
+ u8 sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
DECLARE_MAC_BUF(mac);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, hdr->addr1));
- sta_id = iwl_add_station(priv,
- hdr->addr1, 0, CMD_ASYNC);
+ sta_id = iwl4965_add_station_flags(priv, hdr->addr1,
+ 0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
- lq->lq.sta_id = sta_id;
- lq->lq.rs_table[0].rate_n_flags = 0;
- lq->ibss_sta_added = 1;
- rs_initialize_lq(priv, sta);
+ lq_sta->lq.sta_id = sta_id;
+ lq_sta->lq.rs_table[0].rate_n_flags = 0;
+ lq_sta->ibss_sta_added = 1;
+ rs_initialize_lq(priv, conf, sta);
}
- if (!lq->ibss_sta_added)
+ if (!lq_sta->ibss_sta_added)
goto done;
}
done:
+ if ((i < 0) || (i > IWL_RATE_COUNT)) {
+ sel->rate = rate_lowest(local, local->oper_hw_mode, sta);
+ return;
+ }
sta_info_put(sta);
- if ((i < 0) || (i > IWL_RATE_COUNT))
- return rs_get_lowest_rate(local);
- return &priv->ieee_rates[i];
+ sel->rate = &priv->ieee_rates[i];
}
static void *rs_alloc_sta(void *priv, gfp_t gfp)
{
- struct iwl_rate_scale_priv *crl;
+ struct iwl4965_lq_sta *lq_sta;
int i, j;
IWL_DEBUG_RATE("create station rate scale window\n");
- crl = kzalloc(sizeof(struct iwl_rate_scale_priv), gfp);
+ lq_sta = kzalloc(sizeof(struct iwl4965_lq_sta), gfp);
- if (crl == NULL)
+ if (lq_sta == NULL)
return NULL;
- crl->lq.sta_id = 0xff;
+ 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(&(crl->lq_info[j].win[i]));
+ rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
- return crl;
+ return lq_sta;
}
static void rs_rate_init(void *priv_rate, void *priv_sta,
@@ -1801,16 +2098,17 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
struct sta_info *sta)
{
int i, j;
+ struct ieee80211_conf *conf = &local->hw.conf;
struct ieee80211_hw_mode *mode = local->oper_hw_mode;
- struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
- struct iwl_rate_scale_priv *crl = priv_sta;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)priv_rate;
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
- crl->flush_timer = 0;
- crl->supp_rates = sta->supp_rates;
+ lq_sta->flush_timer = 0;
+ lq_sta->supp_rates = sta->supp_rates;
sta->txrate = 3;
for (j = 0; j < LQ_SIZE; j++)
for (i = 0; i < IWL_RATE_COUNT; i++)
- rs_rate_scale_clear_window(&(crl->lq_info[j].win[i]));
+ rs_rate_scale_clear_window(&(lq_sta->lq_info[j].win[i]));
IWL_DEBUG_RATE("rate scale global init\n");
/* TODO: what is a good starting rate for STA? About middle? Maybe not
@@ -1818,9 +2116,9 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
- crl->ibss_sta_added = 0;
+ lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
- u8 sta_id = iwl_hw_find_station(priv, sta->addr);
+ u8 sta_id = iwl4965_hw_find_station(priv, sta->addr);
DECLARE_MAC_BUF(mac);
/* for IBSS the call are from tasklet */
@@ -1830,77 +2128,89 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_RATE("LQ: ADD station %s\n",
print_mac(mac, sta->addr));
- sta_id = iwl_add_station(priv,
- sta->addr, 0, CMD_ASYNC);
+ sta_id = iwl4965_add_station_flags(priv, sta->addr,
+ 0, CMD_ASYNC, NULL);
}
if ((sta_id != IWL_INVALID_STATION)) {
- crl->lq.sta_id = sta_id;
- crl->lq.rs_table[0].rate_n_flags = 0;
+ lq_sta->lq.sta_id = sta_id;
+ lq_sta->lq.rs_table[0].rate_n_flags = 0;
}
/* FIXME: this is w/a remove it later */
priv->assoc_station_added = 1;
}
+ /* Find highest tx rate supported by hardware and destination station */
for (i = 0; i < mode->num_rates; i++) {
if ((sta->supp_rates & BIT(i)) &&
(mode->rates[i].flags & IEEE80211_RATE_SUPPORTED))
sta->txrate = i;
}
sta->last_txrate = sta->txrate;
- /* For MODE_IEEE80211A mode cck rate are at end
- * rate table
- */
+ /* For MODE_IEEE80211A, cck rates are at end of rate table */
if (local->hw.conf.phymode == MODE_IEEE80211A)
sta->last_txrate += IWL_FIRST_OFDM_RATE;
- crl->is_dup = priv->is_dup;
- crl->valid_antenna = priv->valid_antenna;
- crl->antenna = priv->antenna;
- crl->is_green = rs_use_green(priv);
- crl->active_rate = priv->active_rate;
- crl->active_rate &= ~(0x1000);
- crl->active_rate_basic = priv->active_rate_basic;
- crl->phymode = priv->phymode;
-#ifdef CONFIG_IWLWIFI_HT
- crl->active_siso_rate = (priv->current_assoc_ht.supp_rates[0] << 1);
- crl->active_siso_rate |= (priv->current_assoc_ht.supp_rates[0] & 0x1);
- crl->active_siso_rate &= ~((u16)0x2);
- crl->active_siso_rate = crl->active_siso_rate << IWL_FIRST_OFDM_RATE;
-
- crl->active_mimo_rate = (priv->current_assoc_ht.supp_rates[1] << 1);
- crl->active_mimo_rate |= (priv->current_assoc_ht.supp_rates[1] & 0x1);
- crl->active_mimo_rate &= ~((u16)0x2);
- crl->active_mimo_rate = crl->active_mimo_rate << IWL_FIRST_OFDM_RATE;
- IWL_DEBUG_HT("MIMO RATE 0x%X SISO MASK 0x%X\n", crl->active_siso_rate,
- crl->active_mimo_rate);
-#endif /*CONFIG_IWLWIFI_HT*/
+ lq_sta->is_dup = 0;
+ lq_sta->valid_antenna = priv->valid_antenna;
+ lq_sta->antenna = priv->antenna;
+ lq_sta->is_green = rs_use_green(priv, conf);
+ lq_sta->active_rate = priv->active_rate;
+ lq_sta->active_rate &= ~(0x1000);
+ lq_sta->active_rate_basic = priv->active_rate_basic;
+ lq_sta->phymode = priv->phymode;
+#ifdef CONFIG_IWL4965_HT
+ /*
+ * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+ * supp_rates[] does not; shift to convert format, force 9 MBits off.
+ */
+ lq_sta->active_siso_rate = (priv->current_ht_config.supp_mcs_set[0] << 1);
+ lq_sta->active_siso_rate |=
+ (priv->current_ht_config.supp_mcs_set[0] & 0x1);
+ lq_sta->active_siso_rate &= ~((u16)0x2);
+ lq_sta->active_siso_rate =
+ lq_sta->active_siso_rate << IWL_FIRST_OFDM_RATE;
+
+ /* Same here */
+ lq_sta->active_mimo_rate = (priv->current_ht_config.supp_mcs_set[1] << 1);
+ lq_sta->active_mimo_rate |=
+ (priv->current_ht_config.supp_mcs_set[1] & 0x1);
+ lq_sta->active_mimo_rate &= ~((u16)0x2);
+ lq_sta->active_mimo_rate =
+ lq_sta->active_mimo_rate << IWL_FIRST_OFDM_RATE;
+ IWL_DEBUG_HT("SISO RATE 0x%X MIMO RATE 0x%X\n",
+ lq_sta->active_siso_rate,
+ lq_sta->active_mimo_rate);
+#endif /*CONFIG_IWL4965_HT*/
#ifdef CONFIG_MAC80211_DEBUGFS
- crl->drv = priv;
+ lq_sta->drv = priv;
#endif
if (priv->assoc_station_added)
priv->lq_mngr.lq_ready = 1;
- rs_initialize_lq(priv, sta);
+ rs_initialize_lq(priv, conf, sta);
}
-static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
- struct iwl_rate *tx_mcs,
- struct iwl_link_quality_cmd *lq_cmd)
+static void rs_fill_link_cmd(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *tx_mcs,
+ struct iwl4965_link_quality_cmd *lq_cmd)
{
int index = 0;
int rate_idx;
int repeat_rate = 0;
u8 ant_toggle_count = 0;
u8 use_ht_possible = 1;
- struct iwl_rate new_rate;
- struct iwl_scale_tbl_info tbl_type = { 0 };
+ struct iwl4965_rate new_rate;
+ struct iwl4965_scale_tbl_info tbl_type = { 0 };
- rs_dbgfs_set_mcs(lq_data, tx_mcs, index);
+ /* Override starting rate (index 0) if needed for debug purposes */
+ rs_dbgfs_set_mcs(lq_sta, tx_mcs, index);
- rs_get_tbl_info_from_mcs(tx_mcs, lq_data->phymode,
+ /* Interpret rate_n_flags */
+ rs_get_tbl_info_from_mcs(tx_mcs, lq_sta->phymode,
&tbl_type, &rate_idx);
+ /* How many times should we repeat the initial rate? */
if (is_legacy(tbl_type.lq_type)) {
ant_toggle_count = 1;
repeat_rate = IWL_NUMBER_TRY;
@@ -1909,19 +2219,27 @@ static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
lq_cmd->general_params.mimo_delimiter =
is_mimo(tbl_type.lq_type) ? 1 : 0;
+
+ /* Fill 1st table entry (index 0) */
lq_cmd->rs_table[index].rate_n_flags =
cpu_to_le32(tx_mcs->rate_n_flags);
new_rate.rate_n_flags = tx_mcs->rate_n_flags;
if (is_mimo(tbl_type.lq_type) || (tbl_type.antenna_type == ANT_MAIN))
- lq_cmd->general_params.single_stream_ant_msk = 1;
+ lq_cmd->general_params.single_stream_ant_msk
+ = LINK_QUAL_ANT_A_MSK;
else
- lq_cmd->general_params.single_stream_ant_msk = 2;
+ lq_cmd->general_params.single_stream_ant_msk
+ = LINK_QUAL_ANT_B_MSK;
index++;
repeat_rate--;
+ /* Fill rest of rate table */
while (index < LINK_QUAL_MAX_RETRY_NUM) {
+ /* Repeat initial/next rate.
+ * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
+ * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_count <
@@ -1933,22 +2251,30 @@ static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
}
}
- rs_dbgfs_set_mcs(lq_data, &new_rate, index);
+ /* Override next rate if needed for debug purposes */
+ rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+ /* Fill next table entry */
lq_cmd->rs_table[index].rate_n_flags =
cpu_to_le32(new_rate.rate_n_flags);
repeat_rate--;
index++;
}
- rs_get_tbl_info_from_mcs(&new_rate, lq_data->phymode, &tbl_type,
+ rs_get_tbl_info_from_mcs(&new_rate, lq_sta->phymode, &tbl_type,
&rate_idx);
+ /* Indicate to uCode which entries might be MIMO.
+ * If initial rate was MIMO, this will finally end up
+ * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
if (is_mimo(tbl_type.lq_type))
lq_cmd->general_params.mimo_delimiter = index;
- rs_get_lower_rate(lq_data, &tbl_type, rate_idx,
+ /* Get next rate */
+ rs_get_lower_rate(lq_sta, &tbl_type, rate_idx,
use_ht_possible, &new_rate);
+ /* How many times should we repeat the next rate? */
if (is_legacy(tbl_type.lq_type)) {
if (ant_toggle_count < NUM_TRY_BEFORE_ANTENNA_TOGGLE)
ant_toggle_count++;
@@ -1960,9 +2286,14 @@ static void rs_fill_link_cmd(struct iwl_rate_scale_priv *lq_data,
} else
repeat_rate = IWL_HT_NUMBER_TRY;
+ /* Don't allow HT rates after next pass.
+ * rs_get_lower_rate() will change type to LQ_A or LQ_G. */
use_ht_possible = 0;
- rs_dbgfs_set_mcs(lq_data, &new_rate, index);
+ /* Override next rate if needed for debug purposes */
+ rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+ /* Fill next table entry */
lq_cmd->rs_table[index].rate_n_flags =
cpu_to_le32(new_rate.rate_n_flags);
@@ -1987,27 +2318,27 @@ static void rs_free(void *priv_rate)
static void rs_clear(void *priv_rate)
{
- struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *) priv_rate;
IWL_DEBUG_RATE("enter\n");
priv->lq_mngr.lq_ready = 0;
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
if (priv->lq_mngr.agg_ctrl.granted_ba)
iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);
-#endif /*CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
IWL_DEBUG_RATE("leave\n");
}
static void rs_free_sta(void *priv, void *priv_sta)
{
- struct iwl_rate_scale_priv *rs_priv = priv_sta;
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
IWL_DEBUG_RATE("enter\n");
- kfree(rs_priv);
+ kfree(lq_sta);
IWL_DEBUG_RATE("leave\n");
}
@@ -2018,19 +2349,19 @@ static int open_file_generic(struct inode *inode, struct file *file)
file->private_data = inode->i_private;
return 0;
}
-static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
- struct iwl_rate *mcs, int index)
+static void rs_dbgfs_set_mcs(struct iwl4965_lq_sta *lq_sta,
+ struct iwl4965_rate *mcs, int index)
{
u32 base_rate;
- if (rs_priv->phymode == (u8) MODE_IEEE80211A)
+ if (lq_sta->phymode == (u8) MODE_IEEE80211A)
base_rate = 0x800D;
else
base_rate = 0x820A;
- if (rs_priv->dbg_fixed.rate_n_flags) {
+ if (lq_sta->dbg_fixed.rate_n_flags) {
if (index < 12)
- mcs->rate_n_flags = rs_priv->dbg_fixed.rate_n_flags;
+ mcs->rate_n_flags = lq_sta->dbg_fixed.rate_n_flags;
else
mcs->rate_n_flags = base_rate;
IWL_DEBUG_RATE("Fixed rate ON\n");
@@ -2043,7 +2374,7 @@ static void rs_dbgfs_set_mcs(struct iwl_rate_scale_priv *rs_priv,
static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
- struct iwl_rate_scale_priv *rs_priv = file->private_data;
+ struct iwl4965_lq_sta *lq_sta = file->private_data;
char buf[64];
int buf_size;
u32 parsed_rate;
@@ -2054,20 +2385,20 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
return -EFAULT;
if (sscanf(buf, "%x", &parsed_rate) == 1)
- rs_priv->dbg_fixed.rate_n_flags = parsed_rate;
+ lq_sta->dbg_fixed.rate_n_flags = parsed_rate;
else
- rs_priv->dbg_fixed.rate_n_flags = 0;
+ lq_sta->dbg_fixed.rate_n_flags = 0;
- rs_priv->active_rate = 0x0FFF;
- rs_priv->active_siso_rate = 0x1FD0;
- rs_priv->active_mimo_rate = 0x1FD0;
+ lq_sta->active_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */
+ lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
+ lq_sta->active_mimo_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */
IWL_DEBUG_RATE("sta_id %d rate 0x%X\n",
- rs_priv->lq.sta_id, rs_priv->dbg_fixed.rate_n_flags);
+ lq_sta->lq.sta_id, lq_sta->dbg_fixed.rate_n_flags);
- if (rs_priv->dbg_fixed.rate_n_flags) {
- rs_fill_link_cmd(rs_priv, &rs_priv->dbg_fixed, &rs_priv->lq);
- rs_send_lq_cmd(rs_priv->drv, &rs_priv->lq, CMD_ASYNC);
+ if (lq_sta->dbg_fixed.rate_n_flags) {
+ rs_fill_link_cmd(lq_sta, &lq_sta->dbg_fixed, &lq_sta->lq);
+ rs_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC);
}
return count;
@@ -2080,38 +2411,38 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
int desc = 0;
int i = 0;
- struct iwl_rate_scale_priv *rs_priv = file->private_data;
+ struct iwl4965_lq_sta *lq_sta = file->private_data;
- desc += sprintf(buff+desc, "sta_id %d\n", rs_priv->lq.sta_id);
+ desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
- rs_priv->total_failed, rs_priv->total_success,
- rs_priv->active_rate);
+ lq_sta->total_failed, lq_sta->total_success,
+ lq_sta->active_rate);
desc += sprintf(buff+desc, "fixed rate 0x%X\n",
- rs_priv->dbg_fixed.rate_n_flags);
+ lq_sta->dbg_fixed.rate_n_flags);
desc += sprintf(buff+desc, "general:"
"flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
- rs_priv->lq.general_params.flags,
- rs_priv->lq.general_params.mimo_delimiter,
- rs_priv->lq.general_params.single_stream_ant_msk,
- rs_priv->lq.general_params.dual_stream_ant_msk);
+ lq_sta->lq.general_params.flags,
+ lq_sta->lq.general_params.mimo_delimiter,
+ lq_sta->lq.general_params.single_stream_ant_msk,
+ lq_sta->lq.general_params.dual_stream_ant_msk);
desc += sprintf(buff+desc, "agg:"
"time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
- le16_to_cpu(rs_priv->lq.agg_params.agg_time_limit),
- rs_priv->lq.agg_params.agg_dis_start_th,
- rs_priv->lq.agg_params.agg_frame_cnt_limit);
+ le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit),
+ lq_sta->lq.agg_params.agg_dis_start_th,
+ lq_sta->lq.agg_params.agg_frame_cnt_limit);
desc += sprintf(buff+desc,
"Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
- rs_priv->lq.general_params.start_rate_index[0],
- rs_priv->lq.general_params.start_rate_index[1],
- rs_priv->lq.general_params.start_rate_index[2],
- rs_priv->lq.general_params.start_rate_index[3]);
+ lq_sta->lq.general_params.start_rate_index[0],
+ lq_sta->lq.general_params.start_rate_index[1],
+ lq_sta->lq.general_params.start_rate_index[2],
+ lq_sta->lq.general_params.start_rate_index[3]);
for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
desc += sprintf(buff+desc, " rate[%d] 0x%X\n",
- i, le32_to_cpu(rs_priv->lq.rs_table[i].rate_n_flags));
+ i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
}
@@ -2128,22 +2459,22 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
int desc = 0;
int i, j;
- struct iwl_rate_scale_priv *rs_priv = file->private_data;
+ struct iwl4965_lq_sta *lq_sta = file->private_data;
for (i = 0; i < LQ_SIZE; i++) {
desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n"
"rate=0x%X\n",
- rs_priv->active_tbl == i?"*":"x",
- rs_priv->lq_info[i].lq_type,
- rs_priv->lq_info[i].is_SGI,
- rs_priv->lq_info[i].is_fat,
- rs_priv->lq_info[i].is_dup,
- rs_priv->lq_info[i].current_rate.rate_n_flags);
+ lq_sta->active_tbl == i?"*":"x",
+ lq_sta->lq_info[i].lq_type,
+ lq_sta->lq_info[i].is_SGI,
+ lq_sta->lq_info[i].is_fat,
+ lq_sta->lq_info[i].is_dup,
+ lq_sta->lq_info[i].current_rate.rate_n_flags);
for (j = 0; j < IWL_RATE_COUNT; j++) {
desc += sprintf(buff+desc,
- "counter=%d success=%d %%=%d\n",
- rs_priv->lq_info[i].win[j].counter,
- rs_priv->lq_info[i].win[j].success_counter,
- rs_priv->lq_info[i].win[j].success_ratio);
+ "counter=%d success=%d %%=%d\n",
+ lq_sta->lq_info[i].win[j].counter,
+ lq_sta->lq_info[i].win[j].success_counter,
+ lq_sta->lq_info[i].win[j].success_ratio);
}
}
return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
@@ -2157,20 +2488,20 @@ static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
static void rs_add_debugfs(void *priv, void *priv_sta,
struct dentry *dir)
{
- struct iwl_rate_scale_priv *rs_priv = priv_sta;
- rs_priv->rs_sta_dbgfs_scale_table_file =
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
+ lq_sta->rs_sta_dbgfs_scale_table_file =
debugfs_create_file("rate_scale_table", 0600, dir,
- rs_priv, &rs_sta_dbgfs_scale_table_ops);
- rs_priv->rs_sta_dbgfs_stats_table_file =
+ lq_sta, &rs_sta_dbgfs_scale_table_ops);
+ lq_sta->rs_sta_dbgfs_stats_table_file =
debugfs_create_file("rate_stats_table", 0600, dir,
- rs_priv, &rs_sta_dbgfs_stats_table_ops);
+ lq_sta, &rs_sta_dbgfs_stats_table_ops);
}
static void rs_remove_debugfs(void *priv, void *priv_sta)
{
- struct iwl_rate_scale_priv *rs_priv = priv_sta;
- debugfs_remove(rs_priv->rs_sta_dbgfs_scale_table_file);
- debugfs_remove(rs_priv->rs_sta_dbgfs_stats_table_file);
+ struct iwl4965_lq_sta *lq_sta = priv_sta;
+ debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file);
+ debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
}
#endif
@@ -2191,13 +2522,13 @@ static struct rate_control_ops rs_ops = {
#endif
};
-int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
+int iwl4965_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
{
struct ieee80211_local *local = hw_to_local(hw);
- struct iwl_priv *priv = hw->priv;
- struct iwl_rate_scale_priv *rs_priv;
+ struct iwl4965_priv *priv = hw->priv;
+ struct iwl4965_lq_sta *lq_sta;
struct sta_info *sta;
- int count = 0, i;
+ int cnt = 0, i;
u32 samples = 0, success = 0, good = 0;
unsigned long now = jiffies;
u32 max_time = 0;
@@ -2213,10 +2544,10 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
return sprintf(buf, "station %d not found\n", sta_id);
}
- rs_priv = (void *)sta->rate_ctrl_priv;
+ lq_sta = (void *)sta->rate_ctrl_priv;
- lq_type = rs_priv->lq_info[rs_priv->active_tbl].lq_type;
- antenna = rs_priv->lq_info[rs_priv->active_tbl].antenna_type;
+ lq_type = lq_sta->lq_info[lq_sta->active_tbl].lq_type;
+ antenna = lq_sta->lq_info[lq_sta->active_tbl].antenna_type;
if (is_legacy(lq_type))
i = IWL_RATE_54M_INDEX;
@@ -2225,35 +2556,35 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
while (1) {
u64 mask;
int j;
- int active = rs_priv->active_tbl;
+ int active = lq_sta->active_tbl;
- count +=
- sprintf(&buf[count], " %2dMbs: ", iwl_rates[i].ieee / 2);
+ cnt +=
+ sprintf(&buf[cnt], " %2dMbs: ", iwl4965_rates[i].ieee / 2);
mask = (1ULL << (IWL_RATE_MAX_WINDOW - 1));
for (j = 0; j < IWL_RATE_MAX_WINDOW; j++, mask >>= 1)
- buf[count++] =
- (rs_priv->lq_info[active].win[i].data & mask)
+ buf[cnt++] =
+ (lq_sta->lq_info[active].win[i].data & mask)
? '1' : '0';
- samples += rs_priv->lq_info[active].win[i].counter;
- good += rs_priv->lq_info[active].win[i].success_counter;
- success += rs_priv->lq_info[active].win[i].success_counter *
- iwl_rates[i].ieee;
+ samples += lq_sta->lq_info[active].win[i].counter;
+ good += lq_sta->lq_info[active].win[i].success_counter;
+ success += lq_sta->lq_info[active].win[i].success_counter *
+ iwl4965_rates[i].ieee;
- if (rs_priv->lq_info[active].win[i].stamp) {
+ if (lq_sta->lq_info[active].win[i].stamp) {
int delta =
jiffies_to_msecs(now -
- rs_priv->lq_info[active].win[i].stamp);
+ lq_sta->lq_info[active].win[i].stamp);
if (delta > max_time)
max_time = delta;
- count += sprintf(&buf[count], "%5dms\n", delta);
+ cnt += sprintf(&buf[cnt], "%5dms\n", delta);
} else
- buf[count++] = '\n';
+ buf[cnt++] = '\n';
- j = iwl_get_prev_ieee_rate(i);
+ j = iwl4965_get_prev_ieee_rate(i);
if (j == i)
break;
i = j;
@@ -2261,37 +2592,38 @@ int iwl_fill_rs_info(struct ieee80211_hw *hw, char *buf, u8 sta_id)
/* Display the average rate of all samples taken.
*
- * NOTE: We multiple # of samples by 2 since the IEEE measurement
- * added from iwl_rates is actually 2X the rate */
+ * NOTE: We multiply # of samples by 2 since the IEEE measurement
+ * added from iwl4965_rates is actually 2X the rate */
if (samples)
- count += sprintf(&buf[count],
+ cnt += sprintf(&buf[cnt],
"\nAverage rate is %3d.%02dMbs over last %4dms\n"
"%3d%% success (%d good packets over %d tries)\n",
success / (2 * samples), (success * 5 / samples) % 10,
max_time, good * 100 / samples, good, samples);
else
- count += sprintf(&buf[count], "\nAverage rate: 0Mbs\n");
- count += sprintf(&buf[count], "\nrate scale type %d anntena %d "
+ cnt += sprintf(&buf[cnt], "\nAverage rate: 0Mbs\n");
+
+ cnt += sprintf(&buf[cnt], "\nrate scale type %d antenna %d "
"active_search %d rate index %d\n", lq_type, antenna,
- rs_priv->search_better_tbl, sta->last_txrate);
+ lq_sta->search_better_tbl, sta->last_txrate);
sta_info_put(sta);
- return count;
+ return cnt;
}
-void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
priv->lq_mngr.lq_ready = 1;
}
-void iwl_rate_control_register(struct ieee80211_hw *hw)
+void iwl4965_rate_control_register(struct ieee80211_hw *hw)
{
ieee80211_rate_control_register(&rs_ops);
}
-void iwl_rate_control_unregister(struct ieee80211_hw *hw)
+void iwl4965_rate_control_unregister(struct ieee80211_hw *hw)
{
ieee80211_rate_control_unregister(&rs_ops);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
index c6325f72df68..55f707382787 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.h
@@ -29,11 +29,11 @@
#include "iwl-4965.h"
-struct iwl_rate_info {
- u8 plcp;
- u8 plcp_siso;
- u8 plcp_mimo;
- u8 ieee;
+struct iwl4965_rate_info {
+ u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */
+ u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */
+ u8 plcp_mimo; /* uCode API: IWL_RATE_MIMO_6M_PLCP, etc. */
+ u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */
u8 prev_ieee; /* previous rate in IEEE speeds */
u8 next_ieee; /* next rate in IEEE speeds */
u8 prev_rs; /* previous rate used in rs algo */
@@ -42,6 +42,10 @@ struct iwl_rate_info {
u8 next_rs_tgg; /* next rate used in TGG rs algo */
};
+/*
+ * These serve as indexes into
+ * struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
+ */
enum {
IWL_RATE_1M_INDEX = 0,
IWL_RATE_2M_INDEX,
@@ -69,20 +73,21 @@ enum {
};
/* #define vs. enum to keep from defaulting to 'large integer' */
-#define IWL_RATE_6M_MASK (1<<IWL_RATE_6M_INDEX)
-#define IWL_RATE_9M_MASK (1<<IWL_RATE_9M_INDEX)
-#define IWL_RATE_12M_MASK (1<<IWL_RATE_12M_INDEX)
-#define IWL_RATE_18M_MASK (1<<IWL_RATE_18M_INDEX)
-#define IWL_RATE_24M_MASK (1<<IWL_RATE_24M_INDEX)
-#define IWL_RATE_36M_MASK (1<<IWL_RATE_36M_INDEX)
-#define IWL_RATE_48M_MASK (1<<IWL_RATE_48M_INDEX)
-#define IWL_RATE_54M_MASK (1<<IWL_RATE_54M_INDEX)
-#define IWL_RATE_60M_MASK (1<<IWL_RATE_60M_INDEX)
-#define IWL_RATE_1M_MASK (1<<IWL_RATE_1M_INDEX)
-#define IWL_RATE_2M_MASK (1<<IWL_RATE_2M_INDEX)
-#define IWL_RATE_5M_MASK (1<<IWL_RATE_5M_INDEX)
-#define IWL_RATE_11M_MASK (1<<IWL_RATE_11M_INDEX)
-
+#define IWL_RATE_6M_MASK (1 << IWL_RATE_6M_INDEX)
+#define IWL_RATE_9M_MASK (1 << IWL_RATE_9M_INDEX)
+#define IWL_RATE_12M_MASK (1 << IWL_RATE_12M_INDEX)
+#define IWL_RATE_18M_MASK (1 << IWL_RATE_18M_INDEX)
+#define IWL_RATE_24M_MASK (1 << IWL_RATE_24M_INDEX)
+#define IWL_RATE_36M_MASK (1 << IWL_RATE_36M_INDEX)
+#define IWL_RATE_48M_MASK (1 << IWL_RATE_48M_INDEX)
+#define IWL_RATE_54M_MASK (1 << IWL_RATE_54M_INDEX)
+#define IWL_RATE_60M_MASK (1 << IWL_RATE_60M_INDEX)
+#define IWL_RATE_1M_MASK (1 << IWL_RATE_1M_INDEX)
+#define IWL_RATE_2M_MASK (1 << IWL_RATE_2M_INDEX)
+#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX)
+#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX)
+
+/* 4965 uCode API values for legacy bit rates, both OFDM and CCK */
enum {
IWL_RATE_6M_PLCP = 13,
IWL_RATE_9M_PLCP = 15,
@@ -99,7 +104,7 @@ enum {
IWL_RATE_11M_PLCP = 110,
};
-/* OFDM HT rate plcp */
+/* 4965 uCode API values for OFDM high-throughput (HT) bit rates */
enum {
IWL_RATE_SISO_6M_PLCP = 0,
IWL_RATE_SISO_12M_PLCP = 1,
@@ -121,6 +126,7 @@ enum {
IWL_RATE_MIMO_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
};
+/* MAC header values for bit rates */
enum {
IWL_RATE_6M_IEEE = 12,
IWL_RATE_9M_IEEE = 18,
@@ -163,20 +169,15 @@ enum {
(IWL_OFDM_BASIC_RATES_MASK | \
IWL_CCK_BASIC_RATES_MASK)
-#define IWL_RATES_MASK ((1<<IWL_RATE_COUNT)-1)
+#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
#define IWL_INVALID_VALUE -1
#define IWL_MIN_RSSI_VAL -100
#define IWL_MAX_RSSI_VAL 0
-#define IWL_LEGACY_SWITCH_ANTENNA 0
-#define IWL_LEGACY_SWITCH_SISO 1
-#define IWL_LEGACY_SWITCH_MIMO 2
-
-#define IWL_RS_GOOD_RATIO 12800
-
-#define IWL_ACTION_LIMIT 3
+/* These values specify how many Tx frame attempts before
+ * searching for a new modulation mode */
#define IWL_LEGACY_FAILURE_LIMIT 160
#define IWL_LEGACY_SUCCESS_LIMIT 480
#define IWL_LEGACY_TABLE_COUNT 160
@@ -185,82 +186,104 @@ enum {
#define IWL_NONE_LEGACY_SUCCESS_LIMIT 4500
#define IWL_NONE_LEGACY_TABLE_COUNT 1500
-#define IWL_RATE_SCALE_SWITCH (10880)
+/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
+#define IWL_RS_GOOD_RATIO 12800 /* 100% */
+#define IWL_RATE_SCALE_SWITCH 10880 /* 85% */
+#define IWL_RATE_HIGH_TH 10880 /* 85% */
+#define IWL_RATE_INCREASE_TH 8960 /* 70% */
+#define IWL_RATE_DECREASE_TH 1920 /* 15% */
+/* possible actions when in legacy mode */
+#define IWL_LEGACY_SWITCH_ANTENNA 0
+#define IWL_LEGACY_SWITCH_SISO 1
+#define IWL_LEGACY_SWITCH_MIMO 2
+
+/* possible actions when in siso mode */
#define IWL_SISO_SWITCH_ANTENNA 0
#define IWL_SISO_SWITCH_MIMO 1
#define IWL_SISO_SWITCH_GI 2
+/* possible actions when in mimo mode */
#define IWL_MIMO_SWITCH_ANTENNA_A 0
#define IWL_MIMO_SWITCH_ANTENNA_B 1
#define IWL_MIMO_SWITCH_GI 2
-#define LQ_SIZE 2
+#define IWL_ACTION_LIMIT 3 /* # possible actions */
+
+#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */
-extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT];
+extern const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT];
-enum iwl_table_type {
+enum iwl4965_table_type {
LQ_NONE,
- LQ_G,
+ LQ_G, /* legacy types */
LQ_A,
- LQ_SISO,
+ LQ_SISO, /* high-throughput types */
LQ_MIMO,
LQ_MAX,
};
-enum iwl_antenna_type {
+#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
+#define is_siso(tbl) (((tbl) == LQ_SISO))
+#define is_mimo(tbl) (((tbl) == LQ_MIMO))
+#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
+#define is_a_band(tbl) (((tbl) == LQ_A))
+#define is_g_and(tbl) (((tbl) == LQ_G))
+
+/* 4965 has 2 antennas/chains for Tx (but 3 for Rx) */
+enum iwl4965_antenna_type {
ANT_NONE,
ANT_MAIN,
ANT_AUX,
ANT_BOTH,
};
-static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
+static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
{
- u8 rate = iwl_rates[rate_index].prev_ieee;
+ u8 rate = iwl4965_rates[rate_index].prev_ieee;
if (rate == IWL_RATE_INVALID)
rate = rate_index;
return rate;
}
-extern int iwl_rate_index_from_plcp(int plcp);
+extern int iwl4965_rate_index_from_plcp(int plcp);
/**
- * iwl_fill_rs_info - Fill an output text buffer with the rate representation
+ * iwl4965_fill_rs_info - Fill an output text buffer with the rate representation
*
* NOTE: This is provided as a quick mechanism for a user to visualize
- * the performance of the rate control alogirthm and is not meant to be
+ * the performance of the rate control algorithm and is not meant to be
* parsed software.
*/
-extern int iwl_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
+extern int iwl4965_fill_rs_info(struct ieee80211_hw *, char *buf, u8 sta_id);
/**
- * iwl_rate_scale_init - Initialize the rate scale table based on assoc info
+ * iwl4965_rate_scale_init - Initialize the rate scale table based on assoc info
*
- * The specific througput table used is based on the type of network
+ * The specific throughput table used is based on the type of network
* the associated with, including A, B, G, and G w/ TGG protection
*/
-extern void iwl_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+extern void iwl4965_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
/**
- * iwl_rate_control_register - Register the rate control algorithm callbacks
+ * iwl4965_rate_control_register - Register the rate control algorithm callbacks
*
* Since the rate control algorithm is hardware specific, there is no need
* or reason to place it as a stand alone module. The driver can call
- * iwl_rate_control_register in order to register the rate control callbacks
+ * iwl4965_rate_control_register in order to register the rate control callbacks
* with the mac80211 subsystem. This should be performed prior to calling
* ieee80211_register_hw
*
*/
-extern void iwl_rate_control_register(struct ieee80211_hw *hw);
+extern void iwl4965_rate_control_register(struct ieee80211_hw *hw);
/**
- * iwl_rate_control_unregister - Unregister the rate control callbacks
+ * iwl4965_rate_control_unregister - Unregister the rate control callbacks
*
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
*/
-extern void iwl_rate_control_unregister(struct ieee80211_hw *hw);
+extern void iwl4965_rate_control_unregister(struct ieee80211_hw *hw);
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 891f90d2f019..04db34ba814b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -36,13 +36,13 @@
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
-#define IWL 4965
-
-#include "iwlwifi.h"
#include "iwl-4965.h"
#include "iwl-helpers.h"
+static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv);
+
#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, \
@@ -63,7 +63,7 @@
* maps to IWL_RATE_INVALID
*
*/
-const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = {
+const struct iwl4965_rate_info iwl4965_rates[IWL_RATE_COUNT] = {
IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */
IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */
IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */
@@ -85,16 +85,16 @@ static int is_fat_channel(__le32 rxon_flags)
(rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK);
}
-static u8 is_single_stream(struct iwl_priv *priv)
+static u8 is_single_stream(struct iwl4965_priv *priv)
{
-#ifdef CONFIG_IWLWIFI_HT
- if (!priv->is_ht_enabled || !priv->current_assoc_ht.is_ht ||
- (priv->active_rate_ht[1] == 0) ||
+#ifdef CONFIG_IWL4965_HT
+ if (!priv->current_ht_config.is_ht ||
+ (priv->current_ht_config.supp_mcs_set[1] == 0) ||
(priv->ps_mode == IWL_MIMO_PS_STATIC))
return 1;
#else
return 1;
-#endif /*CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT */
return 0;
}
@@ -104,7 +104,7 @@ static u8 is_single_stream(struct iwl_priv *priv)
* MIMO (dual stream) requires at least 2, but works better with 3.
* This does not determine *which* chains to use, just how many.
*/
-static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv,
+static int iwl4965_get_rx_chain_counter(struct iwl4965_priv *priv,
u8 *idle_state, u8 *rx_state)
{
u8 is_single = is_single_stream(priv);
@@ -133,32 +133,32 @@ static int iwl4965_get_rx_chain_counter(struct iwl_priv *priv,
return 0;
}
-int iwl_hw_rxq_stop(struct iwl_priv *priv)
+int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv)
{
int rc;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- /* stop HW */
- iwl_write_restricted(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- rc = iwl_poll_restricted_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ /* stop Rx DMA */
+ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ rc = iwl4965_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
(1 << 24), 1000);
if (rc < 0)
IWL_ERROR("Can't stop Rx DMA.\n");
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
+u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *addr)
{
int i;
int start = 0;
@@ -190,104 +190,114 @@ u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *addr)
return ret;
}
-static int iwl4965_nic_set_pwr_src(struct iwl_priv *priv, int pwr_max)
+static int iwl4965_nic_set_pwr_src(struct iwl4965_priv *priv, int pwr_max)
{
- int rc = 0;
+ int ret;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
- if (rc) {
+ ret = iwl4965_grab_nic_access(priv);
+ if (ret) {
spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
+ return ret;
}
if (!pwr_max) {
u32 val;
- rc = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
+ ret = pci_read_config_dword(priv->pci_dev, PCI_POWER_SOURCE,
&val);
if (val & PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT)
- iwl_set_bits_mask_restricted_reg(
- priv, APMG_PS_CTRL_REG,
+ iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
~APMG_PS_CTRL_MSK_PWR_SRC);
} else
- iwl_set_bits_mask_restricted_reg(
- priv, APMG_PS_CTRL_REG,
+ iwl4965_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
~APMG_PS_CTRL_MSK_PWR_SRC);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
+ return ret;
}
-static int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+static int iwl4965_rx_init(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
{
int rc;
unsigned long flags;
+ unsigned int rb_size;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- /* stop HW */
- iwl_write_restricted(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+ if (iwl4965_param_amsdu_size_8K)
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+ else
+ rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+ /* Stop Rx DMA */
+ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+ /* Reset driver's Rx queue write index */
+ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
- iwl_write_restricted(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
- iwl_write_restricted(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+ /* Tell device where to find RBD circular buffer in DRAM */
+ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
rxq->dma_addr >> 8);
- iwl_write_restricted(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+ /* Tell device where in DRAM to update its Rx status */
+ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
(priv->hw_setting.shared_phys +
- offsetof(struct iwl_shared, val0)) >> 4);
+ offsetof(struct iwl4965_shared, val0)) >> 4);
- iwl_write_restricted(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+ /* Enable Rx DMA, enable host interrupt, Rx buffer size 4k, 256 RBDs */
+ iwl4965_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
- IWL_FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K |
+ rb_size |
/*0x10 << 4 | */
(RX_QUEUE_SIZE_LOG <<
FH_RCSR_RX_CONFIG_RBDCB_SIZE_BITSHIFT));
/*
- * iwl_write32(priv,CSR_INT_COAL_REG,0);
+ * iwl4965_write32(priv,CSR_INT_COAL_REG,0);
*/
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-static int iwl4965_kw_init(struct iwl_priv *priv)
+/* Tell 4965 where to find the "keep warm" buffer */
+static int iwl4965_kw_init(struct iwl4965_priv *priv)
{
unsigned long flags;
int rc;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
goto out;
- iwl_write_restricted(priv, IWL_FH_KW_MEM_ADDR_REG,
+ iwl4965_write_direct32(priv, IWL_FH_KW_MEM_ADDR_REG,
priv->kw.dma_addr >> 4);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
out:
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
-static int iwl4965_kw_alloc(struct iwl_priv *priv)
+static int iwl4965_kw_alloc(struct iwl4965_priv *priv)
{
struct pci_dev *dev = priv->pci_dev;
- struct iwl_kw *kw = &priv->kw;
+ struct iwl4965_kw *kw = &priv->kw;
kw->size = IWL4965_KW_SIZE; /* TBW need set somewhere else */
kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
@@ -300,14 +310,19 @@ static int iwl4965_kw_alloc(struct iwl_priv *priv)
#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
-int iwl4965_set_fat_chan_info(struct iwl_priv *priv, int phymode, u16 channel,
- const struct iwl_eeprom_channel *eeprom_ch,
+/**
+ * iwl4965_set_fat_chan_info - Copy fat channel info into driver's priv.
+ *
+ * Does not set up a command, or touch hardware.
+ */
+int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode, u16 channel,
+ const struct iwl4965_eeprom_channel *eeprom_ch,
u8 fat_extension_channel)
{
- struct iwl_channel_info *ch_info;
+ struct iwl4965_channel_info *ch_info;
- ch_info = (struct iwl_channel_info *)
- iwl_get_channel_info(priv, phymode, channel);
+ ch_info = (struct iwl4965_channel_info *)
+ iwl4965_get_channel_info(priv, phymode, channel);
if (!is_channel_valid(ch_info))
return -1;
@@ -340,10 +355,13 @@ int iwl4965_set_fat_chan_info(struct iwl_priv *priv, int phymode, u16 channel,
return 0;
}
-static void iwl4965_kw_free(struct iwl_priv *priv)
+/**
+ * iwl4965_kw_free - Free the "keep warm" buffer
+ */
+static void iwl4965_kw_free(struct iwl4965_priv *priv)
{
struct pci_dev *dev = priv->pci_dev;
- struct iwl_kw *kw = &priv->kw;
+ struct iwl4965_kw *kw = &priv->kw;
if (kw->v_addr) {
pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
@@ -358,7 +376,7 @@ static void iwl4965_kw_free(struct iwl_priv *priv)
* @param priv
* @return error code
*/
-static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
+static int iwl4965_txq_ctx_reset(struct iwl4965_priv *priv)
{
int rc = 0;
int txq_id, slots_num;
@@ -366,9 +384,10 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
iwl4965_kw_free(priv);
- iwl_hw_txq_ctx_free(priv);
+ /* Free all tx/cmd queues and keep-warm buffer */
+ iwl4965_hw_txq_ctx_free(priv);
- /* Tx CMD queue */
+ /* Alloc keep-warm buffer */
rc = iwl4965_kw_alloc(priv);
if (rc) {
IWL_ERROR("Keep Warm allocation failed");
@@ -377,28 +396,31 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (unlikely(rc)) {
IWL_ERROR("TX reset failed");
spin_unlock_irqrestore(&priv->lock, flags);
goto error_reset;
}
- iwl_write_restricted_reg(priv, SCD_TXFACT, 0);
- iwl_release_restricted_access(priv);
+ /* Turn off all Tx DMA channels */
+ iwl4965_write_prph(priv, KDR_SCD_TXFACT, 0);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
+ /* Tell 4965 where to find the keep-warm buffer */
rc = iwl4965_kw_init(priv);
if (rc) {
IWL_ERROR("kw_init failed\n");
goto error_reset;
}
- /* Tx queue(s) */
+ /* Alloc and init all (default 16) Tx queues,
+ * including the command queue (#4) */
for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
+ rc = iwl4965_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
txq_id);
if (rc) {
IWL_ERROR("Tx %d queue init failed\n", txq_id);
@@ -409,32 +431,32 @@ static int iwl4965_txq_ctx_reset(struct iwl_priv *priv)
return rc;
error:
- iwl_hw_txq_ctx_free(priv);
+ iwl4965_hw_txq_ctx_free(priv);
error_reset:
iwl4965_kw_free(priv);
error_kw:
return rc;
}
-int iwl_hw_nic_init(struct iwl_priv *priv)
+int iwl4965_hw_nic_init(struct iwl4965_priv *priv)
{
int rc;
unsigned long flags;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
u8 rev_id;
u32 val;
u8 val_link;
- iwl_power_init_handle(priv);
+ iwl4965_power_init_handle(priv);
/* nic_init */
spin_lock_irqsave(&priv->lock, flags);
- iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- rc = iwl_poll_bit(priv, CSR_GP_CNTRL,
+ iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ rc = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (rc < 0) {
@@ -443,26 +465,26 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
return rc;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_read_restricted_reg(priv, APMG_CLK_CTRL_REG);
+ iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
- iwl_write_restricted_reg(priv, APMG_CLK_CTRL_REG,
+ iwl4965_write_prph(priv, APMG_CLK_CTRL_REG,
APMG_CLK_VAL_DMA_CLK_RQT |
APMG_CLK_VAL_BSM_CLK_RQT);
- iwl_read_restricted_reg(priv, APMG_CLK_CTRL_REG);
+ iwl4965_read_prph(priv, APMG_CLK_CTRL_REG);
udelay(20);
- iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
+ iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
- iwl_release_restricted_access(priv);
- iwl_write32(priv, CSR_INT_COALESCING, 512 / 32);
+ iwl4965_release_nic_access(priv);
+ iwl4965_write32(priv, CSR_INT_COALESCING, 512 / 32);
spin_unlock_irqrestore(&priv->lock, flags);
/* Determine HW type */
@@ -484,11 +506,6 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
- /* Read the EEPROM */
- rc = iwl_eeprom_init(priv);
- if (rc)
- return rc;
-
if (priv->eeprom.calib_version < EEPROM_TX_POWER_VERSION_NEW) {
IWL_ERROR("Older EEPROM detected! Aborting.\n");
return -EINVAL;
@@ -503,51 +520,53 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
/* set CSR_HW_CONFIG_REG for uCode use */
- iwl_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R |
+ iwl4965_set_bit(priv, CSR_SW_VER, CSR_HW_IF_CONFIG_REG_BIT_KEDRON_R |
CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc < 0) {
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO("Failed to init the card\n");
return rc;
}
- iwl_read_restricted_reg(priv, APMG_PS_CTRL_REG);
- iwl_set_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl4965_read_prph(priv, APMG_PS_CTRL_REG);
+ iwl4965_set_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
udelay(5);
- iwl_clear_bits_restricted_reg(priv, APMG_PS_CTRL_REG,
+ iwl4965_clear_bits_prph(priv, APMG_PS_CTRL_REG,
APMG_PS_CTRL_VAL_RESET_REQ);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_hw_card_show_info(priv);
+ iwl4965_hw_card_show_info(priv);
/* end nic_init */
/* Allocate the RX queue, or reset if it is already allocated */
if (!rxq->bd) {
- rc = iwl_rx_queue_alloc(priv);
+ rc = iwl4965_rx_queue_alloc(priv);
if (rc) {
IWL_ERROR("Unable to initialize Rx queue\n");
return -ENOMEM;
}
} else
- iwl_rx_queue_reset(priv, rxq);
+ iwl4965_rx_queue_reset(priv, rxq);
- iwl_rx_replenish(priv);
+ iwl4965_rx_replenish(priv);
iwl4965_rx_init(priv, rxq);
spin_lock_irqsave(&priv->lock, flags);
rxq->need_update = 1;
- iwl_rx_queue_update_write_ptr(priv, rxq);
+ iwl4965_rx_queue_update_write_ptr(priv, rxq);
spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* Allocate and init all Tx and Command queues */
rc = iwl4965_txq_ctx_reset(priv);
if (rc)
return rc;
@@ -563,7 +582,7 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
return 0;
}
-int iwl_hw_nic_stop_master(struct iwl_priv *priv)
+int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv)
{
int rc = 0;
u32 reg_val;
@@ -572,16 +591,16 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
/* set stop master bit */
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+ iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- reg_val = iwl_read32(priv, CSR_GP_CNTRL);
+ reg_val = iwl4965_read32(priv, CSR_GP_CNTRL);
if (CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE ==
(reg_val & CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE))
IWL_DEBUG_INFO("Card in power save, master is already "
"stopped\n");
else {
- rc = iwl_poll_bit(priv, CSR_RESET,
+ rc = iwl4965_poll_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (rc < 0) {
@@ -596,65 +615,69 @@ int iwl_hw_nic_stop_master(struct iwl_priv *priv)
return rc;
}
-void iwl_hw_txq_ctx_stop(struct iwl_priv *priv)
+/**
+ * iwl4965_hw_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory
+ */
+void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv)
{
int txq_id;
unsigned long flags;
- /* reset TFD queues */
+ /* Stop each Tx DMA channel, and wait for it to be idle */
for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++) {
spin_lock_irqsave(&priv->lock, flags);
- if (iwl_grab_restricted_access(priv)) {
+ if (iwl4965_grab_nic_access(priv)) {
spin_unlock_irqrestore(&priv->lock, flags);
continue;
}
- iwl_write_restricted(priv,
+ iwl4965_write_direct32(priv,
IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
0x0);
- iwl_poll_restricted_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
+ iwl4965_poll_direct_bit(priv, IWL_FH_TSSR_TX_STATUS_REG,
IWL_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
(txq_id), 200);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
- iwl_hw_txq_ctx_free(priv);
+ /* Deallocate memory for all Tx queues */
+ iwl4965_hw_txq_ctx_free(priv);
}
-int iwl_hw_nic_reset(struct iwl_priv *priv)
+int iwl4965_hw_nic_reset(struct iwl4965_priv *priv)
{
int rc = 0;
unsigned long flags;
- iwl_hw_nic_stop_master(priv);
+ iwl4965_hw_nic_stop_master(priv);
spin_lock_irqsave(&priv->lock, flags);
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
udelay(10);
- iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- rc = iwl_poll_bit(priv, CSR_RESET,
+ iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ rc = iwl4965_poll_bit(priv, CSR_RESET,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
udelay(10);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (!rc) {
- iwl_write_restricted_reg(priv, APMG_CLK_EN_REG,
+ iwl4965_write_prph(priv, APMG_CLK_EN_REG,
APMG_CLK_VAL_DMA_CLK_RQT |
APMG_CLK_VAL_BSM_CLK_RQT);
udelay(10);
- iwl_set_bits_restricted_reg(priv, APMG_PCIDEV_STT_REG,
+ iwl4965_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
@@ -684,7 +707,7 @@ int iwl_hw_nic_reset(struct iwl_priv *priv)
*/
static void iwl4965_bg_statistics_periodic(unsigned long data)
{
- struct iwl_priv *priv = (struct iwl_priv *)data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)data;
queue_work(priv->workqueue, &priv->statistics_work);
}
@@ -692,27 +715,27 @@ static void iwl4965_bg_statistics_periodic(unsigned long data)
/**
* iwl4965_bg_statistics_work - Send the statistics request to the hardware.
*
- * This is queued by iwl_bg_statistics_periodic.
+ * This is queued by iwl4965_bg_statistics_periodic.
*/
static void iwl4965_bg_statistics_work(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
statistics_work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_send_statistics_request(priv);
+ iwl4965_send_statistics_request(priv);
mutex_unlock(&priv->mutex);
}
#define CT_LIMIT_CONST 259
#define TM_CT_KILL_THRESHOLD 110
-void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
+void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv)
{
- struct iwl_ct_kill_config cmd;
+ struct iwl4965_ct_kill_config cmd;
u32 R1, R2, R3;
u32 temp_th;
u32 crit_temperature;
@@ -720,7 +743,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
int rc = 0;
spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -738,7 +761,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
crit_temperature = ((temp_th * (R3-R1))/CT_LIMIT_CONST) + R2;
cmd.critical_temperature_R = cpu_to_le32(crit_temperature);
- rc = iwl_send_cmd_pdu(priv,
+ rc = iwl4965_send_cmd_pdu(priv,
REPLY_CT_KILL_CONFIG_CMD, sizeof(cmd), &cmd);
if (rc)
IWL_ERROR("REPLY_CT_KILL_CONFIG_CMD failed\n");
@@ -746,7 +769,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
IWL_DEBUG_INFO("REPLY_CT_KILL_CONFIG_CMD succeeded\n");
}
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
/* "false alarms" are signals that our DSP tries to lock onto,
* but then determines that they are either noise, or transmissions
@@ -756,7 +779,7 @@ void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
* enough to receive all of our own network traffic, but not so
* high that our DSP gets too busy trying to lock onto non-network
* activity/noise. */
-static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
+static int iwl4965_sens_energy_cck(struct iwl4965_priv *priv,
u32 norm_fa,
u32 rx_enable_time,
struct statistics_general_data *rx_info)
@@ -782,7 +805,7 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
u32 false_alarms = norm_fa * 200 * 1024;
u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
- struct iwl_sensitivity_data *data = NULL;
+ struct iwl4965_sensitivity_data *data = NULL;
data = &(priv->sensitivity_data);
@@ -792,11 +815,11 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
* This is background noise, which may include transmissions from other
* networks, measured during silence before our network's beacon */
silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
- ALL_BAND_FILTER)>>8);
+ ALL_BAND_FILTER) >> 8);
silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
- ALL_BAND_FILTER)>>8);
+ ALL_BAND_FILTER) >> 8);
silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
- ALL_BAND_FILTER)>>8);
+ ALL_BAND_FILTER) >> 8);
val = max(silence_rssi_b, silence_rssi_c);
max_silence_rssi = max(silence_rssi_a, (u8) val);
@@ -947,7 +970,7 @@ static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
}
-static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
+static int iwl4965_sens_auto_corr_ofdm(struct iwl4965_priv *priv,
u32 norm_fa,
u32 rx_enable_time)
{
@@ -955,7 +978,7 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
u32 false_alarms = norm_fa * 200 * 1024;
u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
- struct iwl_sensitivity_data *data = NULL;
+ struct iwl4965_sensitivity_data *data = NULL;
data = &(priv->sensitivity_data);
@@ -1012,22 +1035,22 @@ static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
return 0;
}
-static int iwl_sensitivity_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static int iwl4965_sensitivity_callback(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd, struct sk_buff *skb)
{
/* We didn't cache the SKB; let the caller free it */
return 1;
}
/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
-static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
+static int iwl4965_sensitivity_write(struct iwl4965_priv *priv, u8 flags)
{
int rc = 0;
- struct iwl_sensitivity_cmd cmd ;
- struct iwl_sensitivity_data *data = NULL;
- struct iwl_host_cmd cmd_out = {
+ struct iwl4965_sensitivity_cmd cmd ;
+ struct iwl4965_sensitivity_data *data = NULL;
+ struct iwl4965_host_cmd cmd_out = {
.id = SENSITIVITY_CMD,
- .len = sizeof(struct iwl_sensitivity_cmd),
+ .len = sizeof(struct iwl4965_sensitivity_cmd),
.meta.flags = flags,
.data = &cmd,
};
@@ -1071,10 +1094,11 @@ static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
data->auto_corr_cck, data->auto_corr_cck_mrc,
data->nrg_th_cck);
+ /* Update uCode's "work" table, and copy it to DSP */
cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
if (flags & CMD_ASYNC)
- cmd_out.meta.u.callback = iwl_sensitivity_callback;
+ cmd_out.meta.u.callback = iwl4965_sensitivity_callback;
/* Don't send command to uCode if nothing has changed */
if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
@@ -1087,7 +1111,7 @@ static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
sizeof(u16)*HD_TABLE_SIZE);
- rc = iwl_send_cmd(priv, &cmd_out);
+ rc = iwl4965_send_cmd(priv, &cmd_out);
if (!rc) {
IWL_DEBUG_CALIB("SENSITIVITY_CMD succeeded\n");
return rc;
@@ -1096,11 +1120,11 @@ static int iwl4965_sensitivity_write(struct iwl_priv *priv, u8 flags)
return 0;
}
-void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
+void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags, u8 force)
{
int rc = 0;
int i;
- struct iwl_sensitivity_data *data = NULL;
+ struct iwl4965_sensitivity_data *data = NULL;
IWL_DEBUG_CALIB("Start iwl4965_init_sensitivity\n");
@@ -1110,7 +1134,7 @@ void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
/* Clear driver's sensitivity algo data */
data = &(priv->sensitivity_data);
- memset(data, 0, sizeof(struct iwl_sensitivity_data));
+ memset(data, 0, sizeof(struct iwl4965_sensitivity_data));
data->num_in_cck_no_fa = 0;
data->nrg_curr_state = IWL_FA_TOO_MANY;
@@ -1154,21 +1178,21 @@ void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags, u8 force)
/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
* Called after every association, but this runs only once!
* ... once chain noise is calibrated the first time, it's good forever. */
-void iwl4965_chain_noise_reset(struct iwl_priv *priv)
+void iwl4965_chain_noise_reset(struct iwl4965_priv *priv)
{
- struct iwl_chain_noise_data *data = NULL;
+ struct iwl4965_chain_noise_data *data = NULL;
int rc = 0;
data = &(priv->chain_noise_data);
- if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
- struct iwl_calibration_cmd cmd;
+ if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl4965_is_associated(priv)) {
+ struct iwl4965_calibration_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
cmd.diff_gain_a = 0;
cmd.diff_gain_b = 0;
cmd.diff_gain_c = 0;
- rc = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
sizeof(cmd), &cmd);
msleep(4);
data->state = IWL_CHAIN_NOISE_ACCUMULATE;
@@ -1183,10 +1207,10 @@ void iwl4965_chain_noise_reset(struct iwl_priv *priv)
* 1) Which antennas are connected.
* 2) Differential rx gain settings to balance the 3 receivers.
*/
-static void iwl4965_noise_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *stat_resp)
+static void iwl4965_noise_calibration(struct iwl4965_priv *priv,
+ struct iwl4965_notif_statistics *stat_resp)
{
- struct iwl_chain_noise_data *data = NULL;
+ struct iwl4965_chain_noise_data *data = NULL;
int rc = 0;
u32 chain_noise_a;
@@ -1385,7 +1409,7 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv,
/* Differential gain gets sent to uCode only once */
if (!data->radio_write) {
- struct iwl_calibration_cmd cmd;
+ struct iwl4965_calibration_cmd cmd;
data->radio_write = 1;
memset(&cmd, 0, sizeof(cmd));
@@ -1393,7 +1417,7 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv,
cmd.diff_gain_a = data->delta_gain_code[0];
cmd.diff_gain_b = data->delta_gain_code[1];
cmd.diff_gain_c = data->delta_gain_code[2];
- rc = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
sizeof(cmd), &cmd);
if (rc)
IWL_DEBUG_CALIB("fail sending cmd "
@@ -1416,8 +1440,8 @@ static void iwl4965_noise_calibration(struct iwl_priv *priv,
return;
}
-static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
- struct iwl_notif_statistics *resp)
+static void iwl4965_sensitivity_calibration(struct iwl4965_priv *priv,
+ struct iwl4965_notif_statistics *resp)
{
int rc = 0;
u32 rx_enable_time;
@@ -1427,7 +1451,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
u32 bad_plcp_ofdm;
u32 norm_fa_ofdm;
u32 norm_fa_cck;
- struct iwl_sensitivity_data *data = NULL;
+ struct iwl4965_sensitivity_data *data = NULL;
struct statistics_rx_non_phy *rx_info = &(resp->rx.general);
struct statistics_rx *statistics = &(resp->rx);
unsigned long flags;
@@ -1435,7 +1459,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
data = &(priv->sensitivity_data);
- if (!iwl_is_associated(priv)) {
+ if (!iwl4965_is_associated(priv)) {
IWL_DEBUG_CALIB("<< - not associated\n");
return;
}
@@ -1523,7 +1547,7 @@ static void iwl4965_sensitivity_calibration(struct iwl_priv *priv,
static void iwl4965_bg_sensitivity_work(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
sensitivity_work);
mutex_lock(&priv->mutex);
@@ -1549,11 +1573,11 @@ static void iwl4965_bg_sensitivity_work(struct work_struct *work)
mutex_unlock(&priv->mutex);
return;
}
-#endif /*CONFIG_IWLWIFI_SENSITIVITY*/
+#endif /*CONFIG_IWL4965_SENSITIVITY*/
static void iwl4965_bg_txpower_work(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
txpower_work);
/* If a scan happened to start before we got here
@@ -1569,7 +1593,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
/* Regardless of if we are assocaited, we must reconfigure the
* TX power since frames can be sent on non-radar channels while
* not associated */
- iwl_hw_reg_send_txpower(priv);
+ iwl4965_hw_reg_send_txpower(priv);
/* Update last_temperature to keep is_calib_needed from running
* when it isn't needed... */
@@ -1581,24 +1605,31 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
/*
* Acquire priv->lock before calling this function !
*/
-static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
+static void iwl4965_set_wr_ptrs(struct iwl4965_priv *priv, int txq_id, u32 index)
{
- iwl_write_restricted(priv, HBUS_TARG_WRPTR,
+ iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
(index & 0xff) | (txq_id << 8));
- iwl_write_restricted_reg(priv, SCD_QUEUE_RDPTR(txq_id), index);
+ iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(txq_id), index);
}
-/*
- * Acquire priv->lock before calling this function !
+/**
+ * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
+ * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
+ * @scd_retry: (1) Indicates queue will be used in aggregation mode
+ *
+ * NOTE: Acquire priv->lock before calling this function !
*/
-static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
+static void iwl4965_tx_queue_set_status(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq,
int tx_fifo_id, int scd_retry)
{
int txq_id = txq->q.id;
+
+ /* Find out whether to activate Tx queue */
int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
- iwl_write_restricted_reg(priv, SCD_QUEUE_STATUS_BITS(txq_id),
+ /* Set up and activate */
+ iwl4965_write_prph(priv, KDR_SCD_QUEUE_STATUS_BITS(txq_id),
(active << SCD_QUEUE_STTS_REG_POS_ACTIVE) |
(tx_fifo_id << SCD_QUEUE_STTS_REG_POS_TXF) |
(scd_retry << SCD_QUEUE_STTS_REG_POS_WSL) |
@@ -1608,7 +1639,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
txq->sched_retry = scd_retry;
IWL_DEBUG_INFO("%s %s Queue %d on AC %d\n",
- active ? "Activete" : "Deactivate",
+ active ? "Activate" : "Deactivate",
scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
}
@@ -1622,17 +1653,17 @@ static const u16 default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_HCCA_2
};
-static inline void iwl4965_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+static inline void iwl4965_txq_ctx_activate(struct iwl4965_priv *priv, int txq_id)
{
set_bit(txq_id, &priv->txq_ctx_active_msk);
}
-static inline void iwl4965_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+static inline void iwl4965_txq_ctx_deactivate(struct iwl4965_priv *priv, int txq_id)
{
clear_bit(txq_id, &priv->txq_ctx_active_msk);
}
-int iwl4965_alive_notify(struct iwl_priv *priv)
+int iwl4965_alive_notify(struct iwl4965_priv *priv)
{
u32 a;
int i = 0;
@@ -1641,45 +1672,55 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
memset(&(priv->sensitivity_data), 0,
- sizeof(struct iwl_sensitivity_data));
+ sizeof(struct iwl4965_sensitivity_data));
memset(&(priv->chain_noise_data), 0,
- sizeof(struct iwl_chain_noise_data));
+ sizeof(struct iwl4965_chain_noise_data));
for (i = 0; i < NUM_RX_CHAINS; i++)
priv->chain_noise_data.delta_gain_code[i] =
CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
-#endif /* CONFIG_IWLWIFI_SENSITIVITY*/
- rc = iwl_grab_restricted_access(priv);
+#endif /* CONFIG_IWL4965_SENSITIVITY*/
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- priv->scd_base_addr = iwl_read_restricted_reg(priv, SCD_SRAM_BASE_ADDR);
+ /* Clear 4965's internal Tx Scheduler data base */
+ priv->scd_base_addr = iwl4965_read_prph(priv, KDR_SCD_SRAM_BASE_ADDR);
a = priv->scd_base_addr + SCD_CONTEXT_DATA_OFFSET;
for (; a < priv->scd_base_addr + SCD_TX_STTS_BITMAP_OFFSET; a += 4)
- iwl_write_restricted_mem(priv, a, 0);
+ iwl4965_write_targ_mem(priv, a, 0);
for (; a < priv->scd_base_addr + SCD_TRANSLATE_TBL_OFFSET; a += 4)
- iwl_write_restricted_mem(priv, a, 0);
+ iwl4965_write_targ_mem(priv, a, 0);
for (; a < sizeof(u16) * priv->hw_setting.max_txq_num; a += 4)
- iwl_write_restricted_mem(priv, a, 0);
+ iwl4965_write_targ_mem(priv, a, 0);
- iwl_write_restricted_reg(priv, SCD_DRAM_BASE_ADDR,
+ /* Tel 4965 where to find Tx byte count tables */
+ iwl4965_write_prph(priv, KDR_SCD_DRAM_BASE_ADDR,
(priv->hw_setting.shared_phys +
- offsetof(struct iwl_shared, queues_byte_cnt_tbls)) >> 10);
- iwl_write_restricted_reg(priv, SCD_QUEUECHAIN_SEL, 0);
+ offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
- /* initiate the queues */
+ /* Disable chain mode for all queues */
+ iwl4965_write_prph(priv, KDR_SCD_QUEUECHAIN_SEL, 0);
+
+ /* Initialize each Tx queue (including the command queue) */
for (i = 0; i < priv->hw_setting.max_txq_num; i++) {
- iwl_write_restricted_reg(priv, SCD_QUEUE_RDPTR(i), 0);
- iwl_write_restricted(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
- iwl_write_restricted_mem(priv, priv->scd_base_addr +
+
+ /* TFD circular buffer read/write indexes */
+ iwl4965_write_prph(priv, KDR_SCD_QUEUE_RDPTR(i), 0);
+ iwl4965_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+
+ /* Max Tx Window size for Scheduler-ACK mode */
+ iwl4965_write_targ_mem(priv, priv->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(i),
(SCD_WIN_SIZE <<
SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
- iwl_write_restricted_mem(priv, priv->scd_base_addr +
+
+ /* Frame limit */
+ iwl4965_write_targ_mem(priv, priv->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(i) +
sizeof(u32),
(SCD_FRAME_LIMIT <<
@@ -1687,87 +1728,98 @@ int iwl4965_alive_notify(struct iwl_priv *priv)
SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
}
- iwl_write_restricted_reg(priv, SCD_INTERRUPT_MASK,
+ iwl4965_write_prph(priv, KDR_SCD_INTERRUPT_MASK,
(1 << priv->hw_setting.max_txq_num) - 1);
- iwl_write_restricted_reg(priv, SCD_TXFACT,
+ /* Activate all Tx DMA/FIFO channels */
+ iwl4965_write_prph(priv, KDR_SCD_TXFACT,
SCD_TXFACT_REG_TXFIFO_MASK(0, 7));
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
- /* map qos queues to fifos one-to-one */
+
+ /* Map each Tx/cmd queue to its corresponding fifo */
for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
int ac = default_queue_to_tx_fifo[i];
iwl4965_txq_ctx_activate(priv, i);
iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
}
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-int iwl_hw_set_hw_setting(struct iwl_priv *priv)
+/**
+ * iwl4965_hw_set_hw_setting
+ *
+ * Called when initializing driver
+ */
+int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv)
{
+ /* Allocate area for Tx byte count tables and Rx queue status */
priv->hw_setting.shared_virt =
pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl_shared),
+ sizeof(struct iwl4965_shared),
&priv->hw_setting.shared_phys);
if (!priv->hw_setting.shared_virt)
return -1;
- memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl_shared));
+ memset(priv->hw_setting.shared_virt, 0, sizeof(struct iwl4965_shared));
- priv->hw_setting.max_txq_num = iwl_param_queues_num;
+ priv->hw_setting.max_txq_num = iwl4965_param_queues_num;
priv->hw_setting.ac_queue_count = AC_NUM;
-
- priv->hw_setting.cck_flag = RATE_MCS_CCK_MSK;
- priv->hw_setting.tx_cmd_len = sizeof(struct iwl_tx_cmd);
+ priv->hw_setting.tx_cmd_len = sizeof(struct iwl4965_tx_cmd);
priv->hw_setting.max_rxq_size = RX_QUEUE_SIZE;
priv->hw_setting.max_rxq_log = RX_QUEUE_SIZE_LOG;
-
+ if (iwl4965_param_amsdu_size_8K)
+ priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_8K;
+ else
+ priv->hw_setting.rx_buf_size = IWL_RX_BUF_SIZE_4K;
+ priv->hw_setting.max_pkt_size = priv->hw_setting.rx_buf_size - 256;
priv->hw_setting.max_stations = IWL4965_STATION_COUNT;
priv->hw_setting.bcast_sta_id = IWL4965_BROADCAST_ID;
return 0;
}
/**
- * iwl_hw_txq_ctx_free - Free TXQ Context
+ * iwl4965_hw_txq_ctx_free - Free TXQ Context
*
* Destroy all TX DMA queues and structures
*/
-void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
+void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv)
{
int txq_id;
/* Tx queues */
for (txq_id = 0; txq_id < priv->hw_setting.max_txq_num; txq_id++)
- iwl_tx_queue_free(priv, &priv->txq[txq_id]);
+ iwl4965_tx_queue_free(priv, &priv->txq[txq_id]);
+ /* Keep-warm buffer */
iwl4965_kw_free(priv);
}
/**
- * iwl_hw_txq_free_tfd - Free one TFD, those at index [txq->q.last_used]
+ * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
*
- * Does NOT advance any indexes
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
*/
-int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
{
- struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
- struct iwl_tfd_frame *bd = &bd_tmp[txq->q.last_used];
+ struct iwl4965_tfd_frame *bd_tmp = (struct iwl4965_tfd_frame *)&txq->bd[0];
+ struct iwl4965_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
struct pci_dev *dev = priv->pci_dev;
int i;
int counter = 0;
int index, is_odd;
- /* classify bd */
+ /* Host command buffers stay mapped in memory, nothing to clean */
if (txq->q.id == IWL_CMD_QUEUE_NUM)
- /* nothing to cleanup after for host commands */
return 0;
- /* sanity check */
+ /* Sanity check on number of chunks */
counter = IWL_GET_BITS(*bd, num_tbs);
if (counter > MAX_NUM_OF_TBS) {
IWL_ERROR("Too many chunks: %i\n", counter);
@@ -1775,8 +1827,8 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
return 0;
}
- /* unmap chunks if any */
-
+ /* Unmap chunks, if any.
+ * TFD info for odd chunks is different format than for even chunks. */
for (i = 0; i < counter; i++) {
index = i / 2;
is_odd = i & 0x1;
@@ -1796,19 +1848,20 @@ int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
IWL_GET_BITS(bd->pa[index], tb1_len),
PCI_DMA_TODEVICE);
- if (txq->txb[txq->q.last_used].skb[i]) {
- struct sk_buff *skb = txq->txb[txq->q.last_used].skb[i];
+ /* Free SKB, if any, for this chunk */
+ if (txq->txb[txq->q.read_ptr].skb[i]) {
+ struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
dev_kfree_skb(skb);
- txq->txb[txq->q.last_used].skb[i] = NULL;
+ txq->txb[txq->q.read_ptr].skb[i] = NULL;
}
}
return 0;
}
-int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power)
{
- IWL_ERROR("TODO: Implement iwl_hw_reg_set_txpower!\n");
+ IWL_ERROR("TODO: Implement iwl4965_hw_reg_set_txpower!\n");
return -EINVAL;
}
@@ -1830,6 +1883,17 @@ static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
return 1;
}
+/**
+ * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
+ *
+ * Determines power supply voltage compensation for txpower calculations.
+ * Returns number of 1/2-dB steps to subtract from gain table index,
+ * to compensate for difference between power supply voltage during
+ * factory measurements, vs. current power supply voltage.
+ *
+ * Voltage indication is higher for lower voltage.
+ * Lower voltage requires more gain (lower gain table index).
+ */
static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
s32 current_voltage)
{
@@ -1850,12 +1914,12 @@ static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
return comp;
}
-static const struct iwl_channel_info *
-iwl4965_get_channel_txpower_info(struct iwl_priv *priv, u8 phymode, u16 channel)
+static const struct iwl4965_channel_info *
+iwl4965_get_channel_txpower_info(struct iwl4965_priv *priv, u8 phymode, u16 channel)
{
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv, phymode, channel);
+ ch_info = iwl4965_get_channel_info(priv, phymode, channel);
if (!is_channel_valid(ch_info))
return NULL;
@@ -1889,7 +1953,7 @@ static s32 iwl4965_get_tx_atten_grp(u16 channel)
return -1;
}
-static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
+static u32 iwl4965_get_sub_band(const struct iwl4965_priv *priv, u32 channel)
{
s32 b = -1;
@@ -1917,15 +1981,23 @@ static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
}
}
-static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
- struct iwl_eeprom_calib_ch_info *chan_info)
+/**
+ * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
+ *
+ * Interpolates factory measurements from the two sample channels within a
+ * sub-band, to apply to channel of interest. Interpolation is proportional to
+ * differences in channel frequencies, which is proportional to differences
+ * in channel number.
+ */
+static int iwl4965_interpolate_chan(struct iwl4965_priv *priv, u32 channel,
+ struct iwl4965_eeprom_calib_ch_info *chan_info)
{
s32 s = -1;
u32 c;
u32 m;
- const struct iwl_eeprom_calib_measure *m1;
- const struct iwl_eeprom_calib_measure *m2;
- struct iwl_eeprom_calib_measure *omeas;
+ const struct iwl4965_eeprom_calib_measure *m1;
+ const struct iwl4965_eeprom_calib_measure *m2;
+ struct iwl4965_eeprom_calib_measure *omeas;
u32 ch_i1;
u32 ch_i2;
@@ -2000,7 +2072,7 @@ static s32 back_off_table[] = {
/* Thermal compensation values for txpower for various frequency ranges ...
* ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
-static struct iwl_txpower_comp_entry {
+static struct iwl4965_txpower_comp_entry {
s32 degrees_per_05db_a;
s32 degrees_per_05db_a_denom;
} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
@@ -2250,9 +2322,9 @@ static const struct gain_entry gain_table[2][108] = {
}
};
-static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+static int iwl4965_fill_txpower_tbl(struct iwl4965_priv *priv, u8 band, u16 channel,
u8 is_fat, u8 ctrl_chan_high,
- struct iwl_tx_power_db *tx_power_tbl)
+ struct iwl4965_tx_power_db *tx_power_tbl)
{
u8 saturation_power;
s32 target_power;
@@ -2264,9 +2336,9 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
s32 txatten_grp = CALIB_CH_GROUP_MAX;
int i;
int c;
- const struct iwl_channel_info *ch_info = NULL;
- struct iwl_eeprom_calib_ch_info ch_eeprom_info;
- const struct iwl_eeprom_calib_measure *measurement;
+ const struct iwl4965_channel_info *ch_info = NULL;
+ struct iwl4965_eeprom_calib_ch_info ch_eeprom_info;
+ const struct iwl4965_eeprom_calib_measure *measurement;
s16 voltage;
s32 init_voltage;
s32 voltage_compensation;
@@ -2405,7 +2477,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
/* for each of 33 bit-rates (including 1 for CCK) */
for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
u8 is_mimo_rate;
- union iwl_tx_power_dual_stream tx_power;
+ union iwl4965_tx_power_dual_stream tx_power;
/* for mimo, reduce each chain's txpower by half
* (3dB, 6 steps), so total output power is regulatory
@@ -2502,14 +2574,14 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
}
/**
- * iwl_hw_reg_send_txpower - Configure the TXPOWER level user limit
+ * iwl4965_hw_reg_send_txpower - Configure the TXPOWER level user limit
*
* Uses the active RXON for channel, band, and characteristics (fat, high)
* The power limit is taken from priv->user_txpower_limit.
*/
-int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
+int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv)
{
- struct iwl_txpowertable_cmd cmd = { 0 };
+ struct iwl4965_txpowertable_cmd cmd = { 0 };
int rc = 0;
u8 band = 0;
u8 is_fat = 0;
@@ -2541,23 +2613,23 @@ int iwl_hw_reg_send_txpower(struct iwl_priv *priv)
if (rc)
return rc;
- rc = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
return rc;
}
-int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
+int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel)
{
int rc;
u8 band = 0;
u8 is_fat = 0;
u8 ctrl_chan_high = 0;
- struct iwl_channel_switch_cmd cmd = { 0 };
- const struct iwl_channel_info *ch_info;
+ struct iwl4965_channel_switch_cmd cmd = { 0 };
+ const struct iwl4965_channel_info *ch_info;
band = ((priv->phymode == MODE_IEEE80211B) ||
(priv->phymode == MODE_IEEE80211G));
- ch_info = iwl_get_channel_info(priv, priv->phymode, channel);
+ ch_info = iwl4965_get_channel_info(priv, priv->phymode, channel);
is_fat = is_fat_channel(priv->staging_rxon.flags);
@@ -2583,32 +2655,36 @@ int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel)
return rc;
}
- rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
return rc;
}
#define RTS_HCCA_RETRY_LIMIT 3
#define RTS_DFAULT_RETRY_LIMIT 60
-void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd,
struct ieee80211_tx_control *ctrl,
struct ieee80211_hdr *hdr, int sta_id,
int is_hcca)
{
- u8 rate;
+ struct iwl4965_tx_cmd *tx = &cmd->cmd.tx;
u8 rts_retry_limit = 0;
u8 data_retry_limit = 0;
- __le32 tx_flags;
u16 fc = le16_to_cpu(hdr->frame_control);
+ u8 rate_plcp;
+ u16 rate_flags = 0;
+ int rate_idx = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
- tx_flags = cmd->cmd.tx.tx_flags;
-
- rate = iwl_rates[ctrl->tx_rate].plcp;
+ rate_plcp = iwl4965_rates[rate_idx].plcp;
rts_retry_limit = (is_hcca) ?
RTS_HCCA_RETRY_LIMIT : RTS_DFAULT_RETRY_LIMIT;
+ if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
+ rate_flags |= RATE_MCS_CCK_MSK;
+
+
if (ieee80211_is_probe_response(fc)) {
data_retry_limit = 3;
if (data_retry_limit < rts_retry_limit)
@@ -2619,44 +2695,56 @@ void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
if (priv->data_retry_limit != -1)
data_retry_limit = priv->data_retry_limit;
- if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
+
+ if (ieee80211_is_data(fc)) {
+ tx->initial_rate_index = 0;
+ tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+ } else {
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_AUTH:
case IEEE80211_STYPE_DEAUTH:
case IEEE80211_STYPE_ASSOC_REQ:
case IEEE80211_STYPE_REASSOC_REQ:
- if (tx_flags & TX_CMD_FLG_RTS_MSK) {
- tx_flags &= ~TX_CMD_FLG_RTS_MSK;
- tx_flags |= TX_CMD_FLG_CTS_MSK;
+ if (tx->tx_flags & TX_CMD_FLG_RTS_MSK) {
+ tx->tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+ tx->tx_flags |= TX_CMD_FLG_CTS_MSK;
}
break;
default:
break;
}
+
+ /* Alternate between antenna A and B for successive frames */
+ if (priv->use_ant_b_for_management_frame) {
+ priv->use_ant_b_for_management_frame = 0;
+ rate_flags |= RATE_MCS_ANT_B_MSK;
+ } else {
+ priv->use_ant_b_for_management_frame = 1;
+ rate_flags |= RATE_MCS_ANT_A_MSK;
+ }
}
- cmd->cmd.tx.rts_retry_limit = rts_retry_limit;
- cmd->cmd.tx.data_retry_limit = data_retry_limit;
- cmd->cmd.tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, 0);
- cmd->cmd.tx.tx_flags = tx_flags;
+ tx->rts_retry_limit = rts_retry_limit;
+ tx->data_retry_limit = data_retry_limit;
+ tx->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
}
-int iwl_hw_get_rx_read(struct iwl_priv *priv)
+int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv)
{
- struct iwl_shared *shared_data = priv->hw_setting.shared_virt;
+ struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
return IWL_GET_BITS(*shared_data, rb_closed_stts_rb_num);
}
-int iwl_hw_get_temperature(struct iwl_priv *priv)
+int iwl4965_hw_get_temperature(struct iwl4965_priv *priv)
{
return priv->temperature;
}
-unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl_frame *frame, u8 rate)
+unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+ struct iwl4965_frame *frame, u8 rate)
{
- struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+ struct iwl4965_tx_beacon_cmd *tx_beacon_cmd;
unsigned int frame_size;
tx_beacon_cmd = &frame->u.beacon;
@@ -2665,9 +2753,9 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd->tx.sta_id = IWL4965_BROADCAST_ID;
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
- frame_size = iwl_fill_beacon_frame(priv,
+ frame_size = iwl4965_fill_beacon_frame(priv,
tx_beacon_cmd->frame,
- BROADCAST_ADDR,
+ iwl4965_broadcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
BUG_ON(frame_size > MAX_MPDU_SIZE);
@@ -2675,53 +2763,59 @@ unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP))
tx_beacon_cmd->tx.rate_n_flags =
- iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
+ iwl4965_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK);
else
tx_beacon_cmd->tx.rate_n_flags =
- iwl_hw_set_rate_n_flags(rate, 0);
+ iwl4965_hw_set_rate_n_flags(rate, 0);
tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK);
return (sizeof(*tx_beacon_cmd) + frame_size);
}
-int iwl_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+/*
+ * Tell 4965 where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
{
int rc;
unsigned long flags;
int txq_id = txq->q.id;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
- iwl_write_restricted(priv, FH_MEM_CBBC_QUEUE(txq_id),
+ /* Circular buffer (TFD queue in DRAM) physical base address */
+ iwl4965_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
txq->q.dma_addr >> 8);
- iwl_write_restricted(
+
+ /* Enable DMA channel, using same id as for TFD queue */
+ iwl4965_write_direct32(
priv, IWL_FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
IWL_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-static inline u8 iwl4965_get_dma_hi_address(dma_addr_t addr)
-{
- return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
-}
-
-int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *ptr,
dma_addr_t addr, u16 len)
{
int index, is_odd;
- struct iwl_tfd_frame *tfd = ptr;
+ struct iwl4965_tfd_frame *tfd = ptr;
u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
+ /* Each TFD can point to a maximum 20 Tx buffers */
if ((num_tbs >= MAX_NUM_OF_TBS) || (num_tbs < 0)) {
IWL_ERROR("Error can not send more than %d chunks\n",
MAX_NUM_OF_TBS);
@@ -2734,7 +2828,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
if (!is_odd) {
tfd->pa[index].tb1_addr = cpu_to_le32(addr);
IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
- iwl4965_get_dma_hi_address(addr));
+ iwl_get_dma_hi_address(addr));
IWL_SET_BITS(tfd->pa[index], tb1_len, len);
} else {
IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
@@ -2748,7 +2842,7 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
return 0;
}
-void iwl_hw_card_show_info(struct iwl_priv *priv)
+static void iwl4965_hw_card_show_info(struct iwl4965_priv *priv)
{
u16 hw_version = priv->eeprom.board_revision_4965;
@@ -2763,32 +2857,41 @@ void iwl_hw_card_show_info(struct iwl_priv *priv)
#define IWL_TX_CRC_SIZE 4
#define IWL_TX_DELIMITER_SIZE 4
-int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, u16 byte_cnt)
+/**
+ * iwl4965_tx_queue_update_wr_ptr - Set up entry in Tx byte-count array
+ */
+int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq, u16 byte_cnt)
{
int len;
int txq_id = txq->q.id;
- struct iwl_shared *shared_data = priv->hw_setting.shared_virt;
+ struct iwl4965_shared *shared_data = priv->hw_setting.shared_virt;
if (txq->need_update == 0)
return 0;
len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ /* Set up byte count within first 256 entries */
IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[txq->q.first_empty], byte_cnt, len);
+ tfd_offset[txq->q.write_ptr], byte_cnt, len);
- if (txq->q.first_empty < IWL4965_MAX_WIN_SIZE)
+ /* If within first 64 entries, duplicate at end */
+ if (txq->q.write_ptr < IWL4965_MAX_WIN_SIZE)
IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[IWL4965_QUEUE_SIZE + txq->q.first_empty],
+ tfd_offset[IWL4965_QUEUE_SIZE + txq->q.write_ptr],
byte_cnt, len);
return 0;
}
-/* Set up Rx receiver/antenna/chain usage in "staging" RXON image.
- * This should not be used for scan command ... it puts data in wrong place. */
-void iwl4965_set_rxon_chain(struct iwl_priv *priv)
+/**
+ * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
+ *
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+void iwl4965_set_rxon_chain(struct iwl4965_priv *priv)
{
u8 is_single = is_single_stream(priv);
u8 idle_state, rx_state;
@@ -2819,19 +2922,19 @@ void iwl4965_set_rxon_chain(struct iwl_priv *priv)
IWL_DEBUG_ASSOC("rx chain %X\n", priv->staging_rxon.rx_chain);
}
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
/*
get the traffic load value for tid
*/
-static u32 iwl4965_tl_get_load(struct iwl_priv *priv, u8 tid)
+static u32 iwl4965_tl_get_load(struct iwl4965_priv *priv, u8 tid)
{
u32 load = 0;
u32 current_time = jiffies_to_msecs(jiffies);
u32 time_diff;
s32 index;
unsigned long flags;
- struct iwl_traffic_load *tid_ptr = NULL;
+ struct iwl4965_traffic_load *tid_ptr = NULL;
if (tid >= TID_MAX_LOAD_COUNT)
return 0;
@@ -2872,13 +2975,13 @@ static u32 iwl4965_tl_get_load(struct iwl_priv *priv, u8 tid)
increment traffic load value for tid and also remove
any old values if passed the certian time period
*/
-static void iwl4965_tl_add_packet(struct iwl_priv *priv, u8 tid)
+static void iwl4965_tl_add_packet(struct iwl4965_priv *priv, u8 tid)
{
u32 current_time = jiffies_to_msecs(jiffies);
u32 time_diff;
s32 index;
unsigned long flags;
- struct iwl_traffic_load *tid_ptr = NULL;
+ struct iwl4965_traffic_load *tid_ptr = NULL;
if (tid >= TID_MAX_LOAD_COUNT)
return;
@@ -2935,14 +3038,19 @@ enum HT_STATUS {
BA_STATUS_ACTIVE,
};
-static u8 iwl4964_tl_ba_avail(struct iwl_priv *priv)
+/**
+ * iwl4964_tl_ba_avail - Find out if an unused aggregation queue is available
+ */
+static u8 iwl4964_tl_ba_avail(struct iwl4965_priv *priv)
{
int i;
- struct iwl_lq_mngr *lq;
+ struct iwl4965_lq_mngr *lq;
u8 count = 0;
u16 msk;
- lq = (struct iwl_lq_mngr *)&(priv->lq_mngr);
+ lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
+
+ /* Find out how many agg queues are in use */
for (i = 0; i < TID_MAX_LOAD_COUNT ; i++) {
msk = 1 << i;
if ((lq->agg_ctrl.granted_ba & msk) ||
@@ -2956,10 +3064,10 @@ static u8 iwl4964_tl_ba_avail(struct iwl_priv *priv)
return 0;
}
-static void iwl4965_ba_status(struct iwl_priv *priv,
+static void iwl4965_ba_status(struct iwl4965_priv *priv,
u8 tid, enum HT_STATUS status);
-static int iwl4965_perform_addba(struct iwl_priv *priv, u8 tid, u32 length,
+static int iwl4965_perform_addba(struct iwl4965_priv *priv, u8 tid, u32 length,
u32 ba_timeout)
{
int rc;
@@ -2971,7 +3079,7 @@ static int iwl4965_perform_addba(struct iwl_priv *priv, u8 tid, u32 length,
return rc;
}
-static int iwl4965_perform_delba(struct iwl_priv *priv, u8 tid)
+static int iwl4965_perform_delba(struct iwl4965_priv *priv, u8 tid)
{
int rc;
@@ -2982,8 +3090,8 @@ static int iwl4965_perform_delba(struct iwl_priv *priv, u8 tid)
return rc;
}
-static void iwl4965_turn_on_agg_for_tid(struct iwl_priv *priv,
- struct iwl_lq_mngr *lq,
+static void iwl4965_turn_on_agg_for_tid(struct iwl4965_priv *priv,
+ struct iwl4965_lq_mngr *lq,
u8 auto_agg, u8 tid)
{
u32 tid_msk = (1 << tid);
@@ -3030,12 +3138,12 @@ static void iwl4965_turn_on_agg_for_tid(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
}
-static void iwl4965_turn_on_agg(struct iwl_priv *priv, u8 tid)
+static void iwl4965_turn_on_agg(struct iwl4965_priv *priv, u8 tid)
{
- struct iwl_lq_mngr *lq;
+ struct iwl4965_lq_mngr *lq;
unsigned long flags;
- lq = (struct iwl_lq_mngr *)&(priv->lq_mngr);
+ lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
if ((tid < TID_MAX_LOAD_COUNT))
iwl4965_turn_on_agg_for_tid(priv, lq, lq->agg_ctrl.auto_agg,
@@ -3055,13 +3163,13 @@ static void iwl4965_turn_on_agg(struct iwl_priv *priv, u8 tid)
}
-void iwl4965_turn_off_agg(struct iwl_priv *priv, u8 tid)
+void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid)
{
u32 tid_msk;
- struct iwl_lq_mngr *lq;
+ struct iwl4965_lq_mngr *lq;
unsigned long flags;
- lq = (struct iwl_lq_mngr *)&(priv->lq_mngr);
+ lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
if ((tid < TID_MAX_LOAD_COUNT)) {
tid_msk = 1 << tid;
@@ -3084,14 +3192,17 @@ void iwl4965_turn_off_agg(struct iwl_priv *priv, u8 tid)
}
}
-static void iwl4965_ba_status(struct iwl_priv *priv,
+/**
+ * iwl4965_ba_status - Update driver's link quality mgr with tid's HT status
+ */
+static void iwl4965_ba_status(struct iwl4965_priv *priv,
u8 tid, enum HT_STATUS status)
{
- struct iwl_lq_mngr *lq;
+ struct iwl4965_lq_mngr *lq;
u32 tid_msk = (1 << tid);
unsigned long flags;
- lq = (struct iwl_lq_mngr *)&(priv->lq_mngr);
+ lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
if ((tid >= TID_MAX_LOAD_COUNT))
goto out;
@@ -3124,14 +3235,14 @@ static void iwl4965_ba_status(struct iwl_priv *priv,
static void iwl4965_bg_agg_work(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv,
agg_work);
u32 tid;
u32 retry_tid;
u32 tid_msk;
unsigned long flags;
- struct iwl_lq_mngr *lq = (struct iwl_lq_mngr *)&(priv->lq_mngr);
+ struct iwl4965_lq_mngr *lq = (struct iwl4965_lq_mngr *)&(priv->lq_mngr);
spin_lock_irqsave(&priv->lq_mngr.lock, flags);
retry_tid = lq->agg_ctrl.tid_retry;
@@ -3154,90 +3265,13 @@ static void iwl4965_bg_agg_work(struct work_struct *work)
spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
return;
}
-#endif /*CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
-int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd,
- u8 sta_id, dma_addr_t txcmd_phys,
- struct ieee80211_hdr *hdr, u8 hdr_len,
- struct ieee80211_tx_control *ctrl, void *sta_in)
+/* TODO: move this functionality to rate scaling */
+void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *hdr)
{
- struct iwl_tx_cmd cmd;
- struct iwl_tx_cmd *tx = (struct iwl_tx_cmd *)&out_cmd->cmd.payload[0];
- dma_addr_t scratch_phys;
- u8 unicast = 0;
- u8 is_data = 1;
- u16 fc;
- u16 rate_flags;
- int rate_index = min(ctrl->tx_rate & 0xffff, IWL_RATE_COUNT - 1);
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
- __le16 *qc;
-#endif /*CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
-
- unicast = !is_multicast_ether_addr(hdr->addr1);
-
- fc = le16_to_cpu(hdr->frame_control);
- if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA)
- is_data = 0;
-
- memcpy(&cmd, &(out_cmd->cmd.tx), sizeof(struct iwl_tx_cmd));
- memset(tx, 0, sizeof(struct iwl_tx_cmd));
- memcpy(tx->hdr, hdr, hdr_len);
-
- tx->len = cmd.len;
- tx->driver_txop = cmd.driver_txop;
- tx->stop_time.life_time = cmd.stop_time.life_time;
- tx->tx_flags = cmd.tx_flags;
- tx->sta_id = cmd.sta_id;
- tx->tid_tspec = cmd.tid_tspec;
- tx->timeout.pm_frame_timeout = cmd.timeout.pm_frame_timeout;
- tx->next_frame_len = cmd.next_frame_len;
-
- tx->sec_ctl = cmd.sec_ctl;
- memcpy(&(tx->key[0]), &(cmd.key[0]), 16);
- tx->tx_flags = cmd.tx_flags;
-
- tx->rts_retry_limit = cmd.rts_retry_limit;
- tx->data_retry_limit = cmd.data_retry_limit;
-
- scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
- offsetof(struct iwl_tx_cmd, scratch);
- tx->dram_lsb_ptr = cpu_to_le32(scratch_phys);
- tx->dram_msb_ptr = iwl4965_get_dma_hi_address(scratch_phys);
-
- /* Hard coded to start at the highest retry fallback position
- * until the 4965 specific rate control algorithm is tied in */
- tx->initial_rate_index = LINK_QUAL_MAX_RETRY_NUM - 1;
-
- /* Alternate between antenna A and B for successive frames */
- if (priv->use_ant_b_for_management_frame) {
- priv->use_ant_b_for_management_frame = 0;
- rate_flags = RATE_MCS_ANT_B_MSK;
- } else {
- priv->use_ant_b_for_management_frame = 1;
- rate_flags = RATE_MCS_ANT_A_MSK;
- }
+ __le16 *qc = ieee80211_get_qos_ctrl(hdr);
- if (!unicast || !is_data) {
- if ((rate_index >= IWL_FIRST_CCK_RATE) &&
- (rate_index <= IWL_LAST_CCK_RATE))
- rate_flags |= RATE_MCS_CCK_MSK;
- } else {
- tx->initial_rate_index = 0;
- tx->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
- }
-
- tx->rate_n_flags = iwl_hw_set_rate_n_flags(iwl_rates[rate_index].plcp,
- rate_flags);
-
- if (ieee80211_is_back_request(fc))
- tx->tx_flags |= TX_CMD_FLG_ACK_MSK |
- TX_CMD_FLG_IMM_BA_RSP_MASK;
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
- qc = ieee80211_get_qos_ctrl(hdr);
if (qc &&
(priv->iw_mode != IEEE80211_IF_TYPE_IBSS)) {
u8 tid = 0;
@@ -3255,11 +3289,11 @@ int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd,
spin_unlock_irqrestore(&priv->lq_mngr.lock, flags);
schedule_work(&priv->agg_work);
}
-#endif
-#endif
- return 0;
}
+#endif /*CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
+
/**
* sign_extend - Sign extend a value using specified bit as sign-bit
*
@@ -3282,7 +3316,7 @@ static s32 sign_extend(u32 oper, int index)
*
* A return of <0 indicates bogus data in the statistics
*/
-int iwl4965_get_temperature(const struct iwl_priv *priv)
+int iwl4965_get_temperature(const struct iwl4965_priv *priv)
{
s32 temperature;
s32 vt;
@@ -3305,11 +3339,12 @@ int iwl4965_get_temperature(const struct iwl_priv *priv)
}
/*
- * Temperature is only 23 bits so sign extend out to 32
+ * Temperature is only 23 bits, so sign extend out to 32.
*
* NOTE If we haven't received a statistics notification yet
* with an updated temperature, use R4 provided to us in the
- * ALIVE response. */
+ * "initialize" ALIVE response.
+ */
if (!test_bit(STATUS_TEMPERATURE, &priv->status))
vt = sign_extend(R4, 23);
else
@@ -3349,7 +3384,7 @@ int iwl4965_get_temperature(const struct iwl_priv *priv)
* Assumes caller will replace priv->last_temperature once calibration
* executed.
*/
-static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
+static int iwl4965_is_temp_calib_needed(struct iwl4965_priv *priv)
{
int temp_diff;
@@ -3382,7 +3417,7 @@ static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
* exactly when to expect beacons, therefore only when we're associated. */
-static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+static void iwl4965_rx_calc_noise(struct iwl4965_priv *priv)
{
struct statistics_rx_non_phy *rx_info
= &(priv->statistics.rx.general);
@@ -3419,9 +3454,9 @@ static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
priv->last_rx_noise);
}
-void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
int change;
s32 temp;
@@ -3448,7 +3483,7 @@ void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
(pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
iwl4965_rx_calc_noise(priv);
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
queue_work(priv->workqueue, &priv->sensitivity_work);
#endif
}
@@ -3483,12 +3518,117 @@ void iwl_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
queue_work(priv->workqueue, &priv->txpower_work);
}
-static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
+static void iwl4965_add_radiotap(struct iwl4965_priv *priv,
+ struct sk_buff *skb,
+ struct iwl4965_rx_phy_res *rx_start,
+ struct ieee80211_rx_status *stats,
+ u32 ampdu_status)
+{
+ s8 signal = stats->ssi;
+ s8 noise = 0;
+ int rate = stats->rate;
+ u64 tsf = stats->mactime;
+ __le16 phy_flags_hw = rx_start->phy_flags;
+ struct iwl4965_rt_rx_hdr {
+ struct ieee80211_radiotap_header rt_hdr;
+ __le64 rt_tsf; /* TSF */
+ u8 rt_flags; /* radiotap packet flags */
+ u8 rt_rate; /* rate in 500kb/s */
+ __le16 rt_channelMHz; /* channel in MHz */
+ __le16 rt_chbitmask; /* channel bitfield */
+ s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
+ s8 rt_dbmnoise;
+ u8 rt_antenna; /* antenna number */
+ } __attribute__ ((packed)) *iwl4965_rt;
+
+ /* TODO: We won't have enough headroom for HT frames. Fix it later. */
+ if (skb_headroom(skb) < sizeof(*iwl4965_rt)) {
+ if (net_ratelimit())
+ printk(KERN_ERR "not enough headroom [%d] for "
+ "radiotap head [%zd]\n",
+ skb_headroom(skb), sizeof(*iwl4965_rt));
+ return;
+ }
+
+ /* put radiotap header in front of 802.11 header and data */
+ iwl4965_rt = (void *)skb_push(skb, sizeof(*iwl4965_rt));
+
+ /* initialise radiotap header */
+ iwl4965_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
+ iwl4965_rt->rt_hdr.it_pad = 0;
+
+ /* total header + data */
+ put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
+ &iwl4965_rt->rt_hdr.it_len);
+
+ /* Indicate all the fields we add to the radiotap header */
+ put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+ (1 << IEEE80211_RADIOTAP_FLAGS) |
+ (1 << IEEE80211_RADIOTAP_RATE) |
+ (1 << IEEE80211_RADIOTAP_CHANNEL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+ (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+ (1 << IEEE80211_RADIOTAP_ANTENNA)),
+ &iwl4965_rt->rt_hdr.it_present);
+
+ /* Zero the flags, we'll add to them as we go */
+ iwl4965_rt->rt_flags = 0;
+
+ put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf);
+
+ iwl4965_rt->rt_dbmsignal = signal;
+ iwl4965_rt->rt_dbmnoise = noise;
+
+ /* Convert the channel frequency and set the flags */
+ put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz);
+ if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_5GHZ),
+ &iwl4965_rt->rt_chbitmask);
+ else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
+ IEEE80211_CHAN_2GHZ),
+ &iwl4965_rt->rt_chbitmask);
+ else /* 802.11g */
+ put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
+ IEEE80211_CHAN_2GHZ),
+ &iwl4965_rt->rt_chbitmask);
+
+ rate = iwl4965_rate_index_from_plcp(rate);
+ if (rate == -1)
+ iwl4965_rt->rt_rate = 0;
+ else
+ iwl4965_rt->rt_rate = iwl4965_rates[rate].ieee;
+
+ /*
+ * "antenna number"
+ *
+ * It seems that the antenna field in the phy flags value
+ * is actually a bitfield. This is undefined by radiotap,
+ * it wants an actual antenna number but I always get "7"
+ * for most legacy frames I receive indicating that the
+ * same frame was received on all three RX chains.
+ *
+ * I think this field should be removed in favour of a
+ * new 802.11n radiotap field "RX chains" that is defined
+ * as a bitmask.
+ */
+ iwl4965_rt->rt_antenna =
+ le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+ /* set the preamble flag if appropriate */
+ if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+ iwl4965_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+ stats->flag |= RX_FLAG_RADIOTAP;
+}
+
+static void iwl4965_handle_data_packet(struct iwl4965_priv *priv, int is_data,
int include_phy,
- struct iwl_rx_mem_buffer *rxb,
+ struct iwl4965_rx_mem_buffer *rxb,
struct ieee80211_rx_status *stats)
{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
struct iwl4965_rx_phy_res *rx_start = (include_phy) ?
(struct iwl4965_rx_phy_res *)&(pkt->u.raw[0]) : NULL;
struct ieee80211_hdr *hdr;
@@ -3524,9 +3664,8 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
rx_start->byte_count = amsdu->byte_count;
rx_end = (__le32 *) (((u8 *) hdr) + len);
}
- if (len > 2342 || len < 16) {
- IWL_DEBUG_DROP("byte count out of range [16,2342]"
- " : %d\n", len);
+ if (len > priv->hw_setting.max_pkt_size || len < 16) {
+ IWL_WARNING("byte count out of range [16,4K] : %d\n", len);
return;
}
@@ -3544,26 +3683,21 @@ static void iwl4965_handle_data_packet(struct iwl_priv *priv, int is_data,
return;
}
- if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
- if (iwl_param_hwcrypto)
- iwl_set_decrypted_flag(priv, rxb->skb,
- ampdu_status, stats);
- iwl_handle_data_packet_monitor(priv, rxb, hdr, len, stats, 0);
- return;
- }
-
stats->flag = 0;
hdr = (struct ieee80211_hdr *)rxb->skb->data;
- if (iwl_param_hwcrypto)
- iwl_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
+ if (iwl4965_param_hwcrypto)
+ iwl4965_set_decrypted_flag(priv, rxb->skb, ampdu_status, stats);
+
+ if (priv->add_radiotap)
+ iwl4965_add_radiotap(priv, rxb->skb, rx_start, stats, ampdu_status);
ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
priv->alloc_rxb_skb--;
rxb->skb = NULL;
#ifdef LED
priv->led_packets += len;
- iwl_setup_activity_timer(priv);
+ iwl4965_setup_activity_timer(priv);
#endif
}
@@ -3601,7 +3735,7 @@ static int iwl4965_calc_rssi(struct iwl4965_rx_phy_res *rx_resp)
return (max_rssi - agc - IWL_RSSI_OFFSET);
}
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
/* Parsed Information Elements */
struct ieee802_11_elems {
@@ -3673,9 +3807,37 @@ static int parse_elems(u8 *start, size_t len, struct ieee802_11_elems *elems)
return 0;
}
-#endif /* CONFIG_IWLWIFI_HT */
-static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info, int mode)
+{
+ ht_info->cap = 0;
+ memset(ht_info->supp_mcs_set, 0, 16);
+
+ ht_info->ht_supported = 1;
+
+ if (mode == MODE_IEEE80211A) {
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
+ ht_info->supp_mcs_set[4] = 0x01;
+ }
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
+ ht_info->cap |= (u16)(IEEE80211_HT_CAP_MIMO_PS &
+ (IWL_MIMO_PS_NONE << 2));
+ if (iwl4965_param_amsdu_size_8K) {
+ printk(KERN_DEBUG "iwl4965 in A-MSDU 8K support mode\n");
+ ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
+ }
+
+ ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+ ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+
+ ht_info->supp_mcs_set[0] = 0xFF;
+ ht_info->supp_mcs_set[1] = 0xFF;
+}
+#endif /* CONFIG_IWL4965_HT */
+
+static void iwl4965_sta_modify_ps_wake(struct iwl4965_priv *priv, int sta_id)
{
unsigned long flags;
@@ -3686,13 +3848,13 @@ static void iwl4965_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
-static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
+static void iwl4965_update_ps_mode(struct iwl4965_priv *priv, u16 ps_bit, u8 *addr)
{
/* FIXME: need locking over ps_status ??? */
- u8 sta_id = iwl_hw_find_station(priv, addr);
+ u8 sta_id = iwl4965_hw_find_station(priv, addr);
if (sta_id != IWL_INVALID_STATION) {
u8 sta_awake = priv->stations[sta_id].
@@ -3707,12 +3869,14 @@ static void iwl4965_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
}
}
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
/* Called for REPLY_4965_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_rx(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
/* Use phy data (Rx signal strength, etc.) contained within
* this rx packet for legacy frames,
* or phy data cached from REPLY_RX_PHY_CMD for HT frames. */
@@ -3731,11 +3895,8 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
(rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
MODE_IEEE80211G : MODE_IEEE80211A,
.antenna = 0,
- .rate = iwl_hw_get_rate(rx_start->rate_n_flags),
+ .rate = iwl4965_hw_get_rate(rx_start->rate_n_flags),
.flag = 0,
-#ifdef CONFIG_IWLWIFI_HT_AGG
- .ordered = 0
-#endif /* CONFIG_IWLWIFI_HT_AGG */
};
u8 network_packet;
@@ -3794,32 +3955,32 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
* which are gathered only when associated, and indicate noise
* only for the associated network channel ...
* Ignore these noise values while scanning (other channels) */
- if (iwl_is_associated(priv) &&
+ if (iwl4965_is_associated(priv) &&
!test_bit(STATUS_SCANNING, &priv->status)) {
stats.noise = priv->last_rx_noise;
- stats.signal = iwl_calc_sig_qual(stats.ssi, stats.noise);
+ stats.signal = iwl4965_calc_sig_qual(stats.ssi, stats.noise);
} else {
stats.noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
- stats.signal = iwl_calc_sig_qual(stats.ssi, 0);
+ stats.signal = iwl4965_calc_sig_qual(stats.ssi, 0);
}
/* Reset beacon noise level if not associated. */
- if (!iwl_is_associated(priv))
+ if (!iwl4965_is_associated(priv))
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-#ifdef CONFIG_IWLWIFI_DEBUG
- /* TODO: Parts of iwl_report_frame are broken for 4965 */
- if (iwl_debug_level & (IWL_DL_RX))
+#ifdef CONFIG_IWL4965_DEBUG
+ /* TODO: Parts of iwl4965_report_frame are broken for 4965 */
+ if (iwl4965_debug_level & (IWL_DL_RX))
/* Set "1" to report good data frames in groups of 100 */
- iwl_report_frame(priv, pkt, header, 1);
+ iwl4965_report_frame(priv, pkt, header, 1);
- if (iwl_debug_level & (IWL_DL_RX | IWL_DL_STATS))
+ if (iwl4965_debug_level & (IWL_DL_RX | IWL_DL_STATS))
IWL_DEBUG_RX("Rssi %d, noise %d, qual %d, TSF %lu\n",
stats.ssi, stats.noise, stats.signal,
(long unsigned int)le64_to_cpu(rx_start->timestamp));
#endif
- network_packet = iwl_is_network_packet(priv, header);
+ network_packet = iwl4965_is_network_packet(priv, header);
if (network_packet) {
priv->last_rx_rssi = stats.ssi;
priv->last_beacon_time = priv->ucode_beacon_time;
@@ -3863,27 +4024,31 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
break;
/*
- * TODO: There is no callback function from upper
- * stack to inform us when associated status. this
- * work around to sniff assoc_resp management frame
- * and finish the association process.
+ * TODO: Use the new callback function from
+ * mac80211 instead of sniffing these packets.
*/
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
if (network_packet) {
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
u8 *pos = NULL;
struct ieee802_11_elems elems;
-#endif /*CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT */
struct ieee80211_mgmt *mgnt =
(struct ieee80211_mgmt *)header;
+ /* We have just associated, give some
+ * time for the 4-way handshake if
+ * any. Don't start scan too early. */
+ priv->next_scan_jiffies = jiffies +
+ IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
+
priv->assoc_id = (~((1 << 15) | (1 << 14))
& le16_to_cpu(mgnt->u.assoc_resp.aid));
priv->assoc_capability =
le16_to_cpu(
mgnt->u.assoc_resp.capab_info);
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
pos = mgnt->u.assoc_resp.variable;
if (!parse_elems(pos,
len - (pos - (u8 *) mgnt),
@@ -3892,7 +4057,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
elems.ht_cap_param)
break;
}
-#endif /*CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT */
/* assoc_id is 0 no association */
if (!priv->assoc_id)
break;
@@ -3907,7 +4072,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
case IEEE80211_STYPE_PROBE_REQ:
if ((priv->iw_mode == IEEE80211_IF_TYPE_IBSS) &&
- !iwl_is_associated(priv)) {
+ !iwl4965_is_associated(priv)) {
DECLARE_MAC_BUF(mac1);
DECLARE_MAC_BUF(mac2);
DECLARE_MAC_BUF(mac3);
@@ -3924,7 +4089,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
break;
case IEEE80211_FTYPE_CTL:
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BACK_REQ:
IWL_DEBUG_HT("IEEE80211_STYPE_BACK_REQ arrived\n");
@@ -3935,7 +4100,6 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
break;
}
#endif
-
break;
case IEEE80211_FTYPE_DATA: {
@@ -3953,7 +4117,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
print_mac(mac1, header->addr1),
print_mac(mac2, header->addr2),
print_mac(mac3, header->addr3));
- else if (unlikely(is_duplicate_packet(priv, header)))
+ else if (unlikely(iwl4965_is_duplicate_packet(priv, header)))
IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
print_mac(mac1, header->addr1),
print_mac(mac2, header->addr2),
@@ -3971,22 +4135,22 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv,
/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
* This will be used later in iwl4965_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-static void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_rx_phy(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
priv->last_phy_res[0] = 1;
memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
sizeof(struct iwl4965_rx_phy_res));
}
-static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_missed_beacon_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_missed_beacon_notif *missed_beacon;
+#ifdef CONFIG_IWL4965_SENSITIVITY
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
@@ -3999,13 +4163,18 @@ static void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)))
queue_work(priv->workqueue, &priv->sensitivity_work);
}
-#endif /*CONFIG_IWLWIFI_SENSITIVITY*/
+#endif /*CONFIG_IWL4965_SENSITIVITY*/
}
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
-static void iwl4965_set_tx_status(struct iwl_priv *priv, int txq_id, int idx,
+/**
+ * iwl4965_set_tx_status - Update driver's record of one Tx frame's status
+ *
+ * This will get sent to mac80211.
+ */
+static void iwl4965_set_tx_status(struct iwl4965_priv *priv, int txq_id, int idx,
u32 status, u32 retry_count, u32 rate)
{
struct ieee80211_tx_status *tx_status =
@@ -4017,24 +4186,34 @@ static void iwl4965_set_tx_status(struct iwl_priv *priv, int txq_id, int idx,
}
-static void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv,
+/**
+ * iwl4965_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
+ */
+static void iwl4965_sta_modify_enable_tid_tx(struct iwl4965_priv *priv,
int sta_id, int tid)
{
unsigned long flags;
+ /* Remove "disable" flag, to enable Tx for this TID */
spin_lock_irqsave(&priv->sta_lock, flags);
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
-static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwl_compressed_ba_resp*
+/**
+ * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
+ */
+static int iwl4965_tx_status_reply_compressed_ba(struct iwl4965_priv *priv,
+ struct iwl4965_ht_agg *agg,
+ struct iwl4965_compressed_ba_resp*
ba_resp)
{
@@ -4048,16 +4227,20 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
IWL_ERROR("Received BA when not expected\n");
return -EINVAL;
}
+
+ /* Mark that the expected block-ack response arrived */
agg->wait_for_ba = 0;
IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->ba_seq_ctl);
- sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl>>4);
- if (sh < 0) /* tbw something is wrong with indeces */
+
+ /* Calculate shift to align block-ack bits with our Tx window bits */
+ sh = agg->start_idx - SEQ_TO_INDEX(ba_seq_ctl >> 4);
+ if (sh < 0) /* tbw something is wrong with indices */
sh += 0x100;
- /* don't use 64 bits for now */
+ /* don't use 64-bit values for now */
bitmap0 = resp_bitmap0 >> sh;
bitmap1 = resp_bitmap1 >> sh;
- bitmap0 |= (resp_bitmap1 & ((1<<sh)|((1<<sh)-1))) << (32 - sh);
+ bitmap0 |= (resp_bitmap1 & ((1 << sh) | ((1 << sh) - 1))) << (32 - sh);
if (agg->frame_count > (64 - sh)) {
IWL_DEBUG_TX_REPLY("more frames than bitmap size");
@@ -4065,10 +4248,12 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
}
/* check for success or failure according to the
- * transmitted bitmap and back bitmap */
+ * transmitted bitmap and block-ack bitmap */
bitmap0 &= agg->bitmap0;
bitmap1 &= agg->bitmap1;
+ /* For each frame attempted in aggregation,
+ * update driver's record of tx frame's status. */
for (i = 0; i < agg->frame_count ; i++) {
int idx = (agg->start_idx + i) & 0xff;
ack = bitmap0 & (1 << i);
@@ -4084,20 +4269,36 @@ static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
return 0;
}
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
+/**
+ * iwl4965_queue_dec_wrap - Decrement queue index, wrap back to end if needed
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (s/b power of 2)
+ */
+static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
{
return (index == 0) ? n_bd - 1 : index - 1;
}
-static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+/**
+ * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
+ *
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+static void iwl4965_rx_reply_compressed_ba(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
int index;
- struct iwl_tx_queue *txq = NULL;
- struct iwl_ht_agg *agg;
+ struct iwl4965_tx_queue *txq = NULL;
+ struct iwl4965_ht_agg *agg;
+
+ /* "flow" corresponds to Tx queue */
u16 ba_resp_scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+ /* "ssn" is start of block-ack Tx window, corresponds to index
+ * (in Tx queue's circular buffer) of first TFD/frame in window */
u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
if (ba_resp_scd_flow >= ARRAY_SIZE(priv->txq)) {
@@ -4107,9 +4308,11 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
txq = &priv->txq[ba_resp_scd_flow];
agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
- index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
- /* TODO: Need to get this copy more sefely - now good for debug */
+ /* Find index just before block-ack window */
+ index = iwl4965_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+ /* TODO: Need to get this copy more safely - now good for debug */
/*
{
DECLARE_MAC_BUF(mac);
@@ -4132,23 +4335,36 @@ static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
agg->bitmap0);
}
*/
+
+ /* Update driver's record of ACK vs. not for each frame in window */
iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
- /* releases all the TFDs until the SSN */
- if (txq->q.last_used != (ba_resp_scd_ssn & 0xff))
- iwl_tx_queue_reclaim(priv, ba_resp_scd_flow, index);
+
+ /* Release all TFDs before the SSN, i.e. all TFDs in front of
+ * block-ack window (we assume that they've been successfully
+ * transmitted ... if not, it's too late anyway). */
+ if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff))
+ iwl4965_tx_queue_reclaim(priv, ba_resp_scd_flow, index);
}
-static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id)
+/**
+ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+ */
+static void iwl4965_tx_queue_stop_scheduler(struct iwl4965_priv *priv, u16 txq_id)
{
- iwl_write_restricted_reg(priv,
- SCD_QUEUE_STATUS_BITS(txq_id),
+ /* Simply stop the queue, but don't change any configuration;
+ * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+ iwl4965_write_prph(priv,
+ KDR_SCD_QUEUE_STATUS_BITS(txq_id),
(0 << SCD_QUEUE_STTS_REG_POS_ACTIVE)|
(1 << SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
}
-static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+/**
+ * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+ */
+static int iwl4965_tx_queue_set_q2ratid(struct iwl4965_priv *priv, u16 ra_tid,
u16 txq_id)
{
u32 tbl_dw_addr;
@@ -4160,22 +4376,25 @@ static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
tbl_dw_addr = priv->scd_base_addr +
SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
- tbl_dw = iwl_read_restricted_mem(priv, tbl_dw_addr);
+ tbl_dw = iwl4965_read_targ_mem(priv, tbl_dw_addr);
if (txq_id & 0x1)
tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
else
tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
- iwl_write_restricted_mem(priv, tbl_dw_addr, tbl_dw);
+ iwl4965_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
return 0;
}
/**
- * txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
+ * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+ *
+ * NOTE: txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID,
+ * i.e. it must be one of the higher queues used for aggregation
*/
-static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
+static int iwl4965_tx_queue_agg_enable(struct iwl4965_priv *priv, int txq_id,
int tx_fifo, int sta_id, int tid,
u16 ssn_idx)
{
@@ -4189,43 +4408,48 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
ra_tid = BUILD_RAxTID(sta_id, tid);
- iwl_sta_modify_enable_tid_tx(priv, sta_id, tid);
+ /* Modify device's station table to Tx this TID */
+ iwl4965_sta_modify_enable_tid_tx(priv, sta_id, tid);
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
+ /* Stop this Tx queue before configuring it */
iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+ /* Map receiver-address / traffic-ID to this queue */
iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+ /* Set this queue as a chain-building queue */
+ iwl4965_set_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
- iwl_set_bits_restricted_reg(priv, SCD_QUEUECHAIN_SEL, (1<<txq_id));
-
- priv->txq[txq_id].q.last_used = (ssn_idx & 0xff);
- priv->txq[txq_id].q.first_empty = (ssn_idx & 0xff);
-
- /* supposes that ssn_idx is valid (!= 0xFFF) */
+ /* Place first TFD at index corresponding to start sequence number.
+ * Assumes that ssn_idx is valid (!= 0xFFF) */
+ priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+ priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
- iwl_write_restricted_mem(priv,
+ /* Set up Tx window size and frame limit for this queue */
+ iwl4965_write_targ_mem(priv,
priv->scd_base_addr + SCD_CONTEXT_QUEUE_OFFSET(txq_id),
(SCD_WIN_SIZE << SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
- iwl_write_restricted_mem(priv, priv->scd_base_addr +
+ iwl4965_write_targ_mem(priv, priv->scd_base_addr +
SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
(SCD_FRAME_LIMIT << SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
& SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
- iwl_set_bits_restricted_reg(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
+ iwl4965_set_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
+ /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
@@ -4234,7 +4458,7 @@ static int iwl4965_tx_queue_agg_enable(struct iwl_priv *priv, int txq_id,
/**
* txq_id must be greater than IWL_BACK_QUEUE_FIRST_ID
*/
-static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
+static int iwl4965_tx_queue_agg_disable(struct iwl4965_priv *priv, u16 txq_id,
u16 ssn_idx, u8 tx_fifo)
{
unsigned long flags;
@@ -4247,7 +4471,7 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
}
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
@@ -4255,56 +4479,50 @@ static int iwl4965_tx_queue_agg_disable(struct iwl_priv *priv, u16 txq_id,
iwl4965_tx_queue_stop_scheduler(priv, txq_id);
- iwl_clear_bits_restricted_reg(priv, SCD_QUEUECHAIN_SEL, (1 << txq_id));
+ iwl4965_clear_bits_prph(priv, KDR_SCD_QUEUECHAIN_SEL, (1 << txq_id));
- priv->txq[txq_id].q.last_used = (ssn_idx & 0xff);
- priv->txq[txq_id].q.first_empty = (ssn_idx & 0xff);
+ priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+ priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
/* supposes that ssn_idx is valid (!= 0xFFF) */
iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
- iwl_clear_bits_restricted_reg(priv, SCD_INTERRUPT_MASK, (1 << txq_id));
+ iwl4965_clear_bits_prph(priv, KDR_SCD_INTERRUPT_MASK, (1 << txq_id));
iwl4965_txq_ctx_deactivate(priv, txq_id);
iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
-#endif/* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
-/*
- * RATE SCALE CODE
- */
-int iwl4965_init_hw_rates(struct iwl_priv *priv, struct ieee80211_rate *rates)
-{
- return 0;
-}
-
+#endif/* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
/**
* iwl4965_add_station - Initialize a station's hardware rate table
*
- * The uCode contains a table of fallback rates and retries per rate
+ * The uCode's station table contains a table of fallback rates
* for automatic fallback during transmission.
*
- * NOTE: This initializes the table for a single retry per data rate
- * which is not optimal. Setting up an intelligent retry per rate
- * requires feedback from transmission, which isn't exposed through
- * rc80211_simple which is what this driver is currently using.
+ * NOTE: This sets up a default set of values. These will be replaced later
+ * if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ * rc80211_simple.
*
+ * 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).
*/
-void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
{
int i, r;
- struct iwl_link_quality_cmd link_cmd = {
+ struct iwl4965_link_quality_cmd link_cmd = {
.reserved1 = 0,
};
u16 rate_flags;
- /* Set up the rate scaling to start at 54M and fallback
- * all the way to 1M in IEEE order and then spin on IEEE */
+ /* Set up the rate scaling to start at selected rate, fall back
+ * all the way down to 1M in IEEE order, and then spin on 1M */
if (is_ap)
r = IWL_RATE_54M_INDEX;
else if (priv->phymode == MODE_IEEE80211A)
@@ -4317,11 +4535,13 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
+ /* Use Tx antenna B only */
rate_flags |= RATE_MCS_ANT_B_MSK;
rate_flags &= ~RATE_MCS_ANT_A_MSK;
+
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);
+ iwl4965_hw_set_rate_n_flags(iwl4965_rates[r].plcp, rate_flags);
+ r = iwl4965_get_prev_ieee_rate(r);
}
link_cmd.general_params.single_stream_ant_msk = 2;
@@ -4332,18 +4552,18 @@ void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
/* Update the rate scaling for control frame Tx to AP */
link_cmd.sta_id = is_ap ? IWL_AP_ID : IWL4965_BROADCAST_ID;
- iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd),
+ iwl4965_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, sizeof(link_cmd),
&link_cmd);
}
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
-static u8 iwl_is_channel_extension(struct iwl_priv *priv, int phymode,
+static u8 iwl4965_is_channel_extension(struct iwl4965_priv *priv, int phymode,
u16 channel, u8 extension_chan_offset)
{
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv, phymode, channel);
+ ch_info = iwl4965_get_channel_info(priv, phymode, channel);
if (!is_channel_valid(ch_info))
return 0;
@@ -4357,36 +4577,37 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, int phymode,
return 0;
}
-static u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
- const struct sta_ht_info *ht_info)
+static u8 iwl4965_is_fat_tx_allowed(struct iwl4965_priv *priv,
+ struct ieee80211_ht_info *sta_ht_inf)
{
+ struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
- if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
+ if ((!iwl_ht_conf->is_ht) ||
+ (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
+ (iwl_ht_conf->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO))
return 0;
- if (ht_info->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ)
- return 0;
-
- if (ht_info->extension_chan_offset == IWL_EXT_CHANNEL_OFFSET_AUTO)
- return 0;
+ if (sta_ht_inf) {
+ if ((!sta_ht_inf->ht_supported) ||
+ (!sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH))
+ return 0;
+ }
- /* no fat tx allowed on 2.4GHZ */
- if (priv->phymode != MODE_IEEE80211A)
- return 0;
- return (iwl_is_channel_extension(priv, priv->phymode,
- ht_info->control_channel,
- ht_info->extension_chan_offset));
+ return (iwl4965_is_channel_extension(priv, priv->phymode,
+ iwl_ht_conf->control_channel,
+ iwl_ht_conf->extension_chan_offset));
}
-void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info)
+void iwl4965_set_rxon_ht(struct iwl4965_priv *priv, struct iwl_ht_info *ht_info)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
u32 val;
if (!ht_info->is_ht)
return;
- if (iwl_is_fat_tx_allowed(priv, ht_info))
+ /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */
+ if (iwl4965_is_fat_tx_allowed(priv, NULL))
rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK;
else
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
@@ -4400,7 +4621,7 @@ void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info)
return;
}
- /* Note: control channel is oposit to extension channel */
+ /* Note: control channel is opposite of extension channel */
switch (ht_info->extension_chan_offset) {
case IWL_EXT_CHANNEL_OFFSET_ABOVE:
rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
@@ -4416,66 +4637,56 @@ void iwl4965_set_rxon_ht(struct iwl_priv *priv, struct sta_ht_info *ht_info)
break;
}
- val = ht_info->operating_mode;
+ val = ht_info->ht_protection;
rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
- priv->active_rate_ht[0] = ht_info->supp_rates[0];
- priv->active_rate_ht[1] = ht_info->supp_rates[1];
iwl4965_set_rxon_chain(priv);
IWL_DEBUG_ASSOC("supported HT rate 0x%X %X "
"rxon flags 0x%X operation mode :0x%X "
"extension channel offset 0x%x "
"control chan %d\n",
- priv->active_rate_ht[0], priv->active_rate_ht[1],
- le32_to_cpu(rxon->flags), ht_info->operating_mode,
+ ht_info->supp_mcs_set[0], ht_info->supp_mcs_set[1],
+ le32_to_cpu(rxon->flags), ht_info->ht_protection,
ht_info->extension_chan_offset,
ht_info->control_channel);
return;
}
-void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index)
+void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_inf)
{
__le32 sta_flags;
- struct sta_ht_info *ht_info = &priv->current_assoc_ht;
- priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
- if (!ht_info->is_ht)
+ if (!sta_ht_inf || !sta_ht_inf->ht_supported)
goto done;
sta_flags = priv->stations[index].sta.station_flags;
- if (ht_info->tx_mimo_ps_mode == IWL_MIMO_PS_DYNAMIC)
+ if (((sta_ht_inf->cap & IEEE80211_HT_CAP_MIMO_PS >> 2))
+ == IWL_MIMO_PS_DYNAMIC)
sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
else
sta_flags &= ~STA_FLG_RTS_MIMO_PROT_MSK;
sta_flags |= cpu_to_le32(
- (u32)ht_info->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+ (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
sta_flags |= cpu_to_le32(
- (u32)ht_info->mpdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
-
- sta_flags &= (~STA_FLG_FAT_EN_MSK);
- ht_info->tx_chan_width = IWL_CHANNEL_WIDTH_20MHZ;
- ht_info->chan_width_cap = IWL_CHANNEL_WIDTH_20MHZ;
+ (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
- if (iwl_is_fat_tx_allowed(priv, ht_info)) {
+ if (iwl4965_is_fat_tx_allowed(priv, sta_ht_inf))
sta_flags |= STA_FLG_FAT_EN_MSK;
- ht_info->chan_width_cap = IWL_CHANNEL_WIDTH_40MHZ;
- if (ht_info->supported_chan_width == IWL_CHANNEL_WIDTH_40MHZ)
- ht_info->tx_chan_width = IWL_CHANNEL_WIDTH_40MHZ;
- }
- priv->current_channel_width = ht_info->tx_chan_width;
+ else
+ sta_flags &= (~STA_FLG_FAT_EN_MSK);
+
priv->stations[index].sta.station_flags = sta_flags;
done:
return;
}
-#ifdef CONFIG_IWLWIFI_HT_AGG
-
-static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
+static void iwl4965_sta_modify_add_ba_tid(struct iwl4965_priv *priv,
int sta_id, int tid, u16 ssn)
{
unsigned long flags;
@@ -4488,10 +4699,10 @@ static void iwl4965_sta_modify_add_ba_tid(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
-static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
+static void iwl4965_sta_modify_del_ba_tid(struct iwl4965_priv *priv,
int sta_id, int tid)
{
unsigned long flags;
@@ -4503,9 +4714,39 @@ static void iwl4965_sta_modify_del_ba_tid(struct iwl_priv *priv,
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+}
+
+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+ enum ieee80211_ampdu_mlme_action action,
+ const u8 *addr, u16 tid, u16 ssn)
+{
+ struct iwl4965_priv *priv = hw->priv;
+ int sta_id;
+ DECLARE_MAC_BUF(mac);
+
+ IWL_DEBUG_HT("A-MPDU action on da=%s tid=%d ",
+ print_mac(mac, addr), tid);
+ sta_id = iwl4965_hw_find_station(priv, addr);
+ switch (action) {
+ case IEEE80211_AMPDU_RX_START:
+ IWL_DEBUG_HT("start Rx\n");
+ iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, ssn);
+ break;
+ case IEEE80211_AMPDU_RX_STOP:
+ IWL_DEBUG_HT("stop Rx\n");
+ iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
+ break;
+ default:
+ IWL_DEBUG_HT("unknown\n");
+ return -EINVAL;
+ break;
+ }
+ return 0;
}
+#ifdef CONFIG_IWL4965_HT_AGG
+
static const u16 default_tid_to_tx_fifo[] = {
IWL_TX_FIFO_AC1,
IWL_TX_FIFO_AC0,
@@ -4526,7 +4767,13 @@ static const u16 default_tid_to_tx_fifo[] = {
IWL_TX_FIFO_AC3
};
-static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6).
+ */
+static int iwl4965_txq_ctx_activate_free(struct iwl4965_priv *priv)
{
int txq_id;
@@ -4536,55 +4783,65 @@ static int iwl_txq_ctx_activate_free(struct iwl_priv *priv)
return -1;
}
-int iwl_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid,
+int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da, u16 tid,
u16 *start_seq_num)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
int sta_id;
int tx_fifo;
int txq_id;
int ssn = -1;
unsigned long flags;
- struct iwl_tid_data *tid_data;
+ struct iwl4965_tid_data *tid_data;
DECLARE_MAC_BUF(mac);
+ /* Determine Tx DMA/FIFO channel for this Traffic ID */
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
tx_fifo = default_tid_to_tx_fifo[tid];
else
return -EINVAL;
- IWL_WARNING("iwl-AGG iwl_mac_ht_tx_agg_start on da=%s"
+ IWL_WARNING("iwl-AGG iwl4965_mac_ht_tx_agg_start on da=%s"
" tid=%d\n", print_mac(mac, da), tid);
- sta_id = iwl_hw_find_station(priv, da);
+ /* Get index into station table */
+ sta_id = iwl4965_hw_find_station(priv, da);
if (sta_id == IWL_INVALID_STATION)
return -ENXIO;
- txq_id = iwl_txq_ctx_activate_free(priv);
+ /* Find available Tx queue for aggregation */
+ txq_id = iwl4965_txq_ctx_activate_free(priv);
if (txq_id == -1)
return -ENXIO;
spin_lock_irqsave(&priv->sta_lock, flags);
tid_data = &priv->stations[sta_id].tid[tid];
+
+ /* Get starting sequence number for 1st frame in block ack window.
+ * We'll use least signif byte as 1st frame's index into Tx queue. */
ssn = SEQ_TO_SN(tid_data->seq_number);
tid_data->agg.txq_id = txq_id;
spin_unlock_irqrestore(&priv->sta_lock, flags);
*start_seq_num = ssn;
+
+ /* Update driver's link quality manager */
iwl4965_ba_status(priv, tid, BA_STATUS_ACTIVE);
+
+ /* Set up and enable aggregation for selected Tx queue and FIFO */
return iwl4965_tx_queue_agg_enable(priv, txq_id, tx_fifo,
sta_id, tid, ssn);
}
-int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
+int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
int generator)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
int tx_fifo_id, txq_id, sta_id, ssn = -1;
- struct iwl_tid_data *tid_data;
+ struct iwl4965_tid_data *tid_data;
int rc;
DECLARE_MAC_BUF(mac);
@@ -4598,7 +4855,7 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
else
return -EINVAL;
- sta_id = iwl_hw_find_station(priv, da);
+ sta_id = iwl4965_hw_find_station(priv, da);
if (sta_id == IWL_INVALID_STATION)
return -ENXIO;
@@ -4613,45 +4870,18 @@ int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da, u16 tid,
return rc;
iwl4965_ba_status(priv, tid, BA_STATUS_INITIATOR_DELBA);
- IWL_DEBUG_INFO("iwl_mac_ht_tx_agg_stop on da=%s tid=%d\n",
+ IWL_DEBUG_INFO("iwl4965_mac_ht_tx_agg_stop on da=%s tid=%d\n",
print_mac(mac, da), tid);
return 0;
}
-int iwl_mac_ht_rx_agg_start(struct ieee80211_hw *hw, u8 *da,
- u16 tid, u16 start_seq_num)
-{
- struct iwl_priv *priv = hw->priv;
- int sta_id;
- DECLARE_MAC_BUF(mac);
- IWL_WARNING("iwl-AGG iwl_mac_ht_rx_agg_start on da=%s"
- " tid=%d\n", print_mac(mac, da), tid);
- sta_id = iwl_hw_find_station(priv, da);
- iwl4965_sta_modify_add_ba_tid(priv, sta_id, tid, start_seq_num);
- return 0;
-}
-
-int iwl_mac_ht_rx_agg_stop(struct ieee80211_hw *hw, u8 *da,
- u16 tid, int generator)
-{
- struct iwl_priv *priv = hw->priv;
- int sta_id;
- DECLARE_MAC_BUF(mac);
-
- IWL_WARNING("iwl-AGG iwl_mac_ht_rx_agg_stop on da=%s tid=%d\n",
- print_mac(mac, da), tid);
- sta_id = iwl_hw_find_station(priv, da);
- iwl4965_sta_modify_del_ba_tid(priv, sta_id, tid);
- return 0;
-}
-
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
/* Set up 4965-specific Rx frame reply handlers */
-void iwl_hw_rx_handler_setup(struct iwl_priv *priv)
+void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv)
{
/* Legacy Rx frames */
priv->rx_handlers[REPLY_4965_RX] = iwl4965_rx_reply_rx;
@@ -4663,57 +4893,66 @@ void iwl_hw_rx_handler_setup(struct iwl_priv *priv)
priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
iwl4965_rx_missed_beacon_notif;
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
-#endif /* CONFIG_IWLWIFI_AGG */
-#endif /* CONFIG_IWLWIFI */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
}
-void iwl_hw_setup_deferred_work(struct iwl_priv *priv)
+void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv)
{
INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
INIT_WORK(&priv->statistics_work, iwl4965_bg_statistics_work);
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
INIT_WORK(&priv->sensitivity_work, iwl4965_bg_sensitivity_work);
#endif
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
INIT_WORK(&priv->agg_work, iwl4965_bg_agg_work);
-#endif /* CONFIG_IWLWIFI_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
}
-void iwl_hw_cancel_deferred_work(struct iwl_priv *priv)
+void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv)
{
del_timer_sync(&priv->statistics_periodic);
cancel_delayed_work(&priv->init_alive_start);
}
-struct pci_device_id iwl_hw_card_ids[] = {
- {0x8086, 0x4229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- {0x8086, 0x4230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+struct pci_device_id iwl4965_hw_card_ids[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4229)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4230)},
{0}
};
-int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv)
+/*
+ * The device's EEPROM semaphore prevents conflicts between driver and uCode
+ * when accessing the EEPROM; each access is a series of pulses to/from the
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv)
{
u16 count;
int rc;
for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
- iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+ /* Request semaphore */
+ iwl4965_set_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
- rc = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+
+ /* See if we got it */
+ rc = iwl4965_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
EEPROM_SEM_TIMEOUT);
if (rc >= 0) {
- IWL_DEBUG_IO("Aqcuired semaphore after %d tries.\n",
+ IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
count+1);
return rc;
}
@@ -4722,11 +4961,11 @@ int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv)
return rc;
}
-inline void iwl_eeprom_release_semaphore(struct iwl_priv *priv)
+inline void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv)
{
- iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+ iwl4965_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
}
-MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
+MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h
index 4c700812b45b..78bc148c9f7f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.h
@@ -23,64 +23,777 @@
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
+/*
+ * Please use this file (iwl-4965.h) for driver implementation definitions.
+ * Please use iwl-4965-commands.h for uCode API definitions.
+ * Please use iwl-4965-hw.h for hardware-related definitions.
+ */
+
#ifndef __iwl_4965_h__
#define __iwl_4965_h__
-struct iwl_priv;
-struct sta_ht_info;
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <net/ieee80211_radiotap.h>
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+extern struct pci_device_id iwl4965_hw_card_ids[];
+
+#define DRV_NAME "iwl4965"
+#include "iwl-4965-hw.h"
+#include "iwl-prph.h"
+#include "iwl-4965-debug.h"
+
+/* Default noise level to report when noise measurement is not available.
+ * This may be because we're:
+ * 1) Not associated (4965, no beacon statistics being sent to driver)
+ * 2) Scanning (noise measurement does not apply to associated channel)
+ * 3) Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ * Also, -127 works better than 0 when averaging frames with/without
+ * noise info (e.g. averaging might be done in app); measured dBm values are
+ * always negative ... using a negative value as the default keeps all
+ * averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/* Module parameters accessible from iwl-*.c */
+extern int iwl4965_param_hwcrypto;
+extern int iwl4965_param_queues_num;
+extern int iwl4965_param_amsdu_size_8K;
+
+enum iwl4965_antenna {
+ IWL_ANTENNA_DIVERSITY,
+ IWL_ANTENNA_MAIN,
+ IWL_ANTENNA_AUX
+};
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ * a value of 0 means RTS on all data/management packets
+ * a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ * than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD 2347U
+#define MIN_RTS_THRESHOLD 0U
+#define MAX_RTS_THRESHOLD 2347U
+#define MAX_MSDU_SIZE 2304U
+#define MAX_MPDU_SIZE 2346U
+#define DEFAULT_BEACON_INTERVAL 100U
+#define DEFAULT_SHORT_RETRY_LIMIT 7U
+#define DEFAULT_LONG_RETRY_LIMIT 4U
+
+struct iwl4965_rx_mem_buffer {
+ dma_addr_t dma_addr;
+ struct sk_buff *skb;
+ struct list_head list;
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct iwl4965_queue {
+ int n_bd; /* number of BDs in this queue */
+ int write_ptr; /* 1-st empty entry (index) host_w*/
+ int read_ptr; /* last used entry (index) host_r*/
+ dma_addr_t dma_addr; /* physical addr for BD's */
+ int n_window; /* safe queue window */
+ u32 id;
+ int low_mark; /* low watermark, resume queue if free
+ * space more than this */
+ int high_mark; /* high watermark, stop queue if free
+ * space less than this */
+} __attribute__ ((packed));
+
+#define MAX_NUM_OF_TBS (20)
+
+/* One for each TFD */
+struct iwl4965_tx_info {
+ struct ieee80211_tx_status status;
+ struct sk_buff *skb[MAX_NUM_OF_TBS];
+};
+
+/**
+ * struct iwl4965_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/Tx buffers
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @need_update: indicates need to update read/write index
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+struct iwl4965_tx_queue {
+ struct iwl4965_queue q;
+ struct iwl4965_tfd_frame *bd;
+ struct iwl4965_cmd *cmd;
+ dma_addr_t dma_addr_cmd;
+ struct iwl4965_tx_info *txb;
+ int need_update;
+ int sched_retry;
+ int active;
+};
+
+#define IWL_NUM_SCAN_RATES (2)
+
+struct iwl4965_channel_tgd_info {
+ u8 type;
+ s8 max_power;
+};
+
+struct iwl4965_channel_tgh_info {
+ s64 last_radar_time;
+};
+
+/* current Tx power values to use, one for each rate for each channel.
+ * requested power is limited by:
+ * -- regulatory EEPROM limits for this channel
+ * -- hardware capabilities (clip-powers)
+ * -- spectrum management
+ * -- user preference (e.g. iwconfig)
+ * when requested power is set, base power index must also be set. */
+struct iwl4965_channel_power_info {
+ struct iwl4965_tx_power tpc; /* actual radio and DSP gain settings */
+ s8 power_table_index; /* actual (compenst'd) index into gain table */
+ s8 base_power_index; /* gain index for power at factory temp. */
+ s8 requested_power; /* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct iwl4965_scan_power_info {
+ struct iwl4965_tx_power tpc; /* actual radio and DSP gain settings */
+ s8 power_table_index; /* actual (compenst'd) index into gain table */
+ s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */
+};
+
+/* For fat_extension_channel */
+enum {
+ HT_IE_EXT_CHANNEL_NONE = 0,
+ HT_IE_EXT_CHANNEL_ABOVE,
+ HT_IE_EXT_CHANNEL_INVALID,
+ HT_IE_EXT_CHANNEL_BELOW,
+ HT_IE_EXT_CHANNEL_MAX
+};
+
+/*
+ * One for each channel, holds all channel setup data
+ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
+ * with one another!
+ */
+#define IWL4965_MAX_RATE (33)
+
+struct iwl4965_channel_info {
+ struct iwl4965_channel_tgd_info tgd;
+ struct iwl4965_channel_tgh_info tgh;
+ struct iwl4965_eeprom_channel eeprom; /* EEPROM regulatory limit */
+ struct iwl4965_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for
+ * FAT channel */
+
+ u8 channel; /* channel number */
+ u8 flags; /* flags copied from EEPROM */
+ s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+ s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */
+ s8 min_power; /* always 0 */
+ s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */
+
+ u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
+ u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
+ u8 phymode; /* MODE_IEEE80211{A,B,G} */
+
+ /* Radio/DSP gain settings for each "normal" data Tx rate.
+ * These include, in addition to RF and DSP gain, a few fields for
+ * remembering/modifying gain settings (indexes). */
+ struct iwl4965_channel_power_info power_info[IWL4965_MAX_RATE];
+
+ /* FAT channel info */
+ s8 fat_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+ s8 fat_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
+ s8 fat_min_power; /* always 0 */
+ s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */
+ u8 fat_flags; /* flags copied from EEPROM */
+ u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
+
+ /* Radio/DSP gain settings for each scan rate, for directed scans. */
+ struct iwl4965_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
+};
+
+struct iwl4965_clip_group {
+ /* maximum power level to prevent clipping for each rate, derived by
+ * us from this band's saturation power in EEPROM */
+ const s8 clip_powers[IWL_MAX_RATES];
+};
+
+#include "iwl-4965-rs.h"
+
+#define IWL_TX_FIFO_AC0 0
+#define IWL_TX_FIFO_AC1 1
+#define IWL_TX_FIFO_AC2 2
+#define IWL_TX_FIFO_AC3 3
+#define IWL_TX_FIFO_HCCA_1 5
+#define IWL_TX_FIFO_HCCA_2 6
+#define IWL_TX_FIFO_NONE 7
+
+/* Minimum number of queues. MAX_NUM is defined in hw specific files */
+#define IWL_MIN_NUM_QUEUES 4
+
+/* Power management (not Tx power) structures */
+
+struct iwl4965_power_vec_entry {
+ struct iwl4965_powertable_cmd cmd;
+ u8 no_dtim;
+};
+#define IWL_POWER_RANGE_0 (0)
+#define IWL_POWER_RANGE_1 (1)
+
+#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */
+#define IWL_POWER_INDEX_3 0x03
+#define IWL_POWER_INDEX_5 0x05
+#define IWL_POWER_AC 0x06
+#define IWL_POWER_BATTERY 0x07
+#define IWL_POWER_LIMIT 0x07
+#define IWL_POWER_MASK 0x0F
+#define IWL_POWER_ENABLED 0x10
+#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK)
+
+struct iwl4965_power_mgr {
+ spinlock_t lock;
+ struct iwl4965_power_vec_entry pwr_range_0[IWL_POWER_AC];
+ struct iwl4965_power_vec_entry pwr_range_1[IWL_POWER_AC];
+ u8 active_index;
+ u32 dtim_val;
+};
+
+#define IEEE80211_DATA_LEN 2304
+#define IEEE80211_4ADDR_LEN 30
+#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl4965_frame {
+ union {
+ struct ieee80211_hdr frame;
+ struct iwl4965_tx_beacon_cmd beacon;
+ u8 raw[IEEE80211_FRAME_LEN];
+ u8 cmd[360];
+ } u;
+ struct list_head list;
+};
+
+#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
+#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
+#define SEQ_TO_INDEX(x) (x & 0xff)
+#define INDEX_TO_SEQ(x) (x & 0xff)
+#define SEQ_HUGE_FRAME (0x4000)
+#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+ /* CMD_SIZE_NORMAL = 0, */
+ CMD_SIZE_HUGE = (1 << 0),
+ /* CMD_SYNC = 0, */
+ CMD_ASYNC = (1 << 1),
+ /* CMD_NO_SKB = 0, */
+ CMD_WANT_SKB = (1 << 2),
+};
+
+struct iwl4965_cmd;
+struct iwl4965_priv;
+
+struct iwl4965_cmd_meta {
+ struct iwl4965_cmd_meta *source;
+ union {
+ struct sk_buff *skb;
+ int (*callback)(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd, struct sk_buff *skb);
+ } __attribute__ ((packed)) u;
+
+ /* The CMD_SIZE_HUGE flag bit indicates that the command
+ * structure is stored at the end of the shared queue memory. */
+ u32 flags;
+
+} __attribute__ ((packed));
+
+/**
+ * struct iwl4965_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+struct iwl4965_cmd {
+ struct iwl4965_cmd_meta meta; /* driver data */
+ struct iwl4965_cmd_header hdr; /* uCode API */
+ union {
+ struct iwl4965_addsta_cmd addsta;
+ struct iwl4965_led_cmd led;
+ u32 flags;
+ u8 val8;
+ u16 val16;
+ u32 val32;
+ struct iwl4965_bt_cmd bt;
+ struct iwl4965_rxon_time_cmd rxon_time;
+ struct iwl4965_powertable_cmd powertable;
+ struct iwl4965_qosparam_cmd qosparam;
+ struct iwl4965_tx_cmd tx;
+ struct iwl4965_tx_beacon_cmd tx_beacon;
+ struct iwl4965_rxon_assoc_cmd rxon_assoc;
+ u8 *indirect;
+ u8 payload[360];
+ } __attribute__ ((packed)) cmd;
+} __attribute__ ((packed));
+
+struct iwl4965_host_cmd {
+ u8 id;
+ u16 len;
+ struct iwl4965_cmd_meta meta;
+ const void *data;
+};
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl4965_cmd) - \
+ sizeof(struct iwl4965_cmd_meta))
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
+
+/**
+ * struct iwl4965_rx_queue - Rx queue
+ * @processed: Internal index to last handled Rx packet
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ *
+ * NOTE: rx_free and rx_used are used as a FIFO for iwl4965_rx_mem_buffers
+ */
+struct iwl4965_rx_queue {
+ __le32 *bd;
+ dma_addr_t dma_addr;
+ struct iwl4965_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct iwl4965_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+ u32 processed;
+ u32 read;
+ u32 write;
+ u32 free_count;
+ struct list_head rx_free;
+ struct list_head rx_used;
+ int need_update;
+ spinlock_t lock;
+};
+
+#define IWL_SUPPORTED_RATES_IE_LEN 8
+
+#define SCAN_INTERVAL 100
+
+#define MAX_A_CHANNELS 252
+#define MIN_A_CHANNELS 7
+
+#define MAX_B_CHANNELS 14
+#define MIN_B_CHANNELS 1
+
+#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
+#define STATUS_INT_ENABLED 1
+#define STATUS_RF_KILL_HW 2
+#define STATUS_RF_KILL_SW 3
+#define STATUS_INIT 4
+#define STATUS_ALIVE 5
+#define STATUS_READY 6
+#define STATUS_TEMPERATURE 7
+#define STATUS_GEO_CONFIGURED 8
+#define STATUS_EXIT_PENDING 9
+#define STATUS_IN_SUSPEND 10
+#define STATUS_STATISTICS 11
+#define STATUS_SCANNING 12
+#define STATUS_SCAN_ABORTING 13
+#define STATUS_SCAN_HW 14
+#define STATUS_POWER_PMI 15
+#define STATUS_FW_ERROR 16
+#define STATUS_CONF_PENDING 17
+
+#define MAX_TID_COUNT 9
+
+#define IWL_INVALID_RATE 0xFF
+#define IWL_INVALID_VALUE -1
+
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
+/**
+ * struct iwl4965_ht_agg -- aggregation status while waiting for block-ack
+ * @txq_id: Tx queue used for Tx attempt
+ * @frame_count: # frames attempted by Tx command
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
+ * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
+ * @bitmap1: High order, one bit for each frame pending ACK in Tx window
+ * @rate_n_flags: Rate at which Tx was attempted
+ *
+ * If REPLY_TX indicates that aggregation was attempted, driver must wait
+ * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info
+ * until block ack arrives.
+ */
+struct iwl4965_ht_agg {
+ u16 txq_id;
+ u16 frame_count;
+ u16 wait_for_ba;
+ u16 start_idx;
+ u32 bitmap0;
+ u32 bitmap1;
+ u32 rate_n_flags;
+};
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
+
+struct iwl4965_tid_data {
+ u16 seq_number;
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
+ struct iwl4965_ht_agg agg;
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
+};
+
+struct iwl4965_hw_key {
+ enum ieee80211_key_alg alg;
+ int keylen;
+ u8 key[32];
+};
+
+union iwl4965_ht_rate_supp {
+ u16 rates;
+ struct {
+ u8 siso_rate;
+ u8 mimo_rate;
+ };
+};
+
+#ifdef CONFIG_IWL4965_HT
+#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
+#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC
+
+struct iwl_ht_info {
+ /* self configuration data */
+ u8 is_ht;
+ u8 supported_chan_width;
+ u16 tx_mimo_ps_mode;
+ u8 is_green_field;
+ u8 sgf; /* HT_SHORT_GI_* short guard interval */
+ u8 max_amsdu_size;
+ u8 ampdu_factor;
+ u8 mpdu_density;
+ u8 supp_mcs_set[16];
+ /* BSS related data */
+ u8 control_channel;
+ u8 extension_chan_offset;
+ u8 tx_chan_width;
+ u8 ht_protection;
+ u8 non_GF_STA_present;
+};
+#endif /*CONFIG_IWL4965_HT */
+
+#ifdef CONFIG_IWL4965_QOS
+
+union iwl4965_qos_capabity {
+ struct {
+ u8 edca_count:4; /* bit 0-3 */
+ u8 q_ack:1; /* bit 4 */
+ u8 queue_request:1; /* bit 5 */
+ u8 txop_request:1; /* bit 6 */
+ u8 reserved:1; /* bit 7 */
+ } q_AP;
+ struct {
+ u8 acvo_APSD:1; /* bit 0 */
+ u8 acvi_APSD:1; /* bit 1 */
+ u8 ac_bk_APSD:1; /* bit 2 */
+ u8 ac_be_APSD:1; /* bit 3 */
+ u8 q_ack:1; /* bit 4 */
+ u8 max_len:2; /* bit 5-6 */
+ u8 more_data_ack:1; /* bit 7 */
+ } q_STA;
+ u8 val;
+};
+
+/* QoS structures */
+struct iwl4965_qos_info {
+ int qos_enable;
+ int qos_active;
+ union iwl4965_qos_capabity qos_cap;
+ struct iwl4965_qosparam_cmd def_qos_parm;
+};
+#endif /*CONFIG_IWL4965_QOS */
+
+#define STA_PS_STATUS_WAKE 0
+#define STA_PS_STATUS_SLEEP 1
+
+struct iwl4965_station_entry {
+ struct iwl4965_addsta_cmd sta;
+ struct iwl4965_tid_data tid[MAX_TID_COUNT];
+ u8 used;
+ u8 ps_status;
+ struct iwl4965_hw_key keyinfo;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+ void *v_addr; /* access by driver */
+ dma_addr_t p_addr; /* access by card's busmaster DMA */
+ u32 len; /* bytes */
+};
+
+/* uCode file layout */
+struct iwl4965_ucode {
+ __le32 ver; /* major/minor/subminor */
+ __le32 inst_size; /* bytes of runtime instructions */
+ __le32 data_size; /* bytes of runtime data */
+ __le32 init_size; /* bytes of initialization instructions */
+ __le32 init_data_size; /* bytes of initialization data */
+ __le32 boot_size; /* bytes of bootstrap instructions */
+ u8 data[0]; /* data in same order as "size" elements */
+};
+
+#define IWL_IBSS_MAC_HASH_SIZE 32
+
+struct iwl4965_ibss_seq {
+ u8 mac[ETH_ALEN];
+ u16 seq_num;
+ u16 frag_num;
+ unsigned long packet_time;
+ struct list_head list;
+};
+
+/**
+ * struct iwl4965_driver_hw_info
+ * @max_txq_num: Max # Tx queues supported
+ * @ac_queue_count: # Tx queues for EDCA Access Categories (AC)
+ * @tx_cmd_len: Size of Tx command (but not including frame itself)
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @rx_buffer_size:
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @max_stations:
+ * @bcast_sta_id:
+ * @shared_virt: Pointer to driver/uCode shared Tx Byte Counts and Rx status
+ * @shared_phys: Physical Pointer to Tx Byte Counts and Rx status
+ */
+struct iwl4965_driver_hw_info {
+ u16 max_txq_num;
+ u16 ac_queue_count;
+ u16 tx_cmd_len;
+ u16 max_rxq_size;
+ u32 rx_buf_size;
+ u32 max_pkt_size;
+ u16 max_rxq_log;
+ u8 max_stations;
+ u8 bcast_sta_id;
+ void *shared_virt;
+ dma_addr_t shared_phys;
+};
+
+#define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
+#define HT_SHORT_GI_40MHZ_ONLY (1 << 1)
+
+
+#define IWL_RX_HDR(x) ((struct iwl4965_rx_frame_hdr *)(\
+ x->u.rx_frame.stats.payload + \
+ x->u.rx_frame.stats.phy_count))
+#define IWL_RX_END(x) ((struct iwl4965_rx_frame_end *)(\
+ IWL_RX_HDR(x)->payload + \
+ le16_to_cpu(IWL_RX_HDR(x)->len)))
+#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
+#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
+
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-base.c which are forward declared here
+ * for use by iwl-*.c
+ *
+ *****************************************************************************/
+struct iwl4965_addsta_cmd;
+extern int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ struct iwl4965_addsta_cmd *sta, u8 flags);
+extern u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ int is_ap, u8 flags, void *ht_data);
+extern int iwl4965_is_network_packet(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *header);
+extern int iwl4965_power_init_handle(struct iwl4965_priv *priv);
+extern int iwl4965_eeprom_init(struct iwl4965_priv *priv);
+#ifdef CONFIG_IWL4965_DEBUG
+extern void iwl4965_report_frame(struct iwl4965_priv *priv,
+ struct iwl4965_rx_packet *pkt,
+ struct ieee80211_hdr *header, int group100);
+#else
+static inline void iwl4965_report_frame(struct iwl4965_priv *priv,
+ struct iwl4965_rx_packet *pkt,
+ struct ieee80211_hdr *header,
+ int group100) {}
+#endif
+extern void iwl4965_handle_data_packet_monitor(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb,
+ void *data, short len,
+ struct ieee80211_rx_status *stats,
+ u16 phy_flags);
+extern int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *header);
+extern int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv);
+extern void iwl4965_rx_queue_reset(struct iwl4965_priv *priv,
+ struct iwl4965_rx_queue *rxq);
+extern int iwl4965_calc_db_from_ratio(int sig_ratio);
+extern int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm);
+extern int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq, int count, u32 id);
+extern void iwl4965_rx_replenish(void *data);
+extern void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+extern int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len,
+ const void *data);
+extern int __must_check iwl4965_send_cmd(struct iwl4965_priv *priv,
+ struct iwl4965_host_cmd *cmd);
+extern unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *hdr,
+ const u8 *dest, int left);
+extern int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ struct iwl4965_rx_queue *q);
+extern int iwl4965_send_statistics_request(struct iwl4965_priv *priv);
+extern void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
+ u32 decrypt_res,
+ struct ieee80211_rx_status *stats);
+extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
+
+extern const u8 iwl4965_broadcast_addr[ETH_ALEN];
+
+/*
+ * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
+ * call this... todo... fix that.
+*/
+extern u8 iwl4965_sync_station(struct iwl4965_priv *priv, int sta_id,
+ u16 tx_rate, u8 flags);
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-[34]*.c which are forward declared here
+ * for use by iwl-base.c
+ *
+ * NOTE: The implementation of these functions are hardware specific
+ * which is why they are in the hardware specific files (vs. iwl-base.c)
+ *
+ * Naming convention --
+ * iwl4965_ <-- Its part of iwlwifi (should be changed to iwl4965_)
+ * iwl4965_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl4965_bg_ <-- Called from work queue context
+ * iwl4965_mac_ <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl4965_hw_rx_handler_setup(struct iwl4965_priv *priv);
+extern void iwl4965_hw_setup_deferred_work(struct iwl4965_priv *priv);
+extern void iwl4965_hw_cancel_deferred_work(struct iwl4965_priv *priv);
+extern int iwl4965_hw_rxq_stop(struct iwl4965_priv *priv);
+extern int iwl4965_hw_set_hw_setting(struct iwl4965_priv *priv);
+extern int iwl4965_hw_nic_init(struct iwl4965_priv *priv);
+extern int iwl4965_hw_nic_stop_master(struct iwl4965_priv *priv);
+extern void iwl4965_hw_txq_ctx_free(struct iwl4965_priv *priv);
+extern void iwl4965_hw_txq_ctx_stop(struct iwl4965_priv *priv);
+extern int iwl4965_hw_nic_reset(struct iwl4965_priv *priv);
+extern int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl4965_priv *priv, void *tfd,
+ dma_addr_t addr, u16 len);
+extern int iwl4965_hw_txq_free_tfd(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq);
+extern int iwl4965_hw_get_temperature(struct iwl4965_priv *priv);
+extern int iwl4965_hw_tx_queue_init(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq);
+extern unsigned int iwl4965_hw_get_beacon_cmd(struct iwl4965_priv *priv,
+ struct iwl4965_frame *frame, u8 rate);
+extern int iwl4965_hw_get_rx_read(struct iwl4965_priv *priv);
+extern void iwl4965_hw_build_tx_cmd_rate(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd,
+ struct ieee80211_tx_control *ctrl,
+ struct ieee80211_hdr *hdr,
+ int sta_id, int tx_id);
+extern int iwl4965_hw_reg_send_txpower(struct iwl4965_priv *priv);
+extern int iwl4965_hw_reg_set_txpower(struct iwl4965_priv *priv, s8 power);
+extern void iwl4965_hw_rx_statistics(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb);
+extern void iwl4965_disable_events(struct iwl4965_priv *priv);
+extern int iwl4965_get_temperature(const struct iwl4965_priv *priv);
+
+/**
+ * iwl4965_hw_find_station - Find station id for a given BSSID
+ * @bssid: MAC address of station ID to find
+ *
+ * NOTE: This should not be hardware specific but the code has
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+extern u8 iwl4965_hw_find_station(struct iwl4965_priv *priv, const u8 *bssid);
+
+extern int iwl4965_hw_channel_switch(struct iwl4965_priv *priv, u16 channel);
+extern int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index);
+
+struct iwl4965_priv;
/*
* Forward declare iwl-4965.c functions for iwl-base.c
*/
-extern int iwl_eeprom_aqcuire_semaphore(struct iwl_priv *priv);
-extern void iwl_eeprom_release_semaphore(struct iwl_priv *priv);
+extern int iwl4965_eeprom_acquire_semaphore(struct iwl4965_priv *priv);
+extern void iwl4965_eeprom_release_semaphore(struct iwl4965_priv *priv);
-extern int iwl4965_tx_queue_update_wr_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq,
+extern int iwl4965_tx_queue_update_wr_ptr(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq,
u16 byte_cnt);
-extern void iwl4965_add_station(struct iwl_priv *priv, const u8 *addr,
+extern void iwl4965_add_station(struct iwl4965_priv *priv, const u8 *addr,
int is_ap);
-extern void iwl4965_set_rxon_ht(struct iwl_priv *priv,
- struct sta_ht_info *ht_info);
-
-extern void iwl4965_set_rxon_chain(struct iwl_priv *priv);
-extern int iwl4965_tx_cmd(struct iwl_priv *priv, struct iwl_cmd *out_cmd,
- u8 sta_id, dma_addr_t txcmd_phys,
- struct ieee80211_hdr *hdr, u8 hdr_len,
- struct ieee80211_tx_control *ctrl, void *sta_in);
-extern int iwl4965_init_hw_rates(struct iwl_priv *priv,
- struct ieee80211_rate *rates);
-extern int iwl4965_alive_notify(struct iwl_priv *priv);
-extern void iwl4965_update_rate_scaling(struct iwl_priv *priv, u8 mode);
-extern void iwl4965_set_ht_add_station(struct iwl_priv *priv, u8 index);
-
-extern void iwl4965_chain_noise_reset(struct iwl_priv *priv);
-extern void iwl4965_init_sensitivity(struct iwl_priv *priv, u8 flags,
+extern void iwl4965_set_rxon_chain(struct iwl4965_priv *priv);
+extern int iwl4965_alive_notify(struct iwl4965_priv *priv);
+extern void iwl4965_update_rate_scaling(struct iwl4965_priv *priv, u8 mode);
+extern void iwl4965_chain_noise_reset(struct iwl4965_priv *priv);
+extern void iwl4965_init_sensitivity(struct iwl4965_priv *priv, u8 flags,
u8 force);
-extern int iwl4965_set_fat_chan_info(struct iwl_priv *priv, int phymode,
+extern int iwl4965_set_fat_chan_info(struct iwl4965_priv *priv, int phymode,
u16 channel,
- const struct iwl_eeprom_channel *eeprom_ch,
+ const struct iwl4965_eeprom_channel *eeprom_ch,
u8 fat_extension_channel);
-extern void iwl4965_rf_kill_ct_config(struct iwl_priv *priv);
+extern void iwl4965_rf_kill_ct_config(struct iwl4965_priv *priv);
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
-extern int iwl_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
+#ifdef CONFIG_IWL4965_HT
+extern void iwl4965_init_ht_hw_capab(struct ieee80211_ht_info *ht_info,
+ int mode);
+extern void iwl4965_set_rxon_ht(struct iwl4965_priv *priv,
+ struct iwl_ht_info *ht_info);
+extern void iwl4965_set_ht_add_station(struct iwl4965_priv *priv, u8 index,
+ struct ieee80211_ht_info *sta_ht_inf);
+extern int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+ enum ieee80211_ampdu_mlme_action action,
+ const u8 *addr, u16 tid, u16 ssn);
+#ifdef CONFIG_IWL4965_HT_AGG
+extern int iwl4965_mac_ht_tx_agg_start(struct ieee80211_hw *hw, u8 *da,
u16 tid, u16 *start_seq_num);
-extern int iwl_mac_ht_rx_agg_start(struct ieee80211_hw *hw, u8 *da,
- u16 tid, u16 start_seq_num);
-extern int iwl_mac_ht_rx_agg_stop(struct ieee80211_hw *hw, u8 *da,
+extern int iwl4965_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
u16 tid, int generator);
-extern int iwl_mac_ht_tx_agg_stop(struct ieee80211_hw *hw, u8 *da,
- u16 tid, int generator);
-extern void iwl4965_turn_off_agg(struct iwl_priv *priv, u8 tid);
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /*CONFIG_IWLWIFI_HT */
+extern void iwl4965_turn_off_agg(struct iwl4965_priv *priv, u8 tid);
+extern void iwl4965_tl_get_stats(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *hdr);
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /*CONFIG_IWL4965_HT */
/* Structures, enum, and defines specific to the 4965 */
#define IWL4965_KW_SIZE 0x1000 /*4k */
-struct iwl_kw {
+struct iwl4965_kw {
dma_addr_t dma_addr;
void *v_addr;
size_t size;
@@ -120,21 +833,9 @@ struct iwl_kw {
#define NRG_NUM_PREV_STAT_L 20
#define NUM_RX_CHAINS (3)
-#define TX_POWER_IWL_ILLEGAL_VDET -100000
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
-#define TX_POWER_IWL_CLOSED_LOOP_MIN_POWER 18
-#define TX_POWER_IWL_CLOSED_LOOP_MAX_POWER 34
-#define TX_POWER_IWL_VDET_SLOPE_BELOW_NOMINAL 17
-#define TX_POWER_IWL_VDET_SLOPE_ABOVE_NOMINAL 20
-#define TX_POWER_IWL_NOMINAL_POWER 26
-#define TX_POWER_IWL_CLOSED_LOOP_ITERATION_LIMIT 1
-#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V 7
-#define TX_POWER_IWL_DEGREES_PER_VDET_CODE 11
-#define IWL_TX_POWER_MAX_NUM_PA_MEASUREMENTS 1
-#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
-#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
-
-struct iwl_traffic_load {
+
+struct iwl4965_traffic_load {
unsigned long time_stamp;
u32 packet_count[TID_QUEUE_MAX_SIZE];
u8 queue_count;
@@ -142,8 +843,13 @@ struct iwl_traffic_load {
u32 total;
};
-#ifdef CONFIG_IWLWIFI_HT_AGG
-struct iwl_agg_control {
+#ifdef CONFIG_IWL4965_HT_AGG
+/**
+ * struct iwl4965_agg_control
+ * @requested_ba: bit map of tids requesting aggregation/block-ack
+ * @granted_ba: bit map of tids granted aggregation/block-ack
+ */
+struct iwl4965_agg_control {
unsigned long next_retry;
u32 wait_for_agg_status;
u32 tid_retry;
@@ -152,13 +858,13 @@ struct iwl_agg_control {
u8 auto_agg;
u32 tid_traffic_load_threshold;
u32 ba_timeout;
- struct iwl_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
+ struct iwl4965_traffic_load traffic_load[TID_MAX_LOAD_COUNT];
};
-#endif /*CONFIG_IWLWIFI_HT_AGG */
+#endif /*CONFIG_IWL4965_HT_AGG */
-struct iwl_lq_mngr {
-#ifdef CONFIG_IWLWIFI_HT_AGG
- struct iwl_agg_control agg_ctrl;
+struct iwl4965_lq_mngr {
+#ifdef CONFIG_IWL4965_HT_AGG
+ struct iwl4965_agg_control agg_ctrl;
#endif
spinlock_t lock;
s32 max_window_size;
@@ -179,22 +885,6 @@ struct iwl_lq_mngr {
#define CAL_NUM_OF_BEACONS 20
#define MAXIMUM_ALLOWED_PATHLOSS 15
-/* Param table within SENSITIVITY_CMD */
-#define HD_MIN_ENERGY_CCK_DET_INDEX (0)
-#define HD_MIN_ENERGY_OFDM_DET_INDEX (1)
-#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX (2)
-#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX (3)
-#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX (4)
-#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX (5)
-#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX (6)
-#define HD_BARKER_CORR_TH_ADD_MIN_INDEX (7)
-#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX (8)
-#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9)
-#define HD_OFDM_ENERGY_TH_IN_INDEX (10)
-
-#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0)
-#define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1)
-
#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
#define MAX_FA_OFDM 50
@@ -222,8 +912,6 @@ struct iwl_lq_mngr {
#define AUTO_CORR_STEP_CCK 3
#define AUTO_CORR_MAX_TH_CCK 160
-#define NRG_ALG 0
-#define AUTO_CORR_ALG 1
#define NRG_DIFF 2
#define NRG_STEP_CCK 2
#define NRG_MARGIN 8
@@ -239,24 +927,24 @@ struct iwl_lq_mngr {
#define IN_BAND_FILTER 0xFF
#define MIN_AVERAGE_NOISE_MAX_VALUE 0xFFFFFFFF
-enum iwl_false_alarm_state {
+enum iwl4965_false_alarm_state {
IWL_FA_TOO_MANY = 0,
IWL_FA_TOO_FEW = 1,
IWL_FA_GOOD_RANGE = 2,
};
-enum iwl_chain_noise_state {
+enum iwl4965_chain_noise_state {
IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */
IWL_CHAIN_NOISE_ACCUMULATE = 1,
IWL_CHAIN_NOISE_CALIBRATED = 2,
};
-enum iwl_sensitivity_state {
+enum iwl4965_sensitivity_state {
IWL_SENS_CALIB_ALLOWED = 0,
IWL_SENS_CALIB_NEED_REINIT = 1,
};
-enum iwl_calib_enabled_state {
+enum iwl4965_calib_enabled_state {
IWL_CALIB_DISABLED = 0, /* must be 0 */
IWL_CALIB_ENABLED = 1,
};
@@ -271,7 +959,7 @@ struct statistics_general_data {
};
/* Sensitivity calib data */
-struct iwl_sensitivity_data {
+struct iwl4965_sensitivity_data {
u32 auto_corr_ofdm;
u32 auto_corr_ofdm_mrc;
u32 auto_corr_ofdm_x1;
@@ -300,7 +988,7 @@ struct iwl_sensitivity_data {
};
/* Chain noise (differential Rx gain) calib data */
-struct iwl_chain_noise_data {
+struct iwl4965_chain_noise_data {
u8 state;
u16 beacon_count;
u32 chain_noise_a;
@@ -314,28 +1002,323 @@ struct iwl_chain_noise_data {
u8 radio_write;
};
-/* IWL4965 */
-#define RATE_MCS_CODE_MSK 0x7
-#define RATE_MCS_MIMO_POS 3
-#define RATE_MCS_MIMO_MSK 0x8
-#define RATE_MCS_HT_DUP_POS 5
-#define RATE_MCS_HT_DUP_MSK 0x20
-#define RATE_MCS_FLAGS_POS 8
-#define RATE_MCS_HT_POS 8
-#define RATE_MCS_HT_MSK 0x100
-#define RATE_MCS_CCK_POS 9
-#define RATE_MCS_CCK_MSK 0x200
-#define RATE_MCS_GF_POS 10
-#define RATE_MCS_GF_MSK 0x400
-
-#define RATE_MCS_FAT_POS 11
-#define RATE_MCS_FAT_MSK 0x800
-#define RATE_MCS_DUP_POS 12
-#define RATE_MCS_DUP_MSK 0x1000
-#define RATE_MCS_SGI_POS 13
-#define RATE_MCS_SGI_MSK 0x2000
-
-#define EEPROM_SEM_TIMEOUT 10
-#define EEPROM_SEM_RETRY_LIMIT 1000
-
-#endif /* __iwl_4965_h__ */
+#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
+#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
+
+
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+
+enum {
+ MEASUREMENT_READY = (1 << 0),
+ MEASUREMENT_ACTIVE = (1 << 1),
+};
+
+#endif
+
+struct iwl4965_priv {
+
+ /* ieee device used by generic ieee processing code */
+ struct ieee80211_hw *hw;
+ struct ieee80211_channel *ieee_channels;
+ struct ieee80211_rate *ieee_rates;
+
+ /* temporary frame storage list */
+ struct list_head free_frames;
+ int frames_count;
+
+ u8 phymode;
+ int alloc_rxb_skb;
+ bool add_radiotap;
+
+ void (*rx_handlers[REPLY_MAX])(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb);
+
+ const struct ieee80211_hw_mode *modes;
+
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+ /* spectrum measurement report caching */
+ struct iwl4965_spectrum_notification measure_report;
+ u8 measurement_status;
+#endif
+ /* ucode beacon time */
+ u32 ucode_beacon_time;
+
+ /* we allocate array of iwl4965_channel_info for NIC's valid channels.
+ * Access via channel # using indirect index array */
+ struct iwl4965_channel_info *channel_info; /* channel info array */
+ u8 channel_count; /* # of channels */
+
+ /* each calibration channel group in the EEPROM has a derived
+ * clip setting for each rate. */
+ const struct iwl4965_clip_group clip_groups[5];
+
+ /* thermal calibration */
+ s32 temperature; /* degrees Kelvin */
+ s32 last_temperature;
+
+ /* Scan related variables */
+ unsigned long last_scan_jiffies;
+ unsigned long next_scan_jiffies;
+ unsigned long scan_start;
+ unsigned long scan_pass_start;
+ unsigned long scan_start_tsf;
+ int scan_bands;
+ int one_direct_scan;
+ u8 direct_ssid_len;
+ u8 direct_ssid[IW_ESSID_MAX_SIZE];
+ struct iwl4965_scan_cmd *scan;
+ u8 only_active_channel;
+
+ /* spinlock */
+ spinlock_t lock; /* protect general shared data */
+ spinlock_t hcmd_lock; /* protect hcmd */
+ struct mutex mutex;
+
+ /* basic pci-network driver stuff */
+ struct pci_dev *pci_dev;
+
+ /* pci hardware address support */
+ void __iomem *hw_base;
+
+ /* uCode images, save to reload in case of failure */
+ struct fw_desc ucode_code; /* runtime inst */
+ struct fw_desc ucode_data; /* runtime data original */
+ struct fw_desc ucode_data_backup; /* runtime data save/restore */
+ struct fw_desc ucode_init; /* initialization inst */
+ struct fw_desc ucode_init_data; /* initialization data */
+ struct fw_desc ucode_boot; /* bootstrap inst */
+
+
+ struct iwl4965_rxon_time_cmd rxon_timing;
+
+ /* We declare this const so it can only be
+ * changed via explicit cast within the
+ * routines that actually update the physical
+ * hardware */
+ const struct iwl4965_rxon_cmd active_rxon;
+ struct iwl4965_rxon_cmd staging_rxon;
+
+ int error_recovering;
+ struct iwl4965_rxon_cmd recovery_rxon;
+
+ /* 1st responses from initialize and runtime uCode images.
+ * 4965's initialize alive response contains some calibration data. */
+ struct iwl4965_init_alive_resp card_alive_init;
+ struct iwl4965_alive_resp card_alive;
+
+#ifdef LED
+ /* LED related variables */
+ struct iwl4965_activity_blink activity;
+ unsigned long led_packets;
+ int led_state;
+#endif
+
+ u16 active_rate;
+ u16 active_rate_basic;
+
+ u8 call_post_assoc_from_beacon;
+ u8 assoc_station_added;
+ u8 use_ant_b_for_management_frame; /* Tx antenna selection */
+ u8 valid_antenna; /* Bit mask of antennas actually connected */
+#ifdef CONFIG_IWL4965_SENSITIVITY
+ struct iwl4965_sensitivity_data sensitivity_data;
+ struct iwl4965_chain_noise_data chain_noise_data;
+ u8 start_calib;
+ __le16 sensitivity_tbl[HD_TABLE_SIZE];
+#endif /*CONFIG_IWL4965_SENSITIVITY*/
+
+#ifdef CONFIG_IWL4965_HT
+ struct iwl_ht_info current_ht_config;
+#endif
+ u8 last_phy_res[100];
+
+ /* Rate scaling data */
+ struct iwl4965_lq_mngr lq_mngr;
+
+ /* Rate scaling data */
+ s8 data_retry_limit;
+ u8 retry_rate;
+
+ wait_queue_head_t wait_command_queue;
+
+ int activity_timer_active;
+
+ /* Rx and Tx DMA processing queues */
+ struct iwl4965_rx_queue rxq;
+ struct iwl4965_tx_queue txq[IWL_MAX_NUM_QUEUES];
+ unsigned long txq_ctx_active_msk;
+ struct iwl4965_kw kw; /* keep warm address */
+ u32 scd_base_addr; /* scheduler sram base address */
+
+ unsigned long status;
+ u32 config;
+
+ int last_rx_rssi; /* From Rx packet statisitics */
+ int last_rx_noise; /* From beacon statistics */
+
+ struct iwl4965_power_mgr power_data;
+
+ struct iwl4965_notif_statistics statistics;
+ unsigned long last_statistics_time;
+
+ /* context information */
+ u8 essid[IW_ESSID_MAX_SIZE];
+ u8 essid_len;
+ u16 rates_mask;
+
+ u32 power_mode;
+ u32 antenna;
+ u8 bssid[ETH_ALEN];
+ u16 rts_threshold;
+ u8 mac_addr[ETH_ALEN];
+
+ /*station table variables */
+ spinlock_t sta_lock;
+ int num_stations;
+ struct iwl4965_station_entry stations[IWL_STATION_COUNT];
+
+ /* Indication if ieee80211_ops->open has been called */
+ int is_open;
+
+ u8 mac80211_registered;
+ int is_abg;
+
+ u32 notif_missed_beacons;
+
+ /* Rx'd packet timing information */
+ u32 last_beacon_time;
+ u64 last_tsf;
+
+ /* Duplicate packet detection */
+ u16 last_seq_num;
+ u16 last_frag_num;
+ unsigned long last_packet_time;
+
+ /* Hash table for finding stations in IBSS network */
+ struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
+
+ /* eeprom */
+ struct iwl4965_eeprom eeprom;
+
+ int iw_mode;
+
+ struct sk_buff *ibss_beacon;
+
+ /* Last Rx'd beacon timestamp */
+ u32 timestamp0;
+ u32 timestamp1;
+ u16 beacon_int;
+ struct iwl4965_driver_hw_info hw_setting;
+ struct ieee80211_vif *vif;
+
+ /* Current association information needed to configure the
+ * hardware */
+ u16 assoc_id;
+ u16 assoc_capability;
+ u8 ps_mode;
+
+#ifdef CONFIG_IWL4965_QOS
+ struct iwl4965_qos_info qos_data;
+#endif /*CONFIG_IWL4965_QOS */
+
+ struct workqueue_struct *workqueue;
+
+ struct work_struct up;
+ struct work_struct restart;
+ struct work_struct calibrated_work;
+ struct work_struct scan_completed;
+ struct work_struct rx_replenish;
+ struct work_struct rf_kill;
+ struct work_struct abort_scan;
+ struct work_struct update_link_led;
+ struct work_struct auth_work;
+ struct work_struct report_work;
+ struct work_struct request_scan;
+ struct work_struct beacon_update;
+
+ struct tasklet_struct irq_tasklet;
+
+ struct delayed_work init_alive_start;
+ struct delayed_work alive_start;
+ struct delayed_work activity_timer;
+ struct delayed_work thermal_periodic;
+ struct delayed_work gather_stats;
+ struct delayed_work scan_check;
+ struct delayed_work post_associate;
+
+#define IWL_DEFAULT_TX_POWER 0x0F
+ s8 user_txpower_limit;
+ s8 max_channel_txpower_limit;
+
+#ifdef CONFIG_PM
+ u32 pm_state[16];
+#endif
+
+#ifdef CONFIG_IWL4965_DEBUG
+ /* debugging info */
+ u32 framecnt_to_us;
+ atomic_t restrict_refcnt;
+#endif
+
+ struct work_struct txpower_work;
+#ifdef CONFIG_IWL4965_SENSITIVITY
+ struct work_struct sensitivity_work;
+#endif
+ struct work_struct statistics_work;
+ struct timer_list statistics_periodic;
+
+#ifdef CONFIG_IWL4965_HT_AGG
+ struct work_struct agg_work;
+#endif
+}; /*iwl4965_priv */
+
+static inline int iwl4965_is_associated(struct iwl4965_priv *priv)
+{
+ return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int is_channel_valid(const struct iwl4965_channel_info *ch_info)
+{
+ if (ch_info == NULL)
+ return 0;
+ return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+}
+
+static inline int is_channel_narrow(const struct iwl4965_channel_info *ch_info)
+{
+ return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
+}
+
+static inline int is_channel_radar(const struct iwl4965_channel_info *ch_info)
+{
+ return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+}
+
+static inline u8 is_channel_a_band(const struct iwl4965_channel_info *ch_info)
+{
+ return ch_info->phymode == MODE_IEEE80211A;
+}
+
+static inline u8 is_channel_bg_band(const struct iwl4965_channel_info *ch_info)
+{
+ return ((ch_info->phymode == MODE_IEEE80211B) ||
+ (ch_info->phymode == MODE_IEEE80211G));
+}
+
+static inline int is_channel_passive(const struct iwl4965_channel_info *ch)
+{
+ return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+}
+
+static inline int is_channel_ibss(const struct iwl4965_channel_info *ch)
+{
+ return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
+}
+
+extern const struct iwl4965_channel_info *iwl4965_get_channel_info(
+ const struct iwl4965_priv *priv, int phymode, u16 channel);
+
+/* Requires full declaration of iwl4965_priv before including */
+#include "iwl-4965-io.h"
+
+#endif /* __iwl4965_4965_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-channel.h b/drivers/net/wireless/iwlwifi/iwl-channel.h
deleted file mode 100644
index 023c3f240cea..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-channel.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-#ifndef __iwl_channel_h__
-#define __iwl_channel_h__
-
-#define IWL_NUM_SCAN_RATES (2)
-
-struct iwl_channel_tgd_info {
- u8 type;
- s8 max_power;
-};
-
-struct iwl_channel_tgh_info {
- s64 last_radar_time;
-};
-
-/* current Tx power values to use, one for each rate for each channel.
- * requested power is limited by:
- * -- regulatory EEPROM limits for this channel
- * -- hardware capabilities (clip-powers)
- * -- spectrum management
- * -- user preference (e.g. iwconfig)
- * when requested power is set, base power index must also be set. */
-struct iwl_channel_power_info {
- struct iwl_tx_power tpc; /* actual radio and DSP gain settings */
- s8 power_table_index; /* actual (compenst'd) index into gain table */
- s8 base_power_index; /* gain index for power at factory temp. */
- s8 requested_power; /* power (dBm) requested for this chnl/rate */
-};
-
-/* current scan Tx power values to use, one for each scan rate for each
- * channel. */
-struct iwl_scan_power_info {
- struct iwl_tx_power tpc; /* actual radio and DSP gain settings */
- s8 power_table_index; /* actual (compenst'd) index into gain table */
- s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */
-};
-
-/* Channel unlock period is 15 seconds. If no beacon or probe response
- * has been received within 15 seconds on a locked channel then the channel
- * remains locked. */
-#define TX_UNLOCK_PERIOD 15
-
-/* CSA lock period is 15 seconds. If a CSA has been received on a channel in
- * the last 15 seconds, the channel is locked */
-#define CSA_LOCK_PERIOD 15
-/*
- * One for each channel, holds all channel setup data
- * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
- * with one another!
- */
-#define IWL4965_MAX_RATE (33)
-
-struct iwl_channel_info {
- struct iwl_channel_tgd_info tgd;
- struct iwl_channel_tgh_info tgh;
- struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */
- struct iwl_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for
- * FAT channel */
-
- u8 channel; /* channel number */
- u8 flags; /* flags copied from EEPROM */
- s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
- s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
- s8 min_power; /* always 0 */
- s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */
-
- u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */
- u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
- u8 phymode; /* MODE_IEEE80211{A,B,G} */
-
- /* Radio/DSP gain settings for each "normal" data Tx rate.
- * These include, in addition to RF and DSP gain, a few fields for
- * remembering/modifying gain settings (indexes). */
- struct iwl_channel_power_info power_info[IWL4965_MAX_RATE];
-
-#if IWL == 4965
- /* FAT channel info */
- s8 fat_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
- s8 fat_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
- s8 fat_min_power; /* always 0 */
- s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */
- u8 fat_flags; /* flags copied from EEPROM */
- u8 fat_extension_channel;
-#endif
-
- /* Radio/DSP gain settings for each scan rate, for directed scans. */
- struct iwl_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
-};
-
-struct iwl_clip_group {
- /* maximum power level to prevent clipping for each rate, derived by
- * us from this band's saturation power in EEPROM */
- const s8 clip_powers[IWL_MAX_RATES];
-};
-
-static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
-{
- if (ch_info == NULL)
- return 0;
- return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
-}
-
-static inline int is_channel_narrow(const struct iwl_channel_info *ch_info)
-{
- return (ch_info->flags & EEPROM_CHANNEL_NARROW) ? 1 : 0;
-}
-
-static inline int is_channel_radar(const struct iwl_channel_info *ch_info)
-{
- return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
-}
-
-static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info)
-{
- return ch_info->phymode == MODE_IEEE80211A;
-}
-
-static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info)
-{
- return ((ch_info->phymode == MODE_IEEE80211B) ||
- (ch_info->phymode == MODE_IEEE80211G));
-}
-
-static inline int is_channel_passive(const struct iwl_channel_info *ch)
-{
- return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
-}
-
-static inline int is_channel_ibss(const struct iwl_channel_info *ch)
-{
- return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
-}
-
-extern const struct iwl_channel_info *iwl_get_channel_info(
- const struct iwl_priv *priv, int phymode, u16 channel);
-
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
deleted file mode 100644
index e473c97e3f4f..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ /dev/null
@@ -1,336 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
- * published by the Free Software Foundation.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *****************************************************************************/
-
-#ifndef __iwl_eeprom_h__
-#define __iwl_eeprom_h__
-
-/*
- * This file defines EEPROM related constants, enums, and inline functions.
- *
- */
-
-#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
-#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
-/* EEPROM field values */
-#define ANTENNA_SWITCH_NORMAL 0
-#define ANTENNA_SWITCH_INVERSE 1
-
-enum {
- EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */
- EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */
- /* Bit 2 Reserved */
- EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */
- EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */
- EEPROM_CHANNEL_WIDE = (1 << 5),
- EEPROM_CHANNEL_NARROW = (1 << 6),
- EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */
-};
-
-/* EEPROM field lengths */
-#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11
-
-/* EEPROM field lengths */
-#define EEPROM_BOARD_PBA_NUMBER_LENGTH 11
-#define EEPROM_REGULATORY_SKU_ID_LENGTH 4
-#define EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH 14
-#define EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH 13
-#define EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH 12
-#define EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH 11
-#define EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH 6
-
-#if IWL == 3945
-#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
- EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH)
-#elif IWL == 4965
-#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH 7
-#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH 11
-#define EEPROM_REGULATORY_CHANNELS_LENGTH ( \
- EEPROM_REGULATORY_BAND1_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND2_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND3_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND4_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND5_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND_24_FAT_CHANNELS_LENGTH + \
- EEPROM_REGULATORY_BAND_52_FAT_CHANNELS_LENGTH)
-#endif
-
-#define EEPROM_REGULATORY_NUMBER_OF_BANDS 5
-
-/* SKU Capabilities */
-#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0)
-#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
-#define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7)
-
-/* *regulatory* channel data from eeprom, one for each channel */
-struct iwl_eeprom_channel {
- u8 flags; /* flags copied from EEPROM */
- s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
-} __attribute__ ((packed));
-
-/*
- * Mapping of a Tx power level, at factory calibration temperature,
- * to a radio/DSP gain table index.
- * One for each of 5 "sample" power levels in each band.
- * v_det is measured at the factory, using the 3945's built-in power amplifier
- * (PA) output voltage detector. This same detector is used during Tx of
- * long packets in normal operation to provide feedback as to proper output
- * level.
- * Data copied from EEPROM.
- */
-struct iwl_eeprom_txpower_sample {
- u8 gain_index; /* index into power (gain) setup table ... */
- s8 power; /* ... for this pwr level for this chnl group */
- u16 v_det; /* PA output voltage */
-} __attribute__ ((packed));
-
-/*
- * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
- * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
- * Tx power setup code interpolates between the 5 "sample" power levels
- * to determine the nominal setup for a requested power level.
- * Data copied from EEPROM.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl_eeprom_txpower_group {
- struct iwl_eeprom_txpower_sample samples[5]; /* 5 power levels */
- s32 a, b, c, d, e; /* coefficients for voltage->power
- * formula (signed) */
- s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on
- * frequency (signed) */
- s8 saturation_power; /* highest power possible by h/w in this
- * band */
- u8 group_channel; /* "representative" channel # in this band */
- s16 temperature; /* h/w temperature at factory calib this band
- * (signed) */
-} __attribute__ ((packed));
-
-/*
- * Temperature-based Tx-power compensation data, not band-specific.
- * These coefficients are use to modify a/b/c/d/e coeffs based on
- * difference between current temperature and factory calib temperature.
- * Data copied from EEPROM.
- */
-struct iwl_eeprom_temperature_corr {
- u32 Ta;
- u32 Tb;
- u32 Tc;
- u32 Td;
- u32 Te;
-} __attribute__ ((packed));
-
-#if IWL == 4965
-#define EEPROM_TX_POWER_TX_CHAINS (2)
-#define EEPROM_TX_POWER_BANDS (8)
-#define EEPROM_TX_POWER_MEASUREMENTS (3)
-#define EEPROM_TX_POWER_VERSION (2)
-#define EEPROM_TX_POWER_VERSION_NEW (5)
-
-struct iwl_eeprom_calib_measure {
- u8 temperature;
- u8 gain_idx;
- u8 actual_pow;
- s8 pa_det;
-} __attribute__ ((packed));
-
-struct iwl_eeprom_calib_ch_info {
- u8 ch_num;
- struct iwl_eeprom_calib_measure measurements[EEPROM_TX_POWER_TX_CHAINS]
- [EEPROM_TX_POWER_MEASUREMENTS];
-} __attribute__ ((packed));
-
-struct iwl_eeprom_calib_subband_info {
- u8 ch_from;
- u8 ch_to;
- struct iwl_eeprom_calib_ch_info ch1;
- struct iwl_eeprom_calib_ch_info ch2;
-} __attribute__ ((packed));
-
-struct iwl_eeprom_calib_info {
- u8 saturation_power24;
- u8 saturation_power52;
- s16 voltage; /* signed */
- struct iwl_eeprom_calib_subband_info band_info[EEPROM_TX_POWER_BANDS];
-} __attribute__ ((packed));
-
-#endif
-
-struct iwl_eeprom {
- u8 reserved0[16];
-#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */
- u16 device_id; /* abs.ofs: 16 */
- u8 reserved1[2];
-#define EEPROM_PMC (2*0x0A) /* 2 bytes */
- u16 pmc; /* abs.ofs: 20 */
- u8 reserved2[20];
-#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */
- u8 mac_address[6]; /* abs.ofs: 42 */
- u8 reserved3[58];
-#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */
- u16 board_revision; /* abs.ofs: 106 */
- u8 reserved4[11];
-#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */
- u8 board_pba_number[9]; /* abs.ofs: 119 */
- u8 reserved5[8];
-#define EEPROM_VERSION (2*0x44) /* 2 bytes */
- u16 version; /* abs.ofs: 136 */
-#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */
- u8 sku_cap; /* abs.ofs: 138 */
-#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */
- u8 leds_mode; /* abs.ofs: 139 */
-#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */
- u16 oem_mode;
-#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */
- u16 wowlan_mode; /* abs.ofs: 142 */
-#define EEPROM_LEDS_TIME_INTERVAL (2*0x48) /* 2 bytes */
- u16 leds_time_interval; /* abs.ofs: 144 */
-#define EEPROM_LEDS_OFF_TIME (2*0x49) /* 1 bytes */
- u8 leds_off_time; /* abs.ofs: 146 */
-#define EEPROM_LEDS_ON_TIME (2*0x49+1) /* 1 bytes */
- u8 leds_on_time; /* abs.ofs: 147 */
-#define EEPROM_ALMGOR_M_VERSION (2*0x4A) /* 1 bytes */
- u8 almgor_m_version; /* abs.ofs: 148 */
-#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */
- u8 antenna_switch_type; /* abs.ofs: 149 */
-#if IWL == 3945
- u8 reserved6[42];
-#else
- u8 reserved6[8];
-#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */
- u16 board_revision_4965; /* abs.ofs: 158 */
- u8 reserved7[13];
-#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */
- u8 board_pba_number_4965[9]; /* abs.ofs: 173 */
- u8 reserved8[10];
-#endif
-#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */
- u8 sku_id[4]; /* abs.ofs: 192 */
-#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */
- u16 band_1_count; /* abs.ofs: 196 */
-#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */
- struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 196 */
-#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */
- u16 band_2_count; /* abs.ofs: 226 */
-#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */
- struct iwl_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */
-#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */
- u16 band_3_count; /* abs.ofs: 254 */
-#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */
- struct iwl_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */
-#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */
- u16 band_4_count; /* abs.ofs: 280 */
-#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */
- struct iwl_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */
-#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */
- u16 band_5_count; /* abs.ofs: 304 */
-#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
- struct iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */
-
-/* From here on out the EEPROM diverges between the 4965 and the 3945 */
-#if IWL == 3945
-
- u8 reserved9[194];
-
-#define EEPROM_TXPOWER_CALIB_GROUP0 0x200
-#define EEPROM_TXPOWER_CALIB_GROUP1 0x240
-#define EEPROM_TXPOWER_CALIB_GROUP2 0x280
-#define EEPROM_TXPOWER_CALIB_GROUP3 0x2c0
-#define EEPROM_TXPOWER_CALIB_GROUP4 0x300
-#define IWL_NUM_TX_CALIB_GROUPS 5
- struct iwl_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
-/* abs.ofs: 512 */
-#define EEPROM_CALIB_TEMPERATURE_CORRECT 0x340
- struct iwl_eeprom_temperature_corr corrections; /* abs.ofs: 832 */
- u8 reserved16[172]; /* fill out to full 1024 byte block */
-
-/* 4965AGN adds fat channel support */
-#elif IWL == 4965
-
- u8 reserved10[2];
-#define EEPROM_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */
- struct iwl_eeprom_channel band_24_channels[7]; /* abs.ofs: 320 */
- u8 reserved11[2];
-#define EEPROM_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */
- struct iwl_eeprom_channel band_52_channels[11]; /* abs.ofs: 336 */
- u8 reserved12[6];
-#define EEPROM_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */
- u16 calib_version; /* abs.ofs: 364 */
- u8 reserved13[2];
-#define EEPROM_SATURATION_POWER_OFFSET (2*0xB8) /* 2 bytes */
- u16 satruation_power; /* abs.ofs: 368 */
- u8 reserved14[94];
-#define EEPROM_IWL_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */
- struct iwl_eeprom_calib_info calib_info; /* abs.ofs: 464 */
-
- u8 reserved16[140]; /* fill out to full 1024 byte block */
-
-#endif
-
-} __attribute__ ((packed));
-
-#define IWL_EEPROM_IMAGE_SIZE 1024
-
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index e2a8d95ad9cd..cd2eb1848310 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -252,4 +252,27 @@ static inline unsigned long elapsed_jiffies(unsigned long start,
return end + (MAX_JIFFY_OFFSET - start);
}
+static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
+{
+ return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
+}
+
+/* TODO: Move fw_desc functions to iwl-pci.ko */
+static inline void iwl_free_fw_desc(struct pci_dev *pci_dev,
+ struct fw_desc *desc)
+{
+ if (desc->v_addr)
+ pci_free_consistent(pci_dev, desc->len,
+ desc->v_addr, desc->p_addr);
+ desc->v_addr = NULL;
+ desc->len = 0;
+}
+
+static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev,
+ struct fw_desc *desc)
+{
+ desc->v_addr = pci_alloc_consistent(pci_dev, desc->len, &desc->p_addr);
+ return (desc->v_addr != NULL) ? 0 : -ENOMEM;
+}
+
#endif /* __iwl_helpers_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-hw.h b/drivers/net/wireless/iwlwifi/iwl-hw.h
deleted file mode 100644
index 1aa6fcd39a5e..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-hw.h
+++ /dev/null
@@ -1,537 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license. When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
- * published by the Free Software Foundation.
- *
- * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
- * USA
- *
- * The full GNU General Public License is included in this distribution
- * in the file called LICENSE.GPL.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name Intel Corporation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-#ifndef __iwlwifi_hw_h__
-#define __iwlwifi_hw_h__
-
-/*
- * This file defines hardware constants common to 3945 and 4965.
- *
- * Device-specific constants are defined in iwl-3945-hw.h and iwl-4965-hw.h,
- * although this file contains a few definitions for which the .c
- * implementation is the same for 3945 and 4965, except for the value of
- * a constant.
- *
- * uCode API constants are defined in iwl-commands.h.
- *
- * NOTE: DO NOT PUT OS IMPLEMENTATION-SPECIFIC DECLARATIONS HERE
- *
- * The iwl-*hw.h (and files they include) files should remain OS/driver
- * implementation independent, declaring only the hardware interface.
- */
-
-/* uCode queue management definitions */
-#define IWL_CMD_QUEUE_NUM 4
-#define IWL_CMD_FIFO_NUM 4
-#define IWL_BACK_QUEUE_FIRST_ID 7
-
-/* Tx rates */
-#define IWL_CCK_RATES 4
-#define IWL_OFDM_RATES 8
-
-#if IWL == 3945
-#define IWL_HT_RATES 0
-#elif IWL == 4965
-#define IWL_HT_RATES 16
-#endif
-
-#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
-
-/* Time constants */
-#define SHORT_SLOT_TIME 9
-#define LONG_SLOT_TIME 20
-
-/* RSSI to dBm */
-#if IWL == 3945
-#define IWL_RSSI_OFFSET 95
-#elif IWL == 4965
-#define IWL_RSSI_OFFSET 44
-#endif
-
-#include "iwl-eeprom.h"
-#include "iwl-commands.h"
-
-#define PCI_LINK_CTRL 0x0F0
-#define PCI_POWER_SOURCE 0x0C8
-#define PCI_REG_WUM8 0x0E8
-#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
-
-/*=== CSR (control and status registers) ===*/
-#define CSR_BASE (0x000)
-
-#define CSR_SW_VER (CSR_BASE+0x000)
-#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */
-#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */
-#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */
-#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */
-#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/
-#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */
-#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
-#define CSR_GP_CNTRL (CSR_BASE+0x024)
-#define CSR_HW_REV (CSR_BASE+0x028)
-#define CSR_EEPROM_REG (CSR_BASE+0x02c)
-#define CSR_EEPROM_GP (CSR_BASE+0x030)
-#define CSR_GP_UCODE (CSR_BASE+0x044)
-#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
-#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058)
-#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
-#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
-#define CSR_LED_REG (CSR_BASE+0x094)
-#define CSR_DRAM_INT_TBL_CTL (CSR_BASE+0x0A0)
-#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
-#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
-#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C)
-
-/* HW I/F configuration */
-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MB (0x00000100)
-#define CSR_HW_IF_CONFIG_REG_BIT_ALMAGOR_MM (0x00000200)
-#define CSR_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400)
-#define CSR_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800)
-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000)
-#define CSR_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000)
-#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
-
-/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
- * acknowledged (reset) by host writing "1" to flagged bits. */
-#define CSR_INT_BIT_FH_RX (1<<31) /* Rx DMA, cmd responses, FH_INT[17:16] */
-#define CSR_INT_BIT_HW_ERR (1<<29) /* DMA hardware error FH_INT[31] */
-#define CSR_INT_BIT_DNLD (1<<28) /* uCode Download */
-#define CSR_INT_BIT_FH_TX (1<<27) /* Tx DMA FH_INT[1:0] */
-#define CSR_INT_BIT_MAC_CLK_ACTV (1<<26) /* NIC controller's clock toggled on/off */
-#define CSR_INT_BIT_SW_ERR (1<<25) /* uCode error */
-#define CSR_INT_BIT_RF_KILL (1<<7) /* HW RFKILL switch GP_CNTRL[27] toggled */
-#define CSR_INT_BIT_CT_KILL (1<<6) /* Critical temp (chip too hot) rfkill */
-#define CSR_INT_BIT_SW_RX (1<<3) /* Rx, command responses, 3945 */
-#define CSR_INT_BIT_WAKEUP (1<<1) /* NIC controller waking up (pwr mgmt) */
-#define CSR_INT_BIT_ALIVE (1<<0) /* uCode interrupts once it initializes */
-
-#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \
- CSR_INT_BIT_HW_ERR | \
- CSR_INT_BIT_FH_TX | \
- CSR_INT_BIT_SW_ERR | \
- CSR_INT_BIT_RF_KILL | \
- CSR_INT_BIT_SW_RX | \
- CSR_INT_BIT_WAKEUP | \
- CSR_INT_BIT_ALIVE)
-
-/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
-#define CSR_FH_INT_BIT_ERR (1<<31) /* Error */
-#define CSR_FH_INT_BIT_HI_PRIOR (1<<30) /* High priority Rx, bypass coalescing */
-#define CSR_FH_INT_BIT_RX_CHNL2 (1<<18) /* Rx channel 2 (3945 only) */
-#define CSR_FH_INT_BIT_RX_CHNL1 (1<<17) /* Rx channel 1 */
-#define CSR_FH_INT_BIT_RX_CHNL0 (1<<16) /* Rx channel 0 */
-#define CSR_FH_INT_BIT_TX_CHNL6 (1<<6) /* Tx channel 6 (3945 only) */
-#define CSR_FH_INT_BIT_TX_CHNL1 (1<<1) /* Tx channel 1 */
-#define CSR_FH_INT_BIT_TX_CHNL0 (1<<0) /* Tx channel 0 */
-
-#define CSR_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \
- CSR_FH_INT_BIT_RX_CHNL2 | \
- CSR_FH_INT_BIT_RX_CHNL1 | \
- CSR_FH_INT_BIT_RX_CHNL0)
-
-#define CSR_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL6 | \
- CSR_FH_INT_BIT_TX_CHNL1 | \
- CSR_FH_INT_BIT_TX_CHNL0 )
-
-
-/* RESET */
-#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001)
-#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002)
-#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080)
-#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100)
-#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200)
-
-/* GP (general purpose) CONTROL */
-#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001)
-#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004)
-#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008)
-#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010)
-
-#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001)
-
-#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000)
-#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000)
-#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000)
-
-
-/* EEPROM REG */
-#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
-#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
-
-/* EEPROM GP */
-#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
-#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
-#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
-
-/* UCODE DRV GP */
-#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001)
-#define CSR_UCODE_SW_BIT_RFKILL (0x00000002)
-#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004)
-#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008)
-
-/* GPIO */
-#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200)
-#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000)
-#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC CSR_GPIO_IN_BIT_AUX_POWER
-
-/* GI Chicken Bits */
-#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000)
-#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000)
-
-/* CSR_ANA_PLL_CFG */
-#define CSR_ANA_PLL_CFG_SH (0x00880300)
-
-#define CSR_LED_REG_TRUN_ON (0x00000078)
-#define CSR_LED_REG_TRUN_OFF (0x00000038)
-#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
-
-/* DRAM_INT_TBL_CTRL */
-#define CSR_DRAM_INT_TBL_CTRL_EN (1<<31)
-#define CSR_DRAM_INT_TBL_CTRL_WRAP_CHK (1<<27)
-
-/*=== HBUS (Host-side Bus) ===*/
-#define HBUS_BASE (0x400)
-
-#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c)
-#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010)
-#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018)
-#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c)
-#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044)
-#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048)
-#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c)
-#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050)
-#define HBUS_TARG_WRPTR (HBUS_BASE+0x060)
-
-#define HBUS_TARG_MBX_C (HBUS_BASE+0x030)
-
-
-/* SCD (Scheduler) */
-#define SCD_BASE (CSR_BASE + 0x2E00)
-
-#define SCD_MODE_REG (SCD_BASE + 0x000)
-#define SCD_ARASTAT_REG (SCD_BASE + 0x004)
-#define SCD_TXFACT_REG (SCD_BASE + 0x010)
-#define SCD_TXF4MF_REG (SCD_BASE + 0x014)
-#define SCD_TXF5MF_REG (SCD_BASE + 0x020)
-#define SCD_SBYP_MODE_1_REG (SCD_BASE + 0x02C)
-#define SCD_SBYP_MODE_2_REG (SCD_BASE + 0x030)
-
-/*=== FH (data Flow Handler) ===*/
-#define FH_BASE (0x800)
-
-#define FH_CBCC_TABLE (FH_BASE+0x140)
-#define FH_TFDB_TABLE (FH_BASE+0x180)
-#define FH_RCSR_TABLE (FH_BASE+0x400)
-#define FH_RSSR_TABLE (FH_BASE+0x4c0)
-#define FH_TCSR_TABLE (FH_BASE+0x500)
-#define FH_TSSR_TABLE (FH_BASE+0x680)
-
-/* TFDB (Transmit Frame Buffer Descriptor) */
-#define FH_TFDB(_channel, buf) \
- (FH_TFDB_TABLE+((_channel)*2+(buf))*0x28)
-#define ALM_FH_TFDB_CHNL_BUF_CTRL_REG(_channel) \
- (FH_TFDB_TABLE + 0x50 * _channel)
-/* CBCC _channel is [0,2] */
-#define FH_CBCC(_channel) (FH_CBCC_TABLE+(_channel)*0x8)
-#define FH_CBCC_CTRL(_channel) (FH_CBCC(_channel)+0x00)
-#define FH_CBCC_BASE(_channel) (FH_CBCC(_channel)+0x04)
-
-/* RCSR _channel is [0,2] */
-#define FH_RCSR(_channel) (FH_RCSR_TABLE+(_channel)*0x40)
-#define FH_RCSR_CONFIG(_channel) (FH_RCSR(_channel)+0x00)
-#define FH_RCSR_RBD_BASE(_channel) (FH_RCSR(_channel)+0x04)
-#define FH_RCSR_WPTR(_channel) (FH_RCSR(_channel)+0x20)
-#define FH_RCSR_RPTR_ADDR(_channel) (FH_RCSR(_channel)+0x24)
-
-#if IWL == 3945
-#define FH_RSCSR_CHNL0_WPTR (FH_RCSR_WPTR(0))
-#elif IWL == 4965
-#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
-#endif
-
-/* RSSR */
-#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000)
-#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004)
-/* TCSR */
-#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20)
-#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00)
-#define FH_TCSR_CREDIT(_channel) (FH_TCSR(_channel)+0x04)
-#define FH_TCSR_BUFF_STTS(_channel) (FH_TCSR(_channel)+0x08)
-/* TSSR */
-#define FH_TSSR_CBB_BASE (FH_TSSR_TABLE+0x000)
-#define FH_TSSR_MSG_CONFIG (FH_TSSR_TABLE+0x008)
-#define FH_TSSR_TX_STATUS (FH_TSSR_TABLE+0x010)
-/* 18 - reserved */
-
-/* card static random access memory (SRAM) for processor data and instructs */
-#define RTC_INST_LOWER_BOUND (0x000000)
-#define RTC_DATA_LOWER_BOUND (0x800000)
-
-
-/* DBM */
-
-#define ALM_FH_SRVC_CHNL (6)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20)
-#define ALM_FH_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000)
-
-#define ALM_FH_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
-
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
-#define ALM_FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
-
-#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000)
-
-#define ALM_FH_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080)
-
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020)
-#define ALM_FH_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005)
-
-#define ALM_TB_MAX_BYTES_COUNT (0xFFF0)
-
-#define ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) \
- ((1LU << _channel) << 24)
-#define ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel) \
- ((1LU << _channel) << 16)
-
-#define ALM_FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_channel) \
- (ALM_FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_channel) | \
- ALM_FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_channel))
-#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */
-#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */
-
-#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
-
-#define TFD_QUEUE_MIN 0
-#define TFD_QUEUE_MAX 6
-#define TFD_QUEUE_SIZE_MAX (256)
-
-/* spectrum and channel data structures */
-#define IWL_NUM_SCAN_RATES (2)
-
-#define IWL_SCAN_FLAG_24GHZ (1<<0)
-#define IWL_SCAN_FLAG_52GHZ (1<<1)
-#define IWL_SCAN_FLAG_ACTIVE (1<<2)
-#define IWL_SCAN_FLAG_DIRECT (1<<3)
-
-#define IWL_MAX_CMD_SIZE 1024
-
-#define IWL_DEFAULT_TX_RETRY 15
-#define IWL_MAX_TX_RETRY 16
-
-/*********************************************/
-
-#define RFD_SIZE 4
-#define NUM_TFD_CHUNKS 4
-
-#define RX_QUEUE_SIZE 256
-#define RX_QUEUE_MASK 255
-#define RX_QUEUE_SIZE_LOG 8
-
-/* QoS definitions */
-
-#define CW_MIN_OFDM 15
-#define CW_MAX_OFDM 1023
-#define CW_MIN_CCK 31
-#define CW_MAX_CCK 1023
-
-#define QOS_TX0_CW_MIN_OFDM CW_MIN_OFDM
-#define QOS_TX1_CW_MIN_OFDM CW_MIN_OFDM
-#define QOS_TX2_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 2 - 1)
-#define QOS_TX3_CW_MIN_OFDM ((CW_MIN_OFDM + 1) / 4 - 1)
-
-#define QOS_TX0_CW_MIN_CCK CW_MIN_CCK
-#define QOS_TX1_CW_MIN_CCK CW_MIN_CCK
-#define QOS_TX2_CW_MIN_CCK ((CW_MIN_CCK + 1) / 2 - 1)
-#define QOS_TX3_CW_MIN_CCK ((CW_MIN_CCK + 1) / 4 - 1)
-
-#define QOS_TX0_CW_MAX_OFDM CW_MAX_OFDM
-#define QOS_TX1_CW_MAX_OFDM CW_MAX_OFDM
-#define QOS_TX2_CW_MAX_OFDM CW_MIN_OFDM
-#define QOS_TX3_CW_MAX_OFDM ((CW_MIN_OFDM + 1) / 2 - 1)
-
-#define QOS_TX0_CW_MAX_CCK CW_MAX_CCK
-#define QOS_TX1_CW_MAX_CCK CW_MAX_CCK
-#define QOS_TX2_CW_MAX_CCK CW_MIN_CCK
-#define QOS_TX3_CW_MAX_CCK ((CW_MIN_CCK + 1) / 2 - 1)
-
-#define QOS_TX0_AIFS 3
-#define QOS_TX1_AIFS 7
-#define QOS_TX2_AIFS 2
-#define QOS_TX3_AIFS 2
-
-#define QOS_TX0_ACM 0
-#define QOS_TX1_ACM 0
-#define QOS_TX2_ACM 0
-#define QOS_TX3_ACM 0
-
-#define QOS_TX0_TXOP_LIMIT_CCK 0
-#define QOS_TX1_TXOP_LIMIT_CCK 0
-#define QOS_TX2_TXOP_LIMIT_CCK 6016
-#define QOS_TX3_TXOP_LIMIT_CCK 3264
-
-#define QOS_TX0_TXOP_LIMIT_OFDM 0
-#define QOS_TX1_TXOP_LIMIT_OFDM 0
-#define QOS_TX2_TXOP_LIMIT_OFDM 3008
-#define QOS_TX3_TXOP_LIMIT_OFDM 1504
-
-#define DEF_TX0_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX1_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX2_CW_MIN_OFDM CW_MIN_OFDM
-#define DEF_TX3_CW_MIN_OFDM CW_MIN_OFDM
-
-#define DEF_TX0_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX1_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX2_CW_MIN_CCK CW_MIN_CCK
-#define DEF_TX3_CW_MIN_CCK CW_MIN_CCK
-
-#define DEF_TX0_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX1_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX2_CW_MAX_OFDM CW_MAX_OFDM
-#define DEF_TX3_CW_MAX_OFDM CW_MAX_OFDM
-
-#define DEF_TX0_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX1_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX2_CW_MAX_CCK CW_MAX_CCK
-#define DEF_TX3_CW_MAX_CCK CW_MAX_CCK
-
-#define DEF_TX0_AIFS (2)
-#define DEF_TX1_AIFS (2)
-#define DEF_TX2_AIFS (2)
-#define DEF_TX3_AIFS (2)
-
-#define DEF_TX0_ACM 0
-#define DEF_TX1_ACM 0
-#define DEF_TX2_ACM 0
-#define DEF_TX3_ACM 0
-
-#define DEF_TX0_TXOP_LIMIT_CCK 0
-#define DEF_TX1_TXOP_LIMIT_CCK 0
-#define DEF_TX2_TXOP_LIMIT_CCK 0
-#define DEF_TX3_TXOP_LIMIT_CCK 0
-
-#define DEF_TX0_TXOP_LIMIT_OFDM 0
-#define DEF_TX1_TXOP_LIMIT_OFDM 0
-#define DEF_TX2_TXOP_LIMIT_OFDM 0
-#define DEF_TX3_TXOP_LIMIT_OFDM 0
-
-#define QOS_QOS_SETS 3
-#define QOS_PARAM_SET_ACTIVE 0
-#define QOS_PARAM_SET_DEF_CCK 1
-#define QOS_PARAM_SET_DEF_OFDM 2
-
-#define CTRL_QOS_NO_ACK (0x0020)
-#define DCT_FLAG_EXT_QOS_ENABLED (0x10)
-
-#define U32_PAD(n) ((4-(n))&0x3)
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues
- */
-#define TFD_CTL_COUNT_SET(n) (n<<24)
-#define TFD_CTL_COUNT_GET(ctl) ((ctl>>24) & 7)
-#define TFD_CTL_PAD_SET(n) (n<<28)
-#define TFD_CTL_PAD_GET(ctl) (ctl>>28)
-
-#define TFD_TX_CMD_SLOTS 256
-#define TFD_CMD_SLOTS 32
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
- sizeof(struct iwl_cmd_meta))
-
-/*
- * RX related structures and functions
- */
-#define RX_FREE_BUFFERS 64
-#define RX_LOW_WATERMARK 8
-
-#endif /* __iwlwifi_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
deleted file mode 100644
index 8a8b96fcf48d..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ /dev/null
@@ -1,470 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_io_h__
-#define __iwl_io_h__
-
-#include <linux/io.h>
-
-#include "iwl-debug.h"
-
-/*
- * IO, register, and NIC memory access functions
- *
- * NOTE on naming convention and macro usage for these
- *
- * A single _ prefix before a an access function means that no state
- * check or debug information is printed when that function is called.
- *
- * A double __ prefix before an access function means that state is checked
- * (in the case of *restricted calls) and the current line number is printed
- * in addition to any other debug output.
- *
- * The non-prefixed name is the #define that maps the caller into a
- * #define that provides the caller's __LINE__ to the double prefix version.
- *
- * If you wish to call the function without any debug or state checking,
- * you should use the single _ prefix version (as is used by dependent IO
- * routines, for example _iwl_read_restricted calls the non-check version of
- * _iwl_read32.)
- *
- * These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguring of the hardware I/O. In combination with
- * git-bisect and the IO debug level you can quickly determine the specific
- * commit which breaks the IO sequence to the hardware.
- *
- */
-
-#define _iwl_write32(iwl, ofs, val) writel((val), (iwl)->hw_base + (ofs))
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *iwl,
- u32 ofs, u32 val)
-{
- IWL_DEBUG_IO("write_direct32(0x%08X, 0x%08X) - %s %d\n",
- (u32) (ofs), (u32) (val), f, l);
- _iwl_write32(iwl, ofs, val);
-}
-#define iwl_write32(iwl, ofs, val) \
- __iwl_write32(__FILE__, __LINE__, iwl, ofs, val)
-#else
-#define iwl_write32(iwl, ofs, val) _iwl_write32(iwl, ofs, val)
-#endif
-
-#define _iwl_read32(iwl, ofs) readl((iwl)->hw_base + (ofs))
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *iwl, u32 ofs)
-{
- IWL_DEBUG_IO("read_direct32(0x%08X) - %s %d\n", ofs, f, l);
- return _iwl_read32(iwl, ofs);
-}
-#define iwl_read32(iwl, ofs) __iwl_read32(__FILE__, __LINE__, iwl, ofs)
-#else
-#define iwl_read32(p, o) _iwl_read32(p, o)
-#endif
-
-static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
- u32 bits, u32 mask, int timeout)
-{
- int i = 0;
-
- do {
- if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
- return i;
- mdelay(10);
- i += 10;
- } while (i < timeout);
-
- return -ETIMEDOUT;
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline int __iwl_poll_bit(const char *f, u32 l,
- struct iwl_priv *priv, u32 addr,
- u32 bits, u32 mask, int timeout)
-{
- int rc = _iwl_poll_bit(priv, addr, bits, mask, timeout);
- if (unlikely(rc == -ETIMEDOUT))
- IWL_DEBUG_IO
- ("poll_bit(0x%08X, 0x%08X, 0x%08X) - timedout - %s %d\n",
- addr, bits, mask, f, l);
- else
- IWL_DEBUG_IO
- ("poll_bit(0x%08X, 0x%08X, 0x%08X) = 0x%08X - %s %d\n",
- addr, bits, mask, rc, f, l);
- return rc;
-}
-#define iwl_poll_bit(iwl, addr, bits, mask, timeout) \
- __iwl_poll_bit(__FILE__, __LINE__, iwl, addr, bits, mask, timeout)
-#else
-#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t)
-#endif
-
-static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-{
- _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_set_bit(const char *f, u32 l,
- struct iwl_priv *priv, u32 reg, u32 mask)
-{
- u32 val = _iwl_read32(priv, reg) | mask;
- IWL_DEBUG_IO("set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
- _iwl_write32(priv, reg, val);
-}
-#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m)
-#else
-#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m)
-#endif
-
-static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
-{
- _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_clear_bit(const char *f, u32 l,
- struct iwl_priv *priv, u32 reg, u32 mask)
-{
- u32 val = _iwl_read32(priv, reg) & ~mask;
- IWL_DEBUG_IO("clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
- _iwl_write32(priv, reg, val);
-}
-#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m)
-#else
-#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m)
-#endif
-
-static inline int _iwl_grab_restricted_access(struct iwl_priv *priv)
-{
- int rc;
- u32 gp_ctl;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (atomic_read(&priv->restrict_refcnt))
- return 0;
-#endif
- if (test_bit(STATUS_RF_KILL_HW, &priv->status) ||
- test_bit(STATUS_RF_KILL_SW, &priv->status)) {
- IWL_WARNING("WARNING: Requesting MAC access during RFKILL "
- "wakes up NIC\n");
-
- /* 10 msec allows time for NIC to complete its data save */
- gp_ctl = _iwl_read32(priv, CSR_GP_CNTRL);
- if (gp_ctl & CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY) {
- IWL_DEBUG_RF_KILL("Wait for complete power-down, "
- "gpctl = 0x%08x\n", gp_ctl);
- mdelay(10);
- } else
- IWL_DEBUG_RF_KILL("power-down complete, "
- "gpctl = 0x%08x\n", gp_ctl);
- }
-
- /* this bit wakes up the NIC */
- _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- rc = _iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
- (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 50);
- if (rc < 0) {
- IWL_ERROR("MAC is in deep sleep!\n");
- return -EIO;
- }
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- atomic_inc(&priv->restrict_refcnt);
-#endif
- return 0;
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline int __iwl_grab_restricted_access(const char *f, u32 l,
- struct iwl_priv *priv)
-{
- if (atomic_read(&priv->restrict_refcnt))
- IWL_DEBUG_INFO("Grabbing access while already held at "
- "line %d.\n", l);
-
- IWL_DEBUG_IO("grabbing restricted access - %s %d\n", f, l);
-
- return _iwl_grab_restricted_access(priv);
-}
-#define iwl_grab_restricted_access(priv) \
- __iwl_grab_restricted_access(__FILE__, __LINE__, priv)
-#else
-#define iwl_grab_restricted_access(priv) \
- _iwl_grab_restricted_access(priv)
-#endif
-
-static inline void _iwl_release_restricted_access(struct iwl_priv *priv)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (atomic_dec_and_test(&priv->restrict_refcnt))
-#endif
- _iwl_clear_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_release_restricted_access(const char *f, u32 l,
- struct iwl_priv *priv)
-{
- if (atomic_read(&priv->restrict_refcnt) <= 0)
- IWL_ERROR("Release unheld restricted access at line %d.\n", l);
-
- IWL_DEBUG_IO("releasing restricted access - %s %d\n", f, l);
- _iwl_release_restricted_access(priv);
-}
-#define iwl_release_restricted_access(priv) \
- __iwl_release_restricted_access(__FILE__, __LINE__, priv)
-#else
-#define iwl_release_restricted_access(priv) \
- _iwl_release_restricted_access(priv)
-#endif
-
-static inline u32 _iwl_read_restricted(struct iwl_priv *priv, u32 reg)
-{
- return _iwl_read32(priv, reg);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline u32 __iwl_read_restricted(const char *f, u32 l,
- struct iwl_priv *priv, u32 reg)
-{
- u32 value = _iwl_read_restricted(priv, reg);
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from %s %d\n", f, l);
- IWL_DEBUG_IO("read_restricted(0x%4X) = 0x%08x - %s %d \n", reg, value,
- f, l);
- return value;
-}
-#define iwl_read_restricted(priv, reg) \
- __iwl_read_restricted(__FILE__, __LINE__, priv, reg)
-#else
-#define iwl_read_restricted _iwl_read_restricted
-#endif
-
-static inline void _iwl_write_restricted(struct iwl_priv *priv,
- u32 reg, u32 value)
-{
- _iwl_write32(priv, reg, value);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static void __iwl_write_restricted(u32 line,
- struct iwl_priv *priv, u32 reg, u32 value)
-{
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from line %d\n", line);
- _iwl_write_restricted(priv, reg, value);
-}
-#define iwl_write_restricted(priv, reg, value) \
- __iwl_write_restricted(__LINE__, priv, reg, value)
-#else
-#define iwl_write_restricted _iwl_write_restricted
-#endif
-
-static inline void iwl_write_buffer_restricted(struct iwl_priv *priv,
- u32 reg, u32 len, u32 *values)
-{
- u32 count = sizeof(u32);
-
- if ((priv != NULL) && (values != NULL)) {
- for (; 0 < len; len -= count, reg += count, values++)
- _iwl_write_restricted(priv, reg, *values);
- }
-}
-
-static inline int _iwl_poll_restricted_bit(struct iwl_priv *priv,
- u32 addr, u32 mask, int timeout)
-{
- int i = 0;
-
- do {
- if ((_iwl_read_restricted(priv, addr) & mask) == mask)
- return i;
- mdelay(10);
- i += 10;
- } while (i < timeout);
-
- return -ETIMEDOUT;
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline int __iwl_poll_restricted_bit(const char *f, u32 l,
- struct iwl_priv *priv,
- u32 addr, u32 mask, int timeout)
-{
- int rc = _iwl_poll_restricted_bit(priv, addr, mask, timeout);
-
- if (unlikely(rc == -ETIMEDOUT))
- IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) - "
- "timedout - %s %d\n", addr, mask, f, l);
- else
- IWL_DEBUG_IO("poll_restricted_bit(0x%08X, 0x%08X) = 0x%08X "
- "- %s %d\n", addr, mask, rc, f, l);
- return rc;
-}
-#define iwl_poll_restricted_bit(iwl, addr, mask, timeout) \
- __iwl_poll_restricted_bit(__FILE__, __LINE__, iwl, addr, mask, timeout)
-#else
-#define iwl_poll_restricted_bit _iwl_poll_restricted_bit
-#endif
-
-static inline u32 _iwl_read_restricted_reg(struct iwl_priv *priv, u32 reg)
-{
- _iwl_write_restricted(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
- return _iwl_read_restricted(priv, HBUS_TARG_PRPH_RDAT);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline u32 __iwl_read_restricted_reg(u32 line,
- struct iwl_priv *priv, u32 reg)
-{
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from line %d\n", line);
- return _iwl_read_restricted_reg(priv, reg);
-}
-
-#define iwl_read_restricted_reg(priv, reg) \
- __iwl_read_restricted_reg(__LINE__, priv, reg)
-#else
-#define iwl_read_restricted_reg _iwl_read_restricted_reg
-#endif
-
-static inline void _iwl_write_restricted_reg(struct iwl_priv *priv,
- u32 addr, u32 val)
-{
- _iwl_write_restricted(priv, HBUS_TARG_PRPH_WADDR,
- ((addr & 0x0000FFFF) | (3 << 24)));
- _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT, val);
-}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_write_restricted_reg(u32 line,
- struct iwl_priv *priv,
- u32 addr, u32 val)
-{
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from line %d\n", line);
- _iwl_write_restricted_reg(priv, addr, val);
-}
-
-#define iwl_write_restricted_reg(priv, addr, val) \
- __iwl_write_restricted_reg(__LINE__, priv, addr, val);
-#else
-#define iwl_write_restricted_reg _iwl_write_restricted_reg
-#endif
-
-#define _iwl_set_bits_restricted_reg(priv, reg, mask) \
- _iwl_write_restricted_reg(priv, reg, \
- (_iwl_read_restricted_reg(priv, reg) | mask))
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_set_bits_restricted_reg(u32 line, struct iwl_priv
- *priv, u32 reg, u32 mask)
-{
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from line %d\n", line);
- _iwl_set_bits_restricted_reg(priv, reg, mask);
-}
-#define iwl_set_bits_restricted_reg(priv, reg, mask) \
- __iwl_set_bits_restricted_reg(__LINE__, priv, reg, mask)
-#else
-#define iwl_set_bits_restricted_reg _iwl_set_bits_restricted_reg
-#endif
-
-#define _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
- _iwl_write_restricted_reg( \
- priv, reg, ((_iwl_read_restricted_reg(priv, reg) & mask) | bits))
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void __iwl_set_bits_mask_restricted_reg(u32 line,
- struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
-{
- if (!atomic_read(&priv->restrict_refcnt))
- IWL_ERROR("Unrestricted access from line %d\n", line);
- _iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask);
-}
-
-#define iwl_set_bits_mask_restricted_reg(priv, reg, bits, mask) \
- __iwl_set_bits_mask_restricted_reg(__LINE__, priv, reg, bits, mask)
-#else
-#define iwl_set_bits_mask_restricted_reg _iwl_set_bits_mask_restricted_reg
-#endif
-
-static inline void iwl_clear_bits_restricted_reg(struct iwl_priv
- *priv, u32 reg, u32 mask)
-{
- u32 val = _iwl_read_restricted_reg(priv, reg);
- _iwl_write_restricted_reg(priv, reg, (val & ~mask));
-}
-
-static inline u32 iwl_read_restricted_mem(struct iwl_priv *priv, u32 addr)
-{
- iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, addr);
- return iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
-}
-
-static inline void iwl_write_restricted_mem(struct iwl_priv *priv, u32 addr,
- u32 val)
-{
- iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
- iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, val);
-}
-
-static inline void iwl_write_restricted_mems(struct iwl_priv *priv, u32 addr,
- u32 len, u32 *values)
-{
- iwl_write_restricted(priv, HBUS_TARG_MEM_WADDR, addr);
- for (; 0 < len; len -= sizeof(u32), values++)
- iwl_write_restricted(priv, HBUS_TARG_MEM_WDAT, *values);
-}
-
-static inline void iwl_write_restricted_regs(struct iwl_priv *priv, u32 reg,
- u32 len, u8 *values)
-{
- u32 reg_offset = reg;
- u32 aligment = reg & 0x3;
-
- /* write any non-dword-aligned stuff at the beginning */
- if (len < sizeof(u32)) {
- if ((aligment + len) <= sizeof(u32)) {
- u8 size;
- u32 value = 0;
- size = len - 1;
- memcpy(&value, values, len);
- reg_offset = (reg_offset & 0x0000FFFF);
-
- _iwl_write_restricted(priv,
- HBUS_TARG_PRPH_WADDR,
- (reg_offset | (size << 24)));
- _iwl_write_restricted(priv, HBUS_TARG_PRPH_WDAT,
- value);
- }
-
- return;
- }
-
- /* now write all the dword-aligned stuff */
- for (; reg_offset < (reg + len);
- reg_offset += sizeof(u32), values += sizeof(u32))
- _iwl_write_restricted_reg(priv, reg_offset, *((u32 *) values));
-}
-
-#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-priv.h b/drivers/net/wireless/iwlwifi/iwl-priv.h
deleted file mode 100644
index 6b490d08fea9..000000000000
--- a/drivers/net/wireless/iwlwifi/iwl-priv.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwl_priv_h__
-#define __iwl_priv_h__
-
-#include <linux/workqueue.h>
-
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
-
-enum {
- MEASUREMENT_READY = (1 << 0),
- MEASUREMENT_ACTIVE = (1 << 1),
-};
-
-#endif
-
-struct iwl_priv {
-
- /* ieee device used by generic ieee processing code */
- struct ieee80211_hw *hw;
- struct ieee80211_channel *ieee_channels;
- struct ieee80211_rate *ieee_rates;
-
- /* temporary frame storage list */
- struct list_head free_frames;
- int frames_count;
-
- u8 phymode;
- int alloc_rxb_skb;
-
- void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
-
- const struct ieee80211_hw_mode *modes;
-
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
- /* spectrum measurement report caching */
- struct iwl_spectrum_notification measure_report;
- u8 measurement_status;
-#endif
- /* ucode beacon time */
- u32 ucode_beacon_time;
-
- /* we allocate array of iwl_channel_info for NIC's valid channels.
- * Access via channel # using indirect index array */
- struct iwl_channel_info *channel_info; /* channel info array */
- u8 channel_count; /* # of channels */
-
- /* each calibration channel group in the EEPROM has a derived
- * clip setting for each rate. */
- const struct iwl_clip_group clip_groups[5];
-
- /* thermal calibration */
- s32 temperature; /* degrees Kelvin */
- s32 last_temperature;
-
- /* Scan related variables */
- unsigned long last_scan_jiffies;
- unsigned long scan_start;
- unsigned long scan_pass_start;
- unsigned long scan_start_tsf;
- int scan_bands;
- int one_direct_scan;
- u8 direct_ssid_len;
- u8 direct_ssid[IW_ESSID_MAX_SIZE];
- struct iwl_scan_cmd *scan;
- u8 only_active_channel;
-
- /* spinlock */
- spinlock_t lock; /* protect general shared data */
- spinlock_t hcmd_lock; /* protect hcmd */
- struct mutex mutex;
-
- /* basic pci-network driver stuff */
- struct pci_dev *pci_dev;
-
- /* pci hardware address support */
- void __iomem *hw_base;
-
- /* uCode images, save to reload in case of failure */
- struct fw_image_desc ucode_code; /* runtime inst */
- struct fw_image_desc ucode_data; /* runtime data original */
- struct fw_image_desc ucode_data_backup; /* runtime data save/restore */
- struct fw_image_desc ucode_init; /* initialization inst */
- struct fw_image_desc ucode_init_data; /* initialization data */
- struct fw_image_desc ucode_boot; /* bootstrap inst */
-
-
- struct iwl_rxon_time_cmd rxon_timing;
-
- /* We declare this const so it can only be
- * changed via explicit cast within the
- * routines that actually update the physical
- * hardware */
- const struct iwl_rxon_cmd active_rxon;
- struct iwl_rxon_cmd staging_rxon;
-
- int error_recovering;
- struct iwl_rxon_cmd recovery_rxon;
-
- /* 1st responses from initialize and runtime uCode images.
- * 4965's initialize alive response contains some calibration data. */
- struct iwl_init_alive_resp card_alive_init;
- struct iwl_alive_resp card_alive;
-
-#ifdef LED
- /* LED related variables */
- struct iwl_activity_blink activity;
- unsigned long led_packets;
- int led_state;
-#endif
-
- u16 active_rate;
- u16 active_rate_basic;
-
- u8 call_post_assoc_from_beacon;
- u8 assoc_station_added;
-#if IWL == 4965
- u8 use_ant_b_for_management_frame; /* Tx antenna selection */
- /* HT variables */
- u8 is_dup;
- u8 is_ht_enabled;
- u8 channel_width; /* 0=20MHZ, 1=40MHZ */
- u8 current_channel_width;
- u8 valid_antenna; /* Bit mask of antennas actually connected */
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
- struct iwl_sensitivity_data sensitivity_data;
- struct iwl_chain_noise_data chain_noise_data;
- u8 start_calib;
- __le16 sensitivity_tbl[HD_TABLE_SIZE];
-#endif /*CONFIG_IWLWIFI_SENSITIVITY*/
-
-#ifdef CONFIG_IWLWIFI_HT
- struct sta_ht_info current_assoc_ht;
-#endif
- u8 active_rate_ht[2];
- u8 last_phy_res[100];
-
- /* Rate scaling data */
- struct iwl_lq_mngr lq_mngr;
-#endif
-
- /* Rate scaling data */
- s8 data_retry_limit;
- u8 retry_rate;
-
- wait_queue_head_t wait_command_queue;
-
- int activity_timer_active;
-
- /* Rx and Tx DMA processing queues */
- struct iwl_rx_queue rxq;
- struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
-#if IWL == 4965
- unsigned long txq_ctx_active_msk;
- struct iwl_kw kw; /* keep warm address */
- u32 scd_base_addr; /* scheduler sram base address */
-#endif
-
- unsigned long status;
- u32 config;
-
- int last_rx_rssi; /* From Rx packet statisitics */
- int last_rx_noise; /* From beacon statistics */
-
- struct iwl_power_mgr power_data;
-
- struct iwl_notif_statistics statistics;
- unsigned long last_statistics_time;
-
- /* context information */
- u8 essid[IW_ESSID_MAX_SIZE];
- u8 essid_len;
- u16 rates_mask;
-
- u32 power_mode;
- u32 antenna;
- u8 bssid[ETH_ALEN];
- u16 rts_threshold;
- u8 mac_addr[ETH_ALEN];
-
- /*station table variables */
- spinlock_t sta_lock;
- int num_stations;
- struct iwl_station_entry stations[IWL_STATION_COUNT];
-
- /* Indication if ieee80211_ops->open has been called */
- int is_open;
-
- u8 mac80211_registered;
- int is_abg;
-
- u32 notif_missed_beacons;
-
- /* Rx'd packet timing information */
- u32 last_beacon_time;
- u64 last_tsf;
-
- /* Duplicate packet detection */
- u16 last_seq_num;
- u16 last_frag_num;
- unsigned long last_packet_time;
- struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
-
- /* eeprom */
- struct iwl_eeprom eeprom;
-
- int iw_mode;
-
- struct sk_buff *ibss_beacon;
-
- /* Last Rx'd beacon timestamp */
- u32 timestamp0;
- u32 timestamp1;
- u16 beacon_int;
- struct iwl_driver_hw_info hw_setting;
- int interface_id;
-
- /* Current association information needed to configure the
- * hardware */
- u16 assoc_id;
- u16 assoc_capability;
- u8 ps_mode;
-
-#ifdef CONFIG_IWLWIFI_QOS
- struct iwl_qos_info qos_data;
-#endif /*CONFIG_IWLWIFI_QOS */
-
- struct workqueue_struct *workqueue;
-
- struct work_struct up;
- struct work_struct restart;
- struct work_struct calibrated_work;
- struct work_struct scan_completed;
- struct work_struct rx_replenish;
- struct work_struct rf_kill;
- struct work_struct abort_scan;
- struct work_struct update_link_led;
- struct work_struct auth_work;
- struct work_struct report_work;
- struct work_struct request_scan;
- struct work_struct beacon_update;
-
- struct tasklet_struct irq_tasklet;
-
- struct delayed_work init_alive_start;
- struct delayed_work alive_start;
- struct delayed_work activity_timer;
- struct delayed_work thermal_periodic;
- struct delayed_work gather_stats;
- struct delayed_work scan_check;
- struct delayed_work post_associate;
-
-#define IWL_DEFAULT_TX_POWER 0x0F
- s8 user_txpower_limit;
- s8 max_channel_txpower_limit;
- u32 cck_power_index_compensation;
-
-#ifdef CONFIG_PM
- u32 pm_state[16];
-#endif
-
-#ifdef CONFIG_IWLWIFI_DEBUG
- /* debugging info */
- u32 framecnt_to_us;
- atomic_t restrict_refcnt;
-#endif
-
-#if IWL == 4965
- struct work_struct txpower_work;
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
- struct work_struct sensitivity_work;
-#endif
- struct work_struct statistics_work;
- struct timer_list statistics_periodic;
-
-#ifdef CONFIG_IWLWIFI_HT_AGG
- struct work_struct agg_work;
-#endif
-
-#endif /* 4965 */
-}; /*iwl_priv */
-
-#endif /* __iwl_priv_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 0df41148eadc..4ba121634877 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -8,7 +8,7 @@
* Copyright(c) 2005 - 2007 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU Geeral Public License as
+ * it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
@@ -63,7 +63,10 @@
#ifndef __iwl_prph_h__
#define __iwl_prph_h__
-
+/*
+ * Registers in this file are internal, not PCI bus memory mapped.
+ * Driver accesses these via HBUS_TARG_PRPH_* registers.
+ */
#define PRPH_BASE (0x00000)
#define PRPH_END (0xFFFFF)
@@ -226,4 +229,58 @@
#define BSM_SRAM_SIZE (1024) /* bytes */
+/* 3945 Tx scheduler registers */
+#define ALM_SCD_BASE (PRPH_BASE + 0x2E00)
+#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000)
+#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004)
+#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010)
+#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014)
+#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020)
+#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C)
+#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030)
+
+/*
+ * 4965 Tx Scheduler registers.
+ * Details are documented in iwl-4965-hw.h
+ */
+#define KDR_SCD_BASE (PRPH_BASE + 0xa02c00)
+
+#define KDR_SCD_SRAM_BASE_ADDR (KDR_SCD_BASE + 0x0)
+#define KDR_SCD_EMPTY_BITS (KDR_SCD_BASE + 0x4)
+#define KDR_SCD_DRAM_BASE_ADDR (KDR_SCD_BASE + 0x10)
+#define KDR_SCD_AIT (KDR_SCD_BASE + 0x18)
+#define KDR_SCD_TXFACT (KDR_SCD_BASE + 0x1c)
+#define KDR_SCD_QUEUE_WRPTR(x) (KDR_SCD_BASE + 0x24 + (x) * 4)
+#define KDR_SCD_QUEUE_RDPTR(x) (KDR_SCD_BASE + 0x64 + (x) * 4)
+#define KDR_SCD_SETQUEUENUM (KDR_SCD_BASE + 0xa4)
+#define KDR_SCD_SET_TXSTAT_TXED (KDR_SCD_BASE + 0xa8)
+#define KDR_SCD_SET_TXSTAT_DONE (KDR_SCD_BASE + 0xac)
+#define KDR_SCD_SET_TXSTAT_NOT_SCHD (KDR_SCD_BASE + 0xb0)
+#define KDR_SCD_DECREASE_CREDIT (KDR_SCD_BASE + 0xb4)
+#define KDR_SCD_DECREASE_SCREDIT (KDR_SCD_BASE + 0xb8)
+#define KDR_SCD_LOAD_CREDIT (KDR_SCD_BASE + 0xbc)
+#define KDR_SCD_LOAD_SCREDIT (KDR_SCD_BASE + 0xc0)
+#define KDR_SCD_BAR (KDR_SCD_BASE + 0xc4)
+#define KDR_SCD_BAR_DW0 (KDR_SCD_BASE + 0xc8)
+#define KDR_SCD_BAR_DW1 (KDR_SCD_BASE + 0xcc)
+#define KDR_SCD_QUEUECHAIN_SEL (KDR_SCD_BASE + 0xd0)
+#define KDR_SCD_QUERY_REQ (KDR_SCD_BASE + 0xd8)
+#define KDR_SCD_QUERY_RES (KDR_SCD_BASE + 0xdc)
+#define KDR_SCD_PENDING_FRAMES (KDR_SCD_BASE + 0xe0)
+#define KDR_SCD_INTERRUPT_MASK (KDR_SCD_BASE + 0xe4)
+#define KDR_SCD_INTERRUPT_THRESHOLD (KDR_SCD_BASE + 0xe8)
+#define KDR_SCD_QUERY_MIN_FRAME_SIZE (KDR_SCD_BASE + 0x100)
+#define KDR_SCD_QUEUE_STATUS_BITS(x) (KDR_SCD_BASE + 0x104 + (x) * 4)
+
+/* SP SCD */
+#define SHL_SCD_BASE (PRPH_BASE + 0xa02c00)
+
+#define SHL_SCD_AIT (SHL_SCD_BASE + 0x0c)
+#define SHL_SCD_TXFACT (SHL_SCD_BASE + 0x10)
+#define SHL_SCD_QUEUE_WRPTR(x) (SHL_SCD_BASE + 0x18 + (x) * 4)
+#define SHL_SCD_QUEUE_RDPTR(x) (SHL_SCD_BASE + 0x68 + (x) * 4)
+#define SHL_SCD_QUEUECHAIN_SEL (SHL_SCD_BASE + 0xe8)
+#define SHL_SCD_AGGR_SEL (SHL_SCD_BASE + 0x248)
+#define SHL_SCD_INTERRUPT_MASK (SHL_SCD_BASE + 0x108)
+
#endif /* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 1a6b0e0edf6f..748ac1222abb 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -27,16 +27,6 @@
*
*****************************************************************************/
-/*
- * NOTE: This file (iwl-base.c) is used to build to multiple hardware targets
- * by defining IWL to either 3945 or 4965. The Makefile used when building
- * the base targets will create base-3945.o and base-4965.o
- *
- * The eventual goal is to move as many of the #if IWL / #endif blocks out of
- * this file and into the hardware specific implementation files (iwl-XXXX.c)
- * and leave only the common (non #ifdef sprinkled) code in this file
- */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
@@ -56,16 +46,16 @@
#include <asm/div64.h>
-#define IWL 3945
-
-#include "iwlwifi.h"
#include "iwl-3945.h"
#include "iwl-helpers.h"
-#ifdef CONFIG_IWLWIFI_DEBUG
-u32 iwl_debug_level;
+#ifdef CONFIG_IWL3945_DEBUG
+u32 iwl3945_debug_level;
#endif
+static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq);
+
/******************************************************************************
*
* module boiler plate
@@ -73,13 +63,13 @@ u32 iwl_debug_level;
******************************************************************************/
/* module parameters */
-int iwl_param_disable_hw_scan;
-int iwl_param_debug;
-int iwl_param_disable; /* def: enable radio */
-int iwl_param_antenna; /* def: 0 = both antennas (use diversity) */
-int iwl_param_hwcrypto; /* def: using software encryption */
-int iwl_param_qos_enable = 1;
-int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
+static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */
+static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */
+static int iwl3945_param_disable; /* def: 0 = enable radio */
+static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
+int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
+static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
+int iwl3945_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 8 Tx queues */
/*
* module name, copyright, version, etc.
@@ -89,19 +79,19 @@ int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
#define DRV_DESCRIPTION \
"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL3945_DEBUG
#define VD "d"
#else
#define VD
#endif
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
#define VS "s"
#else
#define VS
#endif
-#define IWLWIFI_VERSION "1.1.17k" VD VS
+#define IWLWIFI_VERSION "1.2.23k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
#define DRV_VERSION IWLWIFI_VERSION
@@ -116,7 +106,7 @@ MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT);
MODULE_LICENSE("GPL");
-__le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
+static __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
{
u16 fc = le16_to_cpu(hdr->frame_control);
int hdr_len = ieee80211_get_hdrlen(fc);
@@ -126,8 +116,8 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
return NULL;
}
-static const struct ieee80211_hw_mode *iwl_get_hw_mode(
- struct iwl_priv *priv, int mode)
+static const struct ieee80211_hw_mode *iwl3945_get_hw_mode(
+ struct iwl3945_priv *priv, int mode)
{
int i;
@@ -138,7 +128,7 @@ static const struct ieee80211_hw_mode *iwl_get_hw_mode(
return NULL;
}
-static int iwl_is_empty_essid(const char *essid, int essid_len)
+static int iwl3945_is_empty_essid(const char *essid, int essid_len)
{
/* Single white space is for Linksys APs */
if (essid_len == 1 && essid[0] == ' ')
@@ -154,13 +144,13 @@ static int iwl_is_empty_essid(const char *essid, int essid_len)
return 1;
}
-static const char *iwl_escape_essid(const char *essid, u8 essid_len)
+static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
{
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
const char *s = essid;
char *d = escaped;
- if (iwl_is_empty_essid(essid, essid_len)) {
+ if (iwl3945_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped;
}
@@ -178,10 +168,10 @@ static const char *iwl_escape_essid(const char *essid, u8 essid_len)
return escaped;
}
-static void iwl_print_hex_dump(int level, void *p, u32 len)
+static void iwl3945_print_hex_dump(int level, void *p, u32 len)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (!(iwl_debug_level & level))
+#ifdef CONFIG_IWL3945_DEBUG
+ if (!(iwl3945_debug_level & level))
return;
print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
@@ -194,24 +184,31 @@ static void iwl_print_hex_dump(int level, void *p, u32 len)
*
* Theory of operation
*
- * A queue is a circular buffers with 'Read' and 'Write' pointers.
- * 2 empty entries always kept in the buffer to protect from overflow.
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill. Driver and device exchange status of each
+ * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
*
* For Tx queue, there are low mark and high mark limits. If, after queuing
* the packet for Tx, free space become < low mark, Tx queue stopped. When
* reclaiming packets (on 'tx done IRQ), if free space become > high mark,
* Tx queue resumed.
*
- * The IWL operates with six queues, one receive queue in the device's
- * sram, one transmit queue for sending commands to the device firmware,
- * and four transmit queues for data.
+ * The 3945 operates with six queues: One receive queue, one transmit queue
+ * (#4) for sending commands to the device firmware, and four transmit queues
+ * (#0-3) for data tx via EDCA. An additional 2 HCCA queues are unused.
***************************************************/
-static int iwl_queue_space(const struct iwl_queue *q)
+static int iwl3945_queue_space(const struct iwl3945_queue *q)
{
- int s = q->last_used - q->first_empty;
+ int s = q->read_ptr - q->write_ptr;
- if (q->last_used > q->first_empty)
+ if (q->read_ptr > q->write_ptr)
s -= q->n_bd;
if (s <= 0)
@@ -223,42 +220,55 @@ static int iwl_queue_space(const struct iwl_queue *q)
return s;
}
-/* XXX: n_bd must be power-of-two size */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
+/**
+ * iwl3945_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl3945_queue_inc_wrap(int index, int n_bd)
{
return ++index & (n_bd - 1);
}
-/* XXX: n_bd must be power-of-two size */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
+/**
+ * iwl3945_queue_dec_wrap - increment queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl3945_queue_dec_wrap(int index, int n_bd)
{
return --index & (n_bd - 1);
}
-static inline int x2_queue_used(const struct iwl_queue *q, int i)
+static inline int x2_queue_used(const struct iwl3945_queue *q, int i)
{
- return q->first_empty > q->last_used ?
- (i >= q->last_used && i < q->first_empty) :
- !(i < q->last_used && i >= q->first_empty);
+ return q->write_ptr > q->read_ptr ?
+ (i >= q->read_ptr && i < q->write_ptr) :
+ !(i < q->read_ptr && i >= q->write_ptr);
}
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
+static inline u8 get_cmd_index(struct iwl3945_queue *q, u32 index, int is_huge)
{
+ /* This is for scan command, the big buffer at end of command array */
if (is_huge)
- return q->n_window;
+ return q->n_window; /* must be power of 2 */
+ /* Otherwise, use normal size buffers */
return index & (q->n_window - 1);
}
-static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+/**
+ * iwl3945_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl3945_queue_init(struct iwl3945_priv *priv, struct iwl3945_queue *q,
int count, int slots_num, u32 id)
{
q->n_bd = count;
q->n_window = slots_num;
q->id = id;
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
- * and iwl_queue_dec_wrap are broken. */
+ /* count must be power-of-two size, otherwise iwl3945_queue_inc_wrap
+ * and iwl3945_queue_dec_wrap are broken. */
BUG_ON(!is_power_of_2(count));
/* slots_num must be power-of-two size, otherwise
@@ -273,27 +283,34 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
if (q->high_mark < 2)
q->high_mark = 2;
- q->first_empty = q->last_used = 0;
+ q->write_ptr = q->read_ptr = 0;
return 0;
}
-static int iwl_tx_queue_alloc(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, u32 id)
+/**
+ * iwl3945_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int iwl3945_tx_queue_alloc(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq, u32 id)
{
struct pci_dev *dev = priv->pci_dev;
+ /* Driver private data, only for Tx (not command) queues,
+ * not shared with device. */
if (id != IWL_CMD_QUEUE_NUM) {
txq->txb = kmalloc(sizeof(txq->txb[0]) *
TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
if (!txq->txb) {
- IWL_ERROR("kmalloc for auxilary BD "
+ IWL_ERROR("kmalloc for auxiliary BD "
"structures failed\n");
goto error;
}
} else
txq->txb = NULL;
+ /* Circular buffer of transmit frame descriptors (TFDs),
+ * shared with device */
txq->bd = pci_alloc_consistent(dev,
sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
&txq->q.dma_addr);
@@ -316,24 +333,33 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
return -ENOMEM;
}
-int iwl_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
+/**
+ * iwl3945_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+int iwl3945_tx_queue_init(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq, int slots_num, u32 txq_id)
{
struct pci_dev *dev = priv->pci_dev;
int len;
int rc = 0;
- /* alocate command space + one big command for scan since scan
- * command is very huge the system will not have two scan at the
- * same time */
- len = sizeof(struct iwl_cmd) * slots_num;
+ /*
+ * Alloc buffer array for commands (Tx or other types of commands).
+ * For the command queue (#4), allocate command space + one big
+ * command for scan, since scan command is very huge; the system will
+ * not have two scans at the same time, so only one is needed.
+ * For data Tx queues (all other queues), no super-size command
+ * space is needed.
+ */
+ len = sizeof(struct iwl3945_cmd) * slots_num;
if (txq_id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
if (!txq->cmd)
return -ENOMEM;
- rc = iwl_tx_queue_alloc(priv, txq, txq_id);
+ /* Alloc driver data array and TFD circular buffer */
+ rc = iwl3945_tx_queue_alloc(priv, txq, txq_id);
if (rc) {
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
@@ -342,26 +368,29 @@ int iwl_tx_queue_init(struct iwl_priv *priv,
txq->need_update = 0;
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ * iwl3945_queue_inc_wrap and iwl3945_queue_dec_wrap are broken. */
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
- iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
- iwl_hw_tx_queue_init(priv, txq);
+ /* Initialize queue high/low-water, head/tail indexes */
+ iwl3945_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+ /* Tell device where to find queue, enable DMA channel. */
+ iwl3945_hw_tx_queue_init(priv, txq);
return 0;
}
/**
- * iwl_tx_queue_free - Deallocate DMA queue.
+ * iwl3945_tx_queue_free - Deallocate DMA queue.
* @txq: Transmit queue to deallocate.
*
* Empty queue by removing and destroying all BD's.
- * Free all buffers. txq itself is not freed.
- *
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
*/
-void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+void iwl3945_tx_queue_free(struct iwl3945_priv *priv, struct iwl3945_tx_queue *txq)
{
- struct iwl_queue *q = &txq->q;
+ struct iwl3945_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev;
int len;
@@ -369,44 +398,47 @@ void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
return;
/* first, empty all BD's */
- for (; q->first_empty != q->last_used;
- q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd))
- iwl_hw_txq_free_tfd(priv, txq);
+ for (; q->write_ptr != q->read_ptr;
+ q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd))
+ iwl3945_hw_txq_free_tfd(priv, txq);
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl3945_cmd) * q->n_window;
if (q->id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
+ /* De-alloc array of command/tx buffers */
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
- /* free buffers belonging to queue itself */
+ /* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
+ pci_free_consistent(dev, sizeof(struct iwl3945_tfd_frame) *
txq->q.n_bd, txq->bd, txq->q.dma_addr);
+ /* De-alloc array of per-TFD driver data */
if (txq->txb) {
kfree(txq->txb);
txq->txb = NULL;
}
- /* 0 fill whole structure */
+ /* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
-const u8 BROADCAST_ADDR[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+const u8 iwl3945_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/*************** STATION TABLE MANAGEMENT ****
- *
- * NOTE: This needs to be overhauled to better synchronize between
- * how the iwl-4965.c is using iwl_hw_find_station vs. iwl-3945.c
- *
- * mac80211 should also be examined to determine if sta_info is duplicating
+ * mac80211 should be examined to determine if sta_info is duplicating
* the functionality provided here
*/
/**************************************************************/
-#if 0 /* temparary disable till we add real remove station */
-static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+#if 0 /* temporary disable till we add real remove station */
+/**
+ * iwl3945_remove_station - Remove driver's knowledge of station.
+ *
+ * NOTE: This does not remove station from device's station table.
+ */
+static u8 iwl3945_remove_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap)
{
int index = IWL_INVALID_STATION;
int i;
@@ -442,7 +474,13 @@ out:
return 0;
}
#endif
-static void iwl_clear_stations_table(struct iwl_priv *priv)
+
+/**
+ * iwl3945_clear_stations_table - Clear the driver's station table
+ *
+ * NOTE: This does not clear or otherwise alter the device's station table.
+ */
+static void iwl3945_clear_stations_table(struct iwl3945_priv *priv)
{
unsigned long flags;
@@ -454,12 +492,14 @@ static void iwl_clear_stations_table(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-
-u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
+/**
+ * iwl3945_add_station - Add station to station tables in driver and device
+ */
+u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8 flags)
{
int i;
int index = IWL_INVALID_STATION;
- struct iwl_station_entry *station;
+ struct iwl3945_station_entry *station;
unsigned long flags_spin;
DECLARE_MAC_BUF(mac);
u8 rate;
@@ -482,7 +522,7 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
index = i;
}
- /* These twh conditions has the same outcome but keep them separate
+ /* These two conditions has the same outcome but keep them separate
since they have different meaning */
if (unlikely(index == IWL_INVALID_STATION)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
@@ -500,30 +540,35 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
station->used = 1;
priv->num_stations++;
- memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
+ /* Set up the REPLY_ADD_STA command to send to device */
+ memset(&station->sta, 0, sizeof(struct iwl3945_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
station->sta.sta.sta_id = index;
station->sta.station_flags = 0;
- rate = (priv->phymode == MODE_IEEE80211A) ? IWL_RATE_6M_PLCP :
- IWL_RATE_1M_PLCP | priv->hw_setting.cck_flag;
+ if (priv->phymode == MODE_IEEE80211A)
+ rate = IWL_RATE_6M_PLCP;
+ else
+ rate = IWL_RATE_1M_PLCP;
/* Turn on both antennas for the station... */
station->sta.rate_n_flags =
- iwl_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
+ iwl3945_hw_set_rate_n_flags(rate, RATE_MCS_ANT_AB_MSK);
station->current_rate.rate_n_flags =
le16_to_cpu(station->sta.rate_n_flags);
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- iwl_send_add_station(priv, &station->sta, flags);
+
+ /* Add station to device's station table */
+ iwl3945_send_add_station(priv, &station->sta, flags);
return index;
}
/*************** DRIVER STATUS FUNCTIONS *****/
-static inline int iwl_is_ready(struct iwl_priv *priv)
+static inline int iwl3945_is_ready(struct iwl3945_priv *priv)
{
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
* set but EXIT_PENDING is not */
@@ -532,29 +577,29 @@ static inline int iwl_is_ready(struct iwl_priv *priv)
!test_bit(STATUS_EXIT_PENDING, &priv->status);
}
-static inline int iwl_is_alive(struct iwl_priv *priv)
+static inline int iwl3945_is_alive(struct iwl3945_priv *priv)
{
return test_bit(STATUS_ALIVE, &priv->status);
}
-static inline int iwl_is_init(struct iwl_priv *priv)
+static inline int iwl3945_is_init(struct iwl3945_priv *priv)
{
return test_bit(STATUS_INIT, &priv->status);
}
-static inline int iwl_is_rfkill(struct iwl_priv *priv)
+static inline int iwl3945_is_rfkill(struct iwl3945_priv *priv)
{
return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
test_bit(STATUS_RF_KILL_SW, &priv->status);
}
-static inline int iwl_is_ready_rf(struct iwl_priv *priv)
+static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
{
- if (iwl_is_rfkill(priv))
+ if (iwl3945_is_rfkill(priv))
return 0;
- return iwl_is_ready(priv);
+ return iwl3945_is_ready(priv);
}
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@@ -613,7 +658,7 @@ static const char *get_cmd_string(u8 cmd)
#define HOST_COMPLETE_TIMEOUT (HZ / 2)
/**
- * iwl_enqueue_hcmd - enqueue a uCode command
+ * iwl3945_enqueue_hcmd - enqueue a uCode command
* @priv: device private data point
* @cmd: a point to the ucode command structure
*
@@ -621,13 +666,13 @@ static const char *get_cmd_string(u8 cmd)
* failed. On success, it turns the index (> 0) of command in the
* command queue.
*/
-static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl3945_enqueue_hcmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
{
- struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
- struct iwl_queue *q = &txq->q;
- struct iwl_tfd_frame *tfd;
+ struct iwl3945_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl3945_queue *q = &txq->q;
+ struct iwl3945_tfd_frame *tfd;
u32 *control_flags;
- struct iwl_cmd *out_cmd;
+ struct iwl3945_cmd *out_cmd;
u32 idx;
u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
dma_addr_t phys_addr;
@@ -642,19 +687,19 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
!(cmd->meta.flags & CMD_SIZE_HUGE));
- if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ if (iwl3945_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERROR("No space for Tx\n");
return -ENOSPC;
}
spin_lock_irqsave(&priv->hcmd_lock, flags);
- tfd = &txq->bd[q->first_empty];
+ tfd = &txq->bd[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
control_flags = (u32 *) tfd;
- idx = get_cmd_index(q, q->first_empty, cmd->meta.flags & CMD_SIZE_HUGE);
+ idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
out_cmd = &txq->cmd[idx];
out_cmd->hdr.cmd = cmd->id;
@@ -666,13 +711,13 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
- INDEX_TO_SEQ(q->first_empty));
+ INDEX_TO_SEQ(q->write_ptr));
if (out_cmd->meta.flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
- offsetof(struct iwl_cmd, hdr);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
+ offsetof(struct iwl3945_cmd, hdr);
+ iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
pad = U32_PAD(cmd->len);
count = TFD_CTL_COUNT_GET(*control_flags);
@@ -682,17 +727,19 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
"%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- fix_size, q->first_empty, idx, IWL_CMD_QUEUE_NUM);
+ fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
txq->need_update = 1;
- q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
- ret = iwl_tx_queue_update_write_ptr(priv, txq);
+
+ /* Increment and update queue's write index */
+ q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
+ ret = iwl3945_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
return ret ? ret : idx;
}
-int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl3945_send_cmd_async(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
{
int ret;
@@ -707,16 +754,16 @@ int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EBUSY;
- ret = iwl_enqueue_hcmd(priv, cmd);
+ ret = iwl3945_enqueue_hcmd(priv, cmd);
if (ret < 0) {
- IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
+ IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
}
return 0;
}
-int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl3945_send_cmd_sync(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
{
int cmd_idx;
int ret;
@@ -738,10 +785,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (cmd->meta.flags & CMD_WANT_SKB)
cmd->meta.source = &cmd->meta;
- cmd_idx = iwl_enqueue_hcmd(priv, cmd);
+ cmd_idx = iwl3945_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
- IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
+ IWL_ERROR("Error sending %s: iwl3945_enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
goto out;
}
@@ -785,7 +832,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cancel:
if (cmd->meta.flags & CMD_WANT_SKB) {
- struct iwl_cmd *qcmd;
+ struct iwl3945_cmd *qcmd;
/* Cancel the CMD_WANT_SKB flag for the cmd in the
* TX cmd queue. Otherwise in case the cmd comes
@@ -804,47 +851,43 @@ out:
return ret;
}
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+int iwl3945_send_cmd(struct iwl3945_priv *priv, struct iwl3945_host_cmd *cmd)
{
- /* A command can not be asynchronous AND expect an SKB to be set. */
- BUG_ON((cmd->meta.flags & CMD_ASYNC) &&
- (cmd->meta.flags & CMD_WANT_SKB));
-
if (cmd->meta.flags & CMD_ASYNC)
- return iwl_send_cmd_async(priv, cmd);
+ return iwl3945_send_cmd_async(priv, cmd);
- return iwl_send_cmd_sync(priv, cmd);
+ return iwl3945_send_cmd_sync(priv, cmd);
}
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
+int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, const void *data)
{
- struct iwl_host_cmd cmd = {
+ struct iwl3945_host_cmd cmd = {
.id = id,
.len = len,
.data = data,
};
- return iwl_send_cmd_sync(priv, &cmd);
+ return iwl3945_send_cmd_sync(priv, &cmd);
}
-static int __must_check iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
+static int __must_check iwl3945_send_cmd_u32(struct iwl3945_priv *priv, u8 id, u32 val)
{
- struct iwl_host_cmd cmd = {
+ struct iwl3945_host_cmd cmd = {
.id = id,
.len = sizeof(val),
.data = &val,
};
- return iwl_send_cmd_sync(priv, &cmd);
+ return iwl3945_send_cmd_sync(priv, &cmd);
}
-int iwl_send_statistics_request(struct iwl_priv *priv)
+int iwl3945_send_statistics_request(struct iwl3945_priv *priv)
{
- return iwl_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
+ return iwl3945_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
}
/**
- * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
+ * iwl3945_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
* @channel: Any channel valid for the requested phymode
@@ -853,9 +896,9 @@ int iwl_send_statistics_request(struct iwl_priv *priv)
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the phymode
*/
-static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
+static int iwl3945_set_rxon_channel(struct iwl3945_priv *priv, u8 phymode, u16 channel)
{
- if (!iwl_get_channel_info(priv, phymode, channel)) {
+ if (!iwl3945_get_channel_info(priv, phymode, channel)) {
IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
channel, phymode);
return -EINVAL;
@@ -879,13 +922,13 @@ static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
}
/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
+ * iwl3945_check_rxon_cmd - validate RXON structure is valid
*
* NOTE: This is really only useful during development and can eventually
* be #ifdef'd out once the driver is stable and folks aren't actively
* making changes
*/
-static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
+static int iwl3945_check_rxon_cmd(struct iwl3945_rxon_cmd *rxon)
{
int error = 0;
int counter = 1;
@@ -951,21 +994,21 @@ static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
le16_to_cpu(rxon->channel));
if (error) {
- IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
+ IWL_ERROR("Not a valid iwl3945_rxon_assoc_cmd field values\n");
return -1;
}
return 0;
}
/**
- * iwl_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
- * @priv: staging_rxon is comapred to active_rxon
+ * iwl3945_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * @priv: staging_rxon is compared to active_rxon
*
- * If the RXON structure is changing sufficient to require a new
- * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
- * to indicate a new tune is required.
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
*/
-static int iwl_full_rxon_required(struct iwl_priv *priv)
+static int iwl3945_full_rxon_required(struct iwl3945_priv *priv)
{
/* These items are only settable from the full RXON command */
@@ -1000,19 +1043,19 @@ static int iwl_full_rxon_required(struct iwl_priv *priv)
return 0;
}
-static int iwl_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl3945_send_rxon_assoc(struct iwl3945_priv *priv)
{
int rc = 0;
- struct iwl_rx_packet *res = NULL;
- struct iwl_rxon_assoc_cmd rxon_assoc;
- struct iwl_host_cmd cmd = {
+ struct iwl3945_rx_packet *res = NULL;
+ struct iwl3945_rxon_assoc_cmd rxon_assoc;
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_RXON_ASSOC,
.len = sizeof(rxon_assoc),
.meta.flags = CMD_WANT_SKB,
.data = &rxon_assoc,
};
- const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl3945_rxon_cmd *rxon1 = &priv->staging_rxon;
+ const struct iwl3945_rxon_cmd *rxon2 = &priv->active_rxon;
if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -1028,11 +1071,11 @@ static int iwl_send_rxon_assoc(struct iwl_priv *priv)
rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
rxon_assoc.reserved = 0;
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl3945_send_cmd_sync(priv, &cmd);
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
rc = -EIO;
@@ -1045,21 +1088,21 @@ static int iwl_send_rxon_assoc(struct iwl_priv *priv)
}
/**
- * iwl_commit_rxon - commit staging_rxon to hardware
+ * iwl3945_commit_rxon - commit staging_rxon to hardware
*
- * The RXON command in staging_rxon is commited to the hardware and
+ * The RXON command in staging_rxon is committed to the hardware and
* the active_rxon structure is updated with the new data. This
* function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes.
*/
-static int iwl_commit_rxon(struct iwl_priv *priv)
+static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
{
/* cast away the const for active_rxon in this function */
- struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
int rc = 0;
DECLARE_MAC_BUF(mac);
- if (!iwl_is_alive(priv))
+ if (!iwl3945_is_alive(priv))
return -1;
/* always get timestamp with Rx frame */
@@ -1070,17 +1113,17 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
priv->staging_rxon.flags |= iwl3945_get_antenna_flags(priv);
- rc = iwl_check_rxon_cmd(&priv->staging_rxon);
+ rc = iwl3945_check_rxon_cmd(&priv->staging_rxon);
if (rc) {
IWL_ERROR("Invalid RXON configuration. Not committing.\n");
return -EINVAL;
}
/* If we don't need to send a full RXON, we can use
- * iwl_rxon_assoc_cmd which is used to reconfigure filter
+ * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
- if (!iwl_full_rxon_required(priv)) {
- rc = iwl_send_rxon_assoc(priv);
+ if (!iwl3945_full_rxon_required(priv)) {
+ rc = iwl3945_send_rxon_assoc(priv);
if (rc) {
IWL_ERROR("Error setting RXON_ASSOC "
"configuration (%d).\n", rc);
@@ -1096,13 +1139,13 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) &&
+ if (iwl3945_is_associated(priv) &&
(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd),
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl3945_rxon_cmd),
&priv->active_rxon);
/* If the mask clearing failed then we set
@@ -1125,8 +1168,8 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
print_mac(mac, priv->staging_rxon.bssid_addr));
/* Apply the new configuration */
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl3945_rxon_cmd), &priv->staging_rxon);
if (rc) {
IWL_ERROR("Error setting new configuration (%d).\n", rc);
return rc;
@@ -1134,18 +1177,18 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
- iwl_clear_stations_table(priv);
+ iwl3945_clear_stations_table(priv);
/* If we issue a new RXON command which required a tune then we must
* send a new TXPOWER command or we won't be able to Tx any frames */
- rc = iwl_hw_reg_send_txpower(priv);
+ rc = iwl3945_hw_reg_send_txpower(priv);
if (rc) {
IWL_ERROR("Error setting Tx power (%d).\n", rc);
return rc;
}
/* Add the broadcast address so we can send broadcast frames */
- if (iwl_add_station(priv, BROADCAST_ADDR, 0, 0) ==
+ if (iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0) ==
IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
@@ -1153,9 +1196,9 @@ static int iwl_commit_rxon(struct iwl_priv *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 */
- if (iwl_is_associated(priv) &&
+ if (iwl3945_is_associated(priv) &&
(priv->iw_mode == IEEE80211_IF_TYPE_STA))
- if (iwl_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
+ if (iwl3945_add_station(priv, priv->active_rxon.bssid_addr, 1, 0)
== IWL_INVALID_STATION) {
IWL_ERROR("Error adding AP address for transmit.\n");
return -EIO;
@@ -1172,9 +1215,9 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
return 0;
}
-static int iwl_send_bt_config(struct iwl_priv *priv)
+static int iwl3945_send_bt_config(struct iwl3945_priv *priv)
{
- struct iwl_bt_cmd bt_cmd = {
+ struct iwl3945_bt_cmd bt_cmd = {
.flags = 3,
.lead_time = 0xAA,
.max_kill = 1,
@@ -1182,15 +1225,15 @@ static int iwl_send_bt_config(struct iwl_priv *priv)
.kill_cts_mask = 0,
};
- return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl_bt_cmd), &bt_cmd);
+ return iwl3945_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ sizeof(struct iwl3945_bt_cmd), &bt_cmd);
}
-static int iwl_send_scan_abort(struct iwl_priv *priv)
+static int iwl3945_send_scan_abort(struct iwl3945_priv *priv)
{
int rc = 0;
- struct iwl_rx_packet *res;
- struct iwl_host_cmd cmd = {
+ struct iwl3945_rx_packet *res;
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
.meta.flags = CMD_WANT_SKB,
};
@@ -1203,13 +1246,13 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
return 0;
}
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl3945_send_cmd_sync(priv, &cmd);
if (rc) {
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
return rc;
}
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
if (res->u.status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
@@ -1227,8 +1270,8 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
return rc;
}
-static int iwl_card_state_sync_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+static int iwl3945_card_state_sync_callback(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd,
struct sk_buff *skb)
{
return 1;
@@ -1237,16 +1280,16 @@ static int iwl_card_state_sync_callback(struct iwl_priv *priv,
/*
* CARD_STATE_CMD
*
- * Use: Sets the internal card state to enable, disable, or halt
+ * Use: Sets the device's internal card state to enable, disable, or halt
*
* When in the 'enable' state the card operates as normal.
* When in the 'disable' state, the card enters into a low power mode.
* When in the 'halt' state, the card is shut down and must be fully
* restarted to come back on.
*/
-static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+static int iwl3945_send_card_state(struct iwl3945_priv *priv, u32 flags, u8 meta_flag)
{
- struct iwl_host_cmd cmd = {
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32),
.data = &flags,
@@ -1254,22 +1297,22 @@ static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
};
if (meta_flag & CMD_ASYNC)
- cmd.meta.u.callback = iwl_card_state_sync_callback;
+ cmd.meta.u.callback = iwl3945_card_state_sync_callback;
- return iwl_send_cmd(priv, &cmd);
+ return iwl3945_send_cmd(priv, &cmd);
}
-static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static int iwl3945_add_sta_sync_callback(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd, struct sk_buff *skb)
{
- struct iwl_rx_packet *res = NULL;
+ struct iwl3945_rx_packet *res = NULL;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
return 1;
}
- res = (struct iwl_rx_packet *)skb->data;
+ res = (struct iwl3945_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -1287,29 +1330,29 @@ static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
return 1;
}
-int iwl_send_add_station(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags)
+int iwl3945_send_add_station(struct iwl3945_priv *priv,
+ struct iwl3945_addsta_cmd *sta, u8 flags)
{
- struct iwl_rx_packet *res = NULL;
+ struct iwl3945_rx_packet *res = NULL;
int rc = 0;
- struct iwl_host_cmd cmd = {
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_ADD_STA,
- .len = sizeof(struct iwl_addsta_cmd),
+ .len = sizeof(struct iwl3945_addsta_cmd),
.meta.flags = flags,
.data = sta,
};
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_add_sta_sync_callback;
+ cmd.meta.u.callback = iwl3945_add_sta_sync_callback;
else
cmd.meta.flags |= CMD_WANT_SKB;
- rc = iwl_send_cmd(priv, &cmd);
+ rc = iwl3945_send_cmd(priv, &cmd);
if (rc || (flags & CMD_ASYNC))
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -1334,7 +1377,7 @@ int iwl_send_add_station(struct iwl_priv *priv,
return rc;
}
-static int iwl_update_sta_key_info(struct iwl_priv *priv,
+static int iwl3945_update_sta_key_info(struct iwl3945_priv *priv,
struct ieee80211_key_conf *keyconf,
u8 sta_id)
{
@@ -1350,7 +1393,6 @@ static int iwl_update_sta_key_info(struct iwl_priv *priv,
break;
case ALG_TKIP:
case ALG_WEP:
- return -EINVAL;
default:
return -EINVAL;
}
@@ -1369,28 +1411,28 @@ static int iwl_update_sta_key_info(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+ iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0);
return 0;
}
-static int iwl_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
+static int iwl3945_clear_sta_key_info(struct iwl3945_priv *priv, u8 sta_id)
{
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
- memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
- memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl_keyinfo));
+ memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key));
+ memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl3945_keyinfo));
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+ iwl3945_send_add_station(priv, &priv->stations[sta_id].sta, 0);
return 0;
}
-static void iwl_clear_free_frames(struct iwl_priv *priv)
+static void iwl3945_clear_free_frames(struct iwl3945_priv *priv)
{
struct list_head *element;
@@ -1400,7 +1442,7 @@ static void iwl_clear_free_frames(struct iwl_priv *priv)
while (!list_empty(&priv->free_frames)) {
element = priv->free_frames.next;
list_del(element);
- kfree(list_entry(element, struct iwl_frame, list));
+ kfree(list_entry(element, struct iwl3945_frame, list));
priv->frames_count--;
}
@@ -1411,9 +1453,9 @@ static void iwl_clear_free_frames(struct iwl_priv *priv)
}
}
-static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
+static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl3945_priv *priv)
{
- struct iwl_frame *frame;
+ struct iwl3945_frame *frame;
struct list_head *element;
if (list_empty(&priv->free_frames)) {
frame = kzalloc(sizeof(*frame), GFP_KERNEL);
@@ -1428,21 +1470,21 @@ static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
element = priv->free_frames.next;
list_del(element);
- return list_entry(element, struct iwl_frame, list);
+ return list_entry(element, struct iwl3945_frame, list);
}
-static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
+static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame *frame)
{
memset(frame, 0, sizeof(*frame));
list_add(&frame->list, &priv->free_frames);
}
-unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
+unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr,
const u8 *dest, int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
+ if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
(priv->iw_mode != IEEE80211_IF_TYPE_AP)))
return 0;
@@ -1455,37 +1497,27 @@ unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
return priv->ibss_beacon->len;
}
-static int iwl_rate_index_from_plcp(int plcp)
-{
- int i = 0;
-
- for (i = 0; i < IWL_RATE_COUNT; i++)
- if (iwl_rates[i].plcp == plcp)
- return i;
- return -1;
-}
-
-static u8 iwl_rate_get_lowest_plcp(int rate_mask)
+static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
{
u8 i;
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
- i = iwl_rates[i].next_ieee) {
+ i = iwl3945_rates[i].next_ieee) {
if (rate_mask & (1 << i))
- return iwl_rates[i].plcp;
+ return iwl3945_rates[i].plcp;
}
return IWL_RATE_INVALID;
}
-static int iwl_send_beacon_cmd(struct iwl_priv *priv)
+static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
{
- struct iwl_frame *frame;
+ struct iwl3945_frame *frame;
unsigned int frame_size;
int rc;
u8 rate;
- frame = iwl_get_free_frame(priv);
+ frame = iwl3945_get_free_frame(priv);
if (!frame) {
IWL_ERROR("Could not obtain free frame buffer for beacon "
@@ -1494,22 +1526,22 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
}
if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
- rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic &
+ rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic &
0xFF0);
if (rate == IWL_INVALID_RATE)
rate = IWL_RATE_6M_PLCP;
} else {
- rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
+ rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
if (rate == IWL_INVALID_RATE)
rate = IWL_RATE_1M_PLCP;
}
- frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
+ frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
- rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
&frame->u.cmd[0]);
- iwl_free_frame(priv, frame);
+ iwl3945_free_frame(priv, frame);
return rc;
}
@@ -1520,22 +1552,22 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
*
******************************************************************************/
-static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac)
+static void get_eeprom_mac(struct iwl3945_priv *priv, u8 *mac)
{
memcpy(mac, priv->eeprom.mac_address, 6);
}
/**
- * iwl_eeprom_init - read EEPROM contents
+ * iwl3945_eeprom_init - read EEPROM contents
*
- * Load the EEPROM from adapter into priv->eeprom
+ * Load the EEPROM contents from adapter into priv->eeprom
*
* NOTE: This routine uses the non-debug IO access functions.
*/
-int iwl_eeprom_init(struct iwl_priv *priv)
+int iwl3945_eeprom_init(struct iwl3945_priv *priv)
{
- u16 *e = (u16 *)&priv->eeprom;
- u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
+ __le16 *e = (__le16 *)&priv->eeprom;
+ u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
u32 r;
int sz = sizeof(priv->eeprom);
int rc;
@@ -1553,20 +1585,21 @@ int iwl_eeprom_init(struct iwl_priv *priv)
return -ENOENT;
}
- rc = iwl_eeprom_aqcuire_semaphore(priv);
+ /* Make sure driver (instead of uCode) is allowed to read EEPROM */
+ rc = iwl3945_eeprom_acquire_semaphore(priv);
if (rc < 0) {
- IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n");
+ IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
return -ENOENT;
}
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
- _iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
- _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+ _iwl3945_write32(priv, CSR_EEPROM_REG, addr << 1);
+ _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
i += IWL_EEPROM_ACCESS_DELAY) {
- r = _iwl_read_restricted(priv, CSR_EEPROM_REG);
+ r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
if (r & CSR_EEPROM_REG_READ_VALID_MSK)
break;
udelay(IWL_EEPROM_ACCESS_DELAY);
@@ -1576,7 +1609,7 @@ int iwl_eeprom_init(struct iwl_priv *priv)
IWL_ERROR("Time out reading EEPROM[%d]", addr);
return -ETIMEDOUT;
}
- e[addr / 2] = le16_to_cpu(r >> 16);
+ e[addr / 2] = cpu_to_le16(r >> 16);
}
return 0;
@@ -1587,22 +1620,17 @@ int iwl_eeprom_init(struct iwl_priv *priv)
* Misc. internal state and helper functions
*
******************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL3945_DEBUG
/**
- * iwl_report_frame - dump frame to syslog during debug sessions
+ * iwl3945_report_frame - dump frame to syslog during debug sessions
*
- * hack this function to show different aspects of received frames,
+ * You may hack this function to show different aspects of received frames,
* including selective frame dumps.
* group100 parameter selects whether to show 1 out of 100 good frames.
- *
- * TODO: ieee80211_hdr stuff is common to 3945 and 4965, so frame type
- * info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats)
- * is 3945-specific and gives bad output for 4965. Need to split the
- * functionality, keep common stuff here.
*/
-void iwl_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
+void iwl3945_report_frame(struct iwl3945_priv *priv,
+ struct iwl3945_rx_packet *pkt,
struct ieee80211_hdr *header, int group100)
{
u32 to_us;
@@ -1624,9 +1652,9 @@ void iwl_report_frame(struct iwl_priv *priv,
u8 agc;
u16 sig_avg;
u16 noise_diff;
- struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
+ struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
u8 *data = IWL_RX_DATA(pkt);
/* MAC header */
@@ -1702,11 +1730,11 @@ void iwl_report_frame(struct iwl_priv *priv,
else
title = "Frame";
- rate = iwl_rate_index_from_plcp(rate_sym);
+ rate = iwl3945_rate_index_from_plcp(rate_sym);
if (rate == -1)
rate = 0;
else
- rate = iwl_rates[rate].ieee / 2;
+ rate = iwl3945_rates[rate].ieee / 2;
/* print frame summary.
* MAC addresses show just the last byte (for brevity),
@@ -1728,25 +1756,25 @@ void iwl_report_frame(struct iwl_priv *priv,
}
}
if (print_dump)
- iwl_print_hex_dump(IWL_DL_RX, data, length);
+ iwl3945_print_hex_dump(IWL_DL_RX, data, length);
}
#endif
-static void iwl_unset_hw_setting(struct iwl_priv *priv)
+static void iwl3945_unset_hw_setting(struct iwl3945_priv *priv)
{
if (priv->hw_setting.shared_virt)
pci_free_consistent(priv->pci_dev,
- sizeof(struct iwl_shared),
+ sizeof(struct iwl3945_shared),
priv->hw_setting.shared_virt,
priv->hw_setting.shared_phys);
}
/**
- * iwl_supported_rate_to_ie - fill in the supported rate in IE field
+ * iwl3945_supported_rate_to_ie - fill in the supported rate in IE field
*
* return : set the bit for each supported rate insert in ie
*/
-static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
+static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate,
u16 basic_rate, int *left)
{
u16 ret_rates = 0, bit;
@@ -1757,7 +1785,7 @@ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*cnt] = iwl_rates[i].ieee |
+ rates[*cnt] = iwl3945_rates[i].ieee |
((bit & basic_rate) ? 0x80 : 0x00);
(*cnt)++;
(*left)--;
@@ -1771,9 +1799,9 @@ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
}
/**
- * iwl_fill_probe_req - fill in all required fields and IE for probe request
+ * iwl3945_fill_probe_req - fill in all required fields and IE for probe request
*/
-static u16 iwl_fill_probe_req(struct iwl_priv *priv,
+static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
struct ieee80211_mgmt *frame,
int left, int is_direct)
{
@@ -1789,9 +1817,9 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
len += 24;
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
- memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN);
+ memcpy(frame->da, iwl3945_broadcast_addr, ETH_ALEN);
memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
- memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN);
+ memcpy(frame->bssid, iwl3945_broadcast_addr, ETH_ALEN);
frame->seq_ctrl = 0;
/* fill in our indirect SSID IE */
@@ -1834,11 +1862,11 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
cck_rates = IWL_CCK_RATES_MASK & active_rates;
- ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
+ ret_rates = iwl3945_supported_rate_to_ie(pos, cck_rates,
priv->active_rate_basic, &left);
active_rates &= ~ret_rates;
- ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
+ ret_rates = iwl3945_supported_rate_to_ie(pos, active_rates,
priv->active_rate_basic, &left);
active_rates &= ~ret_rates;
@@ -1855,7 +1883,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0;
- iwl_supported_rate_to_ie(pos, active_rates,
+ iwl3945_supported_rate_to_ie(pos, active_rates,
priv->active_rate_basic, &left);
if (*pos > 0)
len += 2 + *pos;
@@ -1867,16 +1895,16 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/*
* QoS support
*/
-#ifdef CONFIG_IWLWIFI_QOS
-static int iwl_send_qos_params_command(struct iwl_priv *priv,
- struct iwl_qosparam_cmd *qos)
+#ifdef CONFIG_IWL3945_QOS
+static int iwl3945_send_qos_params_command(struct iwl3945_priv *priv,
+ struct iwl3945_qosparam_cmd *qos)
{
- return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
- sizeof(struct iwl_qosparam_cmd), qos);
+ return iwl3945_send_cmd_pdu(priv, REPLY_QOS_PARAM,
+ sizeof(struct iwl3945_qosparam_cmd), qos);
}
-static void iwl_reset_qos(struct iwl_priv *priv)
+static void iwl3945_reset_qos(struct iwl3945_priv *priv)
{
u16 cw_min = 15;
u16 cw_max = 1023;
@@ -1963,13 +1991,10 @@ static void iwl_reset_qos(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
+static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
{
unsigned long flags;
- if (priv == NULL)
- return;
-
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -1990,16 +2015,16 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
spin_unlock_irqrestore(&priv->lock, flags);
- if (force || iwl_is_associated(priv)) {
+ if (force || iwl3945_is_associated(priv)) {
IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
priv->qos_data.qos_active);
- iwl_send_qos_params_command(priv,
+ iwl3945_send_qos_params_command(priv,
&(priv->qos_data.def_qos_parm));
}
}
-#endif /* CONFIG_IWLWIFI_QOS */
+#endif /* CONFIG_IWL3945_QOS */
/*
* Power management (not Tx power!) functions
*/
@@ -2017,7 +2042,7 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
/* default power management (not Tx power) table values */
/* for tim 0-10 */
-static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
+static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
@@ -2027,7 +2052,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
};
/* for tim > 10 */
-static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
+static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
@@ -2040,11 +2065,11 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};
-int iwl_power_init_handle(struct iwl_priv *priv)
+int iwl3945_power_init_handle(struct iwl3945_priv *priv)
{
int rc = 0, i;
- struct iwl_power_mgr *pow_data;
- int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
+ struct iwl3945_power_mgr *pow_data;
+ int size = sizeof(struct iwl3945_power_vec_entry) * IWL_POWER_AC;
u16 pci_pm;
IWL_DEBUG_POWER("Initialize power \n");
@@ -2063,7 +2088,7 @@ int iwl_power_init_handle(struct iwl_priv *priv)
if (rc != 0)
return 0;
else {
- struct iwl_powertable_cmd *cmd;
+ struct iwl3945_powertable_cmd *cmd;
IWL_DEBUG_POWER("adjust power command flags\n");
@@ -2079,15 +2104,15 @@ int iwl_power_init_handle(struct iwl_priv *priv)
return rc;
}
-static int iwl_update_power_cmd(struct iwl_priv *priv,
- struct iwl_powertable_cmd *cmd, u32 mode)
+static int iwl3945_update_power_cmd(struct iwl3945_priv *priv,
+ struct iwl3945_powertable_cmd *cmd, u32 mode)
{
int rc = 0, i;
u8 skip;
u32 max_sleep = 0;
- struct iwl_power_vec_entry *range;
+ struct iwl3945_power_vec_entry *range;
u8 period = 0;
- struct iwl_power_mgr *pow_data;
+ struct iwl3945_power_mgr *pow_data;
if (mode > IWL_POWER_INDEX_5) {
IWL_DEBUG_POWER("Error invalid power mode \n");
@@ -2100,7 +2125,7 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
else
range = &pow_data->pwr_range_1[1];
- memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
+ memcpy(cmd, &range[mode].cmd, sizeof(struct iwl3945_powertable_cmd));
#ifdef IWL_MAC80211_DISABLE
if (priv->assoc_network != NULL) {
@@ -2143,14 +2168,14 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
return rc;
}
-static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
+static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode)
{
- u32 final_mode = mode;
+ u32 uninitialized_var(final_mode);
int rc;
- struct iwl_powertable_cmd cmd;
+ struct iwl3945_powertable_cmd cmd;
/* If on battery, set to 3,
- * if plugged into AC power, set to CAM ("continuosly aware mode"),
+ * if plugged into AC power, set to CAM ("continuously aware mode"),
* else user level */
switch (mode) {
case IWL_POWER_BATTERY:
@@ -2164,9 +2189,9 @@ static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
break;
}
- iwl_update_power_cmd(priv, &cmd, final_mode);
+ iwl3945_update_power_cmd(priv, &cmd, final_mode);
- rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
+ rc = iwl3945_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
if (final_mode == IWL_POWER_MODE_CAM)
clear_bit(STATUS_POWER_PMI, &priv->status);
@@ -2176,7 +2201,7 @@ static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
return rc;
}
-int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
{
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
@@ -2206,7 +2231,7 @@ int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-const char *iwl_get_tx_fail_reason(u32 status)
+static const char *iwl3945_get_tx_fail_reason(u32 status)
{
switch (status & TX_STATUS_MSK) {
case TX_STATUS_SUCCESS:
@@ -2233,11 +2258,11 @@ const char *iwl_get_tx_fail_reason(u32 status)
}
/**
- * iwl_scan_cancel - Cancel any currently executing HW scan
+ * iwl3945_scan_cancel - Cancel any currently executing HW scan
*
* NOTE: priv->mutex is not required before calling this function
*/
-static int iwl_scan_cancel(struct iwl_priv *priv)
+static int iwl3945_scan_cancel(struct iwl3945_priv *priv)
{
if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
clear_bit(STATUS_SCANNING, &priv->status);
@@ -2260,17 +2285,17 @@ static int iwl_scan_cancel(struct iwl_priv *priv)
}
/**
- * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
+ * iwl3945_scan_cancel_timeout - Cancel any currently executing HW scan
* @ms: amount of time to wait (in milliseconds) for scan to abort
*
* NOTE: priv->mutex must be held before calling this function
*/
-static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long ms)
{
unsigned long now = jiffies;
int ret;
- ret = iwl_scan_cancel(priv);
+ ret = iwl3945_scan_cancel(priv);
if (ret && ms) {
mutex_unlock(&priv->mutex);
while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
@@ -2284,7 +2309,7 @@ static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
return ret;
}
-static void iwl_sequence_reset(struct iwl_priv *priv)
+static void iwl3945_sequence_reset(struct iwl3945_priv *priv)
{
/* Reset ieee stats */
@@ -2295,13 +2320,13 @@ static void iwl_sequence_reset(struct iwl_priv *priv)
priv->last_frag_num = -1;
priv->last_packet_time = 0;
- iwl_scan_cancel(priv);
+ iwl3945_scan_cancel(priv);
}
#define MAX_UCODE_BEACON_INTERVAL 1024
#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA)
-static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
+static __le16 iwl3945_adjust_beacon_interval(u16 beacon_val)
{
u16 new_val = 0;
u16 beacon_factor = 0;
@@ -2314,7 +2339,7 @@ static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
return cpu_to_le16(new_val);
}
-static void iwl_setup_rxon_timing(struct iwl_priv *priv)
+static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
{
u64 interval_tm_unit;
u64 tsf, result;
@@ -2344,14 +2369,14 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv)
priv->rxon_timing.beacon_interval =
cpu_to_le16(beacon_int);
priv->rxon_timing.beacon_interval =
- iwl_adjust_beacon_interval(
+ iwl3945_adjust_beacon_interval(
le16_to_cpu(priv->rxon_timing.beacon_interval));
}
priv->rxon_timing.atim_window = 0;
} else {
priv->rxon_timing.beacon_interval =
- iwl_adjust_beacon_interval(conf->beacon_int);
+ iwl3945_adjust_beacon_interval(conf->beacon_int);
/* TODO: we need to get atim_window from upper stack
* for now we set to 0 */
priv->rxon_timing.atim_window = 0;
@@ -2370,14 +2395,14 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv)
le16_to_cpu(priv->rxon_timing.atim_window));
}
-static int iwl_scan_initiate(struct iwl_priv *priv)
+static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
}
@@ -2404,9 +2429,9 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
return 0;
}
-static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+static int iwl3945_set_rxon_hwcrypto(struct iwl3945_priv *priv, int hw_decrypt)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl3945_rxon_cmd *rxon = &priv->staging_rxon;
if (hw_decrypt)
rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -2416,7 +2441,7 @@ static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
return 0;
}
-static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
+static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode)
{
if (phymode == MODE_IEEE80211A) {
priv->staging_rxon.flags &=
@@ -2424,7 +2449,7 @@ static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
| RXON_FLG_CCK_MSK);
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
} else {
- /* Copied from iwl_bg_post_associate() */
+ /* Copied from iwl3945_bg_post_associate() */
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
@@ -2440,11 +2465,11 @@ static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
}
/*
- * initilize rxon structure with default values fromm eeprom
+ * initialize rxon structure with default values from eeprom
*/
-static void iwl_connection_init_rx_config(struct iwl_priv *priv)
+static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
{
- const struct iwl_channel_info *ch_info;
+ const struct iwl3945_channel_info *ch_info;
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
@@ -2481,7 +2506,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
- ch_info = iwl_get_channel_info(priv, priv->phymode,
+ ch_info = iwl3945_get_channel_info(priv, priv->phymode,
le16_to_cpu(priv->staging_rxon.channel));
if (!ch_info)
@@ -2501,7 +2526,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
else
priv->phymode = MODE_IEEE80211G;
- iwl_set_flags_for_phymode(priv, priv->phymode);
+ iwl3945_set_flags_for_phymode(priv, priv->phymode);
priv->staging_rxon.ofdm_basic_rates =
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
@@ -2509,15 +2534,12 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
(IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
}
-static int iwl_set_mode(struct iwl_priv *priv, int mode)
+static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
{
- if (!iwl_is_ready_rf(priv))
- return -EAGAIN;
-
if (mode == IEEE80211_IF_TYPE_IBSS) {
- const struct iwl_channel_info *ch_info;
+ const struct iwl3945_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv,
+ ch_info = iwl3945_get_channel_info(priv,
priv->phymode,
le16_to_cpu(priv->staging_rxon.channel));
@@ -2528,32 +2550,36 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode)
}
}
+ priv->iw_mode = mode;
+
+ iwl3945_connection_init_rx_config(priv);
+ memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+
+ iwl3945_clear_stations_table(priv);
+
+ /* dont commit rxon if rf-kill is on*/
+ if (!iwl3945_is_ready_rf(priv))
+ return -EAGAIN;
+
cancel_delayed_work(&priv->scan_check);
- if (iwl_scan_cancel_timeout(priv, 100)) {
+ if (iwl3945_scan_cancel_timeout(priv, 100)) {
IWL_WARNING("Aborted scan still in progress after 100ms\n");
IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
return -EAGAIN;
}
- priv->iw_mode = mode;
-
- iwl_connection_init_rx_config(priv);
- memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
-
- iwl_clear_stations_table(priv);
-
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
return 0;
}
-static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
struct ieee80211_tx_control *ctl,
- struct iwl_cmd *cmd,
+ struct iwl3945_cmd *cmd,
struct sk_buff *skb_frag,
int last_frag)
{
- struct iwl_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
+ struct iwl3945_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
switch (keyinfo->alg) {
case ALG_CCMP:
@@ -2596,8 +2622,8 @@ static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
/*
* handle build REPLY_TX command notification.
*/
-static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
+ struct iwl3945_cmd *cmd,
struct ieee80211_tx_control *ctrl,
struct ieee80211_hdr *hdr,
int is_unicast, u8 std_id)
@@ -2645,11 +2671,9 @@ static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
- cmd->cmd.tx.timeout.pm_frame_timeout =
- cpu_to_le16(3);
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
else
- cmd->cmd.tx.timeout.pm_frame_timeout =
- cpu_to_le16(2);
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
} else
cmd->cmd.tx.timeout.pm_frame_timeout = 0;
@@ -2658,41 +2682,44 @@ static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
cmd->cmd.tx.next_frame_len = 0;
}
-static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+/**
+ * iwl3945_get_sta_id - Find station's index within station table
+ */
+static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *hdr)
{
int sta_id;
u16 fc = le16_to_cpu(hdr->frame_control);
- /* If this frame is broadcast or not data then use the broadcast
- * station id */
+ /* If this frame is broadcast or management, use broadcast station id */
if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
is_multicast_ether_addr(hdr->addr1))
return priv->hw_setting.bcast_sta_id;
switch (priv->iw_mode) {
- /* If this frame is part of a BSS network (we're a station), then
- * we use the AP's station id */
+ /* If we are a client station in a BSS network, use the special
+ * AP station entry (that's the only station we communicate with) */
case IEEE80211_IF_TYPE_STA:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
case IEEE80211_IF_TYPE_AP:
- sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
return priv->hw_setting.bcast_sta_id;
- /* If this frame is part of a IBSS network, then we use the
- * target specific station id */
+ /* If this frame is going out to an IBSS network, find the station,
+ * or create a new station table entry */
case IEEE80211_IF_TYPE_IBSS: {
DECLARE_MAC_BUF(mac);
- sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ /* Create new station table entry */
+ sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- sta_id = iwl_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
+ sta_id = iwl3945_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@@ -2700,11 +2727,11 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
IWL_DEBUG_DROP("Station %s not in station map. "
"Defaulting to broadcast...\n",
print_mac(mac, hdr->addr1));
- iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+ iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
}
default:
- IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode);
+ IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
return priv->hw_setting.bcast_sta_id;
}
}
@@ -2712,18 +2739,18 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/*
* start REPLY_TX command process
*/
-static int iwl_tx_skb(struct iwl_priv *priv,
+static int iwl3945_tx_skb(struct iwl3945_priv *priv,
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_tfd_frame *tfd;
+ struct iwl3945_tfd_frame *tfd;
u32 *control_flags;
int txq_id = ctl->queue;
- struct iwl_tx_queue *txq = NULL;
- struct iwl_queue *q = NULL;
+ struct iwl3945_tx_queue *txq = NULL;
+ struct iwl3945_queue *q = NULL;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
- struct iwl_cmd *out_cmd = NULL;
+ struct iwl3945_cmd *out_cmd = NULL;
u16 len, idx, len_org;
u8 id, hdr_len, unicast;
u8 sta_id;
@@ -2735,13 +2762,13 @@ static int iwl_tx_skb(struct iwl_priv *priv,
int rc;
spin_lock_irqsave(&priv->lock, flags);
- if (iwl_is_rfkill(priv)) {
+ if (iwl3945_is_rfkill(priv)) {
IWL_DEBUG_DROP("Dropping - RF KILL\n");
goto drop_unlock;
}
- if (!priv->interface_id) {
- IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
+ if (!priv->vif) {
+ IWL_DEBUG_DROP("Dropping - !priv->vif\n");
goto drop_unlock;
}
@@ -2755,7 +2782,7 @@ static int iwl_tx_skb(struct iwl_priv *priv,
fc = le16_to_cpu(hdr->frame_control);
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL3945_DEBUG
if (ieee80211_is_auth(fc))
IWL_DEBUG_TX("Sending AUTH frame\n");
else if (ieee80211_is_assoc_request(fc))
@@ -2764,16 +2791,19 @@ static int iwl_tx_skb(struct iwl_priv *priv,
IWL_DEBUG_TX("Sending REASSOC frame\n");
#endif
- if (!iwl_is_associated(priv) &&
+ /* drop all data frame if we are not associated */
+ if (!iwl3945_is_associated(priv) && !priv->assoc_id &&
((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
- IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
+ IWL_DEBUG_DROP("Dropping - !iwl3945_is_associated\n");
goto drop_unlock;
}
spin_unlock_irqrestore(&priv->lock, flags);
hdr_len = ieee80211_get_hdrlen(fc);
- sta_id = iwl_get_sta_id(priv, hdr);
+
+ /* Find (or create) index into station table for destination station */
+ sta_id = iwl3945_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
DECLARE_MAC_BUF(mac);
@@ -2794,32 +2824,54 @@ static int iwl_tx_skb(struct iwl_priv *priv,
__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
seq_number += 0x10;
}
+
+ /* Descriptor for chosen Tx queue */
txq = &priv->txq[txq_id];
q = &txq->q;
spin_lock_irqsave(&priv->lock, flags);
- tfd = &txq->bd[q->first_empty];
+ /* Set up first empty TFD within this queue's circular TFD buffer */
+ tfd = &txq->bd[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
control_flags = (u32 *) tfd;
- idx = get_cmd_index(q, q->first_empty, 0);
+ idx = get_cmd_index(q, q->write_ptr, 0);
- memset(&(txq->txb[q->first_empty]), 0, sizeof(struct iwl_tx_info));
- txq->txb[q->first_empty].skb[0] = skb;
- memcpy(&(txq->txb[q->first_empty].status.control),
+ /* Set up driver data for this TFD */
+ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl3945_tx_info));
+ txq->txb[q->write_ptr].skb[0] = skb;
+ memcpy(&(txq->txb[q->write_ptr].status.control),
ctl, sizeof(struct ieee80211_tx_control));
+
+ /* Init first empty entry in queue's array of Tx/cmd buffers */
out_cmd = &txq->cmd[idx];
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
+
+ /*
+ * Set up the Tx-command (not MAC!) header.
+ * Store the chosen Tx queue and TFD index within the sequence field;
+ * after Tx, uCode's Tx response will return this value so driver can
+ * locate the frame within the tx queue and do post-tx processing.
+ */
out_cmd->hdr.cmd = REPLY_TX;
out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
- INDEX_TO_SEQ(q->first_empty)));
- /* copy frags header */
+ INDEX_TO_SEQ(q->write_ptr)));
+
+ /* Copy MAC header from skb into command buffer */
memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
- /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
+ /*
+ * Use the first empty entry in this queue's command buffer array
+ * to contain the Tx command and MAC header concatenated together
+ * (payload data will be in another buffer).
+ * Size of this varies, due to varying MAC header length.
+ * If end is not dword aligned, we'll have 2 extra bytes at the end
+ * of the MAC header (device reads on dword boundaries).
+ * We'll tell device about this padding later.
+ */
len = priv->hw_setting.tx_cmd_len +
- sizeof(struct iwl_cmd_header) + hdr_len;
+ sizeof(struct iwl3945_cmd_header) + hdr_len;
len_org = len;
len = (len + 3) & ~3;
@@ -2829,37 +2881,45 @@ static int iwl_tx_skb(struct iwl_priv *priv,
else
len_org = 0;
- txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
- offsetof(struct iwl_cmd, hdr);
+ /* Physical address of this Tx command's header (not MAC header!),
+ * within command buffer array. */
+ txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl3945_cmd) * idx +
+ offsetof(struct iwl3945_cmd, hdr);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+ /* Add buffer containing Tx command and MAC(!) header to TFD's
+ * first entry */
+ iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
- iwl_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
+ iwl3945_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
- /* 802.11 null functions have no payload... */
+ /* Set up TFD's 2nd entry to point directly to remainder of skb,
+ * if any (802.11 null frames have no payload). */
len = skb->len - hdr_len;
if (len) {
phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
len, PCI_DMA_TODEVICE);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
+ iwl3945_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
}
- /* If there is no payload, then only one TFD is used */
if (!len)
+ /* If there is no payload, then we use only one Tx buffer */
*control_flags = TFD_CTL_COUNT_SET(1);
else
+ /* Else use 2 buffers.
+ * Tell 3945 about any padding after MAC header */
*control_flags = TFD_CTL_COUNT_SET(2) |
TFD_CTL_PAD_SET(U32_PAD(len));
+ /* Total # bytes to be transmitted */
len = (u16)skb->len;
out_cmd->cmd.tx.len = cpu_to_le16(len);
/* TODO need this for burst mode later on */
- iwl_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
+ iwl3945_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
/* set is_hcca to 0; it probably will never be implemented */
- iwl_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+ iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
out_cmd->cmd.tx.tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
@@ -2875,25 +2935,26 @@ static int iwl_tx_skb(struct iwl_priv *priv,
txq->need_update = 0;
}
- iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
+ iwl3945_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
sizeof(out_cmd->cmd.tx));
- iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+ iwl3945_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
ieee80211_get_hdrlen(fc));
- q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
- rc = iwl_tx_queue_update_write_ptr(priv, txq);
+ /* Tell device the write index *just past* this latest filled TFD */
+ q->write_ptr = iwl3945_queue_inc_wrap(q->write_ptr, q->n_bd);
+ rc = iwl3945_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
if (rc)
return rc;
- if ((iwl_queue_space(q) < q->high_mark)
+ if ((iwl3945_queue_space(q) < q->high_mark)
&& priv->mac80211_registered) {
if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags);
txq->need_update = 1;
- iwl_tx_queue_update_write_ptr(priv, txq);
+ iwl3945_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -2908,13 +2969,13 @@ drop:
return -1;
}
-static void iwl_set_rate(struct iwl_priv *priv)
+static void iwl3945_set_rate(struct iwl3945_priv *priv)
{
const struct ieee80211_hw_mode *hw = NULL;
struct ieee80211_rate *rate;
int i;
- hw = iwl_get_hw_mode(priv, priv->phymode);
+ hw = iwl3945_get_hw_mode(priv, priv->phymode);
if (!hw) {
IWL_ERROR("Failed to set rate: unable to get hw mode\n");
return;
@@ -2932,7 +2993,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
if ((rate->val < IWL_RATE_COUNT) &&
(rate->flags & IEEE80211_RATE_SUPPORTED)) {
IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
- rate->val, iwl_rates[rate->val].plcp,
+ rate->val, iwl3945_rates[rate->val].plcp,
(rate->flags & IEEE80211_RATE_BASIC) ?
"*" : "");
priv->active_rate |= (1 << rate->val);
@@ -2940,7 +3001,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
priv->active_rate_basic |= (1 << rate->val);
} else
IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
- rate->val, iwl_rates[rate->val].plcp);
+ rate->val, iwl3945_rates[rate->val].plcp);
}
IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
@@ -2969,7 +3030,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
+static void iwl3945_radio_kill_sw(struct iwl3945_priv *priv, int disable_radio)
{
unsigned long flags;
@@ -2980,21 +3041,21 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
disable_radio ? "OFF" : "ON");
if (disable_radio) {
- iwl_scan_cancel(priv);
+ iwl3945_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
+ iwl3945_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
set_bit(STATUS_RF_KILL_SW, &priv->status);
}
return;
}
spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
clear_bit(STATUS_RF_KILL_SW, &priv->status);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3003,9 +3064,9 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
msleep(10);
spin_lock_irqsave(&priv->lock, flags);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- if (!iwl_grab_restricted_access(priv))
- iwl_release_restricted_access(priv);
+ iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
+ if (!iwl3945_grab_nic_access(priv))
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
@@ -3018,7 +3079,7 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
return;
}
-void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
u32 decrypt_res, struct ieee80211_rx_status *stats)
{
u16 fc =
@@ -3050,97 +3111,9 @@ void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
}
}
-void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
- void *data, short len,
- struct ieee80211_rx_status *stats,
- u16 phy_flags)
-{
- struct iwl_rt_rx_hdr *iwl_rt;
-
- /* First cache any information we need before we overwrite
- * the information provided in the skb from the hardware */
- s8 signal = stats->ssi;
- s8 noise = 0;
- int rate = stats->rate;
- u64 tsf = stats->mactime;
- __le16 phy_flags_hw = cpu_to_le16(phy_flags);
-
- /* We received data from the HW, so stop the watchdog */
- if (len > IWL_RX_BUF_SIZE - sizeof(*iwl_rt)) {
- IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
- return;
- }
-
- /* copy the frame data to write after where the radiotap header goes */
- iwl_rt = (void *)rxb->skb->data;
- memmove(iwl_rt->payload, data, len);
-
- iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- iwl_rt->rt_hdr.it_pad = 0; /* always good to zero */
-
- /* total header + data */
- iwl_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl_rt));
-
- /* Set the size of the skb to the size of the frame */
- skb_put(rxb->skb, sizeof(*iwl_rt) + len);
-
- /* Big bitfield of all the fields we provide in radiotap */
- iwl_rt->rt_hdr.it_present =
- cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
- (1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
- (1 << IEEE80211_RADIOTAP_ANTENNA));
-
- /* Zero the flags, we'll add to them as we go */
- iwl_rt->rt_flags = 0;
-
- iwl_rt->rt_tsf = cpu_to_le64(tsf);
-
- /* Convert to dBm */
- iwl_rt->rt_dbmsignal = signal;
- iwl_rt->rt_dbmnoise = noise;
-
- /* Convert the channel frequency and set the flags */
- iwl_rt->rt_channelMHz = cpu_to_le16(stats->freq);
- if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
- else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
- else /* 802.11g */
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
-
- rate = iwl_rate_index_from_plcp(rate);
- if (rate == -1)
- iwl_rt->rt_rate = 0;
- else
- iwl_rt->rt_rate = iwl_rates[rate].ieee;
-
- /* antenna number */
- iwl_rt->rt_antenna =
- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
- /* set the preamble flag if we have it */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
- iwl_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
- IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
-
- stats->flag |= RX_FLAG_RADIOTAP;
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
- rxb->skb = NULL;
-}
-
-
#define IWL_PACKET_RETRY_TIME HZ
-int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
{
u16 sc = le16_to_cpu(header->seq_ctrl);
u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
@@ -3151,29 +3124,26 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_IBSS:{
struct list_head *p;
- struct iwl_ibss_seq *entry = NULL;
+ struct iwl3945_ibss_seq *entry = NULL;
u8 *mac = header->addr2;
int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
__list_for_each(p, &priv->ibss_mac_hash[index]) {
- entry =
- list_entry(p, struct iwl_ibss_seq, list);
+ entry = list_entry(p, struct iwl3945_ibss_seq, list);
if (!compare_ether_addr(entry->mac, mac))
break;
}
if (p == &priv->ibss_mac_hash[index]) {
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
- IWL_ERROR
- ("Cannot malloc new mac entry\n");
+ IWL_ERROR("Cannot malloc new mac entry\n");
return 0;
}
memcpy(entry->mac, mac, ETH_ALEN);
entry->seq_num = seq;
entry->frag_num = frag;
entry->packet_time = jiffies;
- list_add(&entry->list,
- &priv->ibss_mac_hash[index]);
+ list_add(&entry->list, &priv->ibss_mac_hash[index]);
return 0;
}
last_seq = &entry->seq_num;
@@ -3207,7 +3177,7 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
return 1;
}
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
#include "iwl-spectrum.h"
@@ -3222,7 +3192,7 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
* the lower 3 bytes is the time in usec within one beacon interval
*/
-static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
+static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval)
{
u32 quot;
u32 rem;
@@ -3241,7 +3211,7 @@ static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
* the same as HW timer counter counting down
*/
-static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
{
u32 base_low = base & BEACON_TIME_MASK_LOW;
u32 addon_low = addon & BEACON_TIME_MASK_LOW;
@@ -3260,13 +3230,13 @@ static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
return cpu_to_le32(res);
}
-static int iwl_get_measurement(struct iwl_priv *priv,
+static int iwl3945_get_measurement(struct iwl3945_priv *priv,
struct ieee80211_measurement_params *params,
u8 type)
{
- struct iwl_spectrum_cmd spectrum;
- struct iwl_rx_packet *res;
- struct iwl_host_cmd cmd = {
+ struct iwl3945_spectrum_cmd spectrum;
+ struct iwl3945_rx_packet *res;
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
.meta.flags = CMD_WANT_SKB,
@@ -3276,9 +3246,9 @@ static int iwl_get_measurement(struct iwl_priv *priv,
int spectrum_resp_status;
int duration = le16_to_cpu(params->duration);
- if (iwl_is_associated(priv))
+ if (iwl3945_is_associated(priv))
add_time =
- iwl_usecs_to_beacons(
+ iwl3945_usecs_to_beacons(
le64_to_cpu(params->start_time) - priv->last_tsf,
le16_to_cpu(priv->rxon_timing.beacon_interval));
@@ -3291,9 +3261,9 @@ static int iwl_get_measurement(struct iwl_priv *priv,
cmd.len = sizeof(spectrum);
spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
- if (iwl_is_associated(priv))
+ if (iwl3945_is_associated(priv))
spectrum.start_time =
- iwl_add_beacon_time(priv->last_beacon_time,
+ iwl3945_add_beacon_time(priv->last_beacon_time,
add_time,
le16_to_cpu(priv->rxon_timing.beacon_interval));
else
@@ -3306,11 +3276,11 @@ static int iwl_get_measurement(struct iwl_priv *priv,
spectrum.flags |= RXON_FLG_BAND_24G_MSK |
RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl3945_send_cmd_sync(priv, &cmd);
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl3945_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
@@ -3320,9 +3290,8 @@ static int iwl_get_measurement(struct iwl_priv *priv,
switch (spectrum_resp_status) {
case 0: /* Command will be handled */
if (res->u.spectrum.id != 0xff) {
- IWL_DEBUG_INFO
- ("Replaced existing measurement: %d\n",
- res->u.spectrum.id);
+ IWL_DEBUG_INFO("Replaced existing measurement: %d\n",
+ res->u.spectrum.id);
priv->measurement_status &= ~MEASUREMENT_READY;
}
priv->measurement_status |= MEASUREMENT_ACTIVE;
@@ -3340,8 +3309,8 @@ static int iwl_get_measurement(struct iwl_priv *priv,
}
#endif
-static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
- struct iwl_tx_info *tx_sta)
+static void iwl3945_txstatus_to_ieee(struct iwl3945_priv *priv,
+ struct iwl3945_tx_info *tx_sta)
{
tx_sta->status.ack_signal = 0;
@@ -3360,41 +3329,41 @@ static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
}
/**
- * iwl_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
+ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
*
- * When FW advances 'R' index, all entries between old and
- * new 'R' index need to be reclaimed. As result, some free space
- * forms. If there is enough free space (> low mark), wake Tx queue.
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
*/
-int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+static int iwl3945_tx_queue_reclaim(struct iwl3945_priv *priv, int txq_id, int index)
{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
+ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl3945_queue *q = &txq->q;
int nfreed = 0;
if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
- index, q->n_bd, q->first_empty, q->last_used);
+ index, q->n_bd, q->write_ptr, q->read_ptr);
return 0;
}
- for (index = iwl_queue_inc_wrap(index, q->n_bd);
- q->last_used != index;
- q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) {
+ for (index = iwl3945_queue_inc_wrap(index, q->n_bd);
+ q->read_ptr != index;
+ q->read_ptr = iwl3945_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (txq_id != IWL_CMD_QUEUE_NUM) {
- iwl_txstatus_to_ieee(priv,
- &(txq->txb[txq->q.last_used]));
- iwl_hw_txq_free_tfd(priv, txq);
+ iwl3945_txstatus_to_ieee(priv,
+ &(txq->txb[txq->q.read_ptr]));
+ iwl3945_hw_txq_free_tfd(priv, txq);
} else if (nfreed > 1) {
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
- q->first_empty, q->last_used);
+ q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
}
nfreed++;
}
- if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+ if (iwl3945_queue_space(q) > q->low_mark && (txq_id >= 0) &&
(txq_id != IWL_CMD_QUEUE_NUM) &&
priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
@@ -3403,7 +3372,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
return nfreed;
}
-static int iwl_is_tx_success(u32 status)
+static int iwl3945_is_tx_success(u32 status)
{
return (status & 0xFF) == 0x1;
}
@@ -3413,27 +3382,30 @@ static int iwl_is_tx_success(u32 status)
* Generic RX handler implementations
*
******************************************************************************/
-static void iwl_rx_reply_tx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+/**
+ * iwl3945_rx_reply_tx - Handle Tx response
+ */
+static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl3945_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_status *tx_status;
- struct iwl_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
"is out of range [0-%d] %d %d\n", txq_id,
- index, txq->q.n_bd, txq->q.first_empty,
- txq->q.last_used);
+ index, txq->q.n_bd, txq->q.write_ptr,
+ txq->q.read_ptr);
return;
}
- tx_status = &(txq->txb[txq->q.last_used].status);
+ tx_status = &(txq->txb[txq->q.read_ptr].status);
tx_status->retry_count = tx_resp->failure_frame;
tx_status->queue_number = status;
@@ -3441,28 +3413,28 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv,
tx_status->queue_length |= tx_resp->failure_rts;
tx_status->flags =
- iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+ iwl3945_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
- tx_status->control.tx_rate = iwl_rate_index_from_plcp(tx_resp->rate);
+ tx_status->control.tx_rate = iwl3945_rate_index_from_plcp(tx_resp->rate);
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
- txq_id, iwl_get_tx_fail_reason(status), status,
+ txq_id, iwl3945_get_tx_fail_reason(status), status,
tx_resp->rate, tx_resp->failure_frame);
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
if (index != -1)
- iwl_tx_queue_reclaim(priv, txq_id, index);
+ iwl3945_tx_queue_reclaim(priv, txq_id, index);
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
-static void iwl_rx_reply_alive(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_alive(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_alive_resp *palive;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_alive_resp *palive;
struct delayed_work *pwork;
palive = &pkt->u.alive_frame;
@@ -3476,14 +3448,14 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_DEBUG_INFO("Initialization Alive received.\n");
memcpy(&priv->card_alive_init,
&pkt->u.alive_frame,
- sizeof(struct iwl_init_alive_resp));
+ sizeof(struct iwl3945_init_alive_resp));
pwork = &priv->init_alive_start;
} else {
IWL_DEBUG_INFO("Runtime Alive received.\n");
memcpy(&priv->card_alive, &pkt->u.alive_frame,
- sizeof(struct iwl_alive_resp));
+ sizeof(struct iwl3945_alive_resp));
pwork = &priv->alive_start;
- iwl_disable_events(priv);
+ iwl3945_disable_events(priv);
}
/* We delay the ALIVE response by 5ms to
@@ -3495,19 +3467,19 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_WARNING("uCode did not respond OK.\n");
}
-static void iwl_rx_reply_add_sta(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_add_sta(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
return;
}
-static void iwl_rx_reply_error(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_error(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
@@ -3520,23 +3492,23 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_csa(struct iwl3945_priv *priv, struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
- struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rxon_cmd *rxon = (void *)&priv->active_rxon;
+ struct iwl3945_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
rxon->channel = csa->channel;
priv->staging_rxon.channel = csa->channel;
}
-static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_spectrum_measure_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_spectrum_notification *report = &(pkt->u.spectrum_notif);
if (!report->state) {
IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
@@ -3549,35 +3521,35 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
#endif
}
-static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_pm_sleep_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+#ifdef CONFIG_IWL3945_DEBUG
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
-static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_pm_debug_statistics_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
- iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ iwl3945_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
-static void iwl_bg_beacon_update(struct work_struct *work)
+static void iwl3945_bg_beacon_update(struct work_struct *work)
{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, beacon_update);
+ struct iwl3945_priv *priv =
+ container_of(work, struct iwl3945_priv, beacon_update);
struct sk_buff *beacon;
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
- beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
+ beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
if (!beacon) {
IWL_ERROR("update beacon failed\n");
@@ -3592,15 +3564,15 @@ static void iwl_bg_beacon_update(struct work_struct *work)
priv->ibss_beacon = beacon;
mutex_unlock(&priv->mutex);
- iwl_send_beacon_cmd(priv);
+ iwl3945_send_beacon_cmd(priv);
}
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_beacon_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWL3945_DEBUG
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
u8 rate = beacon->beacon_notify_hdr.rate;
IWL_DEBUG_RX("beacon status %x retries %d iss %d "
@@ -3618,25 +3590,25 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
}
/* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl_rx_reply_scan(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_reply_scan(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanreq_notification *notif =
- (struct iwl_scanreq_notification *)pkt->u.raw;
+#ifdef CONFIG_IWL3945_DEBUG
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_scanreq_notification *notif =
+ (struct iwl3945_scanreq_notification *)pkt->u.raw;
IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
#endif
}
/* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_start_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanstart_notification *notif =
- (struct iwl_scanstart_notification *)pkt->u.raw;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_scanstart_notification *notif =
+ (struct iwl3945_scanstart_notification *)pkt->u.raw;
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
IWL_DEBUG_SCAN("Scan start: "
"%d [802.11%s] "
@@ -3648,12 +3620,12 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
}
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_results_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanresults_notification *notif =
- (struct iwl_scanresults_notification *)pkt->u.raw;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_scanresults_notification *notif =
+ (struct iwl3945_scanresults_notification *)pkt->u.raw;
IWL_DEBUG_SCAN("Scan ch.res: "
"%d [802.11%s] "
@@ -3669,14 +3641,15 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
(priv->last_scan_jiffies, jiffies)));
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_scan_complete_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
scan_notif->scanned_channels,
@@ -3711,6 +3684,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
}
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO("Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
@@ -3729,10 +3703,10 @@ reschedule:
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_rx_card_state_notif(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (void *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
@@ -3740,7 +3714,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
(flags & HW_CARD_DISABLED) ? "Kill" : "On",
(flags & SW_CARD_DISABLED) ? "Kill" : "On");
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
if (flags & HW_CARD_DISABLED)
@@ -3754,7 +3728,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
else
clear_bit(STATUS_RF_KILL_SW, &priv->status);
- iwl_scan_cancel(priv);
+ iwl3945_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
@@ -3766,7 +3740,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
}
/**
- * iwl_setup_rx_handlers - Initialize Rx handler callbacks
+ * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
*
* Setup the RX handlers for each of the reply types sent from the uCode
* to the host.
@@ -3774,61 +3748,58 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
* This function chains into the hardware specific files for them to setup
* any hardware specific handlers as well.
*/
-static void iwl_setup_rx_handlers(struct iwl_priv *priv)
+static void iwl3945_setup_rx_handlers(struct iwl3945_priv *priv)
{
- priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
- priv->rx_handlers[REPLY_ADD_STA] = iwl_rx_reply_add_sta;
- priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
- priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
+ priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
+ priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
+ priv->rx_handlers[REPLY_ERROR] = iwl3945_rx_reply_error;
+ priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl3945_rx_csa;
priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
- iwl_rx_spectrum_measure_notif;
- priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
+ iwl3945_rx_spectrum_measure_notif;
+ priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl3945_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
- iwl_rx_pm_debug_statistics_notif;
- priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
-
- /* NOTE: iwl_rx_statistics is different based on whether
- * the build is for the 3945 or the 4965. See the
- * corresponding implementation in iwl-XXXX.c
- *
- * The same handler is used for both the REPLY to a
- * discrete statistics request from the host as well as
- * for the periodic statistics notification from the uCode
+ iwl3945_rx_pm_debug_statistics_notif;
+ priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
+
+ /*
+ * The same handler is used for both the REPLY to a discrete
+ * statistics request from the host as well as for the periodic
+ * statistics notifications (after received beacons) from the uCode.
*/
- priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_hw_rx_statistics;
- priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_hw_rx_statistics;
+ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
+ priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
- priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
- priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
+ priv->rx_handlers[REPLY_SCAN_CMD] = iwl3945_rx_reply_scan;
+ priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl3945_rx_scan_start_notif;
priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
- iwl_rx_scan_results_notif;
+ iwl3945_rx_scan_results_notif;
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
- iwl_rx_scan_complete_notif;
- priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
- priv->rx_handlers[REPLY_TX] = iwl_rx_reply_tx;
+ iwl3945_rx_scan_complete_notif;
+ priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
+ priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
- /* Setup hardware specific Rx handlers */
- iwl_hw_rx_handler_setup(priv);
+ /* Set up hardware specific Rx handlers */
+ iwl3945_hw_rx_handler_setup(priv);
}
/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * iwl3945_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
* @rxb: Rx buffer to reclaim
*
* If an Rx buffer has an async callback associated with it the callback
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/
-static void iwl_tx_cmd_complete(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl3945_tx_cmd_complete(struct iwl3945_priv *priv,
+ struct iwl3945_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
int huge = sequence & SEQ_HUGE_FRAME;
int cmd_index;
- struct iwl_cmd *cmd;
+ struct iwl3945_cmd *cmd;
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -3849,7 +3820,7 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
!cmd->meta.u.callback(priv, cmd, rxb->skb))
rxb->skb = NULL;
- iwl_tx_queue_reclaim(priv, txq_id, index);
+ iwl3945_tx_queue_reclaim(priv, txq_id, index);
if (!(cmd->meta.flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
@@ -3879,10 +3850,10 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
* The queue is empty (no good data) if WRITE = READ - 1, and is full if
* WRITE = READ.
*
- * During initialization the host sets up the READ queue position to the first
+ * During initialization, the host sets up the READ queue position to the first
* INDEX position, and WRITE to the last (READ - 1 wrapped)
*
- * When the firmware places a packet in a buffer it will advance the READ index
+ * When the firmware places a packet in a buffer, it will advance the READ index
* and fire the RX interrupt. The driver can then query the READ index and
* process as many packets as possible, moving the WRITE index forward as it
* resets the Rx queue buffers with new memory.
@@ -3890,8 +3861,8 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
* The management in the driver is as follows:
* + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
* iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- * to replensish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * to replenish the iwl->rxq->rx_free.
+ * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
* iwl->rxq is replenished and the READ INDEX is updated (updating the
* 'processed' and 'read' driver indexes as well)
* + A received packet is processed and handed to the kernel network stack,
@@ -3904,28 +3875,28 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
*
* Driver sequence:
*
- * iwl_rx_queue_alloc() Allocates rx_free
- * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls
- * iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * iwl3945_rx_queue_alloc() Allocates rx_free
+ * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls
+ * iwl3945_rx_queue_restock
+ * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
* queue, updates firmware pointers, and updates
* the WRITE index. If insufficient rx_free buffers
- * are available, schedules iwl_rx_replenish
+ * are available, schedules iwl3945_rx_replenish
*
* -- enable interrupts --
- * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
+ * ISR - iwl3945_rx() Detach iwl3945_rx_mem_buffers from pool up to the
* READ INDEX, detaching the SKB from the pool.
* Moves the packet buffer from queue to rx_used.
- * Calls iwl_rx_queue_restock to refill any empty
+ * Calls iwl3945_rx_queue_restock to refill any empty
* slots.
* ...
*
*/
/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
+ * iwl3945_rx_queue_space - Return number of free slots available in queue.
*/
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+static int iwl3945_rx_queue_space(const struct iwl3945_rx_queue *q)
{
int s = q->read - q->write;
if (s <= 0)
@@ -3938,15 +3909,9 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
}
/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- *
- * NOTE: This function has 3945 and 4965 specific code sections
- * but is declared in base due to the majority of the
- * implementation being the same (only a numeric constant is
- * different)
- *
+ * iwl3945_rx_queue_update_write_ptr - Update the write pointer for the RX queue
*/
-int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
+int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, struct iwl3945_rx_queue *q)
{
u32 reg = 0;
int rc = 0;
@@ -3957,24 +3922,29 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
if (q->need_update == 0)
goto exit_unlock;
+ /* If power-saving is in use, make sure device is awake */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl3945_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
goto exit_unlock;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc)
goto exit_unlock;
- iwl_write_restricted(priv, FH_RSCSR_CHNL0_WPTR,
+ /* Device expects a multiple of 8 */
+ iwl3945_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
q->write & ~0x7);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
+
+ /* Else device is assumed to be awake */
} else
- iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
+ /* Device expects a multiple of 8 */
+ iwl3945_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
q->need_update = 0;
@@ -3985,42 +3955,43 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
}
/**
- * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
- *
- * NOTE: This function has 3945 and 4965 specific code paths in it.
+ * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
*/
-static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
+static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl3945_priv *priv,
dma_addr_t dma_addr)
{
return cpu_to_le32((u32)dma_addr);
}
/**
- * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
+ * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
*
- * If there are slots in the RX queue that need to be restocked,
+ * If there are slots in the RX queue that need to be restocked,
* and we have free pre-allocated buffers, fill the ranks as much
- * as we can pulling from rx_free.
+ * as we can, pulling from rx_free.
*
* This moves the 'write' index forward to catch up with 'processed', and
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-int iwl_rx_queue_restock(struct iwl_priv *priv)
+static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
{
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl3945_rx_queue *rxq = &priv->rxq;
struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
+ struct iwl3945_rx_mem_buffer *rxb;
unsigned long flags;
int write, rc;
spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
- while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ while ((iwl3945_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ /* Get next free Rx buffer, remove from free list */
element = rxq->rx_free.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
list_del(element);
- rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+
+ /* Point to Rx buffer via next RBD in circular buffer */
+ rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->dma_addr);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
@@ -4032,13 +4003,14 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->rx_replenish);
- /* If we've added more space for the firmware to place data, tell it */
+ /* If we've added more space for the firmware to place data, tell it.
+ * Increment device's write pointer in multiples of 8. */
if ((write != (rxq->write & ~0x7))
|| (abs(rxq->write - rxq->read) > 7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- rc = iwl_rx_queue_update_write_ptr(priv, rxq);
+ rc = iwl3945_rx_queue_update_write_ptr(priv, rxq);
if (rc)
return rc;
}
@@ -4047,24 +4019,25 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
}
/**
- * iwl_rx_replensih - Move all used packet from rx_used to rx_free
+ * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
*
* When moving to rx_free an SKB is allocated for the slot.
*
- * Also restock the Rx queue via iwl_rx_queue_restock.
- * This is called as a scheduled work item (except for during intialization)
+ * Also restock the Rx queue via iwl3945_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
*/
-void iwl_rx_replenish(void *data)
+static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
{
- struct iwl_priv *priv = data;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl3945_rx_queue *rxq = &priv->rxq;
struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
+ struct iwl3945_rx_mem_buffer *rxb;
unsigned long flags;
spin_lock_irqsave(&rxq->lock, flags);
while (!list_empty(&rxq->rx_used)) {
element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ rxb = list_entry(element, struct iwl3945_rx_mem_buffer, list);
+
+ /* Alloc a new receive buffer */
rxb->skb =
alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
if (!rxb->skb) {
@@ -4076,8 +4049,19 @@ void iwl_rx_replenish(void *data)
* more buffers it will schedule replenish */
break;
}
+
+ /* If radiotap head is required, reserve some headroom here.
+ * The physical head count is a variable rx_stats->phy_count.
+ * We reserve 4 bytes here. Plus these extra bytes, the
+ * headroom of the physical head should be enough for the
+ * radiotap head that iwl3945 supported. See iwl3945_rt.
+ */
+ skb_reserve(rxb->skb, 4);
+
priv->alloc_rxb_skb++;
list_del(element);
+
+ /* Get physical address of RB/SKB */
rxb->dma_addr =
pci_map_single(priv->pci_dev, rxb->skb->data,
IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
@@ -4085,18 +4069,38 @@ void iwl_rx_replenish(void *data)
rxq->free_count++;
}
spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+/*
+ * this should be called while priv->lock is locked
+ */
+static void __iwl3945_rx_replenish(void *data)
+{
+ struct iwl3945_priv *priv = data;
+
+ iwl3945_rx_allocate(priv);
+ iwl3945_rx_queue_restock(priv);
+}
+
+
+void iwl3945_rx_replenish(void *data)
+{
+ struct iwl3945_priv *priv = data;
+ unsigned long flags;
+
+ iwl3945_rx_allocate(priv);
spin_lock_irqsave(&priv->lock, flags);
- iwl_rx_queue_restock(priv);
+ iwl3945_rx_queue_restock(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
* non NULL it is unmapped and freed
*/
-void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+static void iwl3945_rx_queue_free(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
{
int i;
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
@@ -4113,21 +4117,25 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
rxq->bd = NULL;
}
-int iwl_rx_queue_alloc(struct iwl_priv *priv)
+int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv)
{
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl3945_rx_queue *rxq = &priv->rxq;
struct pci_dev *dev = priv->pci_dev;
int i;
spin_lock_init(&rxq->lock);
INIT_LIST_HEAD(&rxq->rx_free);
INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
if (!rxq->bd)
return -ENOMEM;
+
/* Fill the rx_used queue with _all_ of the Rx buffers */
for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
/* Set us so that we have processed and used all buffers, but have
* not restocked the Rx queue with fresh buffers */
rxq->read = rxq->write = 0;
@@ -4136,7 +4144,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
return 0;
}
-void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+void iwl3945_rx_queue_reset(struct iwl3945_priv *priv, struct iwl3945_rx_queue *rxq)
{
unsigned long flags;
int i;
@@ -4183,7 +4191,7 @@ static u8 ratio2dB[100] = {
/* Calculates a relative dB value from a ratio of linear
* (i.e. not dB) signal levels.
* Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl_calc_db_from_ratio(int sig_ratio)
+int iwl3945_calc_db_from_ratio(int sig_ratio)
{
/* Anything above 1000:1 just report as 60 dB */
if (sig_ratio > 1000)
@@ -4209,7 +4217,7 @@ int iwl_calc_db_from_ratio(int sig_ratio)
/* Calculate an indication of rx signal quality (a percentage, not dBm!).
* See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
* about formulas used below. */
-int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
+int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm)
{
int sig_qual;
int degradation = PERFECT_RSSI - rssi_dbm;
@@ -4244,24 +4252,30 @@ int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
}
/**
- * iwl_rx_handle - Main entry function for receiving responses from the uCode
+ * iwl3945_rx_handle - Main entry function for receiving responses from uCode
*
* Uses the priv->rx_handlers callback function array to invoke
* the appropriate handlers, including command responses,
* frame-received notifications, and other notifications.
*/
-static void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl3945_rx_handle(struct iwl3945_priv *priv)
{
- struct iwl_rx_mem_buffer *rxb;
- struct iwl_rx_packet *pkt;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl3945_rx_mem_buffer *rxb;
+ struct iwl3945_rx_packet *pkt;
+ struct iwl3945_rx_queue *rxq = &priv->rxq;
u32 r, i;
int reclaim;
unsigned long flags;
+ u8 fill_rx = 0;
+ u32 count = 0;
- r = iwl_hw_get_rx_read(priv);
+ /* uCode's read index (stored in shared DRAM) indicates the last Rx
+ * buffer that the driver may process (last buffer filled by ucode). */
+ r = iwl3945_hw_get_rx_read(priv);
i = rxq->read;
+ if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+ fill_rx = 1;
/* Rx interrupt, but nothing sent from uCode */
if (i == r)
IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
@@ -4269,7 +4283,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
while (i != r) {
rxb = rxq->queue[i];
- /* If an RXB doesn't have a queue slot associated with it
+ /* If an RXB doesn't have a Rx queue slot associated with it,
* then a bug has been introduced in the queue refilling
* routines -- catch it here */
BUG_ON(rxb == NULL);
@@ -4279,7 +4293,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
IWL_RX_BUF_SIZE,
PCI_DMA_FROMDEVICE);
- pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
/* Reclaim a command buffer only if this packet is a response
* to a (driver-originated) command.
@@ -4293,7 +4307,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
/* Based on type of command response or notification,
* handle those that need handling via function in
- * rx_handlers table. See iwl_setup_rx_handlers() */
+ * rx_handlers table. See iwl3945_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
"r = %d, i = %d, %s, 0x%02x\n", r, i,
@@ -4308,11 +4322,11 @@ static void iwl_rx_handle(struct iwl_priv *priv)
}
if (reclaim) {
- /* Invoke any callbacks, transfer the skb to caller,
- * and fire off the (possibly) blocking iwl_send_cmd()
+ /* Invoke any callbacks, transfer the skb to caller, and
+ * fire off the (possibly) blocking iwl3945_send_cmd()
* as we reclaim the driver command queue */
if (rxb && rxb->skb)
- iwl_tx_cmd_complete(priv, rxb);
+ iwl3945_tx_cmd_complete(priv, rxb);
else
IWL_WARNING("Claim null rxb?\n");
}
@@ -4332,15 +4346,28 @@ static void iwl_rx_handle(struct iwl_priv *priv)
list_add_tail(&rxb->list, &priv->rxq.rx_used);
spin_unlock_irqrestore(&rxq->lock, flags);
i = (i + 1) & RX_QUEUE_MASK;
+ /* If there are a lot of unused frames,
+ * restock the Rx queue so ucode won't assert. */
+ if (fill_rx) {
+ count++;
+ if (count >= 8) {
+ priv->rxq.read = i;
+ __iwl3945_rx_replenish(priv);
+ count = 0;
+ }
+ }
}
/* Backtrack one entry */
priv->rxq.read = i;
- iwl_rx_queue_restock(priv);
+ iwl3945_rx_queue_restock(priv);
}
-int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
+/**
+ * iwl3945_tx_queue_update_write_ptr - Send new write index to hardware
+ */
+static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
+ struct iwl3945_tx_queue *txq)
{
u32 reg = 0;
int rc = 0;
@@ -4354,41 +4381,41 @@ int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ reg = iwl3945_read32(priv, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl3945_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return rc;
}
/* restore this queue's parameters in nic hardware. */
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted(priv, HBUS_TARG_WRPTR,
- txq->q.first_empty | (txq_id << 8));
- iwl_release_restricted_access(priv);
+ iwl3945_write_direct32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+ iwl3945_release_nic_access(priv);
/* else not in power-save mode, uCode will never sleep when we're
* trying to tx (during RFKILL, we're not trying to tx). */
} else
- iwl_write32(priv, HBUS_TARG_WRPTR,
- txq->q.first_empty | (txq_id << 8));
+ iwl3945_write32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
txq->need_update = 0;
return rc;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
+#ifdef CONFIG_IWL3945_DEBUG
+static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
{
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RADIO("RX CONFIG:\n");
- iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
@@ -4405,24 +4432,24 @@ static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
}
#endif
-static void iwl_enable_interrupts(struct iwl_priv *priv)
+static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
{
IWL_DEBUG_ISR("Enabling interrupts\n");
set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+ iwl3945_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
}
-static inline void iwl_disable_interrupts(struct iwl_priv *priv)
+static inline void iwl3945_disable_interrupts(struct iwl3945_priv *priv)
{
clear_bit(STATUS_INT_ENABLED, &priv->status);
/* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ iwl3945_write32(priv, CSR_INT_MASK, 0x00000000);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ iwl3945_write32(priv, CSR_INT, 0xffffffff);
+ iwl3945_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
IWL_DEBUG_ISR("Disabled interrupts\n");
}
@@ -4449,7 +4476,7 @@ static const char *desc_lookup(int i)
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-static void iwl_dump_nic_error_log(struct iwl_priv *priv)
+static void iwl3945_dump_nic_error_log(struct iwl3945_priv *priv)
{
u32 i;
u32 desc, time, count, base, data1;
@@ -4458,18 +4485,18 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
- if (!iwl_hw_valid_rtc_data_addr(base)) {
+ if (!iwl3945_hw_valid_rtc_data_addr(base)) {
IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
return;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
- count = iwl_read_restricted_mem(priv, base);
+ count = iwl3945_read_targ_mem(priv, base);
if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
IWL_ERROR("Start IWL Error Log Dump:\n");
@@ -4482,19 +4509,19 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
for (i = ERROR_START_OFFSET;
i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
i += ERROR_ELEM_SIZE) {
- desc = iwl_read_restricted_mem(priv, base + i);
+ desc = iwl3945_read_targ_mem(priv, base + i);
time =
- iwl_read_restricted_mem(priv, base + i + 1 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 1 * sizeof(u32));
blink1 =
- iwl_read_restricted_mem(priv, base + i + 2 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 2 * sizeof(u32));
blink2 =
- iwl_read_restricted_mem(priv, base + i + 3 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 3 * sizeof(u32));
ilink1 =
- iwl_read_restricted_mem(priv, base + i + 4 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 4 * sizeof(u32));
ilink2 =
- iwl_read_restricted_mem(priv, base + i + 5 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 5 * sizeof(u32));
data1 =
- iwl_read_restricted_mem(priv, base + i + 6 * sizeof(u32));
+ iwl3945_read_targ_mem(priv, base + i + 6 * sizeof(u32));
IWL_ERROR
("%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
@@ -4502,18 +4529,18 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
ilink1, ilink2, data1);
}
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
}
-#define EVENT_START_OFFSET (4 * sizeof(u32))
+#define EVENT_START_OFFSET (6 * sizeof(u32))
/**
- * iwl_print_event_log - Dump error event log to syslog
+ * iwl3945_print_event_log - Dump error event log to syslog
*
- * NOTE: Must be called with iwl_grab_restricted_access() already obtained!
+ * NOTE: Must be called with iwl3945_grab_nic_access() already obtained!
*/
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+static void iwl3945_print_event_log(struct iwl3945_priv *priv, u32 start_idx,
u32 num_events, u32 mode)
{
u32 i;
@@ -4537,21 +4564,21 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
/* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */
for (i = 0; i < num_events; i++) {
- ev = iwl_read_restricted_mem(priv, ptr);
+ ev = iwl3945_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
- time = iwl_read_restricted_mem(priv, ptr);
+ time = iwl3945_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
if (mode == 0)
IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
else {
- data = iwl_read_restricted_mem(priv, ptr);
+ data = iwl3945_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
}
}
}
-static void iwl_dump_nic_event_log(struct iwl_priv *priv)
+static void iwl3945_dump_nic_event_log(struct iwl3945_priv *priv)
{
int rc;
u32 base; /* SRAM byte address of event log header */
@@ -4562,29 +4589,29 @@ static void iwl_dump_nic_event_log(struct iwl_priv *priv)
u32 size; /* # entries that we'll print */
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl_hw_valid_rtc_data_addr(base)) {
+ if (!iwl3945_hw_valid_rtc_data_addr(base)) {
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
return;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
/* event log header */
- capacity = iwl_read_restricted_mem(priv, base);
- mode = iwl_read_restricted_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_restricted_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_restricted_mem(priv, base + (3 * sizeof(u32)));
+ capacity = iwl3945_read_targ_mem(priv, base);
+ mode = iwl3945_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl3945_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl3945_read_targ_mem(priv, base + (3 * sizeof(u32)));
size = num_wraps ? capacity : next_entry;
/* bail out if nothing in log */
if (size == 0) {
IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
return;
}
@@ -4594,31 +4621,31 @@ static void iwl_dump_nic_event_log(struct iwl_priv *priv)
/* if uCode has wrapped back to top of log, start at the oldest entry,
* i.e the next one that uCode would fill. */
if (num_wraps)
- iwl_print_event_log(priv, next_entry,
+ iwl3945_print_event_log(priv, next_entry,
capacity - next_entry, mode);
/* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
+ iwl3945_print_event_log(priv, 0, next_entry, mode);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
}
/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
+ * iwl3945_irq_handle_error - called for HW or SW error interrupt from card
*/
-static void iwl_irq_handle_error(struct iwl_priv *priv)
+static void iwl3945_irq_handle_error(struct iwl3945_priv *priv)
{
- /* Set the FW error flag -- cleared on iwl_down */
+ /* Set the FW error flag -- cleared on iwl3945_down */
set_bit(STATUS_FW_ERROR, &priv->status);
/* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_FW_ERRORS) {
- iwl_dump_nic_error_log(priv);
- iwl_dump_nic_event_log(priv);
- iwl_print_rx_config_cmd(&priv->staging_rxon);
+#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & IWL_DL_FW_ERRORS) {
+ iwl3945_dump_nic_error_log(priv);
+ iwl3945_dump_nic_event_log(priv);
+ iwl3945_print_rx_config_cmd(&priv->staging_rxon);
}
#endif
@@ -4632,7 +4659,7 @@ static void iwl_irq_handle_error(struct iwl_priv *priv)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
"Restarting adapter due to uCode error.\n");
- if (iwl_is_associated(priv)) {
+ if (iwl3945_is_associated(priv)) {
memcpy(&priv->recovery_rxon, &priv->active_rxon,
sizeof(priv->recovery_rxon));
priv->error_recovering = 1;
@@ -4641,16 +4668,16 @@ static void iwl_irq_handle_error(struct iwl_priv *priv)
}
}
-static void iwl_error_recovery(struct iwl_priv *priv)
+static void iwl3945_error_recovery(struct iwl3945_priv *priv)
{
unsigned long flags;
memcpy(&priv->staging_rxon, &priv->recovery_rxon,
sizeof(priv->staging_rxon));
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
- iwl_add_station(priv, priv->bssid, 1, 0);
+ iwl3945_add_station(priv, priv->bssid, 1, 0);
spin_lock_irqsave(&priv->lock, flags);
priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
@@ -4658,12 +4685,12 @@ static void iwl_error_recovery(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void iwl_irq_tasklet(struct iwl_priv *priv)
+static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
{
u32 inta, handled = 0;
u32 inta_fh;
unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL3945_DEBUG
u32 inta_mask;
#endif
@@ -4672,18 +4699,19 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* Ack/clear/reset pending uCode interrupts.
* Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
* and will clear only when CSR_FH_INT_STATUS gets cleared. */
- inta = iwl_read32(priv, CSR_INT);
- iwl_write32(priv, CSR_INT, inta);
+ inta = iwl3945_read32(priv, CSR_INT);
+ iwl3945_write32(priv, CSR_INT, inta);
/* Ack/clear/reset pending flow-handler (DMA) interrupts.
* Any new interrupts that happen after this, either while we're
* in this tasklet, or later, will show up in next ISR/tasklet. */
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
- iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+ inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
+ iwl3945_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_ISR) {
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
+#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & IWL_DL_ISR) {
+ /* just for debug */
+ inta_mask = iwl3945_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
}
@@ -4703,9 +4731,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
IWL_ERROR("Microcode HW error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
+ iwl3945_disable_interrupts(priv);
- iwl_irq_handle_error(priv);
+ iwl3945_irq_handle_error(priv);
handled |= CSR_INT_BIT_HW_ERR;
@@ -4714,8 +4742,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
return;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
IWL_DEBUG_ISR("Microcode started or stopped.\n");
@@ -4731,7 +4759,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* HW RF KILL switch toggled (4965 only) */
if (inta & CSR_INT_BIT_RF_KILL) {
int hw_rf_kill = 0;
- if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+ if (!(iwl3945_read32(priv, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
@@ -4761,20 +4789,20 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n",
inta);
- iwl_irq_handle_error(priv);
+ iwl3945_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
/* uCode wakes up after power-down sleep */
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR("Wakeup interrupt\n");
- iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[0]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[1]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[2]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[3]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[4]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[5]);
+ iwl3945_rx_queue_update_write_ptr(priv, &priv->rxq);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[0]);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[1]);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[2]);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[3]);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[4]);
+ iwl3945_tx_queue_update_write_ptr(priv, &priv->txq[5]);
handled |= CSR_INT_BIT_WAKEUP;
}
@@ -4783,19 +4811,19 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
* Rx "responses" (frame-received notification), and other
* notifications from uCode come through here*/
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
- iwl_rx_handle(priv);
+ iwl3945_rx_handle(priv);
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
}
if (inta & CSR_INT_BIT_FH_TX) {
IWL_DEBUG_ISR("Tx interrupt\n");
- iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted(priv,
+ iwl3945_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
+ if (!iwl3945_grab_nic_access(priv)) {
+ iwl3945_write_direct32(priv,
FH_TCSR_CREDIT
(ALM_FH_SRVC_CHNL), 0x0);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
}
handled |= CSR_INT_BIT_FH_TX;
}
@@ -4810,13 +4838,13 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
}
/* Re-enable all interrupts */
- iwl_enable_interrupts(priv);
+ iwl3945_enable_interrupts(priv);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
- inta = iwl_read32(priv, CSR_INT);
- inta_mask = iwl_read32(priv, CSR_INT_MASK);
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+#ifdef CONFIG_IWL3945_DEBUG
+ if (iwl3945_debug_level & (IWL_DL_ISR)) {
+ inta = iwl3945_read32(priv, CSR_INT);
+ inta_mask = iwl3945_read32(priv, CSR_INT_MASK);
+ inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
}
@@ -4824,9 +4852,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static irqreturn_t iwl_isr(int irq, void *data)
+static irqreturn_t iwl3945_isr(int irq, void *data)
{
- struct iwl_priv *priv = data;
+ struct iwl3945_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
if (!priv)
@@ -4838,12 +4866,12 @@ static irqreturn_t iwl_isr(int irq, void *data)
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ inta_mask = iwl3945_read32(priv, CSR_INT_MASK); /* just for debug */
+ iwl3945_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
- inta = iwl_read32(priv, CSR_INT);
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ inta = iwl3945_read32(priv, CSR_INT);
+ inta_fh = iwl3945_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
@@ -4862,7 +4890,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ /* iwl3945_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
unplugged:
spin_unlock(&priv->lock);
@@ -4871,18 +4899,18 @@ unplugged:
none:
/* re-enable interrupts here since we don't have anything to service. */
- iwl_enable_interrupts(priv);
+ iwl3945_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
/************************** EEPROM BANDS ****************************
*
- * The iwl_eeprom_band definitions below provide the mapping from the
+ * The iwl3945_eeprom_band definitions below provide the mapping from the
* EEPROM contents to the specific channel number supported for each
* band.
*
- * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * For example, iwl3945_priv->eeprom.band_3_channels[4] from the band_3
* definition below maps to physical channel 42 in the 5.2GHz spectrum.
* The specific geography and calibration information for that channel
* is contained in the eeprom map itself.
@@ -4908,58 +4936,58 @@ unplugged:
*********************************************************************/
/* 2.4 GHz */
-static const u8 iwl_eeprom_band_1[14] = {
+static const u8 iwl3945_eeprom_band_1[14] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
/* 5.2 GHz bands */
-static const u8 iwl_eeprom_band_2[] = {
+static const u8 iwl3945_eeprom_band_2[] = { /* 4915-5080MHz */
183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
};
-static const u8 iwl_eeprom_band_3[] = { /* 5205-5320MHz */
+static const u8 iwl3945_eeprom_band_3[] = { /* 5170-5320MHz */
34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
};
-static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
+static const u8 iwl3945_eeprom_band_4[] = { /* 5500-5700MHz */
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
};
-static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
+static const u8 iwl3945_eeprom_band_5[] = { /* 5725-5825MHz */
145, 149, 153, 157, 161, 165
};
-static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
+static void iwl3945_init_band_reference(const struct iwl3945_priv *priv, int band,
int *eeprom_ch_count,
- const struct iwl_eeprom_channel
+ const struct iwl3945_eeprom_channel
**eeprom_ch_info,
const u8 **eeprom_ch_index)
{
switch (band) {
case 1: /* 2.4GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
+ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_1);
*eeprom_ch_info = priv->eeprom.band_1_channels;
- *eeprom_ch_index = iwl_eeprom_band_1;
+ *eeprom_ch_index = iwl3945_eeprom_band_1;
break;
- case 2: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
+ case 2: /* 4.9GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_2);
*eeprom_ch_info = priv->eeprom.band_2_channels;
- *eeprom_ch_index = iwl_eeprom_band_2;
+ *eeprom_ch_index = iwl3945_eeprom_band_2;
break;
case 3: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
+ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_3);
*eeprom_ch_info = priv->eeprom.band_3_channels;
- *eeprom_ch_index = iwl_eeprom_band_3;
+ *eeprom_ch_index = iwl3945_eeprom_band_3;
break;
- case 4: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
+ case 4: /* 5.5GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_4);
*eeprom_ch_info = priv->eeprom.band_4_channels;
- *eeprom_ch_index = iwl_eeprom_band_4;
+ *eeprom_ch_index = iwl3945_eeprom_band_4;
break;
- case 5: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
+ case 5: /* 5.7GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl3945_eeprom_band_5);
*eeprom_ch_info = priv->eeprom.band_5_channels;
- *eeprom_ch_index = iwl_eeprom_band_5;
+ *eeprom_ch_index = iwl3945_eeprom_band_5;
break;
default:
BUG();
@@ -4967,7 +4995,12 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
}
}
-const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
+/**
+ * iwl3945_get_channel_info - Find driver's private channel info
+ *
+ * Based on band and channel number.
+ */
+const struct iwl3945_channel_info *iwl3945_get_channel_info(const struct iwl3945_priv *priv,
int phymode, u16 channel)
{
int i;
@@ -4994,13 +5027,16 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
-static int iwl_init_channel_map(struct iwl_priv *priv)
+/**
+ * iwl3945_init_channel_map - Set up driver's info for all possible channels
+ */
+static int iwl3945_init_channel_map(struct iwl3945_priv *priv)
{
int eeprom_ch_count = 0;
const u8 *eeprom_ch_index = NULL;
- const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
+ const struct iwl3945_eeprom_channel *eeprom_ch_info = NULL;
int band, ch;
- struct iwl_channel_info *ch_info;
+ struct iwl3945_channel_info *ch_info;
if (priv->channel_count) {
IWL_DEBUG_INFO("Channel map already initialized.\n");
@@ -5016,15 +5052,15 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
priv->channel_count =
- ARRAY_SIZE(iwl_eeprom_band_1) +
- ARRAY_SIZE(iwl_eeprom_band_2) +
- ARRAY_SIZE(iwl_eeprom_band_3) +
- ARRAY_SIZE(iwl_eeprom_band_4) +
- ARRAY_SIZE(iwl_eeprom_band_5);
+ ARRAY_SIZE(iwl3945_eeprom_band_1) +
+ ARRAY_SIZE(iwl3945_eeprom_band_2) +
+ ARRAY_SIZE(iwl3945_eeprom_band_3) +
+ ARRAY_SIZE(iwl3945_eeprom_band_4) +
+ ARRAY_SIZE(iwl3945_eeprom_band_5);
IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
- priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
+ priv->channel_info = kzalloc(sizeof(struct iwl3945_channel_info) *
priv->channel_count, GFP_KERNEL);
if (!priv->channel_info) {
IWL_ERROR("Could not allocate channel_info\n");
@@ -5039,7 +5075,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
* what just in the EEPROM) */
for (band = 1; band <= 5; band++) {
- iwl_init_band_reference(priv, band, &eeprom_ch_count,
+ iwl3945_init_band_reference(priv, band, &eeprom_ch_count,
&eeprom_ch_info, &eeprom_ch_index);
/* Loop through each band adding each of the channels */
@@ -5103,6 +5139,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
}
}
+ /* Set up txpower settings in driver for all channels */
if (iwl3945_txpower_set_from_eeprom(priv))
return -EIO;
@@ -5132,7 +5169,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
-static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
+static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv, int phymode)
{
if (phymode == MODE_IEEE80211A)
return IWL_ACTIVE_DWELL_TIME_52;
@@ -5140,14 +5177,14 @@ static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
return IWL_ACTIVE_DWELL_TIME_24;
}
-static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
+static u16 iwl3945_get_passive_dwell_time(struct iwl3945_priv *priv, int phymode)
{
- u16 active = iwl_get_active_dwell_time(priv, phymode);
+ u16 active = iwl3945_get_active_dwell_time(priv, phymode);
u16 passive = (phymode != MODE_IEEE80211A) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
- if (iwl_is_associated(priv)) {
+ if (iwl3945_is_associated(priv)) {
/* If we're associated, we clamp the maximum passive
* dwell time to be 98% of the beacon interval (minus
* 2 * channel tune time) */
@@ -5163,30 +5200,30 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
return passive;
}
-static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
+static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv, int phymode,
u8 is_active, u8 direct_mask,
- struct iwl_scan_channel *scan_ch)
+ struct iwl3945_scan_channel *scan_ch)
{
const struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode;
- const struct iwl_channel_info *ch_info;
+ const struct iwl3945_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added, i;
- hw_mode = iwl_get_hw_mode(priv, phymode);
+ hw_mode = iwl3945_get_hw_mode(priv, phymode);
if (!hw_mode)
return 0;
channels = hw_mode->channels;
- active_dwell = iwl_get_active_dwell_time(priv, phymode);
- passive_dwell = iwl_get_passive_dwell_time(priv, phymode);
+ active_dwell = iwl3945_get_active_dwell_time(priv, phymode);
+ passive_dwell = iwl3945_get_passive_dwell_time(priv, phymode);
for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
if (channels[i].chan ==
le16_to_cpu(priv->active_rxon.channel)) {
- if (iwl_is_associated(priv)) {
+ if (iwl3945_is_associated(priv)) {
IWL_DEBUG_SCAN
("Skipping current channel %d\n",
le16_to_cpu(priv->active_rxon.channel));
@@ -5197,7 +5234,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
scan_ch->channel = channels[i].chan;
- ch_info = iwl_get_channel_info(priv, phymode, scan_ch->channel);
+ ch_info = iwl3945_get_channel_info(priv, phymode, scan_ch->channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
scan_ch->channel);
@@ -5219,7 +5256,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set power levels to defaults */
+ /* Set txpower levels to defaults */
scan_ch->tpc.dsp_atten = 110;
/* scan_pwr_info->tpc.dsp_atten; */
@@ -5229,8 +5266,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
else {
scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
- * power level
- scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
+ * power level:
+ * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
*/
}
@@ -5248,7 +5285,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
return added;
}
-static void iwl_reset_channel_flag(struct iwl_priv *priv)
+static void iwl3945_reset_channel_flag(struct iwl3945_priv *priv)
{
int i, j;
for (i = 0; i < 3; i++) {
@@ -5258,13 +5295,13 @@ static void iwl_reset_channel_flag(struct iwl_priv *priv)
}
}
-static void iwl_init_hw_rates(struct iwl_priv *priv,
+static void iwl3945_init_hw_rates(struct iwl3945_priv *priv,
struct ieee80211_rate *rates)
{
int i;
for (i = 0; i < IWL_RATE_COUNT; i++) {
- rates[i].rate = iwl_rates[i].ieee * 5;
+ rates[i].rate = iwl3945_rates[i].ieee * 5;
rates[i].val = i; /* Rate scaling will work on indexes */
rates[i].val2 = i;
rates[i].flags = IEEE80211_RATE_SUPPORTED;
@@ -5276,7 +5313,7 @@ static void iwl_init_hw_rates(struct iwl_priv *priv,
* If CCK 1M then set rate flag to CCK else CCK_2
* which is CCK | PREAMBLE2
*/
- rates[i].flags |= (iwl_rates[i].plcp == 10) ?
+ rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
}
@@ -5287,11 +5324,11 @@ static void iwl_init_hw_rates(struct iwl_priv *priv,
}
/**
- * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ * iwl3945_init_geos - Initialize mac80211's geo/channel info based from eeprom
*/
-static int iwl_init_geos(struct iwl_priv *priv)
+static int iwl3945_init_geos(struct iwl3945_priv *priv)
{
- struct iwl_channel_info *ch;
+ struct iwl3945_channel_info *ch;
struct ieee80211_hw_mode *modes;
struct ieee80211_channel *channels;
struct ieee80211_channel *geo_ch;
@@ -5337,7 +5374,7 @@ static int iwl_init_geos(struct iwl_priv *priv)
/* 5.2GHz channels start after the 2.4GHz channels */
modes[A].mode = MODE_IEEE80211A;
- modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
+ modes[A].channels = &channels[ARRAY_SIZE(iwl3945_eeprom_band_1)];
modes[A].rates = &rates[4];
modes[A].num_rates = 8; /* just OFDM */
modes[A].num_channels = 0;
@@ -5357,7 +5394,7 @@ static int iwl_init_geos(struct iwl_priv *priv)
priv->ieee_channels = channels;
priv->ieee_rates = rates;
- iwl_init_hw_rates(priv, rates);
+ iwl3945_init_hw_rates(priv, rates);
for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
ch = &priv->channel_info[i];
@@ -5440,57 +5477,21 @@ static int iwl_init_geos(struct iwl_priv *priv)
*
******************************************************************************/
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
+static void iwl3945_dealloc_ucode_pci(struct iwl3945_priv *priv)
{
- if (priv->ucode_code.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_code.len,
- priv->ucode_code.v_addr,
- priv->ucode_code.p_addr);
- priv->ucode_code.v_addr = NULL;
- }
- if (priv->ucode_data.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_data.len,
- priv->ucode_data.v_addr,
- priv->ucode_data.p_addr);
- priv->ucode_data.v_addr = NULL;
- }
- if (priv->ucode_data_backup.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_data_backup.len,
- priv->ucode_data_backup.v_addr,
- priv->ucode_data_backup.p_addr);
- priv->ucode_data_backup.v_addr = NULL;
- }
- if (priv->ucode_init.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_init.len,
- priv->ucode_init.v_addr,
- priv->ucode_init.p_addr);
- priv->ucode_init.v_addr = NULL;
- }
- if (priv->ucode_init_data.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_init_data.len,
- priv->ucode_init_data.v_addr,
- priv->ucode_init_data.p_addr);
- priv->ucode_init_data.v_addr = NULL;
- }
- if (priv->ucode_boot.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_boot.len,
- priv->ucode_boot.v_addr,
- priv->ucode_boot.p_addr);
- priv->ucode_boot.v_addr = NULL;
- }
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
}
/**
- * iwl_verify_inst_full - verify runtime uCode image in card vs. host,
+ * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
* looking at all data.
*/
-static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
+static int iwl3945_verify_inst_full(struct iwl3945_priv *priv, __le32 * image, u32 len)
{
u32 val;
u32 save_len = len;
@@ -5499,18 +5500,18 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
errcnt = 0;
for (; len > 0; len -= sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
+ val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
IWL_ERROR("uCode INST section is invalid at "
"offset 0x%x, is 0x%x, s/b 0x%x\n",
@@ -5522,22 +5523,21 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
}
}
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
if (!errcnt)
- IWL_DEBUG_INFO
- ("ucode image in INSTRUCTION memory is good\n");
+ IWL_DEBUG_INFO("ucode image in INSTRUCTION memory is good\n");
return rc;
}
/**
- * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
* using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too.
*/
-static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+static int iwl3945_verify_inst_sparse(struct iwl3945_priv *priv, __le32 *image, u32 len)
{
u32 val;
int rc = 0;
@@ -5546,7 +5546,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc)
return rc;
@@ -5554,9 +5554,9 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR,
+ iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR,
i + RTC_INST_LOWER_BOUND);
- val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
+ val = _iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
#if 0 /* Enable this if you want to see details */
IWL_ERROR("uCode INST section is invalid at "
@@ -5570,17 +5570,17 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
}
}
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
return rc;
}
/**
- * iwl_verify_ucode - determine which instruction image is in SRAM,
+ * iwl3945_verify_ucode - determine which instruction image is in SRAM,
* and verify its contents
*/
-static int iwl_verify_ucode(struct iwl_priv *priv)
+static int iwl3945_verify_ucode(struct iwl3945_priv *priv)
{
__le32 *image;
u32 len;
@@ -5589,7 +5589,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try bootstrap */
image = (__le32 *)priv->ucode_boot.v_addr;
len = priv->ucode_boot.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl3945_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
return 0;
@@ -5598,7 +5598,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try initialize */
image = (__le32 *)priv->ucode_init.v_addr;
len = priv->ucode_init.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl3945_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
return 0;
@@ -5607,7 +5607,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try runtime/protocol */
image = (__le32 *)priv->ucode_code.v_addr;
len = priv->ucode_code.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl3945_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
return 0;
@@ -5615,18 +5615,19 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
- /* Show first several data entries in instruction SRAM.
- * Selection of bootstrap image is arbitrary. */
+ /* Since nothing seems to match, show first several data entries in
+ * instruction SRAM, so maybe visual inspection will give a clue.
+ * Selection of bootstrap image (vs. other images) is arbitrary. */
image = (__le32 *)priv->ucode_boot.v_addr;
len = priv->ucode_boot.len;
- rc = iwl_verify_inst_full(priv, image, len);
+ rc = iwl3945_verify_inst_full(priv, image, len);
return rc;
}
/* check contents of special bootstrap uCode SRAM */
-static int iwl_verify_bsm(struct iwl_priv *priv)
+static int iwl3945_verify_bsm(struct iwl3945_priv *priv)
{
__le32 *image = priv->ucode_boot.v_addr;
u32 len = priv->ucode_boot.len;
@@ -5636,11 +5637,11 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
IWL_DEBUG_INFO("Begin verify bsm\n");
/* verify BSM SRAM contents */
- val = iwl_read_restricted_reg(priv, BSM_WR_DWCOUNT_REG);
+ val = iwl3945_read_prph(priv, BSM_WR_DWCOUNT_REG);
for (reg = BSM_SRAM_LOWER_BOUND;
reg < BSM_SRAM_LOWER_BOUND + len;
reg += sizeof(u32), image ++) {
- val = iwl_read_restricted_reg(priv, reg);
+ val = iwl3945_read_prph(priv, reg);
if (val != le32_to_cpu(*image)) {
IWL_ERROR("BSM uCode verification failed at "
"addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
@@ -5657,7 +5658,7 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
}
/**
- * iwl_load_bsm - Load bootstrap instructions
+ * iwl3945_load_bsm - Load bootstrap instructions
*
* BSM operation:
*
@@ -5688,7 +5689,7 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
* the runtime uCode instructions and the backup data cache into SRAM,
* and re-launches the runtime uCode from where it left off.
*/
-static int iwl_load_bsm(struct iwl_priv *priv)
+static int iwl3945_load_bsm(struct iwl3945_priv *priv)
{
__le32 *image = priv->ucode_boot.v_addr;
u32 len = priv->ucode_boot.len;
@@ -5708,8 +5709,8 @@ static int iwl_load_bsm(struct iwl_priv *priv)
return -EINVAL;
/* Tell bootstrap uCode where to find the "Initialize" uCode
- * in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
- * NOTE: iwl_initialize_alive_start() will replace these values,
+ * in host DRAM ... host DRAM physical address bits 31:0 for 3945.
+ * NOTE: iwl3945_initialize_alive_start() will replace these values,
* after the "initialize" uCode has run, to point to
* runtime/protocol instructions and backup data cache. */
pinst = priv->ucode_init.p_addr;
@@ -5717,42 +5718,42 @@ static int iwl_load_bsm(struct iwl_priv *priv)
inst_len = priv->ucode_init.len;
data_len = priv->ucode_init_data.len;
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+ iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+ iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
/* Fill BSM memory with bootstrap instructions */
for (reg_offset = BSM_SRAM_LOWER_BOUND;
reg_offset < BSM_SRAM_LOWER_BOUND + len;
reg_offset += sizeof(u32), image++)
- _iwl_write_restricted_reg(priv, reg_offset,
+ _iwl3945_write_prph(priv, reg_offset,
le32_to_cpu(*image));
- rc = iwl_verify_bsm(priv);
+ rc = iwl3945_verify_bsm(priv);
if (rc) {
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
return rc;
}
/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
- iwl_write_restricted_reg(priv, BSM_WR_MEM_SRC_REG, 0x0);
- iwl_write_restricted_reg(priv, BSM_WR_MEM_DST_REG,
+ iwl3945_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+ iwl3945_write_prph(priv, BSM_WR_MEM_DST_REG,
RTC_INST_LOWER_BOUND);
- iwl_write_restricted_reg(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+ iwl3945_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
/* Load bootstrap code into instruction SRAM now,
* to prepare to load "initialize" uCode */
- iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
+ iwl3945_write_prph(priv, BSM_WR_CTRL_REG,
BSM_WR_CTRL_REG_BIT_START);
/* Wait for load of bootstrap uCode to finish */
for (i = 0; i < 100; i++) {
- done = iwl_read_restricted_reg(priv, BSM_WR_CTRL_REG);
+ done = iwl3945_read_prph(priv, BSM_WR_CTRL_REG);
if (!(done & BSM_WR_CTRL_REG_BIT_START))
break;
udelay(10);
@@ -5766,29 +5767,29 @@ static int iwl_load_bsm(struct iwl_priv *priv)
/* Enable future boot loads whenever power management unit triggers it
* (e.g. when powering back up after power-save shutdown) */
- iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
+ iwl3945_write_prph(priv, BSM_WR_CTRL_REG,
BSM_WR_CTRL_REG_BIT_START_EN);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
return 0;
}
-static void iwl_nic_start(struct iwl_priv *priv)
+static void iwl3945_nic_start(struct iwl3945_priv *priv)
{
/* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
+ iwl3945_write32(priv, CSR_RESET, 0);
}
/**
- * iwl_read_ucode - Read uCode images from disk file.
+ * iwl3945_read_ucode - Read uCode images from disk file.
*
* Copy into buffers for card to fetch via bus-mastering
*/
-static int iwl_read_ucode(struct iwl_priv *priv)
+static int iwl3945_read_ucode(struct iwl3945_priv *priv)
{
- struct iwl_ucode *ucode;
- int rc = 0;
+ struct iwl3945_ucode *ucode;
+ int ret = 0;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
const char *name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode";
@@ -5798,9 +5799,10 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
- rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
- if (rc < 0) {
- IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
+ ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
+ if (ret < 0) {
+ IWL_ERROR("%s firmware file req failed: Reason %d\n",
+ name, ret);
goto error;
}
@@ -5810,7 +5812,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Make sure that we got at least our header! */
if (ucode_raw->size < sizeof(*ucode)) {
IWL_ERROR("File size way too small!\n");
- rc = -EINVAL;
+ ret = -EINVAL;
goto err_release;
}
@@ -5825,16 +5827,11 @@ static int iwl_read_ucode(struct iwl_priv *priv)
boot_size = le32_to_cpu(ucode->boot_size);
IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
- IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
- inst_size);
- IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
- data_size);
- IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n",
- init_size);
- IWL_DEBUG_INFO("f/w package hdr init data size = %u\n",
- init_data_size);
- IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n",
- boot_size);
+ IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
+ IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
+ IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
+ IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
+ IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
/* Verify size of file vs. image size info in file's header */
if (ucode_raw->size < sizeof(*ucode) +
@@ -5843,43 +5840,40 @@ static int iwl_read_ucode(struct iwl_priv *priv)
IWL_DEBUG_INFO("uCode file size %d too small\n",
(int)ucode_raw->size);
- rc = -EINVAL;
+ ret = -EINVAL;
goto err_release;
}
/* Verify that uCode images will fit in card's SRAM */
if (inst_size > IWL_MAX_INST_SIZE) {
- IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
- (int)inst_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
+ inst_size);
+ ret = -EINVAL;
goto err_release;
}
if (data_size > IWL_MAX_DATA_SIZE) {
- IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
- (int)data_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
+ data_size);
+ ret = -EINVAL;
goto err_release;
}
if (init_size > IWL_MAX_INST_SIZE) {
- IWL_DEBUG_INFO
- ("uCode init instr len %d too large to fit in card\n",
- (int)init_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode init instr len %d too large to fit in\n",
+ init_size);
+ ret = -EINVAL;
goto err_release;
}
if (init_data_size > IWL_MAX_DATA_SIZE) {
- IWL_DEBUG_INFO
- ("uCode init data len %d too large to fit in card\n",
- (int)init_data_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode init data len %d too large to fit in\n",
+ init_data_size);
+ ret = -EINVAL;
goto err_release;
}
if (boot_size > IWL_MAX_BSM_SIZE) {
- IWL_DEBUG_INFO
- ("uCode boot instr len %d too large to fit in bsm\n",
- (int)boot_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode boot instr len %d too large to fit in\n",
+ boot_size);
+ ret = -EINVAL;
goto err_release;
}
@@ -5889,66 +5883,54 @@ static int iwl_read_ucode(struct iwl_priv *priv)
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
priv->ucode_code.len = inst_size;
- priv->ucode_code.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_code.len,
- &(priv->ucode_code.p_addr));
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
priv->ucode_data.len = data_size;
- priv->ucode_data.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_data.len,
- &(priv->ucode_data.p_addr));
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
priv->ucode_data_backup.len = data_size;
- priv->ucode_data_backup.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_data_backup.len,
- &(priv->ucode_data_backup.p_addr));
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+ if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+ !priv->ucode_data_backup.v_addr)
+ goto err_pci_alloc;
/* Initialization instructions and data */
- priv->ucode_init.len = init_size;
- priv->ucode_init.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_init.len,
- &(priv->ucode_init.p_addr));
-
- priv->ucode_init_data.len = init_data_size;
- priv->ucode_init_data.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_init_data.len,
- &(priv->ucode_init_data.p_addr));
+ if (init_size && init_data_size) {
+ priv->ucode_init.len = init_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+ priv->ucode_init_data.len = init_data_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+ if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+ goto err_pci_alloc;
+ }
/* Bootstrap (instructions only, no data) */
- priv->ucode_boot.len = boot_size;
- priv->ucode_boot.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_boot.len,
- &(priv->ucode_boot.p_addr));
+ if (boot_size) {
+ priv->ucode_boot.len = boot_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
- if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
- !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
- !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
- goto err_pci_alloc;
+ if (!priv->ucode_boot.v_addr)
+ goto err_pci_alloc;
+ }
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
src = &ucode->data[0];
len = priv->ucode_code.len;
- IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
- * NOTE: Copy into backup buffer will be done in iwl_up() */
+ * NOTE: Copy into backup buffer will be done in iwl3945_up() */
src = &ucode->data[inst_size];
len = priv->ucode_data.len;
- IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
@@ -5956,8 +5938,8 @@ static int iwl_read_ucode(struct iwl_priv *priv)
if (init_size) {
src = &ucode->data[inst_size + data_size];
len = priv->ucode_init.len;
- IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n",
+ len);
memcpy(priv->ucode_init.v_addr, src, len);
}
@@ -5983,19 +5965,19 @@ static int iwl_read_ucode(struct iwl_priv *priv)
err_pci_alloc:
IWL_ERROR("failed to allocate pci memory\n");
- rc = -ENOMEM;
- iwl_dealloc_ucode_pci(priv);
+ ret = -ENOMEM;
+ iwl3945_dealloc_ucode_pci(priv);
err_release:
release_firmware(ucode_raw);
error:
- return rc;
+ return ret;
}
/**
- * iwl_set_ucode_ptrs - Set uCode address location
+ * iwl3945_set_ucode_ptrs - Set uCode address location
*
* Tell initialization uCode where to find runtime uCode.
*
@@ -6003,7 +5985,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
* We need to replace them to load runtime uCode inst and data,
* and to save runtime data when powering down.
*/
-static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
+static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
{
dma_addr_t pinst;
dma_addr_t pdata;
@@ -6015,24 +5997,24 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
pdata = priv->ucode_data_backup.p_addr;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
/* Tell bootstrap uCode where to find image to load */
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+ iwl3945_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl3945_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
priv->ucode_data.len);
/* Inst bytecount must be last to set up, bit 31 signals uCode
* that all new ptr/size info is in place */
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+ iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
priv->ucode_code.len | BSM_DRAM_INST_LOAD);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -6042,17 +6024,13 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
}
/**
- * iwl_init_alive_start - Called after REPLY_ALIVE notification receieved
+ * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
*
* Called after REPLY_ALIVE notification received from "initialize" uCode.
*
- * The 4965 "initialize" ALIVE reply contains calibration data for:
- * Voltage, temperature, and MIMO tx gain correction, now stored in priv
- * (3945 does not contain this data).
- *
* Tell "initialize" uCode to go ahead and load the runtime uCode.
-*/
-static void iwl_init_alive_start(struct iwl_priv *priv)
+ */
+static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
{
/* Check alive response for "valid" sign from uCode */
if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
@@ -6065,7 +6043,7 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "initialize" alive if code weren't properly loaded. */
- if (iwl_verify_ucode(priv)) {
+ if (iwl3945_verify_ucode(priv)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
@@ -6076,7 +6054,7 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
* load and launch runtime uCode, which will send us another "Alive"
* notification. */
IWL_DEBUG_INFO("Initialization Alive received.\n");
- if (iwl_set_ucode_ptrs(priv)) {
+ if (iwl3945_set_ucode_ptrs(priv)) {
/* Runtime instruction load won't happen;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
@@ -6090,11 +6068,11 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
/**
- * iwl_alive_start - called after REPLY_ALIVE notification received
+ * iwl3945_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
- * Alive gets handled by iwl_init_alive_start()).
+ * Alive gets handled by iwl3945_init_alive_start()).
*/
-static void iwl_alive_start(struct iwl_priv *priv)
+static void iwl3945_alive_start(struct iwl3945_priv *priv)
{
int rc = 0;
int thermal_spin = 0;
@@ -6112,30 +6090,30 @@ static void iwl_alive_start(struct iwl_priv *priv)
/* Initialize uCode has loaded Runtime uCode ... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "runtime" alive if code weren't properly loaded. */
- if (iwl_verify_ucode(priv)) {
+ if (iwl3945_verify_ucode(priv)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Bad runtime uCode load.\n");
goto restart;
}
- iwl_clear_stations_table(priv);
+ iwl3945_clear_stations_table(priv);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl3945_grab_nic_access(priv);
if (rc) {
IWL_WARNING("Can not read rfkill status from adapter\n");
return;
}
- rfkill = iwl_read_restricted_reg(priv, APMG_RFKILL_REG);
+ rfkill = iwl3945_read_prph(priv, APMG_RFKILL_REG);
IWL_DEBUG_INFO("RFKILL status: 0x%x\n", rfkill);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
if (rfkill & 0x1) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
/* if rfkill is not on, then wait for thermal
* sensor in adapter to kick in */
- while (iwl_hw_get_temperature(priv) == 0) {
+ while (iwl3945_hw_get_temperature(priv) == 0) {
thermal_spin++;
udelay(10);
}
@@ -6146,68 +6124,49 @@ static void iwl_alive_start(struct iwl_priv *priv)
} else
set_bit(STATUS_RF_KILL_HW, &priv->status);
- /* After the ALIVE response, we can process host commands */
+ /* After the ALIVE response, we can send commands to 3945 uCode */
set_bit(STATUS_ALIVE, &priv->status);
/* Clear out the uCode error bit if it is set */
clear_bit(STATUS_FW_ERROR, &priv->status);
- rc = iwl_init_channel_map(priv);
+ rc = iwl3945_init_channel_map(priv);
if (rc) {
IWL_ERROR("initializing regulatory failed: %d\n", rc);
return;
}
- iwl_init_geos(priv);
+ iwl3945_init_geos(priv);
+ iwl3945_reset_channel_flag(priv);
- if (iwl_is_rfkill(priv))
+ if (iwl3945_is_rfkill(priv))
return;
- if (!priv->mac80211_registered) {
- /* Unlock so any user space entry points can call back into
- * the driver without a deadlock... */
- mutex_unlock(&priv->mutex);
- iwl_rate_control_register(priv->hw);
- rc = ieee80211_register_hw(priv->hw);
- priv->hw->conf.beacon_int = 100;
- mutex_lock(&priv->mutex);
-
- if (rc) {
- iwl_rate_control_unregister(priv->hw);
- IWL_ERROR("Failed to register network "
- "device (error %d)\n", rc);
- return;
- }
-
- priv->mac80211_registered = 1;
-
- iwl_reset_channel_flag(priv);
- } else
- ieee80211_start_queues(priv->hw);
+ ieee80211_start_queues(priv->hw);
priv->active_rate = priv->rates_mask;
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
- iwl_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
+ iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
- if (iwl_is_associated(priv)) {
- struct iwl_rxon_cmd *active_rxon =
- (struct iwl_rxon_cmd *)(&priv->active_rxon);
+ if (iwl3945_is_associated(priv)) {
+ struct iwl3945_rxon_cmd *active_rxon =
+ (struct iwl3945_rxon_cmd *)(&priv->active_rxon);
memcpy(&priv->staging_rxon, &priv->active_rxon,
sizeof(priv->staging_rxon));
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv);
+ iwl3945_connection_init_rx_config(priv);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
}
- /* Configure BT coexistence */
- iwl_send_bt_config(priv);
+ /* Configure Bluetooth device coexistence support */
+ iwl3945_send_bt_config(priv);
/* Configure the adapter for unassociated operation */
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
/* At this point, the NIC is initialized and operational */
priv->notif_missed_beacons = 0;
@@ -6216,9 +6175,10 @@ static void iwl_alive_start(struct iwl_priv *priv)
iwl3945_reg_txpower_periodic(priv);
IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ wake_up_interruptible(&priv->wait_command_queue);
if (priv->error_recovering)
- iwl_error_recovery(priv);
+ iwl3945_error_recovery(priv);
return;
@@ -6226,9 +6186,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv);
+static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv);
-static void __iwl_down(struct iwl_priv *priv)
+static void __iwl3945_down(struct iwl3945_priv *priv)
{
unsigned long flags;
int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -6241,7 +6201,7 @@ static void __iwl_down(struct iwl_priv *priv)
if (!exit_pending)
set_bit(STATUS_EXIT_PENDING, &priv->status);
- iwl_clear_stations_table(priv);
+ iwl3945_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
@@ -6252,17 +6212,17 @@ static void __iwl_down(struct iwl_priv *priv)
clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* stop and reset the on-board processor */
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ iwl3945_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
+ iwl3945_disable_interrupts(priv);
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
- /* If we have not previously called iwl_init() then
+ /* If we have not previously called iwl3945_init() then
* clear all bits but the RF Kill and SUSPEND bits and return */
- if (!iwl_is_init(priv)) {
+ if (!iwl3945_is_init(priv)) {
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
STATUS_RF_KILL_HW |
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
@@ -6284,51 +6244,50 @@ static void __iwl_down(struct iwl_priv *priv)
STATUS_FW_ERROR;
spin_lock_irqsave(&priv->lock, flags);
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ iwl3945_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_hw_txq_ctx_stop(priv);
- iwl_hw_rxq_stop(priv);
+ iwl3945_hw_txq_ctx_stop(priv);
+ iwl3945_hw_rxq_stop(priv);
spin_lock_irqsave(&priv->lock, flags);
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
+ if (!iwl3945_grab_nic_access(priv)) {
+ iwl3945_write_prph(priv, APMG_CLK_DIS_REG,
APMG_CLK_VAL_DMA_CLK_RQT);
- iwl_release_restricted_access(priv);
+ iwl3945_release_nic_access(priv);
}
spin_unlock_irqrestore(&priv->lock, flags);
udelay(5);
- iwl_hw_nic_stop_master(priv);
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- iwl_hw_nic_reset(priv);
+ iwl3945_hw_nic_stop_master(priv);
+ iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl3945_hw_nic_reset(priv);
exit:
- memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+ memset(&priv->card_alive, 0, sizeof(struct iwl3945_alive_resp));
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
priv->ibss_beacon = NULL;
/* clear out any free frames */
- iwl_clear_free_frames(priv);
+ iwl3945_clear_free_frames(priv);
}
-static void iwl_down(struct iwl_priv *priv)
+static void iwl3945_down(struct iwl3945_priv *priv)
{
mutex_lock(&priv->mutex);
- __iwl_down(priv);
+ __iwl3945_down(priv);
mutex_unlock(&priv->mutex);
- iwl_cancel_deferred_work(priv);
+ iwl3945_cancel_deferred_work(priv);
}
#define MAX_HW_RESTARTS 5
-static int __iwl_up(struct iwl_priv *priv)
+static int __iwl3945_up(struct iwl3945_priv *priv)
{
- DECLARE_MAC_BUF(mac);
int rc, i;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
@@ -6339,44 +6298,65 @@ static int __iwl_up(struct iwl_priv *priv)
if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
IWL_WARNING("Radio disabled by SW RF kill (module "
"parameter)\n");
- return 0;
+ return -ENODEV;
}
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ /* If platform's RF_KILL switch is NOT set to KILL */
+ if (iwl3945_read32(priv, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ else {
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+ IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+ return -ENODEV;
+ }
+ }
- rc = iwl_hw_nic_init(priv);
+ if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+ IWL_ERROR("ucode not available for device bringup\n");
+ return -EIO;
+ }
+
+ iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+ rc = iwl3945_hw_nic_init(priv);
if (rc) {
IWL_ERROR("Unable to int nic\n");
return rc;
}
/* make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
/* clear (again), then enable host interrupts */
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl_enable_interrupts(priv);
+ iwl3945_write32(priv, CSR_INT, 0xFFFFFFFF);
+ iwl3945_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl3945_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Copy original ucode data image from disk into backup cache.
* This will be used to initialize the on-board processor's
* data SRAM for a clean start when the runtime program first loads. */
memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
- priv->ucode_data.len);
+ priv->ucode_data.len);
+
+ /* We return success when we resume from suspend and rf_kill is on. */
+ if (test_bit(STATUS_RF_KILL_HW, &priv->status))
+ return 0;
for (i = 0; i < MAX_HW_RESTARTS; i++) {
- iwl_clear_stations_table(priv);
+ iwl3945_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
* prepare to load the "initialize" uCode */
- rc = iwl_load_bsm(priv);
+ rc = iwl3945_load_bsm(priv);
if (rc) {
IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
@@ -6384,14 +6364,7 @@ static int __iwl_up(struct iwl_priv *priv)
}
/* start card; "initialize" will load runtime ucode */
- iwl_nic_start(priv);
-
- /* MAC Address location in EEPROM same for 3945/4965 */
- get_eeprom_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n",
- print_mac(mac, priv->mac_addr));
-
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ iwl3945_nic_start(priv);
IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
@@ -6399,7 +6372,7 @@ static int __iwl_up(struct iwl_priv *priv)
}
set_bit(STATUS_EXIT_PENDING, &priv->status);
- __iwl_down(priv);
+ __iwl3945_down(priv);
/* tried to restart and config the device for as long as our
* patience could withstand */
@@ -6414,35 +6387,35 @@ static int __iwl_up(struct iwl_priv *priv)
*
*****************************************************************************/
-static void iwl_bg_init_alive_start(struct work_struct *data)
+static void iwl3945_bg_init_alive_start(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, init_alive_start.work);
+ struct iwl3945_priv *priv =
+ container_of(data, struct iwl3945_priv, init_alive_start.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_init_alive_start(priv);
+ iwl3945_init_alive_start(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_alive_start(struct work_struct *data)
+static void iwl3945_bg_alive_start(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, alive_start.work);
+ struct iwl3945_priv *priv =
+ container_of(data, struct iwl3945_priv, alive_start.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_alive_start(priv);
+ iwl3945_alive_start(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_rf_kill(struct work_struct *work)
+static void iwl3945_bg_rf_kill(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+ struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, rf_kill);
wake_up_interruptible(&priv->wait_command_queue);
@@ -6451,7 +6424,7 @@ static void iwl_bg_rf_kill(struct work_struct *work)
mutex_lock(&priv->mutex);
- if (!iwl_is_rfkill(priv)) {
+ if (!iwl3945_is_rfkill(priv)) {
IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
"HW and/or SW RF Kill no longer active, restarting "
"device\n");
@@ -6472,10 +6445,10 @@ static void iwl_bg_rf_kill(struct work_struct *work)
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-static void iwl_bg_scan_check(struct work_struct *data)
+static void iwl3945_bg_scan_check(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, scan_check.work);
+ struct iwl3945_priv *priv =
+ container_of(data, struct iwl3945_priv, scan_check.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -6488,22 +6461,22 @@ static void iwl_bg_scan_check(struct work_struct *data)
jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- iwl_send_scan_abort(priv);
+ iwl3945_send_scan_abort(priv);
}
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_request_scan(struct work_struct *data)
+static void iwl3945_bg_request_scan(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, request_scan);
- struct iwl_host_cmd cmd = {
+ struct iwl3945_priv *priv =
+ container_of(data, struct iwl3945_priv, request_scan);
+ struct iwl3945_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
- .len = sizeof(struct iwl_scan_cmd),
+ .len = sizeof(struct iwl3945_scan_cmd),
.meta.flags = CMD_SIZE_HUGE,
};
int rc = 0;
- struct iwl_scan_cmd *scan;
+ struct iwl3945_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u8 direct_mask;
int phymode;
@@ -6512,7 +6485,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
mutex_lock(&priv->mutex);
- if (!iwl_is_ready(priv)) {
+ if (!iwl3945_is_ready(priv)) {
IWL_WARNING("request scan called when driver not ready.\n");
goto done;
}
@@ -6541,7 +6514,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
- if (iwl_is_rfkill(priv)) {
+ if (iwl3945_is_rfkill(priv)) {
IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
goto done;
}
@@ -6557,7 +6530,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
}
if (!priv->scan) {
- priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
+ priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
rc = -ENOMEM;
@@ -6565,12 +6538,12 @@ static void iwl_bg_request_scan(struct work_struct *data)
}
}
scan = priv->scan;
- memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+ memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
- if (iwl_is_associated(priv)) {
+ if (iwl3945_is_associated(priv)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
@@ -6607,14 +6580,14 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (priv->one_direct_scan) {
IWL_DEBUG_SCAN
("Kicking off one direct scan for '%s'\n",
- iwl_escape_essid(priv->direct_ssid,
+ iwl3945_escape_essid(priv->direct_ssid,
priv->direct_ssid_len));
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
direct_mask = 1;
- } else if (!iwl_is_associated(priv) && priv->essid_len) {
+ } else if (!iwl3945_is_associated(priv) && priv->essid_len) {
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->essid_len;
memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
@@ -6625,7 +6598,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.len = cpu_to_le16(
- iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+ iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
@@ -6661,23 +6634,23 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (direct_mask)
IWL_DEBUG_SCAN
("Initiating direct scan for %s.\n",
- iwl_escape_essid(priv->essid, priv->essid_len));
+ iwl3945_escape_essid(priv->essid, priv->essid_len));
else
IWL_DEBUG_SCAN("Initiating indirect scan.\n");
scan->channel_count =
- iwl_get_channels_for_scan(
+ iwl3945_get_channels_for_scan(
priv, phymode, 1, /* active */
direct_mask,
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
- scan->channel_count * sizeof(struct iwl_scan_channel);
+ scan->channel_count * sizeof(struct iwl3945_scan_channel);
cmd.data = scan;
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl3945_send_cmd_sync(priv, &cmd);
if (rc)
goto done;
@@ -6688,50 +6661,52 @@ static void iwl_bg_request_scan(struct work_struct *data)
return;
done:
- /* inform mac80211 sacn aborted */
+ /* inform mac80211 scan aborted */
queue_work(priv->workqueue, &priv->scan_completed);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_up(struct work_struct *data)
+static void iwl3945_bg_up(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+ struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, up);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- __iwl_up(priv);
+ __iwl3945_up(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_restart(struct work_struct *data)
+static void iwl3945_bg_restart(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+ struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv, restart);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- iwl_down(priv);
+ iwl3945_down(priv);
queue_work(priv->workqueue, &priv->up);
}
-static void iwl_bg_rx_replenish(struct work_struct *data)
+static void iwl3945_bg_rx_replenish(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, rx_replenish);
+ struct iwl3945_priv *priv =
+ container_of(data, struct iwl3945_priv, rx_replenish);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_rx_replenish(priv);
+ iwl3945_rx_replenish(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_post_associate(struct work_struct *data)
+#define IWL_DELAY_NEXT_SCAN (HZ*2)
+
+static void iwl3945_bg_post_associate(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv,
+ struct iwl3945_priv *priv = container_of(data, struct iwl3945_priv,
post_associate.work);
int rc = 0;
@@ -6753,20 +6728,20 @@ static void iwl_bg_post_associate(struct work_struct *data)
mutex_lock(&priv->mutex);
- if (!priv->interface_id || !priv->is_open) {
+ if (!priv->vif || !priv->is_open) {
mutex_unlock(&priv->mutex);
return;
}
- iwl_scan_cancel_timeout(priv, 200);
+ iwl3945_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd));
+ iwl3945_setup_rxon_timing(priv);
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
IWL_WARNING("REPLY_RXON_TIMING failed - "
@@ -6795,75 +6770,81 @@ static void iwl_bg_post_associate(struct work_struct *data)
}
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
- iwl_rate_scale_init(priv->hw, IWL_AP_ID);
+ iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
break;
case IEEE80211_IF_TYPE_IBSS:
/* clear out the station table */
- iwl_clear_stations_table(priv);
+ iwl3945_clear_stations_table(priv);
- iwl_add_station(priv, BROADCAST_ADDR, 0, 0);
- iwl_add_station(priv, priv->bssid, 0, 0);
+ iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+ iwl3945_add_station(priv, priv->bssid, 0, 0);
iwl3945_sync_sta(priv, IWL_STA_ID,
(priv->phymode == MODE_IEEE80211A)?
IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
CMD_ASYNC);
- iwl_rate_scale_init(priv->hw, IWL_STA_ID);
- iwl_send_beacon_cmd(priv);
+ iwl3945_rate_scale_init(priv->hw, IWL_STA_ID);
+ iwl3945_send_beacon_cmd(priv);
break;
default:
IWL_ERROR("%s Should not be called in %d mode\n",
- __FUNCTION__, priv->iw_mode);
+ __FUNCTION__, priv->iw_mode);
break;
}
- iwl_sequence_reset(priv);
+ iwl3945_sequence_reset(priv);
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_activate_qos(priv, 0);
-#endif /* CONFIG_IWLWIFI_QOS */
+#ifdef CONFIG_IWL3945_QOS
+ iwl3945_activate_qos(priv, 0);
+#endif /* CONFIG_IWL3945_QOS */
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_abort_scan(struct work_struct *work)
+static void iwl3945_bg_abort_scan(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
- abort_scan);
+ struct iwl3945_priv *priv = container_of(work, struct iwl3945_priv, abort_scan);
- if (!iwl_is_ready(priv))
+ if (!iwl3945_is_ready(priv))
return;
mutex_lock(&priv->mutex);
set_bit(STATUS_SCAN_ABORTING, &priv->status);
- iwl_send_scan_abort(priv);
+ iwl3945_send_scan_abort(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_scan_completed(struct work_struct *work)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+
+static void iwl3945_bg_scan_completed(struct work_struct *work)
{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, scan_completed);
+ struct iwl3945_priv *priv =
+ container_of(work, struct iwl3945_priv, scan_completed);
IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
+ if (test_bit(STATUS_CONF_PENDING, &priv->status))
+ iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+
ieee80211_scan_completed(priv->hw);
/* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */
mutex_lock(&priv->mutex);
- iwl_hw_reg_send_txpower(priv);
+ iwl3945_hw_reg_send_txpower(priv);
mutex_unlock(&priv->mutex);
}
@@ -6873,50 +6854,123 @@ static void iwl_bg_scan_completed(struct work_struct *work)
*
*****************************************************************************/
-static int iwl_mac_start(struct ieee80211_hw *hw)
+#define UCODE_READY_TIMEOUT (2 * HZ)
+
+static int iwl3945_mac_start(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
+ int ret;
IWL_DEBUG_MAC80211("enter\n");
+ if (pci_enable_device(priv->pci_dev)) {
+ IWL_ERROR("Fail to pci_enable_device\n");
+ return -ENODEV;
+ }
+ pci_restore_state(priv->pci_dev);
+ pci_enable_msi(priv->pci_dev);
+
+ ret = request_irq(priv->pci_dev->irq, iwl3945_isr, IRQF_SHARED,
+ DRV_NAME, priv);
+ if (ret) {
+ IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
+ goto out_disable_msi;
+ }
+
/* we should be verifying the device is ready to be opened */
mutex_lock(&priv->mutex);
- priv->is_open = 1;
+ memset(&priv->staging_rxon, 0, sizeof(struct iwl3945_rxon_cmd));
+ /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+ * ucode filename and max sizes are card-specific. */
- if (!iwl_is_rfkill(priv))
- ieee80211_start_queues(priv->hw);
+ if (!priv->ucode_code.len) {
+ ret = iwl3945_read_ucode(priv);
+ if (ret) {
+ IWL_ERROR("Could not read microcode: %d\n", ret);
+ mutex_unlock(&priv->mutex);
+ goto out_release_irq;
+ }
+ }
+
+ ret = __iwl3945_up(priv);
mutex_unlock(&priv->mutex);
+
+ if (ret)
+ goto out_release_irq;
+
+ IWL_DEBUG_INFO("Start UP work.\n");
+
+ if (test_bit(STATUS_IN_SUSPEND, &priv->status))
+ return 0;
+
+ /* Wait for START_ALIVE from ucode. Otherwise callbacks from
+ * mac80211 will not be run successfully. */
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ test_bit(STATUS_READY, &priv->status),
+ UCODE_READY_TIMEOUT);
+ if (!ret) {
+ if (!test_bit(STATUS_READY, &priv->status)) {
+ IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
+ jiffies_to_msecs(UCODE_READY_TIMEOUT));
+ ret = -ETIMEDOUT;
+ goto out_release_irq;
+ }
+ }
+
+ priv->is_open = 1;
IWL_DEBUG_MAC80211("leave\n");
return 0;
+
+out_release_irq:
+ free_irq(priv->pci_dev->irq, priv);
+out_disable_msi:
+ pci_disable_msi(priv->pci_dev);
+ pci_disable_device(priv->pci_dev);
+ priv->is_open = 0;
+ IWL_DEBUG_MAC80211("leave - failed\n");
+ return ret;
}
-static void iwl_mac_stop(struct ieee80211_hw *hw)
+static void iwl3945_mac_stop(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
+ if (!priv->is_open) {
+ IWL_DEBUG_MAC80211("leave - skip\n");
+ return;
+ }
- mutex_lock(&priv->mutex);
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
priv->is_open = 0;
- iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
- mutex_unlock(&priv->mutex);
+
+ if (iwl3945_is_ready_rf(priv)) {
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
+ mutex_lock(&priv->mutex);
+ iwl3945_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ mutex_unlock(&priv->mutex);
+ }
+
+ iwl3945_down(priv);
+
+ flush_workqueue(priv->workqueue);
+ free_irq(priv->pci_dev->irq, priv);
+ pci_disable_msi(priv->pci_dev);
+ pci_save_state(priv->pci_dev);
+ pci_disable_device(priv->pci_dev);
IWL_DEBUG_MAC80211("leave\n");
}
-static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *ctl)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
@@ -6928,29 +6982,29 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate);
- if (iwl_tx_skb(priv, skb, ctl))
+ if (iwl3945_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
-static int iwl_mac_add_interface(struct ieee80211_hw *hw,
+static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
DECLARE_MAC_BUF(mac);
- IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
+ IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
- if (priv->interface_id) {
- IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
+ if (priv->vif) {
+ IWL_DEBUG_MAC80211("leave - vif != NULL\n");
return -EOPNOTSUPP;
}
spin_lock_irqsave(&priv->lock, flags);
- priv->interface_id = conf->if_id;
+ priv->vif = conf->vif;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -6961,106 +7015,108 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
- iwl_set_mode(priv, conf->type);
+ if (iwl3945_is_ready(priv))
+ iwl3945_set_mode(priv, conf->type);
- IWL_DEBUG_MAC80211("leave\n");
mutex_unlock(&priv->mutex);
+ IWL_DEBUG_MAC80211("leave\n");
return 0;
}
/**
- * iwl_mac_config - mac80211 config callback
+ * iwl3945_mac_config - mac80211 config callback
*
* We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
* be set inappropriately and the driver currently sets the hardware up to
* use it whenever needed.
*/
-static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
- const struct iwl_channel_info *ch_info;
+ struct iwl3945_priv *priv = hw->priv;
+ const struct iwl3945_channel_info *ch_info;
unsigned long flags;
+ int ret = 0;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
- if (!iwl_is_ready(priv)) {
+ priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
+ if (!iwl3945_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n");
- mutex_unlock(&priv->mutex);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
- * what is exposed through include/ declrations */
- if (unlikely(!iwl_param_disable_hw_scan &&
+ if (unlikely(!iwl3945_param_disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211("leave - scanning\n");
+ set_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
return 0;
}
spin_lock_irqsave(&priv->lock, flags);
- ch_info = iwl_get_channel_info(priv, conf->phymode, conf->channel);
+ ch_info = iwl3945_get_channel_info(priv, conf->phymode, conf->channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
conf->channel, conf->phymode);
IWL_DEBUG_MAC80211("leave - invalid channel\n");
spin_unlock_irqrestore(&priv->lock, flags);
- mutex_unlock(&priv->mutex);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
- iwl_set_rxon_channel(priv, conf->phymode, conf->channel);
+ iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel);
- iwl_set_flags_for_phymode(priv, conf->phymode);
+ iwl3945_set_flags_for_phymode(priv, conf->phymode);
/* The list of supported rates and rate mask can be different
* for each phymode; since the phymode may have changed, reset
* the rate mask to what mac80211 lists */
- iwl_set_rate(priv);
+ iwl3945_set_rate(priv);
spin_unlock_irqrestore(&priv->lock, flags);
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
- iwl_hw_channel_switch(priv, conf->channel);
- mutex_unlock(&priv->mutex);
- return 0;
+ iwl3945_hw_channel_switch(priv, conf->channel);
+ goto out;
}
#endif
- iwl_radio_kill_sw(priv, !conf->radio_enabled);
+ iwl3945_radio_kill_sw(priv, !conf->radio_enabled);
if (!conf->radio_enabled) {
IWL_DEBUG_MAC80211("leave - radio disabled\n");
- mutex_unlock(&priv->mutex);
- return 0;
+ goto out;
}
- if (iwl_is_rfkill(priv)) {
+ if (iwl3945_is_rfkill(priv)) {
IWL_DEBUG_MAC80211("leave - RF kill\n");
- mutex_unlock(&priv->mutex);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- iwl_set_rate(priv);
+ iwl3945_set_rate(priv);
if (memcmp(&priv->active_rxon,
&priv->staging_rxon, sizeof(priv->staging_rxon)))
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
else
IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
IWL_DEBUG_MAC80211("leave\n");
+out:
+ clear_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
-
- return 0;
+ return ret;
}
-static void iwl_config_ap(struct iwl_priv *priv)
+static void iwl3945_config_ap(struct iwl3945_priv *priv)
{
int rc = 0;
@@ -7072,12 +7128,12 @@ static void iwl_config_ap(struct iwl_priv *priv)
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
/* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl3945_rxon_time_cmd));
+ iwl3945_setup_rxon_timing(priv);
+ rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
IWL_WARNING("REPLY_RXON_TIMING failed - "
@@ -7107,20 +7163,21 @@ static void iwl_config_ap(struct iwl_priv *priv)
}
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
- iwl_add_station(priv, BROADCAST_ADDR, 0, 0);
+ iwl3945_commit_rxon(priv);
+ iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
}
- iwl_send_beacon_cmd(priv);
+ iwl3945_send_beacon_cmd(priv);
/* FIXME - we need to add code here to detect a totally new
* configuration, reset the AP, unassoc, rxon timing, assoc,
* clear sta table, add BCAST sta... */
}
-static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
+static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
unsigned long flags;
int rc;
@@ -7137,9 +7194,11 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
+ if (!iwl3945_is_alive(priv))
+ return -EAGAIN;
+
mutex_lock(&priv->mutex);
- IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
if (conf->bssid)
IWL_DEBUG_MAC80211("bssid: %s\n",
print_mac(mac, conf->bssid));
@@ -7156,8 +7215,8 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
- if (priv->interface_id != if_id) {
- IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
+ if (priv->vif != vif) {
+ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
mutex_unlock(&priv->mutex);
return 0;
}
@@ -7175,11 +7234,14 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
priv->ibss_beacon = conf->beacon;
}
+ if (iwl3945_is_rfkill(priv))
+ goto done;
+
if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
!is_multicast_ether_addr(conf->bssid)) {
/* If there is currently a HW scan going on in the background
* then we need to cancel it else the RXON below will fail. */
- if (iwl_scan_cancel_timeout(priv, 100)) {
+ if (iwl3945_scan_cancel_timeout(priv, 100)) {
IWL_WARNING("Aborted scan still in progress "
"after 100ms\n");
IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
@@ -7195,20 +7257,21 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl_config_ap(priv);
+ iwl3945_config_ap(priv);
else {
- rc = iwl_commit_rxon(priv);
+ rc = iwl3945_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
- iwl_add_station(priv,
+ iwl3945_add_station(priv,
priv->active_rxon.bssid_addr, 1, 0);
}
} else {
- iwl_scan_cancel_timeout(priv, 100);
+ iwl3945_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
}
+ done:
spin_lock_irqsave(&priv->lock, flags);
if (!conf->ssid_len)
memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
@@ -7224,34 +7287,35 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
-static void iwl_configure_filter(struct ieee80211_hw *hw,
+static void iwl3945_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
/*
* XXX: dummy
- * see also iwl_connection_init_rx_config
+ * see also iwl3945_connection_init_rx_config
*/
*total_flags = 0;
}
-static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
-
- if (priv->interface_id == conf->if_id) {
- priv->interface_id = 0;
+ if (iwl3945_is_ready_rf(priv)) {
+ iwl3945_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl3945_commit_rxon(priv);
+ }
+ if (priv->vif == conf->vif) {
+ priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
priv->essid_len = 0;
@@ -7259,22 +7323,20 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211("leave\n");
-
}
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
{
int rc = 0;
unsigned long flags;
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl3945_is_ready_rf(priv)) {
rc = -EIO;
IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
goto out_unlock;
@@ -7286,17 +7348,21 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
+ /* we don't schedule scan within next_scan_jiffies period */
+ if (priv->next_scan_jiffies &&
+ time_after(priv->next_scan_jiffies, jiffies)) {
+ rc = -EAGAIN;
+ goto out_unlock;
+ }
/* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies &&
- time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
- jiffies)) {
+ if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
+ IWL_DELAY_NEXT_SCAN, jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
if (len) {
- IWL_DEBUG_SCAN("direct scan for "
- "%s [%d]\n ",
- iwl_escape_essid(ssid, len), (int)len);
+ IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
+ iwl3945_escape_essid(ssid, len), (int)len);
priv->one_direct_scan = 1;
priv->direct_ssid_len = (u8)
@@ -7305,7 +7371,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
} else
priv->one_direct_scan = 0;
- rc = iwl_scan_initiate(priv);
+ rc = iwl3945_scan_initiate(priv);
IWL_DEBUG_MAC80211("leave\n");
@@ -7316,17 +7382,17 @@ out_unlock:
return rc;
}
-static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
int rc = 0;
u8 sta_id;
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_param_hwcrypto) {
+ if (!iwl3945_param_hwcrypto) {
IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
@@ -7335,7 +7401,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* only support pairwise keys */
return -EOPNOTSUPP;
- sta_id = iwl_hw_find_station(priv, addr);
+ sta_id = iwl3945_hw_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
DECLARE_MAC_BUF(mac);
@@ -7346,24 +7412,24 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
+ iwl3945_scan_cancel_timeout(priv, 100);
switch (cmd) {
case SET_KEY:
- rc = iwl_update_sta_key_info(priv, key, sta_id);
+ rc = iwl3945_update_sta_key_info(priv, key, sta_id);
if (!rc) {
- iwl_set_rxon_hwcrypto(priv, 1);
- iwl_commit_rxon(priv);
+ iwl3945_set_rxon_hwcrypto(priv, 1);
+ iwl3945_commit_rxon(priv);
key->hw_key_idx = sta_id;
IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
}
break;
case DISABLE_KEY:
- rc = iwl_clear_sta_key_info(priv, sta_id);
+ rc = iwl3945_clear_sta_key_info(priv, sta_id);
if (!rc) {
- iwl_set_rxon_hwcrypto(priv, 0);
- iwl_commit_rxon(priv);
+ iwl3945_set_rxon_hwcrypto(priv, 0);
+ iwl3945_commit_rxon(priv);
IWL_DEBUG_MAC80211("disable hwcrypto key\n");
}
break;
@@ -7377,18 +7443,18 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return rc;
}
-static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
{
- struct iwl_priv *priv = hw->priv;
-#ifdef CONFIG_IWLWIFI_QOS
+ struct iwl3945_priv *priv = hw->priv;
+#ifdef CONFIG_IWL3945_QOS
unsigned long flags;
int q;
-#endif /* CONFIG_IWL_QOS */
+#endif /* CONFIG_IWL3945_QOS */
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
return -EIO;
}
@@ -7398,7 +7464,7 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
return 0;
}
-#ifdef CONFIG_IWLWIFI_QOS
+#ifdef CONFIG_IWL3945_QOS
if (!priv->qos_data.qos_enable) {
priv->qos_data.qos_active = 0;
IWL_DEBUG_MAC80211("leave - qos not enabled\n");
@@ -7421,30 +7487,30 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
mutex_lock(&priv->mutex);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl_activate_qos(priv, 1);
- else if (priv->assoc_id && iwl_is_associated(priv))
- iwl_activate_qos(priv, 0);
+ iwl3945_activate_qos(priv, 1);
+ else if (priv->assoc_id && iwl3945_is_associated(priv))
+ iwl3945_activate_qos(priv, 0);
mutex_unlock(&priv->mutex);
-#endif /*CONFIG_IWLWIFI_QOS */
+#endif /*CONFIG_IWL3945_QOS */
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
-static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+static int iwl3945_mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
int i, avail;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
+ struct iwl3945_tx_queue *txq;
+ struct iwl3945_queue *q;
unsigned long flags;
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
return -EIO;
}
@@ -7454,7 +7520,7 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
for (i = 0; i < AC_NUM; i++) {
txq = &priv->txq[i];
q = &txq->q;
- avail = iwl_queue_space(q);
+ avail = iwl3945_queue_space(q);
stats->data[i].len = q->n_window - avail;
stats->data[i].limit = q->n_window - q->high_mark;
@@ -7468,7 +7534,7 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
return 0;
}
-static int iwl_mac_get_stats(struct ieee80211_hw *hw,
+static int iwl3945_mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
IWL_DEBUG_MAC80211("enter\n");
@@ -7477,7 +7543,7 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
+static u64 iwl3945_mac_get_tsf(struct ieee80211_hw *hw)
{
IWL_DEBUG_MAC80211("enter\n");
IWL_DEBUG_MAC80211("leave\n");
@@ -7485,16 +7551,16 @@ static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
return 0;
}
-static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
+static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_reset_qos(priv);
+#ifdef CONFIG_IWL3945_QOS
+ iwl3945_reset_qos(priv);
#endif
cancel_delayed_work(&priv->post_associate);
@@ -7517,13 +7583,19 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&priv->lock, flags);
+ if (!iwl3945_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - not ready\n");
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
- iwl_scan_cancel_timeout(priv, 100);
+ iwl3945_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
}
/* Per mac80211.h: This is only used in IBSS mode... */
@@ -7534,15 +7606,9 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
return;
}
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - not ready\n");
- mutex_unlock(&priv->mutex);
- return;
- }
-
priv->only_active_channel = 0;
- iwl_set_rate(priv);
+ iwl3945_set_rate(priv);
mutex_unlock(&priv->mutex);
@@ -7550,16 +7616,16 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
}
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
mutex_unlock(&priv->mutex);
return -EIO;
@@ -7583,8 +7649,8 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_reset_qos(priv);
+#ifdef CONFIG_IWL3945_QOS
+ iwl3945_reset_qos(priv);
#endif
queue_work(priv->workqueue, &priv->post_associate.work);
@@ -7600,7 +7666,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
*
*****************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL3945_DEBUG
/*
* The following adds a new attribute to the sysfs representation
@@ -7612,7 +7678,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
static ssize_t show_debug_level(struct device_driver *d, char *buf)
{
- return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ return sprintf(buf, "0x%08X\n", iwl3945_debug_level);
}
static ssize_t store_debug_level(struct device_driver *d,
const char *buf, size_t count)
@@ -7625,7 +7691,7 @@ static ssize_t store_debug_level(struct device_driver *d,
printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf);
else
- iwl_debug_level = val;
+ iwl3945_debug_level = val;
return strnlen(buf, count);
}
@@ -7633,7 +7699,7 @@ static ssize_t store_debug_level(struct device_driver *d,
static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
show_debug_level, store_debug_level);
-#endif /* CONFIG_IWLWIFI_DEBUG */
+#endif /* CONFIG_IWL3945_DEBUG */
static ssize_t show_rf_kill(struct device *d,
struct device_attribute *attr, char *buf)
@@ -7644,7 +7710,7 @@ static ssize_t show_rf_kill(struct device *d,
* 2 - HW based RF kill active
* 3 - Both HW and SW based RF kill active
*/
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
(test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
@@ -7655,10 +7721,10 @@ static ssize_t store_rf_kill(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
mutex_lock(&priv->mutex);
- iwl_radio_kill_sw(priv, buf[0] == '1');
+ iwl3945_radio_kill_sw(priv, buf[0] == '1');
mutex_unlock(&priv->mutex);
return count;
@@ -7669,12 +7735,12 @@ static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
- if (!iwl_is_alive(priv))
+ if (!iwl3945_is_alive(priv))
return -EAGAIN;
- return sprintf(buf, "%d\n", iwl_hw_get_temperature(priv));
+ return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
}
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
@@ -7683,15 +7749,15 @@ static ssize_t show_rs_window(struct device *d,
struct device_attribute *attr,
char *buf)
{
- struct iwl_priv *priv = d->driver_data;
- return iwl_fill_rs_info(priv->hw, buf, IWL_AP_ID);
+ struct iwl3945_priv *priv = d->driver_data;
+ return iwl3945_fill_rs_info(priv->hw, buf, IWL_AP_ID);
}
static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
static ssize_t show_tx_power(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
return sprintf(buf, "%d\n", priv->user_txpower_limit);
}
@@ -7699,7 +7765,7 @@ static ssize_t store_tx_power(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
char *p = (char *)buf;
u32 val;
@@ -7708,7 +7774,7 @@ static ssize_t store_tx_power(struct device *d,
printk(KERN_INFO DRV_NAME
": %s is not in decimal form.\n", buf);
else
- iwl_hw_reg_set_txpower(priv, val);
+ iwl3945_hw_reg_set_txpower(priv, val);
return count;
}
@@ -7718,7 +7784,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
static ssize_t show_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
}
@@ -7727,19 +7793,19 @@ static ssize_t store_flags(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
u32 flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl3945_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
flags);
priv->staging_rxon.flags = cpu_to_le32(flags);
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -7752,7 +7818,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
static ssize_t show_filter_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n",
le32_to_cpu(priv->active_rxon.filter_flags));
@@ -7762,20 +7828,20 @@ static ssize_t store_filter_flags(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
u32 filter_flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl3945_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing rxon.filter_flags = "
"0x%04X\n", filter_flags);
priv->staging_rxon.filter_flags =
cpu_to_le32(filter_flags);
- iwl_commit_rxon(priv);
+ iwl3945_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -7789,20 +7855,20 @@ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
static ssize_t show_tune(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n",
(priv->phymode << 8) |
le16_to_cpu(priv->active_rxon.channel));
}
-static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode);
+static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv, u8 phymode);
static ssize_t store_tune(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
char *p = (char *)buf;
u16 tune = simple_strtoul(p, &p, 0);
u8 phymode = (tune >> 8) & 0xff;
@@ -7813,9 +7879,9 @@ static ssize_t store_tune(struct device *d,
mutex_lock(&priv->mutex);
if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
(priv->phymode != phymode)) {
- const struct iwl_channel_info *ch_info;
+ const struct iwl3945_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv, phymode, channel);
+ ch_info = iwl3945_get_channel_info(priv, phymode, channel);
if (!ch_info) {
IWL_WARNING("Requested invalid phymode/channel "
"combination: %d %d\n", phymode, channel);
@@ -7824,18 +7890,18 @@ static ssize_t store_tune(struct device *d,
}
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl3945_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing phymode and "
"rxon.channel = %d %d\n",
phymode, channel);
- iwl_set_rxon_channel(priv, phymode, channel);
- iwl_set_flags_for_phymode(priv, phymode);
+ iwl3945_set_rxon_channel(priv, phymode, channel);
+ iwl3945_set_flags_for_phymode(priv, phymode);
- iwl_set_rate(priv);
- iwl_commit_rxon(priv);
+ iwl3945_set_rate(priv);
+ iwl3945_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -7845,13 +7911,13 @@ static ssize_t store_tune(struct device *d,
static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
static ssize_t show_measurement(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl_spectrum_notification measure_report;
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_spectrum_notification measure_report;
u32 size = sizeof(measure_report), len = 0, ofs = 0;
u8 *data = (u8 *) & measure_report;
unsigned long flags;
@@ -7883,7 +7949,7 @@ static ssize_t store_measurement(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
struct ieee80211_measurement_params params = {
.channel = le16_to_cpu(priv->active_rxon.channel),
.start_time = cpu_to_le64(priv->last_tsf),
@@ -7909,19 +7975,19 @@ static ssize_t store_measurement(struct device *d,
IWL_DEBUG_INFO("Invoking measurement of type %d on "
"channel %d (for '%s')\n", type, params.channel, buf);
- iwl_get_measurement(priv, &params, type);
+ iwl3945_get_measurement(priv, &params, type);
return count;
}
static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
show_measurement, store_measurement);
-#endif /* CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT */
+#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */
static ssize_t show_rate(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
unsigned long flags;
int i;
@@ -7932,13 +7998,13 @@ static ssize_t show_rate(struct device *d,
i = priv->stations[IWL_STA_ID].current_rate.s.rate;
spin_unlock_irqrestore(&priv->sta_lock, flags);
- i = iwl_rate_index_from_plcp(i);
+ i = iwl3945_rate_index_from_plcp(i);
if (i == -1)
return sprintf(buf, "0\n");
return sprintf(buf, "%d%s\n",
- (iwl_rates[i].ieee >> 1),
- (iwl_rates[i].ieee & 0x1) ? ".5" : "");
+ (iwl3945_rates[i].ieee >> 1),
+ (iwl3945_rates[i].ieee & 0x1) ? ".5" : "");
}
static DEVICE_ATTR(rate, S_IRUSR, show_rate, NULL);
@@ -7947,7 +8013,7 @@ static ssize_t store_retry_rate(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
priv->retry_rate = simple_strtoul(buf, NULL, 0);
if (priv->retry_rate <= 0)
@@ -7959,7 +8025,7 @@ static ssize_t store_retry_rate(struct device *d,
static ssize_t show_retry_rate(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
return sprintf(buf, "%d", priv->retry_rate);
}
@@ -7970,14 +8036,14 @@ static ssize_t store_power_level(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
int rc;
int mode;
mode = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
- if (!iwl_is_ready(priv)) {
+ if (!iwl3945_is_ready(priv)) {
rc = -EAGAIN;
goto out;
}
@@ -7988,7 +8054,7 @@ static ssize_t store_power_level(struct device *d,
mode |= IWL_POWER_ENABLED;
if (mode != priv->power_mode) {
- rc = iwl_send_power_mode(priv, IWL_POWER_LEVEL(mode));
+ rc = iwl3945_send_power_mode(priv, IWL_POWER_LEVEL(mode));
if (rc) {
IWL_DEBUG_MAC80211("failed setting power mode.\n");
goto out;
@@ -8024,7 +8090,7 @@ static const s32 period_duration[] = {
static ssize_t show_power_level(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
int level = IWL_POWER_LEVEL(priv->power_mode);
char *p = buf;
@@ -8059,18 +8125,18 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
static ssize_t show_channels(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
int len = 0, i;
struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode = NULL;
int count = 0;
- if (!iwl_is_ready(priv))
+ if (!iwl3945_is_ready(priv))
return -EAGAIN;
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211G);
+ hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211G);
if (!hw_mode)
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211B);
+ hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211B);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
@@ -8097,7 +8163,7 @@ static ssize_t show_channels(struct device *d,
flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
"active/passive" : "passive only");
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211A);
+ hw_mode = iwl3945_get_hw_mode(priv, MODE_IEEE80211A);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
@@ -8133,17 +8199,17 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
- u32 size = sizeof(struct iwl_notif_statistics);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
+ u32 size = sizeof(struct iwl3945_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
int rc = 0;
- if (!iwl_is_alive(priv))
+ if (!iwl3945_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
- rc = iwl_send_statistics_request(priv);
+ rc = iwl3945_send_statistics_request(priv);
mutex_unlock(&priv->mutex);
if (rc) {
@@ -8171,9 +8237,9 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
static ssize_t show_antenna(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
- if (!iwl_is_alive(priv))
+ if (!iwl3945_is_alive(priv))
return -EAGAIN;
return sprintf(buf, "%d\n", priv->antenna);
@@ -8184,7 +8250,7 @@ static ssize_t store_antenna(struct device *d,
const char *buf, size_t count)
{
int ant;
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl3945_priv *priv = dev_get_drvdata(d);
if (count == 0)
return 0;
@@ -8196,7 +8262,7 @@ static ssize_t store_antenna(struct device *d,
if ((ant >= 0) && (ant <= 2)) {
IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
- priv->antenna = (enum iwl_antenna)ant;
+ priv->antenna = (enum iwl3945_antenna)ant;
} else
IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
@@ -8209,8 +8275,8 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
static ssize_t show_status(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- if (!iwl_is_alive(priv))
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)d->driver_data;
+ if (!iwl3945_is_alive(priv))
return -EAGAIN;
return sprintf(buf, "0x%08x\n", (int)priv->status);
}
@@ -8224,7 +8290,7 @@ static ssize_t dump_error_log(struct device *d,
char *p = (char *)buf;
if (p[0] == '1')
- iwl_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+ iwl3945_dump_nic_error_log((struct iwl3945_priv *)d->driver_data);
return strnlen(buf, count);
}
@@ -8238,7 +8304,7 @@ static ssize_t dump_event_log(struct device *d,
char *p = (char *)buf;
if (p[0] == '1')
- iwl_dump_nic_event_log((struct iwl_priv *)d->driver_data);
+ iwl3945_dump_nic_event_log((struct iwl3945_priv *)d->driver_data);
return strnlen(buf, count);
}
@@ -8251,34 +8317,34 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
*
*****************************************************************************/
-static void iwl_setup_deferred_work(struct iwl_priv *priv)
+static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
{
priv->workqueue = create_workqueue(DRV_NAME);
init_waitqueue_head(&priv->wait_command_queue);
- INIT_WORK(&priv->up, iwl_bg_up);
- INIT_WORK(&priv->restart, iwl_bg_restart);
- INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
- INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
- INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
- INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
- INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
- INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
- INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate);
- INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
- INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
- INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
-
- iwl_hw_setup_deferred_work(priv);
+ INIT_WORK(&priv->up, iwl3945_bg_up);
+ INIT_WORK(&priv->restart, iwl3945_bg_restart);
+ INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
+ INIT_WORK(&priv->scan_completed, iwl3945_bg_scan_completed);
+ INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan);
+ INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
+ INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
+ INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
+ INIT_DELAYED_WORK(&priv->post_associate, iwl3945_bg_post_associate);
+ INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
+ INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
+ INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
+
+ iwl3945_hw_setup_deferred_work(priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
- iwl_irq_tasklet, (unsigned long)priv);
+ iwl3945_irq_tasklet, (unsigned long)priv);
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv)
+static void iwl3945_cancel_deferred_work(struct iwl3945_priv *priv)
{
- iwl_hw_cancel_deferred_work(priv);
+ iwl3945_hw_cancel_deferred_work(priv);
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
@@ -8287,14 +8353,14 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->beacon_update);
}
-static struct attribute *iwl_sysfs_entries[] = {
+static struct attribute *iwl3945_sysfs_entries[] = {
&dev_attr_antenna.attr,
&dev_attr_channels.attr,
&dev_attr_dump_errors.attr,
&dev_attr_dump_events.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
&dev_attr_measurement.attr,
#endif
&dev_attr_power_level.attr,
@@ -8311,45 +8377,48 @@ static struct attribute *iwl_sysfs_entries[] = {
NULL
};
-static struct attribute_group iwl_attribute_group = {
+static struct attribute_group iwl3945_attribute_group = {
.name = NULL, /* put in device directory */
- .attrs = iwl_sysfs_entries,
+ .attrs = iwl3945_sysfs_entries,
};
-static struct ieee80211_ops iwl_hw_ops = {
- .tx = iwl_mac_tx,
- .start = iwl_mac_start,
- .stop = iwl_mac_stop,
- .add_interface = iwl_mac_add_interface,
- .remove_interface = iwl_mac_remove_interface,
- .config = iwl_mac_config,
- .config_interface = iwl_mac_config_interface,
- .configure_filter = iwl_configure_filter,
- .set_key = iwl_mac_set_key,
- .get_stats = iwl_mac_get_stats,
- .get_tx_stats = iwl_mac_get_tx_stats,
- .conf_tx = iwl_mac_conf_tx,
- .get_tsf = iwl_mac_get_tsf,
- .reset_tsf = iwl_mac_reset_tsf,
- .beacon_update = iwl_mac_beacon_update,
- .hw_scan = iwl_mac_hw_scan
+static struct ieee80211_ops iwl3945_hw_ops = {
+ .tx = iwl3945_mac_tx,
+ .start = iwl3945_mac_start,
+ .stop = iwl3945_mac_stop,
+ .add_interface = iwl3945_mac_add_interface,
+ .remove_interface = iwl3945_mac_remove_interface,
+ .config = iwl3945_mac_config,
+ .config_interface = iwl3945_mac_config_interface,
+ .configure_filter = iwl3945_configure_filter,
+ .set_key = iwl3945_mac_set_key,
+ .get_stats = iwl3945_mac_get_stats,
+ .get_tx_stats = iwl3945_mac_get_tx_stats,
+ .conf_tx = iwl3945_mac_conf_tx,
+ .get_tsf = iwl3945_mac_get_tsf,
+ .reset_tsf = iwl3945_mac_reset_tsf,
+ .beacon_update = iwl3945_mac_beacon_update,
+ .hw_scan = iwl3945_mac_hw_scan
};
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int err = 0;
u32 pci_id;
- struct iwl_priv *priv;
+ struct iwl3945_priv *priv;
struct ieee80211_hw *hw;
int i;
+ DECLARE_MAC_BUF(mac);
- if (iwl_param_disable_hw_scan) {
+ /* Disabling hardware scan means that mac80211 will perform scans
+ * "the hard way", rather than using device's scan. */
+ if (iwl3945_param_disable_hw_scan) {
IWL_DEBUG_INFO("Disabling hw_scan\n");
- iwl_hw_ops.hw_scan = NULL;
+ iwl3945_hw_ops.hw_scan = NULL;
}
- if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) ||
- (iwl_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+ if ((iwl3945_param_queues_num > IWL_MAX_NUM_QUEUES) ||
+ (iwl3945_param_queues_num < IWL_MIN_NUM_QUEUES)) {
IWL_ERROR("invalid queues_num, should be between %d and %d\n",
IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
err = -EINVAL;
@@ -8358,7 +8427,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* mac80211 allocates memory for this device instance, including
* space for this driver's private structure */
- hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(struct iwl3945_priv), &iwl3945_hw_ops);
if (hw == NULL) {
IWL_ERROR("Can not allocate network device\n");
err = -ENOMEM;
@@ -8373,9 +8442,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->hw = hw;
priv->pci_dev = pdev;
- priv->antenna = (enum iwl_antenna)iwl_param_antenna;
-#ifdef CONFIG_IWLWIFI_DEBUG
- iwl_debug_level = iwl_param_debug;
+
+ /* Select antenna (may be helpful if only one antenna is connected) */
+ priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
+#ifdef CONFIG_IWL3945_DEBUG
+ iwl3945_debug_level = iwl3945_param_debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
priv->retry_rate = 1;
@@ -8394,6 +8465,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Tell mac80211 our Tx characteristics */
hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ /* 4 EDCA QOS priorities */
hw->queues = 4;
spin_lock_init(&priv->lock);
@@ -8414,7 +8486,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
- iwl_clear_stations_table(priv);
+ /* Clear the driver's (not device's) station table */
+ iwl3945_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
@@ -8433,9 +8506,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = pci_request_regions(pdev, DRV_NAME);
if (err)
goto out_pci_disable_device;
+
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, 0x41, 0x00);
+
priv->hw_base = pci_iomap(pdev, 0, 0);
if (!priv->hw_base) {
err = -ENODEV;
@@ -8448,7 +8523,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Initialize module parameter values here */
- if (iwl_param_disable) {
+ /* Disable radio (SW RF KILL) via parameter when loading driver */
+ if (iwl3945_param_disable) {
set_bit(STATUS_RF_KILL_SW, &priv->status);
IWL_DEBUG_INFO("Radio disabled.\n");
}
@@ -8483,78 +8559,82 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->is_abg ? "A" : "");
/* Device-specific setup */
- if (iwl_hw_set_hw_setting(priv)) {
+ if (iwl3945_hw_set_hw_setting(priv)) {
IWL_ERROR("failed to set hw settings\n");
- mutex_unlock(&priv->mutex);
goto out_iounmap;
}
-#ifdef CONFIG_IWLWIFI_QOS
- if (iwl_param_qos_enable)
+#ifdef CONFIG_IWL3945_QOS
+ if (iwl3945_param_qos_enable)
priv->qos_data.qos_enable = 1;
- iwl_reset_qos(priv);
+ iwl3945_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
-#endif /* CONFIG_IWLWIFI_QOS */
+#endif /* CONFIG_IWL3945_QOS */
- iwl_set_rxon_channel(priv, MODE_IEEE80211G, 6);
- iwl_setup_deferred_work(priv);
- iwl_setup_rx_handlers(priv);
+ iwl3945_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+ iwl3945_setup_deferred_work(priv);
+ iwl3945_setup_rx_handlers(priv);
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
- pci_enable_msi(pdev);
+ iwl3945_disable_interrupts(priv);
- err = request_irq(pdev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv);
- if (err) {
- IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
- goto out_disable_msi;
- }
-
- mutex_lock(&priv->mutex);
-
- err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
if (err) {
IWL_ERROR("failed to create sysfs device attributes\n");
- mutex_unlock(&priv->mutex);
goto out_release_irq;
}
- /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
- * ucode filename and max sizes are card-specific. */
- err = iwl_read_ucode(priv);
+ /* nic init */
+ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+ iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ goto out_remove_sysfs;
+ }
+ /* Read the EEPROM */
+ err = iwl3945_eeprom_init(priv);
if (err) {
- IWL_ERROR("Could not read microcode: %d\n", err);
- mutex_unlock(&priv->mutex);
- goto out_pci_alloc;
+ IWL_ERROR("Unable to init EEPROM\n");
+ goto out_remove_sysfs;
}
+ /* MAC Address location in EEPROM same for 3945/4965 */
+ get_eeprom_mac(priv, priv->mac_addr);
+ IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
- mutex_unlock(&priv->mutex);
-
- IWL_DEBUG_INFO("Queing UP work.\n");
+ iwl3945_rate_control_register(priv->hw);
+ err = ieee80211_register_hw(priv->hw);
+ if (err) {
+ IWL_ERROR("Failed to register network device (error %d)\n", err);
+ goto out_remove_sysfs;
+ }
- queue_work(priv->workqueue, &priv->up);
+ priv->hw->conf.beacon_int = 100;
+ priv->mac80211_registered = 1;
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
return 0;
- out_pci_alloc:
- iwl_dealloc_ucode_pci(priv);
-
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ out_remove_sysfs:
+ sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
out_release_irq:
- free_irq(pdev->irq, priv);
-
- out_disable_msi:
- pci_disable_msi(pdev);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- iwl_unset_hw_setting(priv);
+ iwl3945_unset_hw_setting(priv);
out_iounmap:
pci_iounmap(pdev, priv->hw_base);
@@ -8569,9 +8649,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
-static void iwl_pci_remove(struct pci_dev *pdev)
+static void iwl3945_pci_remove(struct pci_dev *pdev)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct iwl3945_priv *priv = pci_get_drvdata(pdev);
struct list_head *p, *q;
int i;
@@ -8582,43 +8662,41 @@ static void iwl_pci_remove(struct pci_dev *pdev)
set_bit(STATUS_EXIT_PENDING, &priv->status);
- iwl_down(priv);
+ iwl3945_down(priv);
/* Free MAC hash list for ADHOC */
for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
list_del(p);
- kfree(list_entry(p, struct iwl_ibss_seq, list));
+ kfree(list_entry(p, struct iwl3945_ibss_seq, list));
}
}
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- iwl_dealloc_ucode_pci(priv);
+ iwl3945_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
- iwl_rx_queue_free(priv, &priv->rxq);
- iwl_hw_txq_ctx_free(priv);
+ iwl3945_rx_queue_free(priv, &priv->rxq);
+ iwl3945_hw_txq_ctx_free(priv);
- iwl_unset_hw_setting(priv);
- iwl_clear_stations_table(priv);
+ iwl3945_unset_hw_setting(priv);
+ iwl3945_clear_stations_table(priv);
if (priv->mac80211_registered) {
ieee80211_unregister_hw(priv->hw);
- iwl_rate_control_unregister(priv->hw);
+ iwl3945_rate_control_unregister(priv->hw);
}
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
- /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
+ /* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- free_irq(pdev->irq, priv);
- pci_disable_msi(pdev);
pci_iounmap(pdev, priv->hw_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -8637,93 +8715,31 @@ static void iwl_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int iwl3945_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
-
- set_bit(STATUS_IN_SUSPEND, &priv->status);
-
- /* Take down the device; powers it off, etc. */
- iwl_down(priv);
+ struct iwl3945_priv *priv = pci_get_drvdata(pdev);
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
+ if (priv->is_open) {
+ set_bit(STATUS_IN_SUSPEND, &priv->status);
+ iwl3945_mac_stop(priv->hw);
+ priv->is_open = 1;
+ }
- pci_save_state(pdev);
- pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
-static void iwl_resume(struct iwl_priv *priv)
+static int iwl3945_pci_resume(struct pci_dev *pdev)
{
- unsigned long flags;
-
- /* The following it a temporary work around due to the
- * suspend / resume not fully initializing the NIC correctly.
- * Without all of the following, resume will not attempt to take
- * down the NIC (it shouldn't really need to) and will just try
- * and bring the NIC back up. However that fails during the
- * ucode verification process. This then causes iwl_down to be
- * called *after* iwl_hw_nic_init() has succeeded -- which
- * then lets the next init sequence succeed. So, we've
- * replicated all of that NIC init code here... */
-
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
- iwl_hw_nic_init(priv);
-
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- /* tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
- APMG_CLK_VAL_DMA_CLK_RQT);
- iwl_release_restricted_access(priv);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- udelay(5);
-
- iwl_hw_nic_reset(priv);
-
- /* Bring the device back up */
- clear_bit(STATUS_IN_SUSPEND, &priv->status);
- queue_work(priv->workqueue, &priv->up);
-}
-
-static int iwl_pci_resume(struct pci_dev *pdev)
-{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
- int err;
-
- printk(KERN_INFO "Coming out of suspend...\n");
+ struct iwl3945_priv *priv = pci_get_drvdata(pdev);
pci_set_power_state(pdev, PCI_D0);
- err = pci_enable_device(pdev);
- pci_restore_state(pdev);
- /*
- * Suspend/Resume resets the PCI configuration space, so we have to
- * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
- * from interfering with C3 CPU state. pci_restore_state won't help
- * here since it only restores the first 64 bytes pci config header.
- */
- pci_write_config_byte(pdev, 0x41, 0x00);
-
- iwl_resume(priv);
+ if (priv->is_open)
+ iwl3945_mac_start(priv->hw);
+ clear_bit(STATUS_IN_SUSPEND, &priv->status);
return 0;
}
@@ -8735,33 +8751,33 @@ static int iwl_pci_resume(struct pci_dev *pdev)
*
*****************************************************************************/
-static struct pci_driver iwl_driver = {
+static struct pci_driver iwl3945_driver = {
.name = DRV_NAME,
- .id_table = iwl_hw_card_ids,
- .probe = iwl_pci_probe,
- .remove = __devexit_p(iwl_pci_remove),
+ .id_table = iwl3945_hw_card_ids,
+ .probe = iwl3945_pci_probe,
+ .remove = __devexit_p(iwl3945_pci_remove),
#ifdef CONFIG_PM
- .suspend = iwl_pci_suspend,
- .resume = iwl_pci_resume,
+ .suspend = iwl3945_pci_suspend,
+ .resume = iwl3945_pci_resume,
#endif
};
-static int __init iwl_init(void)
+static int __init iwl3945_init(void)
{
int ret;
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
- ret = pci_register_driver(&iwl_driver);
+ ret = pci_register_driver(&iwl3945_driver);
if (ret) {
IWL_ERROR("Unable to initialize PCI module\n");
return ret;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
- ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
+#ifdef CONFIG_IWL3945_DEBUG
+ ret = driver_create_file(&iwl3945_driver.driver, &driver_attr_debug_level);
if (ret) {
IWL_ERROR("Unable to create driver sysfs file\n");
- pci_unregister_driver(&iwl_driver);
+ pci_unregister_driver(&iwl3945_driver);
return ret;
}
#endif
@@ -8769,32 +8785,32 @@ static int __init iwl_init(void)
return ret;
}
-static void __exit iwl_exit(void)
+static void __exit iwl3945_exit(void)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
+#ifdef CONFIG_IWL3945_DEBUG
+ driver_remove_file(&iwl3945_driver.driver, &driver_attr_debug_level);
#endif
- pci_unregister_driver(&iwl_driver);
+ pci_unregister_driver(&iwl3945_driver);
}
-module_param_named(antenna, iwl_param_antenna, int, 0444);
+module_param_named(antenna, iwl3945_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl_param_disable, int, 0444);
+module_param_named(disable, iwl3945_param_disable, int, 0444);
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
-module_param_named(hwcrypto, iwl_param_hwcrypto, int, 0444);
+module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444);
MODULE_PARM_DESC(hwcrypto,
"using hardware crypto engine (default 0 [software])\n");
-module_param_named(debug, iwl_param_debug, int, 0444);
+module_param_named(debug, iwl3945_param_debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
-module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444);
+module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-module_param_named(queues_num, iwl_param_queues_num, int, 0444);
+module_param_named(queues_num, iwl3945_param_queues_num, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
/* QoS */
-module_param_named(qos_enable, iwl_param_qos_enable, int, 0444);
+module_param_named(qos_enable, iwl3945_param_qos_enable, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
-module_exit(iwl_exit);
-module_init(iwl_init);
+module_exit(iwl3945_exit);
+module_init(iwl3945_init);
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 6cd57c220631..c86da5cd1df1 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -27,16 +27,6 @@
*
*****************************************************************************/
-/*
- * NOTE: This file (iwl-base.c) is used to build to multiple hardware targets
- * by defining IWL to either 3945 or 4965. The Makefile used when building
- * the base targets will create base-3945.o and base-4965.o
- *
- * The eventual goal is to move as many of the #if IWL / #endif blocks out of
- * this file and into the hardware specific implementation files (iwl-XXXX.c)
- * and leave only the common (non #ifdef sprinkled) code in this file
- */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
@@ -51,21 +41,20 @@
#include <linux/etherdevice.h>
#include <linux/if_arp.h>
-#include <net/ieee80211_radiotap.h>
#include <net/mac80211.h>
#include <asm/div64.h>
-#define IWL 4965
-
-#include "iwlwifi.h"
#include "iwl-4965.h"
#include "iwl-helpers.h"
-#ifdef CONFIG_IWLWIFI_DEBUG
-u32 iwl_debug_level;
+#ifdef CONFIG_IWL4965_DEBUG
+u32 iwl4965_debug_level;
#endif
+static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq);
+
/******************************************************************************
*
* module boiler plate
@@ -73,13 +62,14 @@ u32 iwl_debug_level;
******************************************************************************/
/* module parameters */
-int iwl_param_disable_hw_scan;
-int iwl_param_debug;
-int iwl_param_disable; /* def: enable radio */
-int iwl_param_antenna; /* def: 0 = both antennas (use diversity) */
-int iwl_param_hwcrypto; /* def: using software encryption */
-int iwl_param_qos_enable = 1;
-int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
+static int iwl4965_param_disable_hw_scan; /* def: 0 = use 4965's h/w scan */
+static int iwl4965_param_debug; /* def: 0 = minimal debug log messages */
+static int iwl4965_param_disable; /* def: enable radio */
+static int iwl4965_param_antenna; /* def: 0 = both antennas (use diversity) */
+int iwl4965_param_hwcrypto; /* def: using software encryption */
+static int iwl4965_param_qos_enable = 1; /* def: 1 = use quality of service */
+int iwl4965_param_queues_num = IWL_MAX_NUM_QUEUES; /* def: 16 Tx queues */
+int iwl4965_param_amsdu_size_8K; /* def: enable 8K amsdu size */
/*
* module name, copyright, version, etc.
@@ -88,19 +78,19 @@ int iwl_param_queues_num = IWL_MAX_NUM_QUEUES;
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link 4965AGN driver for Linux"
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
#define VD "d"
#else
#define VD
#endif
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
#define VS "s"
#else
#define VS
#endif
-#define IWLWIFI_VERSION "1.1.17k" VD VS
+#define IWLWIFI_VERSION "1.2.23k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2007 Intel Corporation"
#define DRV_VERSION IWLWIFI_VERSION
@@ -125,8 +115,8 @@ __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr)
return NULL;
}
-static const struct ieee80211_hw_mode *iwl_get_hw_mode(
- struct iwl_priv *priv, int mode)
+static const struct ieee80211_hw_mode *iwl4965_get_hw_mode(
+ struct iwl4965_priv *priv, int mode)
{
int i;
@@ -137,7 +127,7 @@ static const struct ieee80211_hw_mode *iwl_get_hw_mode(
return NULL;
}
-static int iwl_is_empty_essid(const char *essid, int essid_len)
+static int iwl4965_is_empty_essid(const char *essid, int essid_len)
{
/* Single white space is for Linksys APs */
if (essid_len == 1 && essid[0] == ' ')
@@ -153,13 +143,13 @@ static int iwl_is_empty_essid(const char *essid, int essid_len)
return 1;
}
-static const char *iwl_escape_essid(const char *essid, u8 essid_len)
+static const char *iwl4965_escape_essid(const char *essid, u8 essid_len)
{
static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
const char *s = essid;
char *d = escaped;
- if (iwl_is_empty_essid(essid, essid_len)) {
+ if (iwl4965_is_empty_essid(essid, essid_len)) {
memcpy(escaped, "<hidden>", sizeof("<hidden>"));
return escaped;
}
@@ -177,10 +167,10 @@ static const char *iwl_escape_essid(const char *essid, u8 essid_len)
return escaped;
}
-static void iwl_print_hex_dump(int level, void *p, u32 len)
+static void iwl4965_print_hex_dump(int level, void *p, u32 len)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (!(iwl_debug_level & level))
+#ifdef CONFIG_IWL4965_DEBUG
+ if (!(iwl4965_debug_level & level))
return;
print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
@@ -193,24 +183,33 @@ static void iwl_print_hex_dump(int level, void *p, u32 len)
*
* Theory of operation
*
- * A queue is a circular buffers with 'Read' and 'Write' pointers.
- * 2 empty entries always kept in the buffer to protect from overflow.
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill. Driver and device exchange status of each
+ * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels. Each queue is mapped to a single DMA channel.
*
* For Tx queue, there are low mark and high mark limits. If, after queuing
* the packet for Tx, free space become < low mark, Tx queue stopped. When
* reclaiming packets (on 'tx done IRQ), if free space become > high mark,
* Tx queue resumed.
*
- * The IWL operates with six queues, one receive queue in the device's
- * sram, one transmit queue for sending commands to the device firmware,
- * and four transmit queues for data.
+ * The 4965 operates with up to 17 queues: One receive queue, one transmit
+ * queue (#4) for sending commands to the device firmware, and 15 other
+ * Tx queues that may be mapped to prioritized Tx DMA/FIFO channels.
+ *
+ * See more detailed info in iwl-4965-hw.h.
***************************************************/
-static int iwl_queue_space(const struct iwl_queue *q)
+static int iwl4965_queue_space(const struct iwl4965_queue *q)
{
- int s = q->last_used - q->first_empty;
+ int s = q->read_ptr - q->write_ptr;
- if (q->last_used > q->first_empty)
+ if (q->read_ptr > q->write_ptr)
s -= q->n_bd;
if (s <= 0)
@@ -222,42 +221,55 @@ static int iwl_queue_space(const struct iwl_queue *q)
return s;
}
-/* XXX: n_bd must be power-of-two size */
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
+/**
+ * iwl4965_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl4965_queue_inc_wrap(int index, int n_bd)
{
return ++index & (n_bd - 1);
}
-/* XXX: n_bd must be power-of-two size */
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
+/**
+ * iwl4965_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl4965_queue_dec_wrap(int index, int n_bd)
{
return --index & (n_bd - 1);
}
-static inline int x2_queue_used(const struct iwl_queue *q, int i)
+static inline int x2_queue_used(const struct iwl4965_queue *q, int i)
{
- return q->first_empty > q->last_used ?
- (i >= q->last_used && i < q->first_empty) :
- !(i < q->last_used && i >= q->first_empty);
+ return q->write_ptr > q->read_ptr ?
+ (i >= q->read_ptr && i < q->write_ptr) :
+ !(i < q->read_ptr && i >= q->write_ptr);
}
-static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
+static inline u8 get_cmd_index(struct iwl4965_queue *q, u32 index, int is_huge)
{
+ /* This is for scan command, the big buffer at end of command array */
if (is_huge)
- return q->n_window;
+ return q->n_window; /* must be power of 2 */
+ /* Otherwise, use normal size buffers */
return index & (q->n_window - 1);
}
-static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+/**
+ * iwl4965_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl4965_queue_init(struct iwl4965_priv *priv, struct iwl4965_queue *q,
int count, int slots_num, u32 id)
{
q->n_bd = count;
q->n_window = slots_num;
q->id = id;
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
- * and iwl_queue_dec_wrap are broken. */
+ /* count must be power-of-two size, otherwise iwl4965_queue_inc_wrap
+ * and iwl4965_queue_dec_wrap are broken. */
BUG_ON(!is_power_of_2(count));
/* slots_num must be power-of-two size, otherwise
@@ -272,27 +284,34 @@ static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
if (q->high_mark < 2)
q->high_mark = 2;
- q->first_empty = q->last_used = 0;
+ q->write_ptr = q->read_ptr = 0;
return 0;
}
-static int iwl_tx_queue_alloc(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, u32 id)
+/**
+ * iwl4965_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int iwl4965_tx_queue_alloc(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq, u32 id)
{
struct pci_dev *dev = priv->pci_dev;
+ /* Driver private data, only for Tx (not command) queues,
+ * not shared with device. */
if (id != IWL_CMD_QUEUE_NUM) {
txq->txb = kmalloc(sizeof(txq->txb[0]) *
TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
if (!txq->txb) {
- IWL_ERROR("kmalloc for auxilary BD "
+ IWL_ERROR("kmalloc for auxiliary BD "
"structures failed\n");
goto error;
}
} else
txq->txb = NULL;
+ /* Circular buffer of transmit frame descriptors (TFDs),
+ * shared with device */
txq->bd = pci_alloc_consistent(dev,
sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
&txq->q.dma_addr);
@@ -315,24 +334,33 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
return -ENOMEM;
}
-int iwl_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, int slots_num, u32 txq_id)
+/**
+ * iwl4965_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+int iwl4965_tx_queue_init(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq, int slots_num, u32 txq_id)
{
struct pci_dev *dev = priv->pci_dev;
int len;
int rc = 0;
- /* alocate command space + one big command for scan since scan
- * command is very huge the system will not have two scan at the
- * same time */
- len = sizeof(struct iwl_cmd) * slots_num;
+ /*
+ * Alloc buffer array for commands (Tx or other types of commands).
+ * For the command queue (#4), allocate command space + one big
+ * command for scan, since scan command is very huge; the system will
+ * not have two scans at the same time, so only one is needed.
+ * For normal Tx queues (all other queues), no super-size command
+ * space is needed.
+ */
+ len = sizeof(struct iwl4965_cmd) * slots_num;
if (txq_id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
txq->cmd = pci_alloc_consistent(dev, len, &txq->dma_addr_cmd);
if (!txq->cmd)
return -ENOMEM;
- rc = iwl_tx_queue_alloc(priv, txq, txq_id);
+ /* Alloc driver data array and TFD circular buffer */
+ rc = iwl4965_tx_queue_alloc(priv, txq, txq_id);
if (rc) {
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
@@ -341,26 +369,29 @@ int iwl_tx_queue_init(struct iwl_priv *priv,
txq->need_update = 0;
/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
- * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */
+ * iwl4965_queue_inc_wrap and iwl4965_queue_dec_wrap are broken. */
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
- iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
- iwl_hw_tx_queue_init(priv, txq);
+ /* Initialize queue's high/low-water marks, and head/tail indexes */
+ iwl4965_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+ /* Tell device where to find queue */
+ iwl4965_hw_tx_queue_init(priv, txq);
return 0;
}
/**
- * iwl_tx_queue_free - Deallocate DMA queue.
+ * iwl4965_tx_queue_free - Deallocate DMA queue.
* @txq: Transmit queue to deallocate.
*
* Empty queue by removing and destroying all BD's.
- * Free all buffers. txq itself is not freed.
- *
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
*/
-void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+void iwl4965_tx_queue_free(struct iwl4965_priv *priv, struct iwl4965_tx_queue *txq)
{
- struct iwl_queue *q = &txq->q;
+ struct iwl4965_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev;
int len;
@@ -368,45 +399,48 @@ void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq)
return;
/* first, empty all BD's */
- for (; q->first_empty != q->last_used;
- q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd))
- iwl_hw_txq_free_tfd(priv, txq);
+ for (; q->write_ptr != q->read_ptr;
+ q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd))
+ iwl4965_hw_txq_free_tfd(priv, txq);
- len = sizeof(struct iwl_cmd) * q->n_window;
+ len = sizeof(struct iwl4965_cmd) * q->n_window;
if (q->id == IWL_CMD_QUEUE_NUM)
len += IWL_MAX_SCAN_SIZE;
+ /* De-alloc array of command/tx buffers */
pci_free_consistent(dev, len, txq->cmd, txq->dma_addr_cmd);
- /* free buffers belonging to queue itself */
+ /* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
+ pci_free_consistent(dev, sizeof(struct iwl4965_tfd_frame) *
txq->q.n_bd, txq->bd, txq->q.dma_addr);
+ /* De-alloc array of per-TFD driver data */
if (txq->txb) {
kfree(txq->txb);
txq->txb = NULL;
}
- /* 0 fill whole structure */
+ /* 0-fill queue descriptor structure */
memset(txq, 0, sizeof(*txq));
}
-const u8 BROADCAST_ADDR[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+const u8 iwl4965_broadcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/*************** STATION TABLE MANAGEMENT ****
- *
- * NOTE: This needs to be overhauled to better synchronize between
- * how the iwl-4965.c is using iwl_hw_find_station vs. iwl-3945.c
- *
- * mac80211 should also be examined to determine if sta_info is duplicating
+ * mac80211 should be examined to determine if sta_info is duplicating
* the functionality provided here
*/
/**************************************************************/
-#if 0 /* temparary disable till we add real remove station */
-static u8 iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
+#if 0 /* temporary disable till we add real remove station */
+/**
+ * iwl4965_remove_station - Remove driver's knowledge of station.
+ *
+ * NOTE: This does not remove station from device's station table.
+ */
+static u8 iwl4965_remove_station(struct iwl4965_priv *priv, const u8 *addr, int is_ap)
{
int index = IWL_INVALID_STATION;
int i;
@@ -443,7 +477,12 @@ out:
}
#endif
-static void iwl_clear_stations_table(struct iwl_priv *priv)
+/**
+ * iwl4965_clear_stations_table - Clear the driver's station table
+ *
+ * NOTE: This does not clear or otherwise alter the device's station table.
+ */
+static void iwl4965_clear_stations_table(struct iwl4965_priv *priv)
{
unsigned long flags;
@@ -455,11 +494,15 @@ static void iwl_clear_stations_table(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
-u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
+/**
+ * iwl4965_add_station_flags - Add station to tables in driver and device
+ */
+u8 iwl4965_add_station_flags(struct iwl4965_priv *priv, const u8 *addr,
+ int is_ap, u8 flags, void *ht_data)
{
int i;
int index = IWL_INVALID_STATION;
- struct iwl_station_entry *station;
+ struct iwl4965_station_entry *station;
unsigned long flags_spin;
DECLARE_MAC_BUF(mac);
@@ -482,8 +525,8 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
}
- /* These twh conditions has the same outcome but keep them separate
- since they have different meaning */
+ /* These two conditions have the same outcome, but keep them separate
+ since they have different meanings */
if (unlikely(index == IWL_INVALID_STATION)) {
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
return index;
@@ -501,28 +544,32 @@ u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap, u8 flags)
station->used = 1;
priv->num_stations++;
- memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd));
+ /* Set up the REPLY_ADD_STA command to send to device */
+ memset(&station->sta, 0, sizeof(struct iwl4965_addsta_cmd));
memcpy(station->sta.sta.addr, addr, ETH_ALEN);
station->sta.mode = 0;
station->sta.sta.sta_id = index;
station->sta.station_flags = 0;
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
/* BCAST station and IBSS stations do not work in HT mode */
if (index != priv->hw_setting.bcast_sta_id &&
priv->iw_mode != IEEE80211_IF_TYPE_IBSS)
- iwl4965_set_ht_add_station(priv, index);
-#endif /*CONFIG_IWLWIFI_HT*/
+ iwl4965_set_ht_add_station(priv, index,
+ (struct ieee80211_ht_info *) ht_data);
+#endif /*CONFIG_IWL4965_HT*/
spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
- iwl_send_add_station(priv, &station->sta, flags);
+
+ /* Add station to device's station table */
+ iwl4965_send_add_station(priv, &station->sta, flags);
return index;
}
/*************** DRIVER STATUS FUNCTIONS *****/
-static inline int iwl_is_ready(struct iwl_priv *priv)
+static inline int iwl4965_is_ready(struct iwl4965_priv *priv)
{
/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
* set but EXIT_PENDING is not */
@@ -531,29 +578,29 @@ static inline int iwl_is_ready(struct iwl_priv *priv)
!test_bit(STATUS_EXIT_PENDING, &priv->status);
}
-static inline int iwl_is_alive(struct iwl_priv *priv)
+static inline int iwl4965_is_alive(struct iwl4965_priv *priv)
{
return test_bit(STATUS_ALIVE, &priv->status);
}
-static inline int iwl_is_init(struct iwl_priv *priv)
+static inline int iwl4965_is_init(struct iwl4965_priv *priv)
{
return test_bit(STATUS_INIT, &priv->status);
}
-static inline int iwl_is_rfkill(struct iwl_priv *priv)
+static inline int iwl4965_is_rfkill(struct iwl4965_priv *priv)
{
return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
test_bit(STATUS_RF_KILL_SW, &priv->status);
}
-static inline int iwl_is_ready_rf(struct iwl_priv *priv)
+static inline int iwl4965_is_ready_rf(struct iwl4965_priv *priv)
{
- if (iwl_is_rfkill(priv))
+ if (iwl4965_is_rfkill(priv))
return 0;
- return iwl_is_ready(priv);
+ return iwl4965_is_ready(priv);
}
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
@@ -618,7 +665,7 @@ static const char *get_cmd_string(u8 cmd)
#define HOST_COMPLETE_TIMEOUT (HZ / 2)
/**
- * iwl_enqueue_hcmd - enqueue a uCode command
+ * iwl4965_enqueue_hcmd - enqueue a uCode command
* @priv: device private data point
* @cmd: a point to the ucode command structure
*
@@ -626,13 +673,13 @@ static const char *get_cmd_string(u8 cmd)
* failed. On success, it turns the index (> 0) of command in the
* command queue.
*/
-static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl4965_enqueue_hcmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
{
- struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
- struct iwl_queue *q = &txq->q;
- struct iwl_tfd_frame *tfd;
+ struct iwl4965_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl4965_queue *q = &txq->q;
+ struct iwl4965_tfd_frame *tfd;
u32 *control_flags;
- struct iwl_cmd *out_cmd;
+ struct iwl4965_cmd *out_cmd;
u32 idx;
u16 fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
dma_addr_t phys_addr;
@@ -645,19 +692,19 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
!(cmd->meta.flags & CMD_SIZE_HUGE));
- if (iwl_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
+ if (iwl4965_queue_space(q) < ((cmd->meta.flags & CMD_ASYNC) ? 2 : 1)) {
IWL_ERROR("No space for Tx\n");
return -ENOSPC;
}
spin_lock_irqsave(&priv->hcmd_lock, flags);
- tfd = &txq->bd[q->first_empty];
+ tfd = &txq->bd[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
control_flags = (u32 *) tfd;
- idx = get_cmd_index(q, q->first_empty, cmd->meta.flags & CMD_SIZE_HUGE);
+ idx = get_cmd_index(q, q->write_ptr, cmd->meta.flags & CMD_SIZE_HUGE);
out_cmd = &txq->cmd[idx];
out_cmd->hdr.cmd = cmd->id;
@@ -669,30 +716,34 @@ static int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.flags = 0;
out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) |
- INDEX_TO_SEQ(q->first_empty));
+ INDEX_TO_SEQ(q->write_ptr));
if (out_cmd->meta.flags & CMD_SIZE_HUGE)
out_cmd->hdr.sequence |= cpu_to_le16(SEQ_HUGE_FRAME);
phys_addr = txq->dma_addr_cmd + sizeof(txq->cmd[0]) * idx +
- offsetof(struct iwl_cmd, hdr);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
+ offsetof(struct iwl4965_cmd, hdr);
+ iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
IWL_DEBUG_HC("Sending command %s (#%x), seq: 0x%04X, "
"%d bytes at %d[%d]:%d\n",
get_cmd_string(out_cmd->hdr.cmd),
out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
- fix_size, q->first_empty, idx, IWL_CMD_QUEUE_NUM);
+ fix_size, q->write_ptr, idx, IWL_CMD_QUEUE_NUM);
txq->need_update = 1;
+
+ /* Set up entry in queue's byte count circular buffer */
ret = iwl4965_tx_queue_update_wr_ptr(priv, txq, 0);
- q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
- iwl_tx_queue_update_write_ptr(priv, txq);
+
+ /* Increment and update queue's write index */
+ q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+ iwl4965_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->hcmd_lock, flags);
return ret ? ret : idx;
}
-int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl4965_send_cmd_async(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
{
int ret;
@@ -707,16 +758,16 @@ int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return -EBUSY;
- ret = iwl_enqueue_hcmd(priv, cmd);
+ ret = iwl4965_enqueue_hcmd(priv, cmd);
if (ret < 0) {
- IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
+ IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
return ret;
}
return 0;
}
-int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+static int iwl4965_send_cmd_sync(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
{
int cmd_idx;
int ret;
@@ -738,10 +789,10 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
if (cmd->meta.flags & CMD_WANT_SKB)
cmd->meta.source = &cmd->meta;
- cmd_idx = iwl_enqueue_hcmd(priv, cmd);
+ cmd_idx = iwl4965_enqueue_hcmd(priv, cmd);
if (cmd_idx < 0) {
ret = cmd_idx;
- IWL_ERROR("Error sending %s: iwl_enqueue_hcmd failed: %d\n",
+ IWL_ERROR("Error sending %s: iwl4965_enqueue_hcmd failed: %d\n",
get_cmd_string(cmd->id), ret);
goto out;
}
@@ -785,7 +836,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
cancel:
if (cmd->meta.flags & CMD_WANT_SKB) {
- struct iwl_cmd *qcmd;
+ struct iwl4965_cmd *qcmd;
/* Cancel the CMD_WANT_SKB flag for the cmd in the
* TX cmd queue. Otherwise in case the cmd comes
@@ -804,64 +855,75 @@ out:
return ret;
}
-int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+int iwl4965_send_cmd(struct iwl4965_priv *priv, struct iwl4965_host_cmd *cmd)
{
- /* A command can not be asynchronous AND expect an SKB to be set. */
- BUG_ON((cmd->meta.flags & CMD_ASYNC) &&
- (cmd->meta.flags & CMD_WANT_SKB));
-
if (cmd->meta.flags & CMD_ASYNC)
- return iwl_send_cmd_async(priv, cmd);
+ return iwl4965_send_cmd_async(priv, cmd);
- return iwl_send_cmd_sync(priv, cmd);
+ return iwl4965_send_cmd_sync(priv, cmd);
}
-int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
+int iwl4965_send_cmd_pdu(struct iwl4965_priv *priv, u8 id, u16 len, const void *data)
{
- struct iwl_host_cmd cmd = {
+ struct iwl4965_host_cmd cmd = {
.id = id,
.len = len,
.data = data,
};
- return iwl_send_cmd_sync(priv, &cmd);
+ return iwl4965_send_cmd_sync(priv, &cmd);
}
-static int __must_check iwl_send_cmd_u32(struct iwl_priv *priv, u8 id, u32 val)
+static int __must_check iwl4965_send_cmd_u32(struct iwl4965_priv *priv, u8 id, u32 val)
{
- struct iwl_host_cmd cmd = {
+ struct iwl4965_host_cmd cmd = {
.id = id,
.len = sizeof(val),
.data = &val,
};
- return iwl_send_cmd_sync(priv, &cmd);
+ return iwl4965_send_cmd_sync(priv, &cmd);
}
-int iwl_send_statistics_request(struct iwl_priv *priv)
+int iwl4965_send_statistics_request(struct iwl4965_priv *priv)
{
- return iwl_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
+ return iwl4965_send_cmd_u32(priv, REPLY_STATISTICS_CMD, 0);
}
/**
- * iwl_rxon_add_station - add station into station table.
+ * iwl4965_rxon_add_station - add station into station table.
*
* there is only one AP station with id= IWL_AP_ID
- * NOTE: mutex must be held before calling the this fnction
-*/
-static int iwl_rxon_add_station(struct iwl_priv *priv,
+ * NOTE: mutex must be held before calling this fnction
+ */
+static int iwl4965_rxon_add_station(struct iwl4965_priv *priv,
const u8 *addr, int is_ap)
{
u8 sta_id;
- sta_id = iwl_add_station(priv, addr, is_ap, 0);
+ /* Add station to device's station table */
+#ifdef CONFIG_IWL4965_HT
+ struct ieee80211_conf *conf = &priv->hw->conf;
+ struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
+
+ if ((is_ap) &&
+ (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
+ (priv->iw_mode == IEEE80211_IF_TYPE_STA))
+ sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
+ 0, cur_ht_config);
+ else
+#endif /* CONFIG_IWL4965_HT */
+ sta_id = iwl4965_add_station_flags(priv, addr, is_ap,
+ 0, NULL);
+
+ /* Set up default rate scaling table in device's station table */
iwl4965_add_station(priv, addr, is_ap);
return sta_id;
}
/**
- * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON
+ * iwl4965_set_rxon_channel - Set the phymode and channel values in staging RXON
* @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz
* @channel: Any channel valid for the requested phymode
@@ -870,9 +932,10 @@ static int iwl_rxon_add_station(struct iwl_priv *priv,
* NOTE: Does not commit to the hardware; it sets appropriate bit fields
* in the staging RXON flag structure based on the phymode
*/
-static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
+static int iwl4965_set_rxon_channel(struct iwl4965_priv *priv, u8 phymode,
+ u16 channel)
{
- if (!iwl_get_channel_info(priv, phymode, channel)) {
+ if (!iwl4965_get_channel_info(priv, phymode, channel)) {
IWL_DEBUG_INFO("Could not set channel to %d [%d]\n",
channel, phymode);
return -EINVAL;
@@ -896,13 +959,13 @@ static int iwl_set_rxon_channel(struct iwl_priv *priv, u8 phymode, u16 channel)
}
/**
- * iwl_check_rxon_cmd - validate RXON structure is valid
+ * iwl4965_check_rxon_cmd - validate RXON structure is valid
*
* NOTE: This is really only useful during development and can eventually
* be #ifdef'd out once the driver is stable and folks aren't actively
* making changes
*/
-static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
+static int iwl4965_check_rxon_cmd(struct iwl4965_rxon_cmd *rxon)
{
int error = 0;
int counter = 1;
@@ -962,21 +1025,21 @@ static int iwl_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
le16_to_cpu(rxon->channel));
if (error) {
- IWL_ERROR("Not a valid iwl_rxon_assoc_cmd field values\n");
+ IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
return -1;
}
return 0;
}
/**
- * iwl_full_rxon_required - determine if RXON_ASSOC can be used in RXON commit
- * @priv: staging_rxon is comapred to active_rxon
+ * iwl4965_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * @priv: staging_rxon is compared to active_rxon
*
- * If the RXON structure is changing sufficient to require a new
- * tune or to clear and reset the RXON_FILTER_ASSOC_MSK then return 1
- * to indicate a new tune is required.
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
*/
-static int iwl_full_rxon_required(struct iwl_priv *priv)
+static int iwl4965_full_rxon_required(struct iwl4965_priv *priv)
{
/* These items are only settable from the full RXON command */
@@ -1016,19 +1079,19 @@ static int iwl_full_rxon_required(struct iwl_priv *priv)
return 0;
}
-static int iwl_send_rxon_assoc(struct iwl_priv *priv)
+static int iwl4965_send_rxon_assoc(struct iwl4965_priv *priv)
{
int rc = 0;
- struct iwl_rx_packet *res = NULL;
- struct iwl_rxon_assoc_cmd rxon_assoc;
- struct iwl_host_cmd cmd = {
+ struct iwl4965_rx_packet *res = NULL;
+ struct iwl4965_rxon_assoc_cmd rxon_assoc;
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_RXON_ASSOC,
.len = sizeof(rxon_assoc),
.meta.flags = CMD_WANT_SKB,
.data = &rxon_assoc,
};
- const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
- const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+ const struct iwl4965_rxon_cmd *rxon1 = &priv->staging_rxon;
+ const struct iwl4965_rxon_cmd *rxon2 = &priv->active_rxon;
if ((rxon1->flags == rxon2->flags) &&
(rxon1->filter_flags == rxon2->filter_flags) &&
@@ -1054,11 +1117,11 @@ static int iwl_send_rxon_assoc(struct iwl_priv *priv)
priv->staging_rxon.ofdm_ht_dual_stream_basic_rates;
rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain;
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl4965_send_cmd_sync(priv, &cmd);
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_RXON_ASSOC command\n");
rc = -EIO;
@@ -1071,37 +1134,37 @@ static int iwl_send_rxon_assoc(struct iwl_priv *priv)
}
/**
- * iwl_commit_rxon - commit staging_rxon to hardware
+ * iwl4965_commit_rxon - commit staging_rxon to hardware
*
- * The RXON command in staging_rxon is commited to the hardware and
+ * The RXON command in staging_rxon is committed to the hardware and
* the active_rxon structure is updated with the new data. This
* function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes.
*/
-static int iwl_commit_rxon(struct iwl_priv *priv)
+static int iwl4965_commit_rxon(struct iwl4965_priv *priv)
{
/* cast away the const for active_rxon in this function */
- struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+ struct iwl4965_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
DECLARE_MAC_BUF(mac);
int rc = 0;
- if (!iwl_is_alive(priv))
+ if (!iwl4965_is_alive(priv))
return -1;
/* always get timestamp with Rx frame */
priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
- rc = iwl_check_rxon_cmd(&priv->staging_rxon);
+ rc = iwl4965_check_rxon_cmd(&priv->staging_rxon);
if (rc) {
IWL_ERROR("Invalid RXON configuration. Not committing.\n");
return -EINVAL;
}
/* If we don't need to send a full RXON, we can use
- * iwl_rxon_assoc_cmd which is used to reconfigure filter
+ * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
- if (!iwl_full_rxon_required(priv)) {
- rc = iwl_send_rxon_assoc(priv);
+ if (!iwl4965_full_rxon_required(priv)) {
+ rc = iwl4965_send_rxon_assoc(priv);
if (rc) {
IWL_ERROR("Error setting RXON_ASSOC "
"configuration (%d).\n", rc);
@@ -1116,25 +1179,25 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
/* station table will be cleared */
priv->assoc_station_added = 0;
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
if (!priv->error_recovering)
priv->start_calib = 0;
iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
-#endif /* CONFIG_IWLWIFI_SENSITIVITY */
+#endif /* CONFIG_IWL4965_SENSITIVITY */
/* If we are currently associated and the new config requires
* an RXON_ASSOC and the new config wants the associated mask enabled,
* we must clear the associated from the active configuration
* before we apply the new config */
- if (iwl_is_associated(priv) &&
+ if (iwl4965_is_associated(priv) &&
(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) {
IWL_DEBUG_INFO("Toggling associated bit on current RXON\n");
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd),
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl4965_rxon_cmd),
&priv->active_rxon);
/* If the mask clearing failed then we set
@@ -1157,35 +1220,35 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
print_mac(mac, priv->staging_rxon.bssid_addr));
/* Apply the new configuration */
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
- sizeof(struct iwl_rxon_cmd), &priv->staging_rxon);
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON,
+ sizeof(struct iwl4965_rxon_cmd), &priv->staging_rxon);
if (rc) {
IWL_ERROR("Error setting new configuration (%d).\n", rc);
return rc;
}
- iwl_clear_stations_table(priv);
+ iwl4965_clear_stations_table(priv);
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
if (!priv->error_recovering)
priv->start_calib = 0;
priv->sensitivity_data.state = IWL_SENS_CALIB_NEED_REINIT;
iwl4965_init_sensitivity(priv, CMD_ASYNC, 1);
-#endif /* CONFIG_IWLWIFI_SENSITIVITY */
+#endif /* CONFIG_IWL4965_SENSITIVITY */
memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
/* If we issue a new RXON command which required a tune then we must
* send a new TXPOWER command or we won't be able to Tx any frames */
- rc = iwl_hw_reg_send_txpower(priv);
+ rc = iwl4965_hw_reg_send_txpower(priv);
if (rc) {
IWL_ERROR("Error setting Tx power (%d).\n", rc);
return rc;
}
/* Add the broadcast address so we can send broadcast frames */
- if (iwl_rxon_add_station(priv, BROADCAST_ADDR, 0) ==
+ if (iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0) ==
IWL_INVALID_STATION) {
IWL_ERROR("Error adding BROADCAST address for transmit.\n");
return -EIO;
@@ -1193,9 +1256,9 @@ static int iwl_commit_rxon(struct iwl_priv *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 */
- if (iwl_is_associated(priv) &&
+ if (iwl4965_is_associated(priv) &&
(priv->iw_mode == IEEE80211_IF_TYPE_STA)) {
- if (iwl_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
+ if (iwl4965_rxon_add_station(priv, priv->active_rxon.bssid_addr, 1)
== IWL_INVALID_STATION) {
IWL_ERROR("Error adding AP address for transmit.\n");
return -EIO;
@@ -1206,9 +1269,9 @@ static int iwl_commit_rxon(struct iwl_priv *priv)
return 0;
}
-static int iwl_send_bt_config(struct iwl_priv *priv)
+static int iwl4965_send_bt_config(struct iwl4965_priv *priv)
{
- struct iwl_bt_cmd bt_cmd = {
+ struct iwl4965_bt_cmd bt_cmd = {
.flags = 3,
.lead_time = 0xAA,
.max_kill = 1,
@@ -1216,15 +1279,15 @@ static int iwl_send_bt_config(struct iwl_priv *priv)
.kill_cts_mask = 0,
};
- return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl_bt_cmd), &bt_cmd);
+ return iwl4965_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+ sizeof(struct iwl4965_bt_cmd), &bt_cmd);
}
-static int iwl_send_scan_abort(struct iwl_priv *priv)
+static int iwl4965_send_scan_abort(struct iwl4965_priv *priv)
{
int rc = 0;
- struct iwl_rx_packet *res;
- struct iwl_host_cmd cmd = {
+ struct iwl4965_rx_packet *res;
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
.meta.flags = CMD_WANT_SKB,
};
@@ -1237,13 +1300,13 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
return 0;
}
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl4965_send_cmd_sync(priv, &cmd);
if (rc) {
clear_bit(STATUS_SCAN_ABORTING, &priv->status);
return rc;
}
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
if (res->u.status != CAN_ABORT_STATUS) {
/* The scan abort will return 1 for success or
* 2 for "failure". A failure condition can be
@@ -1261,8 +1324,8 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
return rc;
}
-static int iwl_card_state_sync_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+static int iwl4965_card_state_sync_callback(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd,
struct sk_buff *skb)
{
return 1;
@@ -1271,16 +1334,16 @@ static int iwl_card_state_sync_callback(struct iwl_priv *priv,
/*
* CARD_STATE_CMD
*
- * Use: Sets the internal card state to enable, disable, or halt
+ * Use: Sets the device's internal card state to enable, disable, or halt
*
* When in the 'enable' state the card operates as normal.
* When in the 'disable' state, the card enters into a low power mode.
* When in the 'halt' state, the card is shut down and must be fully
* restarted to come back on.
*/
-static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
+static int iwl4965_send_card_state(struct iwl4965_priv *priv, u32 flags, u8 meta_flag)
{
- struct iwl_host_cmd cmd = {
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_CARD_STATE_CMD,
.len = sizeof(u32),
.data = &flags,
@@ -1288,22 +1351,22 @@ static int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag)
};
if (meta_flag & CMD_ASYNC)
- cmd.meta.u.callback = iwl_card_state_sync_callback;
+ cmd.meta.u.callback = iwl4965_card_state_sync_callback;
- return iwl_send_cmd(priv, &cmd);
+ return iwl4965_send_cmd(priv, &cmd);
}
-static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb)
+static int iwl4965_add_sta_sync_callback(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd, struct sk_buff *skb)
{
- struct iwl_rx_packet *res = NULL;
+ struct iwl4965_rx_packet *res = NULL;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
return 1;
}
- res = (struct iwl_rx_packet *)skb->data;
+ res = (struct iwl4965_rx_packet *)skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -1321,29 +1384,29 @@ static int iwl_add_sta_sync_callback(struct iwl_priv *priv,
return 1;
}
-int iwl_send_add_station(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags)
+int iwl4965_send_add_station(struct iwl4965_priv *priv,
+ struct iwl4965_addsta_cmd *sta, u8 flags)
{
- struct iwl_rx_packet *res = NULL;
+ struct iwl4965_rx_packet *res = NULL;
int rc = 0;
- struct iwl_host_cmd cmd = {
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_ADD_STA,
- .len = sizeof(struct iwl_addsta_cmd),
+ .len = sizeof(struct iwl4965_addsta_cmd),
.meta.flags = flags,
.data = sta,
};
if (flags & CMD_ASYNC)
- cmd.meta.u.callback = iwl_add_sta_sync_callback;
+ cmd.meta.u.callback = iwl4965_add_sta_sync_callback;
else
cmd.meta.flags |= CMD_WANT_SKB;
- rc = iwl_send_cmd(priv, &cmd);
+ rc = iwl4965_send_cmd(priv, &cmd);
if (rc || (flags & CMD_ASYNC))
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_ADD_STA (0x%08X)\n",
res->hdr.flags);
@@ -1368,7 +1431,7 @@ int iwl_send_add_station(struct iwl_priv *priv,
return rc;
}
-static int iwl_update_sta_key_info(struct iwl_priv *priv,
+static int iwl4965_update_sta_key_info(struct iwl4965_priv *priv,
struct ieee80211_key_conf *keyconf,
u8 sta_id)
{
@@ -1384,7 +1447,6 @@ static int iwl_update_sta_key_info(struct iwl_priv *priv,
break;
case ALG_TKIP:
case ALG_WEP:
- return -EINVAL;
default:
return -EINVAL;
}
@@ -1403,28 +1465,28 @@ static int iwl_update_sta_key_info(struct iwl_priv *priv,
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO("hwcrypto: modify ucode station key info\n");
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
return 0;
}
-static int iwl_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
+static int iwl4965_clear_sta_key_info(struct iwl4965_priv *priv, u8 sta_id)
{
unsigned long flags;
spin_lock_irqsave(&priv->sta_lock, flags);
- memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
- memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl_keyinfo));
+ memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl4965_hw_key));
+ memset(&priv->stations[sta_id].sta.key, 0, sizeof(struct iwl4965_keyinfo));
priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
spin_unlock_irqrestore(&priv->sta_lock, flags);
IWL_DEBUG_INFO("hwcrypto: clear ucode station key info\n");
- iwl_send_add_station(priv, &priv->stations[sta_id].sta, 0);
+ iwl4965_send_add_station(priv, &priv->stations[sta_id].sta, 0);
return 0;
}
-static void iwl_clear_free_frames(struct iwl_priv *priv)
+static void iwl4965_clear_free_frames(struct iwl4965_priv *priv)
{
struct list_head *element;
@@ -1434,7 +1496,7 @@ static void iwl_clear_free_frames(struct iwl_priv *priv)
while (!list_empty(&priv->free_frames)) {
element = priv->free_frames.next;
list_del(element);
- kfree(list_entry(element, struct iwl_frame, list));
+ kfree(list_entry(element, struct iwl4965_frame, list));
priv->frames_count--;
}
@@ -1445,9 +1507,9 @@ static void iwl_clear_free_frames(struct iwl_priv *priv)
}
}
-static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
+static struct iwl4965_frame *iwl4965_get_free_frame(struct iwl4965_priv *priv)
{
- struct iwl_frame *frame;
+ struct iwl4965_frame *frame;
struct list_head *element;
if (list_empty(&priv->free_frames)) {
frame = kzalloc(sizeof(*frame), GFP_KERNEL);
@@ -1462,21 +1524,21 @@ static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv)
element = priv->free_frames.next;
list_del(element);
- return list_entry(element, struct iwl_frame, list);
+ return list_entry(element, struct iwl4965_frame, list);
}
-static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
+static void iwl4965_free_frame(struct iwl4965_priv *priv, struct iwl4965_frame *frame)
{
memset(frame, 0, sizeof(*frame));
list_add(&frame->list, &priv->free_frames);
}
-unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
+unsigned int iwl4965_fill_beacon_frame(struct iwl4965_priv *priv,
struct ieee80211_hdr *hdr,
const u8 *dest, int left)
{
- if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
+ if (!iwl4965_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != IEEE80211_IF_TYPE_IBSS) &&
(priv->iw_mode != IEEE80211_IF_TYPE_AP)))
return 0;
@@ -1489,10 +1551,11 @@ unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
return priv->ibss_beacon->len;
}
-int iwl_rate_index_from_plcp(int plcp)
+int iwl4965_rate_index_from_plcp(int plcp)
{
int i = 0;
+ /* 4965 HT rate format */
if (plcp & RATE_MCS_HT_MSK) {
i = (plcp & 0xff);
@@ -1506,35 +1569,37 @@ int iwl_rate_index_from_plcp(int plcp)
if ((i >= IWL_FIRST_OFDM_RATE) &&
(i <= IWL_LAST_OFDM_RATE))
return i;
+
+ /* 4965 legacy rate format, search for match in table */
} else {
- for (i = 0; i < ARRAY_SIZE(iwl_rates); i++)
- if (iwl_rates[i].plcp == (plcp &0xFF))
+ for (i = 0; i < ARRAY_SIZE(iwl4965_rates); i++)
+ if (iwl4965_rates[i].plcp == (plcp &0xFF))
return i;
}
return -1;
}
-static u8 iwl_rate_get_lowest_plcp(int rate_mask)
+static u8 iwl4965_rate_get_lowest_plcp(int rate_mask)
{
u8 i;
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
- i = iwl_rates[i].next_ieee) {
+ i = iwl4965_rates[i].next_ieee) {
if (rate_mask & (1 << i))
- return iwl_rates[i].plcp;
+ return iwl4965_rates[i].plcp;
}
return IWL_RATE_INVALID;
}
-static int iwl_send_beacon_cmd(struct iwl_priv *priv)
+static int iwl4965_send_beacon_cmd(struct iwl4965_priv *priv)
{
- struct iwl_frame *frame;
+ struct iwl4965_frame *frame;
unsigned int frame_size;
int rc;
u8 rate;
- frame = iwl_get_free_frame(priv);
+ frame = iwl4965_get_free_frame(priv);
if (!frame) {
IWL_ERROR("Could not obtain free frame buffer for beacon "
@@ -1543,22 +1608,22 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
}
if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
- rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic &
+ rate = iwl4965_rate_get_lowest_plcp(priv->active_rate_basic &
0xFF0);
if (rate == IWL_INVALID_RATE)
rate = IWL_RATE_6M_PLCP;
} else {
- rate = iwl_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
+ rate = iwl4965_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
if (rate == IWL_INVALID_RATE)
rate = IWL_RATE_1M_PLCP;
}
- frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
+ frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
- rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
&frame->u.cmd[0]);
- iwl_free_frame(priv, frame);
+ iwl4965_free_frame(priv, frame);
return rc;
}
@@ -1569,22 +1634,22 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv)
*
******************************************************************************/
-static void get_eeprom_mac(struct iwl_priv *priv, u8 *mac)
+static void get_eeprom_mac(struct iwl4965_priv *priv, u8 *mac)
{
memcpy(mac, priv->eeprom.mac_address, 6);
}
/**
- * iwl_eeprom_init - read EEPROM contents
+ * iwl4965_eeprom_init - read EEPROM contents
*
- * Load the EEPROM from adapter into priv->eeprom
+ * Load the EEPROM contents from adapter into priv->eeprom
*
* NOTE: This routine uses the non-debug IO access functions.
*/
-int iwl_eeprom_init(struct iwl_priv *priv)
+int iwl4965_eeprom_init(struct iwl4965_priv *priv)
{
- u16 *e = (u16 *)&priv->eeprom;
- u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
+ __le16 *e = (__le16 *)&priv->eeprom;
+ u32 gp = iwl4965_read32(priv, CSR_EEPROM_GP);
u32 r;
int sz = sizeof(priv->eeprom);
int rc;
@@ -1602,20 +1667,21 @@ int iwl_eeprom_init(struct iwl_priv *priv)
return -ENOENT;
}
- rc = iwl_eeprom_aqcuire_semaphore(priv);
+ /* Make sure driver (instead of uCode) is allowed to read EEPROM */
+ rc = iwl4965_eeprom_acquire_semaphore(priv);
if (rc < 0) {
- IWL_ERROR("Failed to aqcuire EEPROM semaphore.\n");
+ IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
return -ENOENT;
}
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
- _iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
- _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+ _iwl4965_write32(priv, CSR_EEPROM_REG, addr << 1);
+ _iwl4965_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
i += IWL_EEPROM_ACCESS_DELAY) {
- r = _iwl_read_restricted(priv, CSR_EEPROM_REG);
+ r = _iwl4965_read_direct32(priv, CSR_EEPROM_REG);
if (r & CSR_EEPROM_REG_READ_VALID_MSK)
break;
udelay(IWL_EEPROM_ACCESS_DELAY);
@@ -1626,12 +1692,12 @@ int iwl_eeprom_init(struct iwl_priv *priv)
rc = -ETIMEDOUT;
goto done;
}
- e[addr / 2] = le16_to_cpu(r >> 16);
+ e[addr / 2] = cpu_to_le16(r >> 16);
}
rc = 0;
done:
- iwl_eeprom_release_semaphore(priv);
+ iwl4965_eeprom_release_semaphore(priv);
return rc;
}
@@ -1640,22 +1706,20 @@ done:
* Misc. internal state and helper functions
*
******************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
/**
- * iwl_report_frame - dump frame to syslog during debug sessions
+ * iwl4965_report_frame - dump frame to syslog during debug sessions
*
- * hack this function to show different aspects of received frames,
+ * You may hack this function to show different aspects of received frames,
* including selective frame dumps.
* group100 parameter selects whether to show 1 out of 100 good frames.
*
- * TODO: ieee80211_hdr stuff is common to 3945 and 4965, so frame type
- * info output is okay, but some of this stuff (e.g. iwl_rx_frame_stats)
- * is 3945-specific and gives bad output for 4965. Need to split the
- * functionality, keep common stuff here.
+ * TODO: This was originally written for 3945, need to audit for
+ * proper operation with 4965.
*/
-void iwl_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
+void iwl4965_report_frame(struct iwl4965_priv *priv,
+ struct iwl4965_rx_packet *pkt,
struct ieee80211_hdr *header, int group100)
{
u32 to_us;
@@ -1677,9 +1741,9 @@ void iwl_report_frame(struct iwl_priv *priv,
u8 agc;
u16 sig_avg;
u16 noise_diff;
- struct iwl_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl_rx_frame_end *rx_end = IWL_RX_END(pkt);
+ struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+ struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+ struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
u8 *data = IWL_RX_DATA(pkt);
/* MAC header */
@@ -1755,11 +1819,11 @@ void iwl_report_frame(struct iwl_priv *priv,
else
title = "Frame";
- rate = iwl_rate_index_from_plcp(rate_sym);
+ rate = iwl4965_rate_index_from_plcp(rate_sym);
if (rate == -1)
rate = 0;
else
- rate = iwl_rates[rate].ieee / 2;
+ rate = iwl4965_rates[rate].ieee / 2;
/* print frame summary.
* MAC addresses show just the last byte (for brevity),
@@ -1781,25 +1845,25 @@ void iwl_report_frame(struct iwl_priv *priv,
}
}
if (print_dump)
- iwl_print_hex_dump(IWL_DL_RX, data, length);
+ iwl4965_print_hex_dump(IWL_DL_RX, data, length);
}
#endif
-static void iwl_unset_hw_setting(struct iwl_priv *priv)
+static void iwl4965_unset_hw_setting(struct iwl4965_priv *priv)
{
if (priv->hw_setting.shared_virt)
pci_free_consistent(priv->pci_dev,
- sizeof(struct iwl_shared),
+ sizeof(struct iwl4965_shared),
priv->hw_setting.shared_virt,
priv->hw_setting.shared_phys);
}
/**
- * iwl_supported_rate_to_ie - fill in the supported rate in IE field
+ * iwl4965_supported_rate_to_ie - fill in the supported rate in IE field
*
* return : set the bit for each supported rate insert in ie
*/
-static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
+static u16 iwl4965_supported_rate_to_ie(u8 *ie, u16 supported_rate,
u16 basic_rate, int *left)
{
u16 ret_rates = 0, bit;
@@ -1810,7 +1874,7 @@ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) {
ret_rates |= bit;
- rates[*cnt] = iwl_rates[i].ieee |
+ rates[*cnt] = iwl4965_rates[i].ieee |
((bit & basic_rate) ? 0x80 : 0x00);
(*cnt)++;
(*left)--;
@@ -1823,22 +1887,25 @@ static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
return ret_rates;
}
-#ifdef CONFIG_IWLWIFI_HT
-void static iwl_set_ht_capab(struct ieee80211_hw *hw,
- struct ieee80211_ht_capability *ht_cap,
- u8 use_wide_chan);
+#ifdef CONFIG_IWL4965_HT
+void static iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+ struct ieee80211_ht_cap *ht_cap,
+ u8 use_current_config);
#endif
/**
- * iwl_fill_probe_req - fill in all required fields and IE for probe request
+ * iwl4965_fill_probe_req - fill in all required fields and IE for probe request
*/
-static u16 iwl_fill_probe_req(struct iwl_priv *priv,
+static u16 iwl4965_fill_probe_req(struct iwl4965_priv *priv,
struct ieee80211_mgmt *frame,
int left, int is_direct)
{
int len = 0;
u8 *pos = NULL;
- u16 active_rates, ret_rates, cck_rates;
+ u16 active_rates, ret_rates, cck_rates, active_rate_basic;
+#ifdef CONFIG_IWL4965_HT
+ struct ieee80211_hw_mode *mode;
+#endif /* CONFIG_IWL4965_HT */
/* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */
@@ -1848,9 +1915,9 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
len += 24;
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
- memcpy(frame->da, BROADCAST_ADDR, ETH_ALEN);
+ memcpy(frame->da, iwl4965_broadcast_addr, ETH_ALEN);
memcpy(frame->sa, priv->mac_addr, ETH_ALEN);
- memcpy(frame->bssid, BROADCAST_ADDR, ETH_ALEN);
+ memcpy(frame->bssid, iwl4965_broadcast_addr, ETH_ALEN);
frame->seq_ctrl = 0;
/* fill in our indirect SSID IE */
@@ -1888,17 +1955,19 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
*pos++ = WLAN_EID_SUPP_RATES;
*pos = 0;
- priv->active_rate = priv->rates_mask;
- active_rates = priv->active_rate;
- priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
+ /* exclude 60M rate */
+ active_rates = priv->rates_mask;
+ active_rates &= ~IWL_RATE_60M_MASK;
+
+ active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
cck_rates = IWL_CCK_RATES_MASK & active_rates;
- ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
- priv->active_rate_basic, &left);
+ ret_rates = iwl4965_supported_rate_to_ie(pos, cck_rates,
+ active_rate_basic, &left);
active_rates &= ~ret_rates;
- ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
- priv->active_rate_basic, &left);
+ ret_rates = iwl4965_supported_rate_to_ie(pos, active_rates,
+ active_rate_basic, &left);
active_rates &= ~ret_rates;
len += 2 + *pos;
@@ -1914,25 +1983,22 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0;
- iwl_supported_rate_to_ie(pos, active_rates,
- priv->active_rate_basic, &left);
+ iwl4965_supported_rate_to_ie(pos, active_rates,
+ active_rate_basic, &left);
if (*pos > 0)
len += 2 + *pos;
-#ifdef CONFIG_IWLWIFI_HT
- if (is_direct && priv->is_ht_enabled) {
- u8 use_wide_chan = 1;
-
- if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
- use_wide_chan = 0;
+#ifdef CONFIG_IWL4965_HT
+ mode = priv->hw->conf.mode;
+ if (mode->ht_info.ht_supported) {
pos += (*pos) + 1;
*pos++ = WLAN_EID_HT_CAPABILITY;
- *pos++ = sizeof(struct ieee80211_ht_capability);
- iwl_set_ht_capab(NULL, (struct ieee80211_ht_capability *)pos,
- use_wide_chan);
- len += 2 + sizeof(struct ieee80211_ht_capability);
+ *pos++ = sizeof(struct ieee80211_ht_cap);
+ iwl4965_set_ht_capab(priv->hw,
+ (struct ieee80211_ht_cap *)pos, 0);
+ len += 2 + sizeof(struct ieee80211_ht_cap);
}
-#endif /*CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT */
fill_end:
return (u16)len;
@@ -1941,16 +2007,16 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/*
* QoS support
*/
-#ifdef CONFIG_IWLWIFI_QOS
-static int iwl_send_qos_params_command(struct iwl_priv *priv,
- struct iwl_qosparam_cmd *qos)
+#ifdef CONFIG_IWL4965_QOS
+static int iwl4965_send_qos_params_command(struct iwl4965_priv *priv,
+ struct iwl4965_qosparam_cmd *qos)
{
- return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
- sizeof(struct iwl_qosparam_cmd), qos);
+ return iwl4965_send_cmd_pdu(priv, REPLY_QOS_PARAM,
+ sizeof(struct iwl4965_qosparam_cmd), qos);
}
-static void iwl_reset_qos(struct iwl_priv *priv)
+static void iwl4965_reset_qos(struct iwl4965_priv *priv)
{
u16 cw_min = 15;
u16 cw_max = 1023;
@@ -2037,13 +2103,10 @@ static void iwl_reset_qos(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
+static void iwl4965_activate_qos(struct iwl4965_priv *priv, u8 force)
{
unsigned long flags;
- if (priv == NULL)
- return;
-
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -2057,23 +2120,28 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
!priv->qos_data.qos_cap.q_AP.txop_request)
priv->qos_data.def_qos_parm.qos_flags |=
QOS_PARAM_FLG_TXOP_TYPE_MSK;
-
if (priv->qos_data.qos_active)
priv->qos_data.def_qos_parm.qos_flags |=
QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+#ifdef CONFIG_IWL4965_HT
+ if (priv->current_ht_config.is_ht)
+ priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+#endif /* CONFIG_IWL4965_HT */
+
spin_unlock_irqrestore(&priv->lock, flags);
- if (force || iwl_is_associated(priv)) {
- IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
- priv->qos_data.qos_active);
+ if (force || iwl4965_is_associated(priv)) {
+ IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+ priv->qos_data.qos_active,
+ priv->qos_data.def_qos_parm.qos_flags);
- iwl_send_qos_params_command(priv,
+ iwl4965_send_qos_params_command(priv,
&(priv->qos_data.def_qos_parm));
}
}
-#endif /* CONFIG_IWLWIFI_QOS */
+#endif /* CONFIG_IWL4965_QOS */
/*
* Power management (not Tx power!) functions
*/
@@ -2091,7 +2159,7 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
/* default power management (not Tx power) table values */
/* for tim 0-10 */
-static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
+static struct iwl4965_power_vec_entry range_0[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(300), SLP_VEC(2, 4, 6, 7, 7)}, 0},
@@ -2101,7 +2169,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_AC] = {
};
/* for tim > 10 */
-static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
+static struct iwl4965_power_vec_entry range_1[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
@@ -2114,11 +2182,11 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_AC] = {
SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};
-int iwl_power_init_handle(struct iwl_priv *priv)
+int iwl4965_power_init_handle(struct iwl4965_priv *priv)
{
int rc = 0, i;
- struct iwl_power_mgr *pow_data;
- int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_AC;
+ struct iwl4965_power_mgr *pow_data;
+ int size = sizeof(struct iwl4965_power_vec_entry) * IWL_POWER_AC;
u16 pci_pm;
IWL_DEBUG_POWER("Initialize power \n");
@@ -2137,7 +2205,7 @@ int iwl_power_init_handle(struct iwl_priv *priv)
if (rc != 0)
return 0;
else {
- struct iwl_powertable_cmd *cmd;
+ struct iwl4965_powertable_cmd *cmd;
IWL_DEBUG_POWER("adjust power command flags\n");
@@ -2153,15 +2221,15 @@ int iwl_power_init_handle(struct iwl_priv *priv)
return rc;
}
-static int iwl_update_power_cmd(struct iwl_priv *priv,
- struct iwl_powertable_cmd *cmd, u32 mode)
+static int iwl4965_update_power_cmd(struct iwl4965_priv *priv,
+ struct iwl4965_powertable_cmd *cmd, u32 mode)
{
int rc = 0, i;
u8 skip;
u32 max_sleep = 0;
- struct iwl_power_vec_entry *range;
+ struct iwl4965_power_vec_entry *range;
u8 period = 0;
- struct iwl_power_mgr *pow_data;
+ struct iwl4965_power_mgr *pow_data;
if (mode > IWL_POWER_INDEX_5) {
IWL_DEBUG_POWER("Error invalid power mode \n");
@@ -2174,7 +2242,7 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
else
range = &pow_data->pwr_range_1[1];
- memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd));
+ memcpy(cmd, &range[mode].cmd, sizeof(struct iwl4965_powertable_cmd));
#ifdef IWL_MAC80211_DISABLE
if (priv->assoc_network != NULL) {
@@ -2217,14 +2285,14 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
return rc;
}
-static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
+static int iwl4965_send_power_mode(struct iwl4965_priv *priv, u32 mode)
{
- u32 final_mode = mode;
+ u32 uninitialized_var(final_mode);
int rc;
- struct iwl_powertable_cmd cmd;
+ struct iwl4965_powertable_cmd cmd;
/* If on battery, set to 3,
- * if plugged into AC power, set to CAM ("continuosly aware mode"),
+ * if plugged into AC power, set to CAM ("continuously aware mode"),
* else user level */
switch (mode) {
case IWL_POWER_BATTERY:
@@ -2240,9 +2308,9 @@ static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
cmd.keep_alive_beacons = 0;
- iwl_update_power_cmd(priv, &cmd, final_mode);
+ iwl4965_update_power_cmd(priv, &cmd, final_mode);
- rc = iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
+ rc = iwl4965_send_cmd_pdu(priv, POWER_TABLE_CMD, sizeof(cmd), &cmd);
if (final_mode == IWL_POWER_MODE_CAM)
clear_bit(STATUS_POWER_PMI, &priv->status);
@@ -2252,7 +2320,7 @@ static int iwl_send_power_mode(struct iwl_priv *priv, u32 mode)
return rc;
}
-int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+int iwl4965_is_network_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
{
/* Filter incoming packets to determine if they are targeted toward
* this network, discarding packets coming from ourselves */
@@ -2282,7 +2350,7 @@ int iwl_is_network_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-const char *iwl_get_tx_fail_reason(u32 status)
+static const char *iwl4965_get_tx_fail_reason(u32 status)
{
switch (status & TX_STATUS_MSK) {
case TX_STATUS_SUCCESS:
@@ -2309,11 +2377,11 @@ const char *iwl_get_tx_fail_reason(u32 status)
}
/**
- * iwl_scan_cancel - Cancel any currently executing HW scan
+ * iwl4965_scan_cancel - Cancel any currently executing HW scan
*
* NOTE: priv->mutex is not required before calling this function
*/
-static int iwl_scan_cancel(struct iwl_priv *priv)
+static int iwl4965_scan_cancel(struct iwl4965_priv *priv)
{
if (!test_bit(STATUS_SCAN_HW, &priv->status)) {
clear_bit(STATUS_SCANNING, &priv->status);
@@ -2336,17 +2404,17 @@ static int iwl_scan_cancel(struct iwl_priv *priv)
}
/**
- * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
+ * iwl4965_scan_cancel_timeout - Cancel any currently executing HW scan
* @ms: amount of time to wait (in milliseconds) for scan to abort
*
* NOTE: priv->mutex must be held before calling this function
*/
-static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+static int iwl4965_scan_cancel_timeout(struct iwl4965_priv *priv, unsigned long ms)
{
unsigned long now = jiffies;
int ret;
- ret = iwl_scan_cancel(priv);
+ ret = iwl4965_scan_cancel(priv);
if (ret && ms) {
mutex_unlock(&priv->mutex);
while (!time_after(jiffies, now + msecs_to_jiffies(ms)) &&
@@ -2360,7 +2428,7 @@ static int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
return ret;
}
-static void iwl_sequence_reset(struct iwl_priv *priv)
+static void iwl4965_sequence_reset(struct iwl4965_priv *priv)
{
/* Reset ieee stats */
@@ -2371,13 +2439,13 @@ static void iwl_sequence_reset(struct iwl_priv *priv)
priv->last_frag_num = -1;
priv->last_packet_time = 0;
- iwl_scan_cancel(priv);
+ iwl4965_scan_cancel(priv);
}
#define MAX_UCODE_BEACON_INTERVAL 4096
#define INTEL_CONN_LISTEN_INTERVAL __constant_cpu_to_le16(0xA)
-static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
+static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
{
u16 new_val = 0;
u16 beacon_factor = 0;
@@ -2390,7 +2458,7 @@ static __le16 iwl_adjust_beacon_interval(u16 beacon_val)
return cpu_to_le16(new_val);
}
-static void iwl_setup_rxon_timing(struct iwl_priv *priv)
+static void iwl4965_setup_rxon_timing(struct iwl4965_priv *priv)
{
u64 interval_tm_unit;
u64 tsf, result;
@@ -2420,14 +2488,14 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv)
priv->rxon_timing.beacon_interval =
cpu_to_le16(beacon_int);
priv->rxon_timing.beacon_interval =
- iwl_adjust_beacon_interval(
+ iwl4965_adjust_beacon_interval(
le16_to_cpu(priv->rxon_timing.beacon_interval));
}
priv->rxon_timing.atim_window = 0;
} else {
priv->rxon_timing.beacon_interval =
- iwl_adjust_beacon_interval(conf->beacon_int);
+ iwl4965_adjust_beacon_interval(conf->beacon_int);
/* TODO: we need to get atim_window from upper stack
* for now we set to 0 */
priv->rxon_timing.atim_window = 0;
@@ -2446,14 +2514,14 @@ static void iwl_setup_rxon_timing(struct iwl_priv *priv)
le16_to_cpu(priv->rxon_timing.atim_window));
}
-static int iwl_scan_initiate(struct iwl_priv *priv)
+static int iwl4965_scan_initiate(struct iwl4965_priv *priv)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
IWL_ERROR("APs don't scan.\n");
return 0;
}
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl4965_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
}
@@ -2480,9 +2548,9 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
return 0;
}
-static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+static int iwl4965_set_rxon_hwcrypto(struct iwl4965_priv *priv, int hw_decrypt)
{
- struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
+ struct iwl4965_rxon_cmd *rxon = &priv->staging_rxon;
if (hw_decrypt)
rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
@@ -2492,7 +2560,7 @@ static int iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
return 0;
}
-static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
+static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode)
{
if (phymode == MODE_IEEE80211A) {
priv->staging_rxon.flags &=
@@ -2500,7 +2568,7 @@ static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
| RXON_FLG_CCK_MSK);
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
} else {
- /* Copied from iwl_bg_post_associate() */
+ /* Copied from iwl4965_bg_post_associate() */
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
@@ -2516,11 +2584,11 @@ static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode)
}
/*
- * initilize rxon structure with default values fromm eeprom
+ * initialize rxon structure with default values from eeprom
*/
-static void iwl_connection_init_rx_config(struct iwl_priv *priv)
+static void iwl4965_connection_init_rx_config(struct iwl4965_priv *priv)
{
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
@@ -2557,7 +2625,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
#endif
- ch_info = iwl_get_channel_info(priv, priv->phymode,
+ ch_info = iwl4965_get_channel_info(priv, priv->phymode,
le16_to_cpu(priv->staging_rxon.channel));
if (!ch_info)
@@ -2577,7 +2645,7 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
else
priv->phymode = MODE_IEEE80211G;
- iwl_set_flags_for_phymode(priv, priv->phymode);
+ iwl4965_set_flags_for_phymode(priv, priv->phymode);
priv->staging_rxon.ofdm_basic_rates =
(IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
@@ -2593,15 +2661,12 @@ static void iwl_connection_init_rx_config(struct iwl_priv *priv)
iwl4965_set_rxon_chain(priv);
}
-static int iwl_set_mode(struct iwl_priv *priv, int mode)
+static int iwl4965_set_mode(struct iwl4965_priv *priv, int mode)
{
- if (!iwl_is_ready_rf(priv))
- return -EAGAIN;
-
if (mode == IEEE80211_IF_TYPE_IBSS) {
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv,
+ ch_info = iwl4965_get_channel_info(priv,
priv->phymode,
le16_to_cpu(priv->staging_rxon.channel));
@@ -2612,32 +2677,36 @@ static int iwl_set_mode(struct iwl_priv *priv, int mode)
}
}
+ priv->iw_mode = mode;
+
+ iwl4965_connection_init_rx_config(priv);
+ memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
+
+ iwl4965_clear_stations_table(priv);
+
+ /* dont commit rxon if rf-kill is on*/
+ if (!iwl4965_is_ready_rf(priv))
+ return -EAGAIN;
+
cancel_delayed_work(&priv->scan_check);
- if (iwl_scan_cancel_timeout(priv, 100)) {
+ if (iwl4965_scan_cancel_timeout(priv, 100)) {
IWL_WARNING("Aborted scan still in progress after 100ms\n");
IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
return -EAGAIN;
}
- priv->iw_mode = mode;
-
- iwl_connection_init_rx_config(priv);
- memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
-
- iwl_clear_stations_table(priv);
-
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
return 0;
}
-static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+static void iwl4965_build_tx_cmd_hwcrypto(struct iwl4965_priv *priv,
struct ieee80211_tx_control *ctl,
- struct iwl_cmd *cmd,
+ struct iwl4965_cmd *cmd,
struct sk_buff *skb_frag,
int last_frag)
{
- struct iwl_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
+ struct iwl4965_hw_key *keyinfo = &priv->stations[ctl->key_idx].keyinfo;
switch (keyinfo->alg) {
case ALG_CCMP:
@@ -2680,8 +2749,8 @@ static void iwl_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
/*
* handle build REPLY_TX command notification.
*/
-static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
+static void iwl4965_build_tx_cmd_basic(struct iwl4965_priv *priv,
+ struct iwl4965_cmd *cmd,
struct ieee80211_tx_control *ctrl,
struct ieee80211_hdr *hdr,
int is_unicast, u8 std_id)
@@ -2703,6 +2772,10 @@ static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
+ if (ieee80211_is_back_request(fc))
+ tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+
+
cmd->cmd.tx.sta_id = std_id;
if (ieee80211_get_morefrag(hdr))
tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
@@ -2729,11 +2802,9 @@ static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) {
if ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ ||
(fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ)
- cmd->cmd.tx.timeout.pm_frame_timeout =
- cpu_to_le16(3);
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(3);
else
- cmd->cmd.tx.timeout.pm_frame_timeout =
- cpu_to_le16(2);
+ cmd->cmd.tx.timeout.pm_frame_timeout = cpu_to_le16(2);
} else
cmd->cmd.tx.timeout.pm_frame_timeout = 0;
@@ -2742,40 +2813,47 @@ static void iwl_build_tx_cmd_basic(struct iwl_priv *priv,
cmd->cmd.tx.next_frame_len = 0;
}
-static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+/**
+ * iwl4965_get_sta_id - Find station's index within station table
+ *
+ * If new IBSS station, create new entry in station table
+ */
+static int iwl4965_get_sta_id(struct iwl4965_priv *priv,
+ struct ieee80211_hdr *hdr)
{
int sta_id;
u16 fc = le16_to_cpu(hdr->frame_control);
DECLARE_MAC_BUF(mac);
- /* If this frame is broadcast or not data then use the broadcast
- * station id */
+ /* If this frame is broadcast or management, use broadcast station id */
if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
is_multicast_ether_addr(hdr->addr1))
return priv->hw_setting.bcast_sta_id;
switch (priv->iw_mode) {
- /* If this frame is part of a BSS network (we're a station), then
- * we use the AP's station id */
+ /* If we are a client station in a BSS network, use the special
+ * AP station entry (that's the only station we communicate with) */
case IEEE80211_IF_TYPE_STA:
return IWL_AP_ID;
/* If we are an AP, then find the station, or use BCAST */
case IEEE80211_IF_TYPE_AP:
- sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
return priv->hw_setting.bcast_sta_id;
- /* If this frame is part of a IBSS network, then we use the
- * target specific station id */
+ /* If this frame is going out to an IBSS network, find the station,
+ * or create a new station table entry */
case IEEE80211_IF_TYPE_IBSS:
- sta_id = iwl_hw_find_station(priv, hdr->addr1);
+ sta_id = iwl4965_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- sta_id = iwl_add_station(priv, hdr->addr1, 0, CMD_ASYNC);
+ /* Create new station table entry */
+ sta_id = iwl4965_add_station_flags(priv, hdr->addr1,
+ 0, CMD_ASYNC, NULL);
if (sta_id != IWL_INVALID_STATION)
return sta_id;
@@ -2783,11 +2861,11 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
IWL_DEBUG_DROP("Station %s not in station map. "
"Defaulting to broadcast...\n",
print_mac(mac, hdr->addr1));
- iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
+ iwl4965_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
default:
- IWL_WARNING("Unkown mode of operation: %d", priv->iw_mode);
+ IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode);
return priv->hw_setting.bcast_sta_id;
}
}
@@ -2795,18 +2873,19 @@ static int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
/*
* start REPLY_TX command process
*/
-static int iwl_tx_skb(struct iwl_priv *priv,
+static int iwl4965_tx_skb(struct iwl4965_priv *priv,
struct sk_buff *skb, struct ieee80211_tx_control *ctl)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct iwl_tfd_frame *tfd;
+ struct iwl4965_tfd_frame *tfd;
u32 *control_flags;
int txq_id = ctl->queue;
- struct iwl_tx_queue *txq = NULL;
- struct iwl_queue *q = NULL;
+ struct iwl4965_tx_queue *txq = NULL;
+ struct iwl4965_queue *q = NULL;
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
- struct iwl_cmd *out_cmd = NULL;
+ dma_addr_t scratch_phys;
+ struct iwl4965_cmd *out_cmd = NULL;
u16 len, idx, len_org;
u8 id, hdr_len, unicast;
u8 sta_id;
@@ -2818,13 +2897,13 @@ static int iwl_tx_skb(struct iwl_priv *priv,
int rc;
spin_lock_irqsave(&priv->lock, flags);
- if (iwl_is_rfkill(priv)) {
+ if (iwl4965_is_rfkill(priv)) {
IWL_DEBUG_DROP("Dropping - RF KILL\n");
goto drop_unlock;
}
- if (!priv->interface_id) {
- IWL_DEBUG_DROP("Dropping - !priv->interface_id\n");
+ if (!priv->vif) {
+ IWL_DEBUG_DROP("Dropping - !priv->vif\n");
goto drop_unlock;
}
@@ -2838,7 +2917,7 @@ static int iwl_tx_skb(struct iwl_priv *priv,
fc = le16_to_cpu(hdr->frame_control);
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
if (ieee80211_is_auth(fc))
IWL_DEBUG_TX("Sending AUTH frame\n");
else if (ieee80211_is_assoc_request(fc))
@@ -2847,16 +2926,19 @@ static int iwl_tx_skb(struct iwl_priv *priv,
IWL_DEBUG_TX("Sending REASSOC frame\n");
#endif
- if (!iwl_is_associated(priv) &&
+ /* drop all data frame if we are not associated */
+ if (!iwl4965_is_associated(priv) && !priv->assoc_id &&
((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA)) {
- IWL_DEBUG_DROP("Dropping - !iwl_is_associated\n");
+ IWL_DEBUG_DROP("Dropping - !iwl4965_is_associated\n");
goto drop_unlock;
}
spin_unlock_irqrestore(&priv->lock, flags);
hdr_len = ieee80211_get_hdrlen(fc);
- sta_id = iwl_get_sta_id(priv, hdr);
+
+ /* Find (or create) index into station table for destination station */
+ sta_id = iwl4965_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
DECLARE_MAC_BUF(mac);
@@ -2876,40 +2958,62 @@ static int iwl_tx_skb(struct iwl_priv *priv,
(hdr->seq_ctrl &
__constant_cpu_to_le16(IEEE80211_SCTL_FRAG));
seq_number += 0x10;
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
/* aggregation is on for this <sta,tid> */
if (ctl->flags & IEEE80211_TXCTL_HT_MPDU_AGG)
txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
}
+
+ /* Descriptor for chosen Tx queue */
txq = &priv->txq[txq_id];
q = &txq->q;
spin_lock_irqsave(&priv->lock, flags);
- tfd = &txq->bd[q->first_empty];
+ /* Set up first empty TFD within this queue's circular TFD buffer */
+ tfd = &txq->bd[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
control_flags = (u32 *) tfd;
- idx = get_cmd_index(q, q->first_empty, 0);
+ idx = get_cmd_index(q, q->write_ptr, 0);
- memset(&(txq->txb[q->first_empty]), 0, sizeof(struct iwl_tx_info));
- txq->txb[q->first_empty].skb[0] = skb;
- memcpy(&(txq->txb[q->first_empty].status.control),
+ /* Set up driver data for this TFD */
+ memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl4965_tx_info));
+ txq->txb[q->write_ptr].skb[0] = skb;
+ memcpy(&(txq->txb[q->write_ptr].status.control),
ctl, sizeof(struct ieee80211_tx_control));
+
+ /* Set up first empty entry in queue's array of Tx/cmd buffers */
out_cmd = &txq->cmd[idx];
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(&out_cmd->cmd.tx, 0, sizeof(out_cmd->cmd.tx));
+
+ /*
+ * Set up the Tx-command (not MAC!) header.
+ * Store the chosen Tx queue and TFD index within the sequence field;
+ * after Tx, uCode's Tx response will return this value so driver can
+ * locate the frame within the tx queue and do post-tx processing.
+ */
out_cmd->hdr.cmd = REPLY_TX;
out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
- INDEX_TO_SEQ(q->first_empty)));
- /* copy frags header */
+ INDEX_TO_SEQ(q->write_ptr)));
+
+ /* Copy MAC header from skb into command buffer */
memcpy(out_cmd->cmd.tx.hdr, hdr, hdr_len);
- /* hdr = (struct ieee80211_hdr *)out_cmd->cmd.tx.hdr; */
+ /*
+ * Use the first empty entry in this queue's command buffer array
+ * to contain the Tx command and MAC header concatenated together
+ * (payload data will be in another buffer).
+ * Size of this varies, due to varying MAC header length.
+ * If end is not dword aligned, we'll have 2 extra bytes at the end
+ * of the MAC header (device reads on dword boundaries).
+ * We'll tell device about this padding later.
+ */
len = priv->hw_setting.tx_cmd_len +
- sizeof(struct iwl_cmd_header) + hdr_len;
+ sizeof(struct iwl4965_cmd_header) + hdr_len;
len_org = len;
len = (len + 3) & ~3;
@@ -2919,36 +3023,53 @@ static int iwl_tx_skb(struct iwl_priv *priv,
else
len_org = 0;
- txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl_cmd) * idx +
- offsetof(struct iwl_cmd, hdr);
+ /* Physical address of this Tx command's header (not MAC header!),
+ * within command buffer array. */
+ txcmd_phys = txq->dma_addr_cmd + sizeof(struct iwl4965_cmd) * idx +
+ offsetof(struct iwl4965_cmd, hdr);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
+ /* Add buffer containing Tx command and MAC(!) header to TFD's
+ * first entry */
+ iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT))
- iwl_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
+ iwl4965_build_tx_cmd_hwcrypto(priv, ctl, out_cmd, skb, 0);
- /* 802.11 null functions have no payload... */
+ /* Set up TFD's 2nd entry to point directly to remainder of skb,
+ * if any (802.11 null frames have no payload). */
len = skb->len - hdr_len;
if (len) {
phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
len, PCI_DMA_TODEVICE);
- iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
+ iwl4965_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, len);
}
+ /* Tell 4965 about any 2-byte padding after MAC header */
if (len_org)
out_cmd->cmd.tx.tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+ /* Total # bytes to be transmitted */
len = (u16)skb->len;
out_cmd->cmd.tx.len = cpu_to_le16(len);
/* TODO need this for burst mode later on */
- iwl_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
+ iwl4965_build_tx_cmd_basic(priv, out_cmd, ctl, hdr, unicast, sta_id);
/* set is_hcca to 0; it probably will never be implemented */
- iwl_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+ iwl4965_hw_build_tx_cmd_rate(priv, out_cmd, ctl, hdr, sta_id, 0);
+
+ scratch_phys = txcmd_phys + sizeof(struct iwl4965_cmd_header) +
+ offsetof(struct iwl4965_tx_cmd, scratch);
+ out_cmd->cmd.tx.dram_lsb_ptr = cpu_to_le32(scratch_phys);
+ out_cmd->cmd.tx.dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+
+#ifdef CONFIG_IWL4965_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+ /* TODO: move this functionality to rate scaling */
+ iwl4965_tl_get_stats(priv, hdr);
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /*CONFIG_IWL4965_HT */
- iwl4965_tx_cmd(priv, out_cmd, sta_id, txcmd_phys,
- hdr, hdr_len, ctl, NULL);
if (!ieee80211_get_morefrag(hdr)) {
txq->need_update = 1;
@@ -2961,27 +3082,29 @@ static int iwl_tx_skb(struct iwl_priv *priv,
txq->need_update = 0;
}
- iwl_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
+ iwl4965_print_hex_dump(IWL_DL_TX, out_cmd->cmd.payload,
sizeof(out_cmd->cmd.tx));
- iwl_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
+ iwl4965_print_hex_dump(IWL_DL_TX, (u8 *)out_cmd->cmd.tx.hdr,
ieee80211_get_hdrlen(fc));
+ /* Set up entry for this TFD in Tx byte-count array */
iwl4965_tx_queue_update_wr_ptr(priv, txq, len);
- q->first_empty = iwl_queue_inc_wrap(q->first_empty, q->n_bd);
- rc = iwl_tx_queue_update_write_ptr(priv, txq);
+ /* Tell device the write index *just past* this latest filled TFD */
+ q->write_ptr = iwl4965_queue_inc_wrap(q->write_ptr, q->n_bd);
+ rc = iwl4965_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
if (rc)
return rc;
- if ((iwl_queue_space(q) < q->high_mark)
+ if ((iwl4965_queue_space(q) < q->high_mark)
&& priv->mac80211_registered) {
if (wait_write_ptr) {
spin_lock_irqsave(&priv->lock, flags);
txq->need_update = 1;
- iwl_tx_queue_update_write_ptr(priv, txq);
+ iwl4965_tx_queue_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -2996,13 +3119,13 @@ drop:
return -1;
}
-static void iwl_set_rate(struct iwl_priv *priv)
+static void iwl4965_set_rate(struct iwl4965_priv *priv)
{
const struct ieee80211_hw_mode *hw = NULL;
struct ieee80211_rate *rate;
int i;
- hw = iwl_get_hw_mode(priv, priv->phymode);
+ hw = iwl4965_get_hw_mode(priv, priv->phymode);
if (!hw) {
IWL_ERROR("Failed to set rate: unable to get hw mode\n");
return;
@@ -3020,7 +3143,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
if ((rate->val < IWL_RATE_COUNT) &&
(rate->flags & IEEE80211_RATE_SUPPORTED)) {
IWL_DEBUG_RATE("Adding rate index %d (plcp %d)%s\n",
- rate->val, iwl_rates[rate->val].plcp,
+ rate->val, iwl4965_rates[rate->val].plcp,
(rate->flags & IEEE80211_RATE_BASIC) ?
"*" : "");
priv->active_rate |= (1 << rate->val);
@@ -3028,7 +3151,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
priv->active_rate_basic |= (1 << rate->val);
} else
IWL_DEBUG_RATE("Not adding rate %d (plcp %d)\n",
- rate->val, iwl_rates[rate->val].plcp);
+ rate->val, iwl4965_rates[rate->val].plcp);
}
IWL_DEBUG_RATE("Set active_rate = %0x, active_rate_basic = %0x\n",
@@ -3057,7 +3180,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
+static void iwl4965_radio_kill_sw(struct iwl4965_priv *priv, int disable_radio)
{
unsigned long flags;
@@ -3068,21 +3191,21 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
disable_radio ? "OFF" : "ON");
if (disable_radio) {
- iwl_scan_cancel(priv);
+ iwl4965_scan_cancel(priv);
/* FIXME: This is a workaround for AP */
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_SW_BIT_RFKILL);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
+ iwl4965_send_card_state(priv, CARD_STATE_CMD_DISABLE, 0);
set_bit(STATUS_RF_KILL_SW, &priv->status);
}
return;
}
spin_lock_irqsave(&priv->lock, flags);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
clear_bit(STATUS_RF_KILL_SW, &priv->status);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -3091,9 +3214,9 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
msleep(10);
spin_lock_irqsave(&priv->lock, flags);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- if (!iwl_grab_restricted_access(priv))
- iwl_release_restricted_access(priv);
+ iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+ if (!iwl4965_grab_nic_access(priv))
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
@@ -3106,7 +3229,7 @@ static void iwl_radio_kill_sw(struct iwl_priv *priv, int disable_radio)
return;
}
-void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
+void iwl4965_set_decrypted_flag(struct iwl4965_priv *priv, struct sk_buff *skb,
u32 decrypt_res, struct ieee80211_rx_status *stats)
{
u16 fc =
@@ -3138,97 +3261,10 @@ void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
}
}
-void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
- void *data, short len,
- struct ieee80211_rx_status *stats,
- u16 phy_flags)
-{
- struct iwl_rt_rx_hdr *iwl_rt;
-
- /* First cache any information we need before we overwrite
- * the information provided in the skb from the hardware */
- s8 signal = stats->ssi;
- s8 noise = 0;
- int rate = stats->rate;
- u64 tsf = stats->mactime;
- __le16 phy_flags_hw = cpu_to_le16(phy_flags);
-
- /* We received data from the HW, so stop the watchdog */
- if (len > IWL_RX_BUF_SIZE - sizeof(*iwl_rt)) {
- IWL_DEBUG_DROP("Dropping too large packet in monitor\n");
- return;
- }
-
- /* copy the frame data to write after where the radiotap header goes */
- iwl_rt = (void *)rxb->skb->data;
- memmove(iwl_rt->payload, data, len);
-
- iwl_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- iwl_rt->rt_hdr.it_pad = 0; /* always good to zero */
-
- /* total header + data */
- iwl_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*iwl_rt));
-
- /* Set the size of the skb to the size of the frame */
- skb_put(rxb->skb, sizeof(*iwl_rt) + len);
-
- /* Big bitfield of all the fields we provide in radiotap */
- iwl_rt->rt_hdr.it_present =
- cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
- (1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_RATE) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
- (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
- (1 << IEEE80211_RADIOTAP_ANTENNA));
-
- /* Zero the flags, we'll add to them as we go */
- iwl_rt->rt_flags = 0;
-
- iwl_rt->rt_tsf = cpu_to_le64(tsf);
-
- /* Convert to dBm */
- iwl_rt->rt_dbmsignal = signal;
- iwl_rt->rt_dbmnoise = noise;
-
- /* Convert the channel frequency and set the flags */
- iwl_rt->rt_channelMHz = cpu_to_le16(stats->freq);
- if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ));
- else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ));
- else /* 802.11g */
- iwl_rt->rt_chbitmask =
- cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ));
-
- rate = iwl_rate_index_from_plcp(rate);
- if (rate == -1)
- iwl_rt->rt_rate = 0;
- else
- iwl_rt->rt_rate = iwl_rates[rate].ieee;
-
- /* antenna number */
- iwl_rt->rt_antenna =
- le16_to_cpu(phy_flags_hw & RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
- /* set the preamble flag if we have it */
- if (phy_flags_hw & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
- iwl_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
-
- IWL_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len);
-
- stats->flag |= RX_FLAG_RADIOTAP;
- ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
- rxb->skb = NULL;
-}
-
#define IWL_PACKET_RETRY_TIME HZ
-int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
+int iwl4965_is_duplicate_packet(struct iwl4965_priv *priv, struct ieee80211_hdr *header)
{
u16 sc = le16_to_cpu(header->seq_ctrl);
u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
@@ -3239,29 +3275,26 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_IBSS:{
struct list_head *p;
- struct iwl_ibss_seq *entry = NULL;
+ struct iwl4965_ibss_seq *entry = NULL;
u8 *mac = header->addr2;
int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
__list_for_each(p, &priv->ibss_mac_hash[index]) {
- entry =
- list_entry(p, struct iwl_ibss_seq, list);
+ entry = list_entry(p, struct iwl4965_ibss_seq, list);
if (!compare_ether_addr(entry->mac, mac))
break;
}
if (p == &priv->ibss_mac_hash[index]) {
entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
if (!entry) {
- IWL_ERROR
- ("Cannot malloc new mac entry\n");
+ IWL_ERROR("Cannot malloc new mac entry\n");
return 0;
}
memcpy(entry->mac, mac, ETH_ALEN);
entry->seq_num = seq;
entry->frag_num = frag;
entry->packet_time = jiffies;
- list_add(&entry->list,
- &priv->ibss_mac_hash[index]);
+ list_add(&entry->list, &priv->ibss_mac_hash[index]);
return 0;
}
last_seq = &entry->seq_num;
@@ -3295,7 +3328,7 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
return 1;
}
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
#include "iwl-spectrum.h"
@@ -3310,7 +3343,7 @@ int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr *header)
* the lower 3 bytes is the time in usec within one beacon interval
*/
-static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
+static u32 iwl4965_usecs_to_beacons(u32 usec, u32 beacon_interval)
{
u32 quot;
u32 rem;
@@ -3329,7 +3362,7 @@ static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
* the same as HW timer counter counting down
*/
-static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
{
u32 base_low = base & BEACON_TIME_MASK_LOW;
u32 addon_low = addon & BEACON_TIME_MASK_LOW;
@@ -3348,13 +3381,13 @@ static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
return cpu_to_le32(res);
}
-static int iwl_get_measurement(struct iwl_priv *priv,
+static int iwl4965_get_measurement(struct iwl4965_priv *priv,
struct ieee80211_measurement_params *params,
u8 type)
{
- struct iwl_spectrum_cmd spectrum;
- struct iwl_rx_packet *res;
- struct iwl_host_cmd cmd = {
+ struct iwl4965_spectrum_cmd spectrum;
+ struct iwl4965_rx_packet *res;
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
.data = (void *)&spectrum,
.meta.flags = CMD_WANT_SKB,
@@ -3364,9 +3397,9 @@ static int iwl_get_measurement(struct iwl_priv *priv,
int spectrum_resp_status;
int duration = le16_to_cpu(params->duration);
- if (iwl_is_associated(priv))
+ if (iwl4965_is_associated(priv))
add_time =
- iwl_usecs_to_beacons(
+ iwl4965_usecs_to_beacons(
le64_to_cpu(params->start_time) - priv->last_tsf,
le16_to_cpu(priv->rxon_timing.beacon_interval));
@@ -3379,9 +3412,9 @@ static int iwl_get_measurement(struct iwl_priv *priv,
cmd.len = sizeof(spectrum);
spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
- if (iwl_is_associated(priv))
+ if (iwl4965_is_associated(priv))
spectrum.start_time =
- iwl_add_beacon_time(priv->last_beacon_time,
+ iwl4965_add_beacon_time(priv->last_beacon_time,
add_time,
le16_to_cpu(priv->rxon_timing.beacon_interval));
else
@@ -3394,11 +3427,11 @@ static int iwl_get_measurement(struct iwl_priv *priv,
spectrum.flags |= RXON_FLG_BAND_24G_MSK |
RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl4965_send_cmd_sync(priv, &cmd);
if (rc)
return rc;
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ res = (struct iwl4965_rx_packet *)cmd.meta.u.skb->data;
if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
rc = -EIO;
@@ -3428,8 +3461,8 @@ static int iwl_get_measurement(struct iwl_priv *priv,
}
#endif
-static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
- struct iwl_tx_info *tx_sta)
+static void iwl4965_txstatus_to_ieee(struct iwl4965_priv *priv,
+ struct iwl4965_tx_info *tx_sta)
{
tx_sta->status.ack_signal = 0;
@@ -3448,41 +3481,41 @@ static void iwl_txstatus_to_ieee(struct iwl_priv *priv,
}
/**
- * iwl_tx_queue_reclaim - Reclaim Tx queue entries no more used by NIC.
+ * iwl4965_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
*
- * When FW advances 'R' index, all entries between old and
- * new 'R' index need to be reclaimed. As result, some free space
- * forms. If there is enough free space (> low mark), wake Tx queue.
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
*/
-int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+int iwl4965_tx_queue_reclaim(struct iwl4965_priv *priv, int txq_id, int index)
{
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
- struct iwl_queue *q = &txq->q;
+ struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl4965_queue *q = &txq->q;
int nfreed = 0;
if ((index >= q->n_bd) || (x2_queue_used(q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
- index, q->n_bd, q->first_empty, q->last_used);
+ index, q->n_bd, q->write_ptr, q->read_ptr);
return 0;
}
- for (index = iwl_queue_inc_wrap(index, q->n_bd);
- q->last_used != index;
- q->last_used = iwl_queue_inc_wrap(q->last_used, q->n_bd)) {
+ for (index = iwl4965_queue_inc_wrap(index, q->n_bd);
+ q->read_ptr != index;
+ q->read_ptr = iwl4965_queue_inc_wrap(q->read_ptr, q->n_bd)) {
if (txq_id != IWL_CMD_QUEUE_NUM) {
- iwl_txstatus_to_ieee(priv,
- &(txq->txb[txq->q.last_used]));
- iwl_hw_txq_free_tfd(priv, txq);
+ iwl4965_txstatus_to_ieee(priv,
+ &(txq->txb[txq->q.read_ptr]));
+ iwl4965_hw_txq_free_tfd(priv, txq);
} else if (nfreed > 1) {
IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
- q->first_empty, q->last_used);
+ q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
}
nfreed++;
}
- if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+ if (iwl4965_queue_space(q) > q->low_mark && (txq_id >= 0) &&
(txq_id != IWL_CMD_QUEUE_NUM) &&
priv->mac80211_registered)
ieee80211_wake_queue(priv->hw, txq_id);
@@ -3491,7 +3524,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
return nfreed;
}
-static int iwl_is_tx_success(u32 status)
+static int iwl4965_is_tx_success(u32 status)
{
status &= TX_STATUS_MSK;
return (status == TX_STATUS_SUCCESS)
@@ -3503,22 +3536,22 @@ static int iwl_is_tx_success(u32 status)
* Generic RX handler implementations
*
******************************************************************************/
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
-static inline int iwl_get_ra_sta_id(struct iwl_priv *priv,
+static inline int iwl4965_get_ra_sta_id(struct iwl4965_priv *priv,
struct ieee80211_hdr *hdr)
{
if (priv->iw_mode == IEEE80211_IF_TYPE_STA)
return IWL_AP_ID;
else {
u8 *da = ieee80211_get_DA(hdr);
- return iwl_hw_find_station(priv, da);
+ return iwl4965_hw_find_station(priv, da);
}
}
-static struct ieee80211_hdr *iwl_tx_queue_get_hdr(
- struct iwl_priv *priv, int txq_id, int idx)
+static struct ieee80211_hdr *iwl4965_tx_queue_get_hdr(
+ struct iwl4965_priv *priv, int txq_id, int idx)
{
if (priv->txq[txq_id].txb[idx].skb[0])
return (struct ieee80211_hdr *)priv->txq[txq_id].
@@ -3526,16 +3559,20 @@ static struct ieee80211_hdr *iwl_tx_queue_get_hdr(
return NULL;
}
-static inline u32 iwl_get_scd_ssn(struct iwl_tx_resp *tx_resp)
+static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
{
__le32 *scd_ssn = (__le32 *)((u32 *)&tx_resp->status +
tx_resp->frame_count);
return le32_to_cpu(*scd_ssn) & MAX_SN;
}
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
- struct iwl_ht_agg *agg,
- struct iwl_tx_resp *tx_resp,
+
+/**
+ * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+ */
+static int iwl4965_tx_status_reply_tx(struct iwl4965_priv *priv,
+ struct iwl4965_ht_agg *agg,
+ struct iwl4965_tx_resp *tx_resp,
u16 start_idx)
{
u32 status;
@@ -3547,15 +3584,17 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
u16 seq;
if (agg->wait_for_ba)
- IWL_DEBUG_TX_REPLY("got tx repsons w/o back\n");
+ IWL_DEBUG_TX_REPLY("got tx response w/o block-ack\n");
agg->frame_count = tx_resp->frame_count;
agg->start_idx = start_idx;
agg->rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
agg->bitmap0 = agg->bitmap1 = 0;
+ /* # frames attempted by Tx command */
if (agg->frame_count == 1) {
- struct iwl_tx_queue *txq ;
+ /* Only one frame was attempted; no block-ack will arrive */
+ struct iwl4965_tx_queue *txq ;
status = le32_to_cpu(frame_status[0]);
txq_id = agg->txq_id;
@@ -3564,28 +3603,30 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY("FrameCnt = %d, StartIdx=%d \n",
agg->frame_count, agg->start_idx);
- tx_status = &(priv->txq[txq_id].txb[txq->q.last_used].status);
+ tx_status = &(priv->txq[txq_id].txb[txq->q.read_ptr].status);
tx_status->retry_count = tx_resp->failure_frame;
tx_status->queue_number = status & 0xff;
tx_status->queue_length = tx_resp->bt_kill_count;
tx_status->queue_length |= tx_resp->failure_rts;
- tx_status->flags = iwl_is_tx_success(status)?
+ tx_status->flags = iwl4965_is_tx_success(status)?
IEEE80211_TX_STATUS_ACK : 0;
tx_status->control.tx_rate =
- iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
+ iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
/* FIXME: code repetition end */
IWL_DEBUG_TX_REPLY("1 Frame 0x%x failure :%d\n",
status & 0xff, tx_resp->failure_frame);
IWL_DEBUG_TX_REPLY("Rate Info rate_n_flags=%x\n",
- iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags));
+ iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags));
agg->wait_for_ba = 0;
} else {
+ /* Two or more frames were attempted; expect block-ack */
u64 bitmap = 0;
int start = agg->start_idx;
+ /* Construct bit-map of pending frames within Tx window */
for (i = 0; i < agg->frame_count; i++) {
u16 sc;
status = le32_to_cpu(frame_status[i]);
@@ -3600,7 +3641,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n",
agg->frame_count, txq_id, idx);
- hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
+ hdr = iwl4965_tx_queue_get_hdr(priv, txq_id, idx);
sc = le16_to_cpu(hdr->seq_ctrl);
if (idx != (SEQ_TO_SN(sc) & 0xff)) {
@@ -3649,19 +3690,22 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
#endif
#endif
-static void iwl_rx_reply_tx(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+/**
+ * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+ */
+static void iwl4965_rx_reply_tx(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
- struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct iwl4965_tx_queue *txq = &priv->txq[txq_id];
struct ieee80211_tx_status *tx_status;
- struct iwl_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+ struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
int tid, sta_id;
#endif
#endif
@@ -3669,18 +3713,18 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv,
if ((index >= txq->q.n_bd) || (x2_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
"is out of range [0-%d] %d %d\n", txq_id,
- index, txq->q.n_bd, txq->q.first_empty,
- txq->q.last_used);
+ index, txq->q.n_bd, txq->q.write_ptr,
+ txq->q.read_ptr);
return;
}
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
if (txq->sched_retry) {
- const u32 scd_ssn = iwl_get_scd_ssn(tx_resp);
+ const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
struct ieee80211_hdr *hdr =
- iwl_tx_queue_get_hdr(priv, txq_id, index);
- struct iwl_ht_agg *agg = NULL;
+ iwl4965_tx_queue_get_hdr(priv, txq_id, index);
+ struct iwl4965_ht_agg *agg = NULL;
__le16 *qc = ieee80211_get_qos_ctrl(hdr);
if (qc == NULL) {
@@ -3690,7 +3734,7 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv,
tid = le16_to_cpu(*qc) & 0xf;
- sta_id = iwl_get_ra_sta_id(priv, hdr);
+ sta_id = iwl4965_get_ra_sta_id(priv, hdr);
if (unlikely(sta_id == IWL_INVALID_STATION)) {
IWL_ERROR("Station not known for\n");
return;
@@ -3701,20 +3745,20 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv,
iwl4965_tx_status_reply_tx(priv, agg, tx_resp, index);
if ((tx_resp->frame_count == 1) &&
- !iwl_is_tx_success(status)) {
+ !iwl4965_is_tx_success(status)) {
/* TODO: send BAR */
}
- if ((txq->q.last_used != (scd_ssn & 0xff))) {
- index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
+ if ((txq->q.read_ptr != (scd_ssn & 0xff))) {
+ index = iwl4965_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
"%d index %d\n", scd_ssn , index);
- iwl_tx_queue_reclaim(priv, txq_id, index);
+ iwl4965_tx_queue_reclaim(priv, txq_id, index);
}
} else {
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
- tx_status = &(txq->txb[txq->q.last_used].status);
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
+ tx_status = &(txq->txb[txq->q.read_ptr].status);
tx_status->retry_count = tx_resp->failure_frame;
tx_status->queue_number = status;
@@ -3722,35 +3766,35 @@ static void iwl_rx_reply_tx(struct iwl_priv *priv,
tx_status->queue_length |= tx_resp->failure_rts;
tx_status->flags =
- iwl_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
+ iwl4965_is_tx_success(status) ? IEEE80211_TX_STATUS_ACK : 0;
tx_status->control.tx_rate =
- iwl_hw_get_rate_n_flags(tx_resp->rate_n_flags);
+ iwl4965_hw_get_rate_n_flags(tx_resp->rate_n_flags);
IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags 0x%x "
- "retries %d\n", txq_id, iwl_get_tx_fail_reason(status),
+ "retries %d\n", txq_id, iwl4965_get_tx_fail_reason(status),
status, le32_to_cpu(tx_resp->rate_n_flags),
tx_resp->failure_frame);
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
if (index != -1)
- iwl_tx_queue_reclaim(priv, txq_id, index);
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+ iwl4965_tx_queue_reclaim(priv, txq_id, index);
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
}
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
-static void iwl_rx_reply_alive(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_alive(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_alive_resp *palive;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_alive_resp *palive;
struct delayed_work *pwork;
palive = &pkt->u.alive_frame;
@@ -3764,12 +3808,12 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_DEBUG_INFO("Initialization Alive received.\n");
memcpy(&priv->card_alive_init,
&pkt->u.alive_frame,
- sizeof(struct iwl_init_alive_resp));
+ sizeof(struct iwl4965_init_alive_resp));
pwork = &priv->init_alive_start;
} else {
IWL_DEBUG_INFO("Runtime Alive received.\n");
memcpy(&priv->card_alive, &pkt->u.alive_frame,
- sizeof(struct iwl_alive_resp));
+ sizeof(struct iwl4965_alive_resp));
pwork = &priv->alive_start;
}
@@ -3782,19 +3826,19 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_WARNING("uCode did not respond OK.\n");
}
-static void iwl_rx_reply_add_sta(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_add_sta(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RX("Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
return;
}
-static void iwl_rx_reply_error(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_error(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
IWL_ERROR("Error Reply type 0x%08X cmd %s (0x%02X) "
"seq 0x%04X ser 0x%08X\n",
@@ -3807,23 +3851,23 @@ static void iwl_rx_reply_error(struct iwl_priv *priv,
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_csa(struct iwl4965_priv *priv, struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
- struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rxon_cmd *rxon = (void *)&priv->active_rxon;
+ struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
rxon->channel = csa->channel;
priv->staging_rxon.channel = csa->channel;
}
-static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_spectrum_measure_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
if (!report->state) {
IWL_DEBUG(IWL_DL_11H | IWL_DL_INFO,
@@ -3836,35 +3880,35 @@ static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
#endif
}
-static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_pm_sleep_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
+#ifdef CONFIG_IWL4965_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
-static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_pm_debug_statistics_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
IWL_DEBUG_RADIO("Dumping %d bytes of unhandled "
"notification for %s:\n",
le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
- iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
+ iwl4965_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
-static void iwl_bg_beacon_update(struct work_struct *work)
+static void iwl4965_bg_beacon_update(struct work_struct *work)
{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, beacon_update);
+ struct iwl4965_priv *priv =
+ container_of(work, struct iwl4965_priv, beacon_update);
struct sk_buff *beacon;
/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
- beacon = ieee80211_beacon_get(priv->hw, priv->interface_id, NULL);
+ beacon = ieee80211_beacon_get(priv->hw, priv->vif, NULL);
if (!beacon) {
IWL_ERROR("update beacon failed\n");
@@ -3879,16 +3923,16 @@ static void iwl_bg_beacon_update(struct work_struct *work)
priv->ibss_beacon = beacon;
mutex_unlock(&priv->mutex);
- iwl_send_beacon_cmd(priv);
+ iwl4965_send_beacon_cmd(priv);
}
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_beacon_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_beacon_notif *beacon = &(pkt->u.beacon_status);
- u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+#ifdef CONFIG_IWL4965_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
+ u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
IWL_DEBUG_RX("beacon status %x retries %d iss %d "
"tsf %d %d rate %d\n",
@@ -3905,25 +3949,25 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
}
/* Service response to REPLY_SCAN_CMD (0x80) */
-static void iwl_rx_reply_scan(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_reply_scan(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanreq_notification *notif =
- (struct iwl_scanreq_notification *)pkt->u.raw;
+#ifdef CONFIG_IWL4965_DEBUG
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_scanreq_notification *notif =
+ (struct iwl4965_scanreq_notification *)pkt->u.raw;
IWL_DEBUG_RX("Scan request status = 0x%x\n", notif->status);
#endif
}
/* Service SCAN_START_NOTIFICATION (0x82) */
-static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_scan_start_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanstart_notification *notif =
- (struct iwl_scanstart_notification *)pkt->u.raw;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_scanstart_notification *notif =
+ (struct iwl4965_scanstart_notification *)pkt->u.raw;
priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
IWL_DEBUG_SCAN("Scan start: "
"%d [802.11%s] "
@@ -3935,12 +3979,12 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
}
/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
-static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_scan_results_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scanresults_notification *notif =
- (struct iwl_scanresults_notification *)pkt->u.raw;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_scanresults_notification *notif =
+ (struct iwl4965_scanresults_notification *)pkt->u.raw;
IWL_DEBUG_SCAN("Scan ch.res: "
"%d [802.11%s] "
@@ -3956,14 +4000,15 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
(priv->last_scan_jiffies, jiffies)));
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
}
/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
-static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_scan_complete_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
IWL_DEBUG_SCAN("Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
scan_notif->scanned_channels,
@@ -3998,6 +4043,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
}
priv->last_scan_jiffies = jiffies;
+ priv->next_scan_jiffies = 0;
IWL_DEBUG_INFO("Setting scan to off\n");
clear_bit(STATUS_SCANNING, &priv->status);
@@ -4016,10 +4062,10 @@ reschedule:
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_rx_card_state_notif(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (void *)rxb->skb->data;
u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
unsigned long status = priv->status;
@@ -4030,35 +4076,35 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
RF_CARD_DISABLED)) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted(
+ if (!iwl4965_grab_nic_access(priv)) {
+ iwl4965_write_direct32(
priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
if (!(flags & RXON_CARD_DISABLED)) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted(
+ if (!iwl4965_grab_nic_access(priv)) {
+ iwl4965_write_direct32(
priv, HBUS_TARG_MBX_C,
HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
}
if (flags & RF_CARD_DISABLED) {
- iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_SET,
CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
- iwl_read32(priv, CSR_UCODE_DRV_GP1);
- if (!iwl_grab_restricted_access(priv))
- iwl_release_restricted_access(priv);
+ iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
+ if (!iwl4965_grab_nic_access(priv))
+ iwl4965_release_nic_access(priv);
}
}
@@ -4074,7 +4120,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
clear_bit(STATUS_RF_KILL_SW, &priv->status);
if (!(flags & RXON_CARD_DISABLED))
- iwl_scan_cancel(priv);
+ iwl4965_scan_cancel(priv);
if ((test_bit(STATUS_RF_KILL_HW, &status) !=
test_bit(STATUS_RF_KILL_HW, &priv->status)) ||
@@ -4086,7 +4132,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
}
/**
- * iwl_setup_rx_handlers - Initialize Rx handler callbacks
+ * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
*
* Setup the RX handlers for each of the reply types sent from the uCode
* to the host.
@@ -4094,61 +4140,58 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
* This function chains into the hardware specific files for them to setup
* any hardware specific handlers as well.
*/
-static void iwl_setup_rx_handlers(struct iwl_priv *priv)
+static void iwl4965_setup_rx_handlers(struct iwl4965_priv *priv)
{
- priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
- priv->rx_handlers[REPLY_ADD_STA] = iwl_rx_reply_add_sta;
- priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
- priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
+ priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+ priv->rx_handlers[REPLY_ADD_STA] = iwl4965_rx_reply_add_sta;
+ priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
+ priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
- iwl_rx_spectrum_measure_notif;
- priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
+ iwl4965_rx_spectrum_measure_notif;
+ priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl4965_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
- iwl_rx_pm_debug_statistics_notif;
- priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
-
- /* NOTE: iwl_rx_statistics is different based on whether
- * the build is for the 3945 or the 4965. See the
- * corresponding implementation in iwl-XXXX.c
- *
- * The same handler is used for both the REPLY to a
- * discrete statistics request from the host as well as
- * for the periodic statistics notification from the uCode
+ iwl4965_rx_pm_debug_statistics_notif;
+ priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+
+ /*
+ * The same handler is used for both the REPLY to a discrete
+ * statistics request from the host as well as for the periodic
+ * statistics notifications (after received beacons) from the uCode.
*/
- priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_hw_rx_statistics;
- priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_hw_rx_statistics;
+ priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_hw_rx_statistics;
+ priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_hw_rx_statistics;
- priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan;
- priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif;
+ priv->rx_handlers[REPLY_SCAN_CMD] = iwl4965_rx_reply_scan;
+ priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl4965_rx_scan_start_notif;
priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
- iwl_rx_scan_results_notif;
+ iwl4965_rx_scan_results_notif;
priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
- iwl_rx_scan_complete_notif;
- priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
- priv->rx_handlers[REPLY_TX] = iwl_rx_reply_tx;
+ iwl4965_rx_scan_complete_notif;
+ priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
+ priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
- /* Setup hardware specific Rx handlers */
- iwl_hw_rx_handler_setup(priv);
+ /* Set up hardware specific Rx handlers */
+ iwl4965_hw_rx_handler_setup(priv);
}
/**
- * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * iwl4965_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
* @rxb: Rx buffer to reclaim
*
* If an Rx buffer has an async callback associated with it the callback
* will be executed. The attached skb (if present) will only be freed
* if the callback returns 1
*/
-static void iwl_tx_cmd_complete(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
+static void iwl4965_tx_cmd_complete(struct iwl4965_priv *priv,
+ struct iwl4965_rx_mem_buffer *rxb)
{
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl4965_rx_packet *pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
u16 sequence = le16_to_cpu(pkt->hdr.sequence);
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
int huge = sequence & SEQ_HUGE_FRAME;
int cmd_index;
- struct iwl_cmd *cmd;
+ struct iwl4965_cmd *cmd;
/* If a Tx command is being handled and it isn't in the actual
* command queue then there a command routing bug has been introduced
@@ -4169,7 +4212,7 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
!cmd->meta.u.callback(priv, cmd, rxb->skb))
rxb->skb = NULL;
- iwl_tx_queue_reclaim(priv, txq_id, index);
+ iwl4965_tx_queue_reclaim(priv, txq_id, index);
if (!(cmd->meta.flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
@@ -4181,9 +4224,11 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
/*
* Rx theory of operation
*
- * The host allocates 32 DMA target addresses and passes the host address
- * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
- * 0 to 31
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by 4965. These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the 4965. The driver and 4965 manage the Rx buffers by means
+ * of indexes into the circular buffer.
*
* Rx Queue Indexes
* The host/firmware share two index registers for managing the Rx buffers.
@@ -4199,10 +4244,10 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
* The queue is empty (no good data) if WRITE = READ - 1, and is full if
* WRITE = READ.
*
- * During initialization the host sets up the READ queue position to the first
+ * During initialization, the host sets up the READ queue position to the first
* INDEX position, and WRITE to the last (READ - 1 wrapped)
*
- * When the firmware places a packet in a buffer it will advance the READ index
+ * When the firmware places a packet in a buffer, it will advance the READ index
* and fire the RX interrupt. The driver can then query the READ index and
* process as many packets as possible, moving the WRITE index forward as it
* resets the Rx queue buffers with new memory.
@@ -4210,8 +4255,8 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
* The management in the driver is as follows:
* + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
* iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- * to replensish the iwl->rxq->rx_free.
- * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * to replenish the iwl->rxq->rx_free.
+ * + In iwl4965_rx_replenish (scheduled) if 'processed' != 'read' then the
* iwl->rxq is replenished and the READ INDEX is updated (updating the
* 'processed' and 'read' driver indexes as well)
* + A received packet is processed and handed to the kernel network stack,
@@ -4224,28 +4269,28 @@ static void iwl_tx_cmd_complete(struct iwl_priv *priv,
*
* Driver sequence:
*
- * iwl_rx_queue_alloc() Allocates rx_free
- * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls
- * iwl_rx_queue_restock
- * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ * iwl4965_rx_queue_alloc() Allocates rx_free
+ * iwl4965_rx_replenish() Replenishes rx_free list from rx_used, and calls
+ * iwl4965_rx_queue_restock
+ * iwl4965_rx_queue_restock() Moves available buffers from rx_free into Rx
* queue, updates firmware pointers, and updates
* the WRITE index. If insufficient rx_free buffers
- * are available, schedules iwl_rx_replenish
+ * are available, schedules iwl4965_rx_replenish
*
* -- enable interrupts --
- * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
+ * ISR - iwl4965_rx() Detach iwl4965_rx_mem_buffers from pool up to the
* READ INDEX, detaching the SKB from the pool.
* Moves the packet buffer from queue to rx_used.
- * Calls iwl_rx_queue_restock to refill any empty
+ * Calls iwl4965_rx_queue_restock to refill any empty
* slots.
* ...
*
*/
/**
- * iwl_rx_queue_space - Return number of free slots available in queue.
+ * iwl4965_rx_queue_space - Return number of free slots available in queue.
*/
-static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
+static int iwl4965_rx_queue_space(const struct iwl4965_rx_queue *q)
{
int s = q->read - q->write;
if (s <= 0)
@@ -4258,15 +4303,9 @@ static int iwl_rx_queue_space(const struct iwl_rx_queue *q)
}
/**
- * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
- *
- * NOTE: This function has 3945 and 4965 specific code sections
- * but is declared in base due to the majority of the
- * implementation being the same (only a numeric constant is
- * different)
- *
+ * iwl4965_rx_queue_update_write_ptr - Update the write pointer for the RX queue
*/
-int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
+int iwl4965_rx_queue_update_write_ptr(struct iwl4965_priv *priv, struct iwl4965_rx_queue *q)
{
u32 reg = 0;
int rc = 0;
@@ -4277,24 +4316,29 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
if (q->need_update == 0)
goto exit_unlock;
+ /* If power-saving is in use, make sure device is awake */
if (test_bit(STATUS_POWER_PMI, &priv->status)) {
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl4965_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
goto exit_unlock;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
goto exit_unlock;
- iwl_write_restricted(priv, FH_RSCSR_CHNL0_WPTR,
+ /* Device expects a multiple of 8 */
+ iwl4965_write_direct32(priv, FH_RSCSR_CHNL0_WPTR,
q->write & ~0x7);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
+
+ /* Else device is assumed to be awake */
} else
- iwl_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
+ /* Device expects a multiple of 8 */
+ iwl4965_write32(priv, FH_RSCSR_CHNL0_WPTR, q->write & ~0x7);
q->need_update = 0;
@@ -4305,11 +4349,9 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
}
/**
- * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer pointer.
- *
- * NOTE: This function has 3945 and 4965 specific code paths in it.
+ * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
*/
-static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
+static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl4965_priv *priv,
dma_addr_t dma_addr)
{
return cpu_to_le32((u32)(dma_addr >> 8));
@@ -4317,31 +4359,34 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv,
/**
- * iwl_rx_queue_restock - refill RX queue from pre-allocated pool
+ * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool
*
- * If there are slots in the RX queue that need to be restocked,
+ * If there are slots in the RX queue that need to be restocked,
* and we have free pre-allocated buffers, fill the ranks as much
- * as we can pulling from rx_free.
+ * as we can, pulling from rx_free.
*
* This moves the 'write' index forward to catch up with 'processed', and
* also updates the memory address in the firmware to reference the new
* target buffer.
*/
-int iwl_rx_queue_restock(struct iwl_priv *priv)
+static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
{
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
+ struct iwl4965_rx_mem_buffer *rxb;
unsigned long flags;
int write, rc;
spin_lock_irqsave(&rxq->lock, flags);
write = rxq->write & ~0x7;
- while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ while ((iwl4965_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+ /* Get next free Rx buffer, remove from free list */
element = rxq->rx_free.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
list_del(element);
- rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->dma_addr);
+
+ /* Point to Rx buffer via next RBD in circular buffer */
+ rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv, rxb->dma_addr);
rxq->queue[rxq->write] = rxb;
rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
rxq->free_count--;
@@ -4353,13 +4398,14 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->rx_replenish);
- /* If we've added more space for the firmware to place data, tell it */
+ /* If we've added more space for the firmware to place data, tell it.
+ * Increment device's write pointer in multiples of 8. */
if ((write != (rxq->write & ~0x7))
|| (abs(rxq->write - rxq->read) > 7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
- rc = iwl_rx_queue_update_write_ptr(priv, rxq);
+ rc = iwl4965_rx_queue_update_write_ptr(priv, rxq);
if (rc)
return rc;
}
@@ -4368,26 +4414,28 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
}
/**
- * iwl_rx_replensih - Move all used packet from rx_used to rx_free
+ * iwl4965_rx_replenish - Move all used packet from rx_used to rx_free
*
* When moving to rx_free an SKB is allocated for the slot.
*
- * Also restock the Rx queue via iwl_rx_queue_restock.
- * This is called as a scheduled work item (except for during intialization)
+ * Also restock the Rx queue via iwl4965_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
*/
-void iwl_rx_replenish(void *data)
+static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
{
- struct iwl_priv *priv = data;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
struct list_head *element;
- struct iwl_rx_mem_buffer *rxb;
+ struct iwl4965_rx_mem_buffer *rxb;
unsigned long flags;
spin_lock_irqsave(&rxq->lock, flags);
while (!list_empty(&rxq->rx_used)) {
element = rxq->rx_used.next;
- rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ rxb = list_entry(element, struct iwl4965_rx_mem_buffer, list);
+
+ /* Alloc a new receive buffer */
rxb->skb =
- alloc_skb(IWL_RX_BUF_SIZE, __GFP_NOWARN | GFP_ATOMIC);
+ alloc_skb(priv->hw_setting.rx_buf_size,
+ __GFP_NOWARN | GFP_ATOMIC);
if (!rxb->skb) {
if (net_ratelimit())
printk(KERN_CRIT DRV_NAME
@@ -4399,32 +4447,55 @@ void iwl_rx_replenish(void *data)
}
priv->alloc_rxb_skb++;
list_del(element);
+
+ /* Get physical address of RB/SKB */
rxb->dma_addr =
pci_map_single(priv->pci_dev, rxb->skb->data,
- IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ priv->hw_setting.rx_buf_size, PCI_DMA_FROMDEVICE);
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
}
spin_unlock_irqrestore(&rxq->lock, flags);
+}
+
+/*
+ * this should be called while priv->lock is locked
+*/
+static void __iwl4965_rx_replenish(void *data)
+{
+ struct iwl4965_priv *priv = data;
+
+ iwl4965_rx_allocate(priv);
+ iwl4965_rx_queue_restock(priv);
+}
+
+
+void iwl4965_rx_replenish(void *data)
+{
+ struct iwl4965_priv *priv = data;
+ unsigned long flags;
+
+ iwl4965_rx_allocate(priv);
spin_lock_irqsave(&priv->lock, flags);
- iwl_rx_queue_restock(priv);
+ iwl4965_rx_queue_restock(priv);
spin_unlock_irqrestore(&priv->lock, flags);
}
/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
- * If an SKB has been detached, the POOL needs to have it's SKB set to NULL
+ * If an SKB has been detached, the POOL needs to have its SKB set to NULL
* This free routine walks the list of POOL entries and if SKB is set to
* non NULL it is unmapped and freed
*/
-void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+static void iwl4965_rx_queue_free(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
{
int i;
for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
rxq->pool[i].dma_addr,
- IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ priv->hw_setting.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
dev_kfree_skb(rxq->pool[i].skb);
}
}
@@ -4434,21 +4505,25 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
rxq->bd = NULL;
}
-int iwl_rx_queue_alloc(struct iwl_priv *priv)
+int iwl4965_rx_queue_alloc(struct iwl4965_priv *priv)
{
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
struct pci_dev *dev = priv->pci_dev;
int i;
spin_lock_init(&rxq->lock);
INIT_LIST_HEAD(&rxq->rx_free);
INIT_LIST_HEAD(&rxq->rx_used);
+
+ /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
if (!rxq->bd)
return -ENOMEM;
+
/* Fill the rx_used queue with _all_ of the Rx buffers */
for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
/* Set us so that we have processed and used all buffers, but have
* not restocked the Rx queue with fresh buffers */
rxq->read = rxq->write = 0;
@@ -4457,7 +4532,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
return 0;
}
-void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+void iwl4965_rx_queue_reset(struct iwl4965_priv *priv, struct iwl4965_rx_queue *rxq)
{
unsigned long flags;
int i;
@@ -4471,7 +4546,8 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
if (rxq->pool[i].skb != NULL) {
pci_unmap_single(priv->pci_dev,
rxq->pool[i].dma_addr,
- IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ priv->hw_setting.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
priv->alloc_rxb_skb--;
dev_kfree_skb(rxq->pool[i].skb);
rxq->pool[i].skb = NULL;
@@ -4504,7 +4580,7 @@ static u8 ratio2dB[100] = {
/* Calculates a relative dB value from a ratio of linear
* (i.e. not dB) signal levels.
* Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl_calc_db_from_ratio(int sig_ratio)
+int iwl4965_calc_db_from_ratio(int sig_ratio)
{
/* 1000:1 or higher just report as 60 dB */
if (sig_ratio >= 1000)
@@ -4530,7 +4606,7 @@ int iwl_calc_db_from_ratio(int sig_ratio)
/* Calculate an indication of rx signal quality (a percentage, not dBm!).
* See http://www.ces.clemson.edu/linux/signal_quality.shtml for info
* about formulas used below. */
-int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
+int iwl4965_calc_sig_qual(int rssi_dbm, int noise_dbm)
{
int sig_qual;
int degradation = PERFECT_RSSI - rssi_dbm;
@@ -4565,32 +4641,39 @@ int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
}
/**
- * iwl_rx_handle - Main entry function for receiving responses from the uCode
+ * iwl4965_rx_handle - Main entry function for receiving responses from uCode
*
* Uses the priv->rx_handlers callback function array to invoke
* the appropriate handlers, including command responses,
* frame-received notifications, and other notifications.
*/
-static void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl4965_rx_handle(struct iwl4965_priv *priv)
{
- struct iwl_rx_mem_buffer *rxb;
- struct iwl_rx_packet *pkt;
- struct iwl_rx_queue *rxq = &priv->rxq;
+ struct iwl4965_rx_mem_buffer *rxb;
+ struct iwl4965_rx_packet *pkt;
+ struct iwl4965_rx_queue *rxq = &priv->rxq;
u32 r, i;
int reclaim;
unsigned long flags;
+ u8 fill_rx = 0;
+ u32 count = 0;
- r = iwl_hw_get_rx_read(priv);
+ /* uCode's read index (stored in shared DRAM) indicates the last Rx
+ * buffer that the driver may process (last buffer filled by ucode). */
+ r = iwl4965_hw_get_rx_read(priv);
i = rxq->read;
/* Rx interrupt, but nothing sent from uCode */
if (i == r)
IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
+ if (iwl4965_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
+ fill_rx = 1;
+
while (i != r) {
rxb = rxq->queue[i];
- /* If an RXB doesn't have a queue slot associated with it
+ /* If an RXB doesn't have a Rx queue slot associated with it,
* then a bug has been introduced in the queue refilling
* routines -- catch it here */
BUG_ON(rxb == NULL);
@@ -4598,9 +4681,9 @@ static void iwl_rx_handle(struct iwl_priv *priv)
rxq->queue[i] = NULL;
pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr,
- IWL_RX_BUF_SIZE,
+ priv->hw_setting.rx_buf_size,
PCI_DMA_FROMDEVICE);
- pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ pkt = (struct iwl4965_rx_packet *)rxb->skb->data;
/* Reclaim a command buffer only if this packet is a response
* to a (driver-originated) command.
@@ -4617,7 +4700,7 @@ static void iwl_rx_handle(struct iwl_priv *priv)
/* Based on type of command response or notification,
* handle those that need handling via function in
- * rx_handlers table. See iwl_setup_rx_handlers() */
+ * rx_handlers table. See iwl4965_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
IWL_DEBUG(IWL_DL_HOST_COMMAND | IWL_DL_RX | IWL_DL_ISR,
"r = %d, i = %d, %s, 0x%02x\n", r, i,
@@ -4632,11 +4715,11 @@ static void iwl_rx_handle(struct iwl_priv *priv)
}
if (reclaim) {
- /* Invoke any callbacks, transfer the skb to caller,
- * and fire off the (possibly) blocking iwl_send_cmd()
+ /* Invoke any callbacks, transfer the skb to caller, and
+ * fire off the (possibly) blocking iwl4965_send_cmd()
* as we reclaim the driver command queue */
if (rxb && rxb->skb)
- iwl_tx_cmd_complete(priv, rxb);
+ iwl4965_tx_cmd_complete(priv, rxb);
else
IWL_WARNING("Claim null rxb?\n");
}
@@ -4651,20 +4734,34 @@ static void iwl_rx_handle(struct iwl_priv *priv)
}
pci_unmap_single(priv->pci_dev, rxb->dma_addr,
- IWL_RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
+ priv->hw_setting.rx_buf_size,
+ PCI_DMA_FROMDEVICE);
spin_lock_irqsave(&rxq->lock, flags);
list_add_tail(&rxb->list, &priv->rxq.rx_used);
spin_unlock_irqrestore(&rxq->lock, flags);
i = (i + 1) & RX_QUEUE_MASK;
+ /* If there are a lot of unused frames,
+ * restock the Rx queue so ucode wont assert. */
+ if (fill_rx) {
+ count++;
+ if (count >= 8) {
+ priv->rxq.read = i;
+ __iwl4965_rx_replenish(priv);
+ count = 0;
+ }
+ }
}
/* Backtrack one entry */
priv->rxq.read = i;
- iwl_rx_queue_restock(priv);
+ iwl4965_rx_queue_restock(priv);
}
-int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq)
+/**
+ * iwl4965_tx_queue_update_write_ptr - Send new write index to hardware
+ */
+static int iwl4965_tx_queue_update_write_ptr(struct iwl4965_priv *priv,
+ struct iwl4965_tx_queue *txq)
{
u32 reg = 0;
int rc = 0;
@@ -4678,41 +4775,41 @@ int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
/* wake up nic if it's powered down ...
* uCode will wake up, and interrupt us again, so next
* time we'll skip this part. */
- reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+ reg = iwl4965_read32(priv, CSR_UCODE_DRV_GP1);
if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
IWL_DEBUG_INFO("Requesting wakeup, GP1 = 0x%x\n", reg);
- iwl_set_bit(priv, CSR_GP_CNTRL,
+ iwl4965_set_bit(priv, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
return rc;
}
/* restore this queue's parameters in nic hardware. */
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted(priv, HBUS_TARG_WRPTR,
- txq->q.first_empty | (txq_id << 8));
- iwl_release_restricted_access(priv);
+ iwl4965_write_direct32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
+ iwl4965_release_nic_access(priv);
/* else not in power-save mode, uCode will never sleep when we're
* trying to tx (during RFKILL, we're not trying to tx). */
} else
- iwl_write32(priv, HBUS_TARG_WRPTR,
- txq->q.first_empty | (txq_id << 8));
+ iwl4965_write32(priv, HBUS_TARG_WRPTR,
+ txq->q.write_ptr | (txq_id << 8));
txq->need_update = 0;
return rc;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
+#ifdef CONFIG_IWL4965_DEBUG
+static void iwl4965_print_rx_config_cmd(struct iwl4965_rxon_cmd *rxon)
{
DECLARE_MAC_BUF(mac);
IWL_DEBUG_RADIO("RX CONFIG:\n");
- iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+ iwl4965_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
IWL_DEBUG_RADIO("u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
IWL_DEBUG_RADIO("u32 filter_flags: 0x%08x\n",
@@ -4729,24 +4826,24 @@ static void iwl_print_rx_config_cmd(struct iwl_rxon_cmd *rxon)
}
#endif
-static void iwl_enable_interrupts(struct iwl_priv *priv)
+static void iwl4965_enable_interrupts(struct iwl4965_priv *priv)
{
IWL_DEBUG_ISR("Enabling interrupts\n");
set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+ iwl4965_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
}
-static inline void iwl_disable_interrupts(struct iwl_priv *priv)
+static inline void iwl4965_disable_interrupts(struct iwl4965_priv *priv)
{
clear_bit(STATUS_INT_ENABLED, &priv->status);
/* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
/* acknowledge/clear/reset any interrupts still pending
* from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ iwl4965_write32(priv, CSR_INT, 0xffffffff);
+ iwl4965_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
IWL_DEBUG_ISR("Disabled interrupts\n");
}
@@ -4773,7 +4870,7 @@ static const char *desc_lookup(int i)
#define ERROR_START_OFFSET (1 * sizeof(u32))
#define ERROR_ELEM_SIZE (7 * sizeof(u32))
-static void iwl_dump_nic_error_log(struct iwl_priv *priv)
+static void iwl4965_dump_nic_error_log(struct iwl4965_priv *priv)
{
u32 data2, line;
u32 desc, time, count, base, data1;
@@ -4782,18 +4879,18 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
- if (!iwl_hw_valid_rtc_data_addr(base)) {
+ if (!iwl4965_hw_valid_rtc_data_addr(base)) {
IWL_ERROR("Not valid error log pointer 0x%08X\n", base);
return;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
- count = iwl_read_restricted_mem(priv, base);
+ count = iwl4965_read_targ_mem(priv, base);
if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
IWL_ERROR("Start IWL Error Log Dump:\n");
@@ -4801,15 +4898,15 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
priv->status, priv->config, count);
}
- desc = iwl_read_restricted_mem(priv, base + 1 * sizeof(u32));
- blink1 = iwl_read_restricted_mem(priv, base + 3 * sizeof(u32));
- blink2 = iwl_read_restricted_mem(priv, base + 4 * sizeof(u32));
- ilink1 = iwl_read_restricted_mem(priv, base + 5 * sizeof(u32));
- ilink2 = iwl_read_restricted_mem(priv, base + 6 * sizeof(u32));
- data1 = iwl_read_restricted_mem(priv, base + 7 * sizeof(u32));
- data2 = iwl_read_restricted_mem(priv, base + 8 * sizeof(u32));
- line = iwl_read_restricted_mem(priv, base + 9 * sizeof(u32));
- time = iwl_read_restricted_mem(priv, base + 11 * sizeof(u32));
+ desc = iwl4965_read_targ_mem(priv, base + 1 * sizeof(u32));
+ blink1 = iwl4965_read_targ_mem(priv, base + 3 * sizeof(u32));
+ blink2 = iwl4965_read_targ_mem(priv, base + 4 * sizeof(u32));
+ ilink1 = iwl4965_read_targ_mem(priv, base + 5 * sizeof(u32));
+ ilink2 = iwl4965_read_targ_mem(priv, base + 6 * sizeof(u32));
+ data1 = iwl4965_read_targ_mem(priv, base + 7 * sizeof(u32));
+ data2 = iwl4965_read_targ_mem(priv, base + 8 * sizeof(u32));
+ line = iwl4965_read_targ_mem(priv, base + 9 * sizeof(u32));
+ time = iwl4965_read_targ_mem(priv, base + 11 * sizeof(u32));
IWL_ERROR("Desc Time "
"data1 data2 line\n");
@@ -4819,17 +4916,17 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
ilink1, ilink2);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
#define EVENT_START_OFFSET (4 * sizeof(u32))
/**
- * iwl_print_event_log - Dump error event log to syslog
+ * iwl4965_print_event_log - Dump error event log to syslog
*
- * NOTE: Must be called with iwl_grab_restricted_access() already obtained!
+ * NOTE: Must be called with iwl4965_grab_nic_access() already obtained!
*/
-static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
+static void iwl4965_print_event_log(struct iwl4965_priv *priv, u32 start_idx,
u32 num_events, u32 mode)
{
u32 i;
@@ -4853,21 +4950,21 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
/* "time" is actually "data" for mode 0 (no timestamp).
* place event id # at far right for easier visual parsing. */
for (i = 0; i < num_events; i++) {
- ev = iwl_read_restricted_mem(priv, ptr);
+ ev = iwl4965_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
- time = iwl_read_restricted_mem(priv, ptr);
+ time = iwl4965_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
if (mode == 0)
IWL_ERROR("0x%08x\t%04u\n", time, ev); /* data, ev */
else {
- data = iwl_read_restricted_mem(priv, ptr);
+ data = iwl4965_read_targ_mem(priv, ptr);
ptr += sizeof(u32);
IWL_ERROR("%010u\t0x%08x\t%04u\n", time, data, ev);
}
}
}
-static void iwl_dump_nic_event_log(struct iwl_priv *priv)
+static void iwl4965_dump_nic_event_log(struct iwl4965_priv *priv)
{
int rc;
u32 base; /* SRAM byte address of event log header */
@@ -4878,29 +4975,29 @@ static void iwl_dump_nic_event_log(struct iwl_priv *priv)
u32 size; /* # entries that we'll print */
base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
- if (!iwl_hw_valid_rtc_data_addr(base)) {
+ if (!iwl4965_hw_valid_rtc_data_addr(base)) {
IWL_ERROR("Invalid event log pointer 0x%08X\n", base);
return;
}
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
IWL_WARNING("Can not read from adapter at this time.\n");
return;
}
/* event log header */
- capacity = iwl_read_restricted_mem(priv, base);
- mode = iwl_read_restricted_mem(priv, base + (1 * sizeof(u32)));
- num_wraps = iwl_read_restricted_mem(priv, base + (2 * sizeof(u32)));
- next_entry = iwl_read_restricted_mem(priv, base + (3 * sizeof(u32)));
+ capacity = iwl4965_read_targ_mem(priv, base);
+ mode = iwl4965_read_targ_mem(priv, base + (1 * sizeof(u32)));
+ num_wraps = iwl4965_read_targ_mem(priv, base + (2 * sizeof(u32)));
+ next_entry = iwl4965_read_targ_mem(priv, base + (3 * sizeof(u32)));
size = num_wraps ? capacity : next_entry;
/* bail out if nothing in log */
if (size == 0) {
IWL_ERROR("Start IWL Event Log Dump: nothing in log\n");
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
return;
}
@@ -4910,31 +5007,31 @@ static void iwl_dump_nic_event_log(struct iwl_priv *priv)
/* if uCode has wrapped back to top of log, start at the oldest entry,
* i.e the next one that uCode would fill. */
if (num_wraps)
- iwl_print_event_log(priv, next_entry,
+ iwl4965_print_event_log(priv, next_entry,
capacity - next_entry, mode);
/* (then/else) start at top of log */
- iwl_print_event_log(priv, 0, next_entry, mode);
+ iwl4965_print_event_log(priv, 0, next_entry, mode);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
/**
- * iwl_irq_handle_error - called for HW or SW error interrupt from card
+ * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
*/
-static void iwl_irq_handle_error(struct iwl_priv *priv)
+static void iwl4965_irq_handle_error(struct iwl4965_priv *priv)
{
- /* Set the FW error flag -- cleared on iwl_down */
+ /* Set the FW error flag -- cleared on iwl4965_down */
set_bit(STATUS_FW_ERROR, &priv->status);
/* Cancel currently queued command. */
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_FW_ERRORS) {
- iwl_dump_nic_error_log(priv);
- iwl_dump_nic_event_log(priv);
- iwl_print_rx_config_cmd(&priv->staging_rxon);
+#ifdef CONFIG_IWL4965_DEBUG
+ if (iwl4965_debug_level & IWL_DL_FW_ERRORS) {
+ iwl4965_dump_nic_error_log(priv);
+ iwl4965_dump_nic_event_log(priv);
+ iwl4965_print_rx_config_cmd(&priv->staging_rxon);
}
#endif
@@ -4948,7 +5045,7 @@ static void iwl_irq_handle_error(struct iwl_priv *priv)
IWL_DEBUG(IWL_DL_INFO | IWL_DL_FW_ERRORS,
"Restarting adapter due to uCode error.\n");
- if (iwl_is_associated(priv)) {
+ if (iwl4965_is_associated(priv)) {
memcpy(&priv->recovery_rxon, &priv->active_rxon,
sizeof(priv->recovery_rxon));
priv->error_recovering = 1;
@@ -4957,16 +5054,16 @@ static void iwl_irq_handle_error(struct iwl_priv *priv)
}
}
-static void iwl_error_recovery(struct iwl_priv *priv)
+static void iwl4965_error_recovery(struct iwl4965_priv *priv)
{
unsigned long flags;
memcpy(&priv->staging_rxon, &priv->recovery_rxon,
sizeof(priv->staging_rxon));
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
- iwl_rxon_add_station(priv, priv->bssid, 1);
+ iwl4965_rxon_add_station(priv, priv->bssid, 1);
spin_lock_irqsave(&priv->lock, flags);
priv->assoc_id = le16_to_cpu(priv->staging_rxon.assoc_id);
@@ -4974,12 +5071,12 @@ static void iwl_error_recovery(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void iwl_irq_tasklet(struct iwl_priv *priv)
+static void iwl4965_irq_tasklet(struct iwl4965_priv *priv)
{
u32 inta, handled = 0;
u32 inta_fh;
unsigned long flags;
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
u32 inta_mask;
#endif
@@ -4988,18 +5085,19 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* Ack/clear/reset pending uCode interrupts.
* Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
* and will clear only when CSR_FH_INT_STATUS gets cleared. */
- inta = iwl_read32(priv, CSR_INT);
- iwl_write32(priv, CSR_INT, inta);
+ inta = iwl4965_read32(priv, CSR_INT);
+ iwl4965_write32(priv, CSR_INT, inta);
/* Ack/clear/reset pending flow-handler (DMA) interrupts.
* Any new interrupts that happen after this, either while we're
* in this tasklet, or later, will show up in next ISR/tasklet. */
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
- iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+ inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
+ iwl4965_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & IWL_DL_ISR) {
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
+#ifdef CONFIG_IWL4965_DEBUG
+ if (iwl4965_debug_level & IWL_DL_ISR) {
+ /* just for debug */
+ inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
IWL_DEBUG_ISR("inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
}
@@ -5019,9 +5117,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
IWL_ERROR("Microcode HW error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
+ iwl4965_disable_interrupts(priv);
- iwl_irq_handle_error(priv);
+ iwl4965_irq_handle_error(priv);
handled |= CSR_INT_BIT_HW_ERR;
@@ -5030,8 +5128,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
return;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
+#ifdef CONFIG_IWL4965_DEBUG
+ if (iwl4965_debug_level & (IWL_DL_ISR)) {
/* NIC fires this, but we don't use it, redundant with WAKEUP */
if (inta & CSR_INT_BIT_MAC_CLK_ACTV)
IWL_DEBUG_ISR("Microcode started or stopped.\n");
@@ -5044,10 +5142,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
/* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_MAC_CLK_ACTV | CSR_INT_BIT_ALIVE);
- /* HW RF KILL switch toggled (4965 only) */
+ /* HW RF KILL switch toggled */
if (inta & CSR_INT_BIT_RF_KILL) {
int hw_rf_kill = 0;
- if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+ if (!(iwl4965_read32(priv, CSR_GP_CNTRL) &
CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
hw_rf_kill = 1;
@@ -5067,7 +5165,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
handled |= CSR_INT_BIT_RF_KILL;
}
- /* Chip got too hot and stopped itself (4965 only) */
+ /* Chip got too hot and stopped itself */
if (inta & CSR_INT_BIT_CT_KILL) {
IWL_ERROR("Microcode CT kill error detected.\n");
handled |= CSR_INT_BIT_CT_KILL;
@@ -5077,20 +5175,20 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n",
inta);
- iwl_irq_handle_error(priv);
+ iwl4965_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
/* uCode wakes up after power-down sleep */
if (inta & CSR_INT_BIT_WAKEUP) {
IWL_DEBUG_ISR("Wakeup interrupt\n");
- iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[0]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[1]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[2]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[3]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[4]);
- iwl_tx_queue_update_write_ptr(priv, &priv->txq[5]);
+ iwl4965_rx_queue_update_write_ptr(priv, &priv->rxq);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[0]);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[1]);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[2]);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[3]);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[4]);
+ iwl4965_tx_queue_update_write_ptr(priv, &priv->txq[5]);
handled |= CSR_INT_BIT_WAKEUP;
}
@@ -5099,7 +5197,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
* Rx "responses" (frame-received notification), and other
* notifications from uCode come through here*/
if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
- iwl_rx_handle(priv);
+ iwl4965_rx_handle(priv);
handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
}
@@ -5118,13 +5216,13 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
}
/* Re-enable all interrupts */
- iwl_enable_interrupts(priv);
+ iwl4965_enable_interrupts(priv);
-#ifdef CONFIG_IWLWIFI_DEBUG
- if (iwl_debug_level & (IWL_DL_ISR)) {
- inta = iwl_read32(priv, CSR_INT);
- inta_mask = iwl_read32(priv, CSR_INT_MASK);
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+#ifdef CONFIG_IWL4965_DEBUG
+ if (iwl4965_debug_level & (IWL_DL_ISR)) {
+ inta = iwl4965_read32(priv, CSR_INT);
+ inta_mask = iwl4965_read32(priv, CSR_INT_MASK);
+ inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
IWL_DEBUG_ISR("End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
}
@@ -5132,9 +5230,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static irqreturn_t iwl_isr(int irq, void *data)
+static irqreturn_t iwl4965_isr(int irq, void *data)
{
- struct iwl_priv *priv = data;
+ struct iwl4965_priv *priv = data;
u32 inta, inta_mask;
u32 inta_fh;
if (!priv)
@@ -5146,12 +5244,12 @@ static irqreturn_t iwl_isr(int irq, void *data)
* back-to-back ISRs and sporadic interrupts from our NIC.
* If we have something to service, the tasklet will re-enable ints.
* If we *don't* have something, we'll re-enable before leaving here. */
- inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+ inta_mask = iwl4965_read32(priv, CSR_INT_MASK); /* just for debug */
+ iwl4965_write32(priv, CSR_INT_MASK, 0x00000000);
/* Discover which interrupts are active/pending */
- inta = iwl_read32(priv, CSR_INT);
- inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+ inta = iwl4965_read32(priv, CSR_INT);
+ inta_fh = iwl4965_read32(priv, CSR_FH_INT_STATUS);
/* Ignore interrupt if there's nothing in NIC to service.
* This may be due to IRQ shared with another device,
@@ -5171,7 +5269,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
IWL_DEBUG_ISR("ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
inta, inta_mask, inta_fh);
- /* iwl_irq_tasklet() will service interrupts and re-enable them */
+ /* iwl4965_irq_tasklet() will service interrupts and re-enable them */
tasklet_schedule(&priv->irq_tasklet);
unplugged:
@@ -5180,18 +5278,18 @@ static irqreturn_t iwl_isr(int irq, void *data)
none:
/* re-enable interrupts here since we don't have anything to service. */
- iwl_enable_interrupts(priv);
+ iwl4965_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
/************************** EEPROM BANDS ****************************
*
- * The iwl_eeprom_band definitions below provide the mapping from the
+ * The iwl4965_eeprom_band definitions below provide the mapping from the
* EEPROM contents to the specific channel number supported for each
* band.
*
- * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * For example, iwl4965_priv->eeprom.band_3_channels[4] from the band_3
* definition below maps to physical channel 42 in the 5.2GHz spectrum.
* The specific geography and calibration information for that channel
* is contained in the eeprom map itself.
@@ -5217,76 +5315,77 @@ static irqreturn_t iwl_isr(int irq, void *data)
*********************************************************************/
/* 2.4 GHz */
-static const u8 iwl_eeprom_band_1[14] = {
+static const u8 iwl4965_eeprom_band_1[14] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
};
/* 5.2 GHz bands */
-static const u8 iwl_eeprom_band_2[] = {
+static const u8 iwl4965_eeprom_band_2[] = { /* 4915-5080MHz */
183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
};
-static const u8 iwl_eeprom_band_3[] = { /* 5205-5320MHz */
+static const u8 iwl4965_eeprom_band_3[] = { /* 5170-5320MHz */
34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
};
-static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */
+static const u8 iwl4965_eeprom_band_4[] = { /* 5500-5700MHz */
100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
};
-static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
+static const u8 iwl4965_eeprom_band_5[] = { /* 5725-5825MHz */
145, 149, 153, 157, 161, 165
};
-static u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */
+static u8 iwl4965_eeprom_band_6[] = { /* 2.4 FAT channel */
1, 2, 3, 4, 5, 6, 7
};
-static u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */
+static u8 iwl4965_eeprom_band_7[] = { /* 5.2 FAT channel */
36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
};
-static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
+static void iwl4965_init_band_reference(const struct iwl4965_priv *priv,
+ int band,
int *eeprom_ch_count,
- const struct iwl_eeprom_channel
+ const struct iwl4965_eeprom_channel
**eeprom_ch_info,
const u8 **eeprom_ch_index)
{
switch (band) {
case 1: /* 2.4GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1);
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_1);
*eeprom_ch_info = priv->eeprom.band_1_channels;
- *eeprom_ch_index = iwl_eeprom_band_1;
+ *eeprom_ch_index = iwl4965_eeprom_band_1;
break;
- case 2: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2);
+ case 2: /* 4.9GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_2);
*eeprom_ch_info = priv->eeprom.band_2_channels;
- *eeprom_ch_index = iwl_eeprom_band_2;
+ *eeprom_ch_index = iwl4965_eeprom_band_2;
break;
case 3: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3);
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_3);
*eeprom_ch_info = priv->eeprom.band_3_channels;
- *eeprom_ch_index = iwl_eeprom_band_3;
+ *eeprom_ch_index = iwl4965_eeprom_band_3;
break;
- case 4: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4);
+ case 4: /* 5.5GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_4);
*eeprom_ch_info = priv->eeprom.band_4_channels;
- *eeprom_ch_index = iwl_eeprom_band_4;
+ *eeprom_ch_index = iwl4965_eeprom_band_4;
break;
- case 5: /* 5.2GHz band */
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5);
+ case 5: /* 5.7GHz band */
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_5);
*eeprom_ch_info = priv->eeprom.band_5_channels;
- *eeprom_ch_index = iwl_eeprom_band_5;
+ *eeprom_ch_index = iwl4965_eeprom_band_5;
break;
- case 6:
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
+ case 6: /* 2.4GHz FAT channels */
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_6);
*eeprom_ch_info = priv->eeprom.band_24_channels;
- *eeprom_ch_index = iwl_eeprom_band_6;
+ *eeprom_ch_index = iwl4965_eeprom_band_6;
break;
- case 7:
- *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
+ case 7: /* 5 GHz FAT channels */
+ *eeprom_ch_count = ARRAY_SIZE(iwl4965_eeprom_band_7);
*eeprom_ch_info = priv->eeprom.band_52_channels;
- *eeprom_ch_index = iwl_eeprom_band_7;
+ *eeprom_ch_index = iwl4965_eeprom_band_7;
break;
default:
BUG();
@@ -5294,7 +5393,12 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, int band,
}
}
-const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
+/**
+ * iwl4965_get_channel_info - Find driver's private channel info
+ *
+ * Based on band and channel number.
+ */
+const struct iwl4965_channel_info *iwl4965_get_channel_info(const struct iwl4965_priv *priv,
int phymode, u16 channel)
{
int i;
@@ -5321,13 +5425,16 @@ const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv,
#define CHECK_AND_PRINT(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
? # x " " : "")
-static int iwl_init_channel_map(struct iwl_priv *priv)
+/**
+ * iwl4965_init_channel_map - Set up driver's info for all possible channels
+ */
+static int iwl4965_init_channel_map(struct iwl4965_priv *priv)
{
int eeprom_ch_count = 0;
const u8 *eeprom_ch_index = NULL;
- const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
+ const struct iwl4965_eeprom_channel *eeprom_ch_info = NULL;
int band, ch;
- struct iwl_channel_info *ch_info;
+ struct iwl4965_channel_info *ch_info;
if (priv->channel_count) {
IWL_DEBUG_INFO("Channel map already initialized.\n");
@@ -5343,15 +5450,15 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
IWL_DEBUG_INFO("Initializing regulatory info from EEPROM\n");
priv->channel_count =
- ARRAY_SIZE(iwl_eeprom_band_1) +
- ARRAY_SIZE(iwl_eeprom_band_2) +
- ARRAY_SIZE(iwl_eeprom_band_3) +
- ARRAY_SIZE(iwl_eeprom_band_4) +
- ARRAY_SIZE(iwl_eeprom_band_5);
+ ARRAY_SIZE(iwl4965_eeprom_band_1) +
+ ARRAY_SIZE(iwl4965_eeprom_band_2) +
+ ARRAY_SIZE(iwl4965_eeprom_band_3) +
+ ARRAY_SIZE(iwl4965_eeprom_band_4) +
+ ARRAY_SIZE(iwl4965_eeprom_band_5);
IWL_DEBUG_INFO("Parsing data for %d channels.\n", priv->channel_count);
- priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
+ priv->channel_info = kzalloc(sizeof(struct iwl4965_channel_info) *
priv->channel_count, GFP_KERNEL);
if (!priv->channel_info) {
IWL_ERROR("Could not allocate channel_info\n");
@@ -5366,7 +5473,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
* what just in the EEPROM) */
for (band = 1; band <= 5; band++) {
- iwl_init_band_reference(priv, band, &eeprom_ch_count,
+ iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
&eeprom_ch_info, &eeprom_ch_index);
/* Loop through each band adding each of the channels */
@@ -5430,14 +5537,17 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
}
}
+ /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */
for (band = 6; band <= 7; band++) {
int phymode;
u8 fat_extension_chan;
- iwl_init_band_reference(priv, band, &eeprom_ch_count,
+ iwl4965_init_band_reference(priv, band, &eeprom_ch_count,
&eeprom_ch_info, &eeprom_ch_index);
+ /* EEPROM band 6 is 2.4, band 7 is 5 GHz */
phymode = (band == 6) ? MODE_IEEE80211B : MODE_IEEE80211A;
+
/* Loop through each band adding each of the channels */
for (ch = 0; ch < eeprom_ch_count; ch++) {
@@ -5449,11 +5559,13 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
else
fat_extension_chan = HT_IE_EXT_CHANNEL_ABOVE;
+ /* Set up driver's info for lower half */
iwl4965_set_fat_chan_info(priv, phymode,
eeprom_ch_index[ch],
&(eeprom_ch_info[ch]),
fat_extension_chan);
+ /* Set up driver's info for upper half */
iwl4965_set_fat_chan_info(priv, phymode,
(eeprom_ch_index[ch] + 4),
&(eeprom_ch_info[ch]),
@@ -5487,7 +5599,7 @@ static int iwl_init_channel_map(struct iwl_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
-static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
+static inline u16 iwl4965_get_active_dwell_time(struct iwl4965_priv *priv, int phymode)
{
if (phymode == MODE_IEEE80211A)
return IWL_ACTIVE_DWELL_TIME_52;
@@ -5495,14 +5607,14 @@ static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, int phymode)
return IWL_ACTIVE_DWELL_TIME_24;
}
-static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
+static u16 iwl4965_get_passive_dwell_time(struct iwl4965_priv *priv, int phymode)
{
- u16 active = iwl_get_active_dwell_time(priv, phymode);
+ u16 active = iwl4965_get_active_dwell_time(priv, phymode);
u16 passive = (phymode != MODE_IEEE80211A) ?
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
- if (iwl_is_associated(priv)) {
+ if (iwl4965_is_associated(priv)) {
/* If we're associated, we clamp the maximum passive
* dwell time to be 98% of the beacon interval (minus
* 2 * channel tune time) */
@@ -5518,30 +5630,30 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, int phymode)
return passive;
}
-static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
+static int iwl4965_get_channels_for_scan(struct iwl4965_priv *priv, int phymode,
u8 is_active, u8 direct_mask,
- struct iwl_scan_channel *scan_ch)
+ struct iwl4965_scan_channel *scan_ch)
{
const struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode;
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
u16 passive_dwell = 0;
u16 active_dwell = 0;
int added, i;
- hw_mode = iwl_get_hw_mode(priv, phymode);
+ hw_mode = iwl4965_get_hw_mode(priv, phymode);
if (!hw_mode)
return 0;
channels = hw_mode->channels;
- active_dwell = iwl_get_active_dwell_time(priv, phymode);
- passive_dwell = iwl_get_passive_dwell_time(priv, phymode);
+ active_dwell = iwl4965_get_active_dwell_time(priv, phymode);
+ passive_dwell = iwl4965_get_passive_dwell_time(priv, phymode);
for (i = 0, added = 0; i < hw_mode->num_channels; i++) {
if (channels[i].chan ==
le16_to_cpu(priv->active_rxon.channel)) {
- if (iwl_is_associated(priv)) {
+ if (iwl4965_is_associated(priv)) {
IWL_DEBUG_SCAN
("Skipping current channel %d\n",
le16_to_cpu(priv->active_rxon.channel));
@@ -5552,7 +5664,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
scan_ch->channel = channels[i].chan;
- ch_info = iwl_get_channel_info(priv, phymode, scan_ch->channel);
+ ch_info = iwl4965_get_channel_info(priv, phymode,
+ scan_ch->channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d is INVALID for this SKU.\n",
scan_ch->channel);
@@ -5574,7 +5687,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
scan_ch->active_dwell = cpu_to_le16(active_dwell);
scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
- /* Set power levels to defaults */
+ /* Set txpower levels to defaults */
scan_ch->tpc.dsp_atten = 110;
/* scan_pwr_info->tpc.dsp_atten; */
@@ -5584,8 +5697,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
else {
scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
/* NOTE: if we were doing 6Mb OFDM for scans we'd use
- * power level
- scan_ch->tpc.tx_gain = ((1<<5) | (2 << 3)) | 3;
+ * power level:
+ * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
*/
}
@@ -5603,7 +5716,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, int phymode,
return added;
}
-static void iwl_reset_channel_flag(struct iwl_priv *priv)
+static void iwl4965_reset_channel_flag(struct iwl4965_priv *priv)
{
int i, j;
for (i = 0; i < 3; i++) {
@@ -5613,13 +5726,13 @@ static void iwl_reset_channel_flag(struct iwl_priv *priv)
}
}
-static void iwl_init_hw_rates(struct iwl_priv *priv,
+static void iwl4965_init_hw_rates(struct iwl4965_priv *priv,
struct ieee80211_rate *rates)
{
int i;
for (i = 0; i < IWL_RATE_COUNT; i++) {
- rates[i].rate = iwl_rates[i].ieee * 5;
+ rates[i].rate = iwl4965_rates[i].ieee * 5;
rates[i].val = i; /* Rate scaling will work on indexes */
rates[i].val2 = i;
rates[i].flags = IEEE80211_RATE_SUPPORTED;
@@ -5631,7 +5744,7 @@ static void iwl_init_hw_rates(struct iwl_priv *priv,
* If CCK 1M then set rate flag to CCK else CCK_2
* which is CCK | PREAMBLE2
*/
- rates[i].flags |= (iwl_rates[i].plcp == 10) ?
+ rates[i].flags |= (iwl4965_rates[i].plcp == 10) ?
IEEE80211_RATE_CCK : IEEE80211_RATE_CCK_2;
}
@@ -5639,16 +5752,14 @@ static void iwl_init_hw_rates(struct iwl_priv *priv,
if (IWL_BASIC_RATES_MASK & (1 << i))
rates[i].flags |= IEEE80211_RATE_BASIC;
}
-
- iwl4965_init_hw_rates(priv, rates);
}
/**
- * iwl_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ * iwl4965_init_geos - Initialize mac80211's geo/channel info based from eeprom
*/
-static int iwl_init_geos(struct iwl_priv *priv)
+static int iwl4965_init_geos(struct iwl4965_priv *priv)
{
- struct iwl_channel_info *ch;
+ struct iwl4965_channel_info *ch;
struct ieee80211_hw_mode *modes;
struct ieee80211_channel *channels;
struct ieee80211_channel *geo_ch;
@@ -5658,10 +5769,8 @@ static int iwl_init_geos(struct iwl_priv *priv)
A = 0,
B = 1,
G = 2,
- A_11N = 3,
- G_11N = 4,
};
- int mode_count = 5;
+ int mode_count = 3;
if (priv->modes) {
IWL_DEBUG_INFO("Geography modes already initialized.\n");
@@ -5696,11 +5805,14 @@ static int iwl_init_geos(struct iwl_priv *priv)
/* 5.2GHz channels start after the 2.4GHz channels */
modes[A].mode = MODE_IEEE80211A;
- modes[A].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
+ modes[A].channels = &channels[ARRAY_SIZE(iwl4965_eeprom_band_1)];
modes[A].rates = rates;
modes[A].num_rates = 8; /* just OFDM */
modes[A].rates = &rates[4];
modes[A].num_channels = 0;
+#ifdef CONFIG_IWL4965_HT
+ iwl4965_init_ht_hw_capab(&modes[A].ht_info, MODE_IEEE80211A);
+#endif
modes[B].mode = MODE_IEEE80211B;
modes[B].channels = channels;
@@ -5713,23 +5825,14 @@ static int iwl_init_geos(struct iwl_priv *priv)
modes[G].rates = rates;
modes[G].num_rates = 12; /* OFDM & CCK */
modes[G].num_channels = 0;
-
- modes[G_11N].mode = MODE_IEEE80211G;
- modes[G_11N].channels = channels;
- modes[G_11N].num_rates = 13; /* OFDM & CCK */
- modes[G_11N].rates = rates;
- modes[G_11N].num_channels = 0;
-
- modes[A_11N].mode = MODE_IEEE80211A;
- modes[A_11N].channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)];
- modes[A_11N].rates = &rates[4];
- modes[A_11N].num_rates = 9; /* just OFDM */
- modes[A_11N].num_channels = 0;
+#ifdef CONFIG_IWL4965_HT
+ iwl4965_init_ht_hw_capab(&modes[G].ht_info, MODE_IEEE80211G);
+#endif
priv->ieee_channels = channels;
priv->ieee_rates = rates;
- iwl_init_hw_rates(priv, rates);
+ iwl4965_init_hw_rates(priv, rates);
for (i = 0, geo_ch = channels; i < priv->channel_count; i++) {
ch = &priv->channel_info[i];
@@ -5744,11 +5847,9 @@ static int iwl_init_geos(struct iwl_priv *priv)
if (is_channel_a_band(ch)) {
geo_ch = &modes[A].channels[modes[A].num_channels++];
- modes[A_11N].num_channels++;
} else {
geo_ch = &modes[B].channels[modes[B].num_channels++];
modes[G].num_channels++;
- modes[G_11N].num_channels++;
}
geo_ch->freq = ieee80211chan2mhz(ch->channel);
@@ -5814,57 +5915,22 @@ static int iwl_init_geos(struct iwl_priv *priv)
*
******************************************************************************/
-static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
+static void iwl4965_dealloc_ucode_pci(struct iwl4965_priv *priv)
{
- if (priv->ucode_code.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_code.len,
- priv->ucode_code.v_addr,
- priv->ucode_code.p_addr);
- priv->ucode_code.v_addr = NULL;
- }
- if (priv->ucode_data.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_data.len,
- priv->ucode_data.v_addr,
- priv->ucode_data.p_addr);
- priv->ucode_data.v_addr = NULL;
- }
- if (priv->ucode_data_backup.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_data_backup.len,
- priv->ucode_data_backup.v_addr,
- priv->ucode_data_backup.p_addr);
- priv->ucode_data_backup.v_addr = NULL;
- }
- if (priv->ucode_init.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_init.len,
- priv->ucode_init.v_addr,
- priv->ucode_init.p_addr);
- priv->ucode_init.v_addr = NULL;
- }
- if (priv->ucode_init_data.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_init_data.len,
- priv->ucode_init_data.v_addr,
- priv->ucode_init_data.p_addr);
- priv->ucode_init_data.v_addr = NULL;
- }
- if (priv->ucode_boot.v_addr != NULL) {
- pci_free_consistent(priv->pci_dev,
- priv->ucode_boot.len,
- priv->ucode_boot.v_addr,
- priv->ucode_boot.p_addr);
- priv->ucode_boot.v_addr = NULL;
- }
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+ iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
}
/**
- * iwl_verify_inst_full - verify runtime uCode image in card vs. host,
+ * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
* looking at all data.
*/
-static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
+static int iwl4965_verify_inst_full(struct iwl4965_priv *priv, __le32 *image,
+ u32 len)
{
u32 val;
u32 save_len = len;
@@ -5873,18 +5939,18 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR, RTC_INST_LOWER_BOUND);
errcnt = 0;
for (; len > 0; len -= sizeof(u32), image++) {
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
+ val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
IWL_ERROR("uCode INST section is invalid at "
"offset 0x%x, is 0x%x, s/b 0x%x\n",
@@ -5896,7 +5962,7 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
}
}
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
if (!errcnt)
IWL_DEBUG_INFO
@@ -5907,11 +5973,11 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 * image, u32 len)
/**
- * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ * iwl4965_verify_inst_sparse - verify runtime uCode image in card vs. host,
* using sample data 100 bytes apart. If these sample points are good,
* it's a pretty good bet that everything between them is good, too.
*/
-static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+static int iwl4965_verify_inst_sparse(struct iwl4965_priv *priv, __le32 *image, u32 len)
{
u32 val;
int rc = 0;
@@ -5920,7 +5986,7 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
IWL_DEBUG_INFO("ucode inst image size is %u\n", len);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
return rc;
@@ -5928,9 +5994,9 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
/* read data comes through single port, auto-incr addr */
/* NOTE: Use the debugless read so we don't flood kernel log
* if IWL_DL_IO is set */
- iwl_write_restricted(priv, HBUS_TARG_MEM_RADDR,
+ iwl4965_write_direct32(priv, HBUS_TARG_MEM_RADDR,
i + RTC_INST_LOWER_BOUND);
- val = _iwl_read_restricted(priv, HBUS_TARG_MEM_RDAT);
+ val = _iwl4965_read_direct32(priv, HBUS_TARG_MEM_RDAT);
if (val != le32_to_cpu(*image)) {
#if 0 /* Enable this if you want to see details */
IWL_ERROR("uCode INST section is invalid at "
@@ -5944,17 +6010,17 @@ static int iwl_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
}
}
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
return rc;
}
/**
- * iwl_verify_ucode - determine which instruction image is in SRAM,
+ * iwl4965_verify_ucode - determine which instruction image is in SRAM,
* and verify its contents
*/
-static int iwl_verify_ucode(struct iwl_priv *priv)
+static int iwl4965_verify_ucode(struct iwl4965_priv *priv)
{
__le32 *image;
u32 len;
@@ -5963,7 +6029,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try bootstrap */
image = (__le32 *)priv->ucode_boot.v_addr;
len = priv->ucode_boot.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl4965_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Bootstrap uCode is good in inst SRAM\n");
return 0;
@@ -5972,7 +6038,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try initialize */
image = (__le32 *)priv->ucode_init.v_addr;
len = priv->ucode_init.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl4965_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Initialize uCode is good in inst SRAM\n");
return 0;
@@ -5981,7 +6047,7 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
/* Try runtime/protocol */
image = (__le32 *)priv->ucode_code.v_addr;
len = priv->ucode_code.len;
- rc = iwl_verify_inst_sparse(priv, image, len);
+ rc = iwl4965_verify_inst_sparse(priv, image, len);
if (rc == 0) {
IWL_DEBUG_INFO("Runtime uCode is good in inst SRAM\n");
return 0;
@@ -5989,18 +6055,19 @@ static int iwl_verify_ucode(struct iwl_priv *priv)
IWL_ERROR("NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
- /* Show first several data entries in instruction SRAM.
- * Selection of bootstrap image is arbitrary. */
+ /* Since nothing seems to match, show first several data entries in
+ * instruction SRAM, so maybe visual inspection will give a clue.
+ * Selection of bootstrap image (vs. other images) is arbitrary. */
image = (__le32 *)priv->ucode_boot.v_addr;
len = priv->ucode_boot.len;
- rc = iwl_verify_inst_full(priv, image, len);
+ rc = iwl4965_verify_inst_full(priv, image, len);
return rc;
}
/* check contents of special bootstrap uCode SRAM */
-static int iwl_verify_bsm(struct iwl_priv *priv)
+static int iwl4965_verify_bsm(struct iwl4965_priv *priv)
{
__le32 *image = priv->ucode_boot.v_addr;
u32 len = priv->ucode_boot.len;
@@ -6010,11 +6077,11 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
IWL_DEBUG_INFO("Begin verify bsm\n");
/* verify BSM SRAM contents */
- val = iwl_read_restricted_reg(priv, BSM_WR_DWCOUNT_REG);
+ val = iwl4965_read_prph(priv, BSM_WR_DWCOUNT_REG);
for (reg = BSM_SRAM_LOWER_BOUND;
reg < BSM_SRAM_LOWER_BOUND + len;
reg += sizeof(u32), image ++) {
- val = iwl_read_restricted_reg(priv, reg);
+ val = iwl4965_read_prph(priv, reg);
if (val != le32_to_cpu(*image)) {
IWL_ERROR("BSM uCode verification failed at "
"addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
@@ -6031,7 +6098,7 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
}
/**
- * iwl_load_bsm - Load bootstrap instructions
+ * iwl4965_load_bsm - Load bootstrap instructions
*
* BSM operation:
*
@@ -6062,7 +6129,7 @@ static int iwl_verify_bsm(struct iwl_priv *priv)
* the runtime uCode instructions and the backup data cache into SRAM,
* and re-launches the runtime uCode from where it left off.
*/
-static int iwl_load_bsm(struct iwl_priv *priv)
+static int iwl4965_load_bsm(struct iwl4965_priv *priv)
{
__le32 *image = priv->ucode_boot.v_addr;
u32 len = priv->ucode_boot.len;
@@ -6082,8 +6149,8 @@ static int iwl_load_bsm(struct iwl_priv *priv)
return -EINVAL;
/* Tell bootstrap uCode where to find the "Initialize" uCode
- * in host DRAM ... bits 31:0 for 3945, bits 35:4 for 4965.
- * NOTE: iwl_initialize_alive_start() will replace these values,
+ * in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+ * NOTE: iwl4965_initialize_alive_start() will replace these values,
* after the "initialize" uCode has run, to point to
* runtime/protocol instructions and backup data cache. */
pinst = priv->ucode_init.p_addr >> 4;
@@ -6091,42 +6158,42 @@ static int iwl_load_bsm(struct iwl_priv *priv)
inst_len = priv->ucode_init.len;
data_len = priv->ucode_init_data.len;
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc)
return rc;
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+ iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+ iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
/* Fill BSM memory with bootstrap instructions */
for (reg_offset = BSM_SRAM_LOWER_BOUND;
reg_offset < BSM_SRAM_LOWER_BOUND + len;
reg_offset += sizeof(u32), image++)
- _iwl_write_restricted_reg(priv, reg_offset,
+ _iwl4965_write_prph(priv, reg_offset,
le32_to_cpu(*image));
- rc = iwl_verify_bsm(priv);
+ rc = iwl4965_verify_bsm(priv);
if (rc) {
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
return rc;
}
/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
- iwl_write_restricted_reg(priv, BSM_WR_MEM_SRC_REG, 0x0);
- iwl_write_restricted_reg(priv, BSM_WR_MEM_DST_REG,
+ iwl4965_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+ iwl4965_write_prph(priv, BSM_WR_MEM_DST_REG,
RTC_INST_LOWER_BOUND);
- iwl_write_restricted_reg(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+ iwl4965_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
/* Load bootstrap code into instruction SRAM now,
* to prepare to load "initialize" uCode */
- iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
+ iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
BSM_WR_CTRL_REG_BIT_START);
/* Wait for load of bootstrap uCode to finish */
for (i = 0; i < 100; i++) {
- done = iwl_read_restricted_reg(priv, BSM_WR_CTRL_REG);
+ done = iwl4965_read_prph(priv, BSM_WR_CTRL_REG);
if (!(done & BSM_WR_CTRL_REG_BIT_START))
break;
udelay(10);
@@ -6140,29 +6207,30 @@ static int iwl_load_bsm(struct iwl_priv *priv)
/* Enable future boot loads whenever power management unit triggers it
* (e.g. when powering back up after power-save shutdown) */
- iwl_write_restricted_reg(priv, BSM_WR_CTRL_REG,
+ iwl4965_write_prph(priv, BSM_WR_CTRL_REG,
BSM_WR_CTRL_REG_BIT_START_EN);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
return 0;
}
-static void iwl_nic_start(struct iwl_priv *priv)
+static void iwl4965_nic_start(struct iwl4965_priv *priv)
{
/* Remove all resets to allow NIC to operate */
- iwl_write32(priv, CSR_RESET, 0);
+ iwl4965_write32(priv, CSR_RESET, 0);
}
+
/**
- * iwl_read_ucode - Read uCode images from disk file.
+ * iwl4965_read_ucode - Read uCode images from disk file.
*
* Copy into buffers for card to fetch via bus-mastering
*/
-static int iwl_read_ucode(struct iwl_priv *priv)
+static int iwl4965_read_ucode(struct iwl4965_priv *priv)
{
- struct iwl_ucode *ucode;
- int rc = 0;
+ struct iwl4965_ucode *ucode;
+ int ret;
const struct firmware *ucode_raw;
const char *name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode";
u8 *src;
@@ -6171,9 +6239,10 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
- rc = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
- if (rc < 0) {
- IWL_ERROR("%s firmware file req failed: Reason %d\n", name, rc);
+ ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
+ if (ret < 0) {
+ IWL_ERROR("%s firmware file req failed: Reason %d\n",
+ name, ret);
goto error;
}
@@ -6183,7 +6252,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
/* Make sure that we got at least our header! */
if (ucode_raw->size < sizeof(*ucode)) {
IWL_ERROR("File size way too small!\n");
- rc = -EINVAL;
+ ret = -EINVAL;
goto err_release;
}
@@ -6216,43 +6285,43 @@ static int iwl_read_ucode(struct iwl_priv *priv)
IWL_DEBUG_INFO("uCode file size %d too small\n",
(int)ucode_raw->size);
- rc = -EINVAL;
+ ret = -EINVAL;
goto err_release;
}
/* Verify that uCode images will fit in card's SRAM */
if (inst_size > IWL_MAX_INST_SIZE) {
- IWL_DEBUG_INFO("uCode instr len %d too large to fit in card\n",
- (int)inst_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode instr len %d too large to fit in\n",
+ inst_size);
+ ret = -EINVAL;
goto err_release;
}
if (data_size > IWL_MAX_DATA_SIZE) {
- IWL_DEBUG_INFO("uCode data len %d too large to fit in card\n",
- (int)data_size);
- rc = -EINVAL;
+ IWL_DEBUG_INFO("uCode data len %d too large to fit in\n",
+ data_size);
+ ret = -EINVAL;
goto err_release;
}
if (init_size > IWL_MAX_INST_SIZE) {
IWL_DEBUG_INFO
- ("uCode init instr len %d too large to fit in card\n",
- (int)init_size);
- rc = -EINVAL;
+ ("uCode init instr len %d too large to fit in\n",
+ init_size);
+ ret = -EINVAL;
goto err_release;
}
if (init_data_size > IWL_MAX_DATA_SIZE) {
IWL_DEBUG_INFO
- ("uCode init data len %d too large to fit in card\n",
- (int)init_data_size);
- rc = -EINVAL;
+ ("uCode init data len %d too large to fit in\n",
+ init_data_size);
+ ret = -EINVAL;
goto err_release;
}
if (boot_size > IWL_MAX_BSM_SIZE) {
IWL_DEBUG_INFO
- ("uCode boot instr len %d too large to fit in bsm\n",
- (int)boot_size);
- rc = -EINVAL;
+ ("uCode boot instr len %d too large to fit in\n",
+ boot_size);
+ ret = -EINVAL;
goto err_release;
}
@@ -6262,66 +6331,50 @@ static int iwl_read_ucode(struct iwl_priv *priv)
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
priv->ucode_code.len = inst_size;
- priv->ucode_code.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_code.len,
- &(priv->ucode_code.p_addr));
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
priv->ucode_data.len = data_size;
- priv->ucode_data.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_data.len,
- &(priv->ucode_data.p_addr));
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
priv->ucode_data_backup.len = data_size;
- priv->ucode_data_backup.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_data_backup.len,
- &(priv->ucode_data_backup.p_addr));
-
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
/* Initialization instructions and data */
- priv->ucode_init.len = init_size;
- priv->ucode_init.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_init.len,
- &(priv->ucode_init.p_addr));
-
- priv->ucode_init_data.len = init_data_size;
- priv->ucode_init_data.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_init_data.len,
- &(priv->ucode_init_data.p_addr));
+ if (init_size && init_data_size) {
+ priv->ucode_init.len = init_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+ priv->ucode_init_data.len = init_data_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+ if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+ goto err_pci_alloc;
+ }
/* Bootstrap (instructions only, no data) */
- priv->ucode_boot.len = boot_size;
- priv->ucode_boot.v_addr =
- pci_alloc_consistent(priv->pci_dev,
- priv->ucode_boot.len,
- &(priv->ucode_boot.p_addr));
+ if (boot_size) {
+ priv->ucode_boot.len = boot_size;
+ iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
- if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
- !priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr ||
- !priv->ucode_boot.v_addr || !priv->ucode_data_backup.v_addr)
- goto err_pci_alloc;
+ if (!priv->ucode_boot.v_addr)
+ goto err_pci_alloc;
+ }
/* Copy images into buffers for card's bus-master reads ... */
/* Runtime instructions (first block of data in file) */
src = &ucode->data[0];
len = priv->ucode_code.len;
- IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) uCode instr len %Zd\n", len);
memcpy(priv->ucode_code.v_addr, src, len);
IWL_DEBUG_INFO("uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
- * NOTE: Copy into backup buffer will be done in iwl_up() */
+ * NOTE: Copy into backup buffer will be done in iwl4965_up() */
src = &ucode->data[inst_size];
len = priv->ucode_data.len;
- IWL_DEBUG_INFO("Copying (but not loading) uCode data len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
memcpy(priv->ucode_data.v_addr, src, len);
memcpy(priv->ucode_data_backup.v_addr, src, len);
@@ -6329,8 +6382,8 @@ static int iwl_read_ucode(struct iwl_priv *priv)
if (init_size) {
src = &ucode->data[inst_size + data_size];
len = priv->ucode_init.len;
- IWL_DEBUG_INFO("Copying (but not loading) init instr len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) init instr len %Zd\n",
+ len);
memcpy(priv->ucode_init.v_addr, src, len);
}
@@ -6338,16 +6391,15 @@ static int iwl_read_ucode(struct iwl_priv *priv)
if (init_data_size) {
src = &ucode->data[inst_size + data_size + init_size];
len = priv->ucode_init_data.len;
- IWL_DEBUG_INFO("Copying (but not loading) init data len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) init data len %Zd\n",
+ len);
memcpy(priv->ucode_init_data.v_addr, src, len);
}
/* Bootstrap instructions (5th block) */
src = &ucode->data[inst_size + data_size + init_size + init_data_size];
len = priv->ucode_boot.len;
- IWL_DEBUG_INFO("Copying (but not loading) boot instr len %d\n",
- (int)len);
+ IWL_DEBUG_INFO("Copying (but not loading) boot instr len %Zd\n", len);
memcpy(priv->ucode_boot.v_addr, src, len);
/* We have our copies now, allow OS release its copies */
@@ -6356,19 +6408,19 @@ static int iwl_read_ucode(struct iwl_priv *priv)
err_pci_alloc:
IWL_ERROR("failed to allocate pci memory\n");
- rc = -ENOMEM;
- iwl_dealloc_ucode_pci(priv);
+ ret = -ENOMEM;
+ iwl4965_dealloc_ucode_pci(priv);
err_release:
release_firmware(ucode_raw);
error:
- return rc;
+ return ret;
}
/**
- * iwl_set_ucode_ptrs - Set uCode address location
+ * iwl4965_set_ucode_ptrs - Set uCode address location
*
* Tell initialization uCode where to find runtime uCode.
*
@@ -6376,7 +6428,7 @@ static int iwl_read_ucode(struct iwl_priv *priv)
* We need to replace them to load runtime uCode inst and data,
* and to save runtime data when powering down.
*/
-static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
+static int iwl4965_set_ucode_ptrs(struct iwl4965_priv *priv)
{
dma_addr_t pinst;
dma_addr_t pdata;
@@ -6388,24 +6440,24 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
pdata = priv->ucode_data_backup.p_addr >> 4;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_restricted_access(priv);
+ rc = iwl4965_grab_nic_access(priv);
if (rc) {
spin_unlock_irqrestore(&priv->lock, flags);
return rc;
}
/* Tell bootstrap uCode where to find image to load */
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_PTR_REG, pinst);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_PTR_REG, pdata);
- iwl_write_restricted_reg(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+ iwl4965_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+ iwl4965_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+ iwl4965_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
priv->ucode_data.len);
/* Inst bytecount must be last to set up, bit 31 signals uCode
* that all new ptr/size info is in place */
- iwl_write_restricted_reg(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+ iwl4965_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
priv->ucode_code.len | BSM_DRAM_INST_LOAD);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -6415,7 +6467,7 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
}
/**
- * iwl_init_alive_start - Called after REPLY_ALIVE notification receieved
+ * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
*
* Called after REPLY_ALIVE notification received from "initialize" uCode.
*
@@ -6425,7 +6477,7 @@ static int iwl_set_ucode_ptrs(struct iwl_priv *priv)
*
* Tell "initialize" uCode to go ahead and load the runtime uCode.
*/
-static void iwl_init_alive_start(struct iwl_priv *priv)
+static void iwl4965_init_alive_start(struct iwl4965_priv *priv)
{
/* Check alive response for "valid" sign from uCode */
if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
@@ -6438,7 +6490,7 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "initialize" alive if code weren't properly loaded. */
- if (iwl_verify_ucode(priv)) {
+ if (iwl4965_verify_ucode(priv)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Bad \"initialize\" uCode load.\n");
@@ -6452,7 +6504,7 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
* load and launch runtime uCode, which will send us another "Alive"
* notification. */
IWL_DEBUG_INFO("Initialization Alive received.\n");
- if (iwl_set_ucode_ptrs(priv)) {
+ if (iwl4965_set_ucode_ptrs(priv)) {
/* Runtime instruction load won't happen;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Couldn't set up uCode pointers.\n");
@@ -6466,11 +6518,11 @@ static void iwl_init_alive_start(struct iwl_priv *priv)
/**
- * iwl_alive_start - called after REPLY_ALIVE notification received
+ * iwl4965_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
- * Alive gets handled by iwl_init_alive_start()).
+ * Alive gets handled by iwl4965_init_alive_start()).
*/
-static void iwl_alive_start(struct iwl_priv *priv)
+static void iwl4965_alive_start(struct iwl4965_priv *priv)
{
int rc = 0;
@@ -6486,14 +6538,14 @@ static void iwl_alive_start(struct iwl_priv *priv)
/* Initialize uCode has loaded Runtime uCode ... verify inst image.
* This is a paranoid check, because we would not have gotten the
* "runtime" alive if code weren't properly loaded. */
- if (iwl_verify_ucode(priv)) {
+ if (iwl4965_verify_ucode(priv)) {
/* Runtime instruction load was bad;
* take it all the way back down so we can try again */
IWL_DEBUG_INFO("Bad runtime uCode load.\n");
goto restart;
}
- iwl_clear_stations_table(priv);
+ iwl4965_clear_stations_table(priv);
rc = iwl4965_alive_notify(priv);
if (rc) {
@@ -6502,78 +6554,61 @@ static void iwl_alive_start(struct iwl_priv *priv)
goto restart;
}
- /* After the ALIVE response, we can process host commands */
+ /* After the ALIVE response, we can send host commands to 4965 uCode */
set_bit(STATUS_ALIVE, &priv->status);
/* Clear out the uCode error bit if it is set */
clear_bit(STATUS_FW_ERROR, &priv->status);
- rc = iwl_init_channel_map(priv);
+ rc = iwl4965_init_channel_map(priv);
if (rc) {
IWL_ERROR("initializing regulatory failed: %d\n", rc);
return;
}
- iwl_init_geos(priv);
+ iwl4965_init_geos(priv);
+ iwl4965_reset_channel_flag(priv);
- if (iwl_is_rfkill(priv))
+ if (iwl4965_is_rfkill(priv))
return;
- if (!priv->mac80211_registered) {
- /* Unlock so any user space entry points can call back into
- * the driver without a deadlock... */
- mutex_unlock(&priv->mutex);
- iwl_rate_control_register(priv->hw);
- rc = ieee80211_register_hw(priv->hw);
- priv->hw->conf.beacon_int = 100;
- mutex_lock(&priv->mutex);
-
- if (rc) {
- iwl_rate_control_unregister(priv->hw);
- IWL_ERROR("Failed to register network "
- "device (error %d)\n", rc);
- return;
- }
-
- priv->mac80211_registered = 1;
-
- iwl_reset_channel_flag(priv);
- } else
- ieee80211_start_queues(priv->hw);
+ ieee80211_start_queues(priv->hw);
priv->active_rate = priv->rates_mask;
priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
- iwl_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
+ iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(priv->power_mode));
- if (iwl_is_associated(priv)) {
- struct iwl_rxon_cmd *active_rxon =
- (struct iwl_rxon_cmd *)(&priv->active_rxon);
+ if (iwl4965_is_associated(priv)) {
+ struct iwl4965_rxon_cmd *active_rxon =
+ (struct iwl4965_rxon_cmd *)(&priv->active_rxon);
memcpy(&priv->staging_rxon, &priv->active_rxon,
sizeof(priv->staging_rxon));
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl_connection_init_rx_config(priv);
+ iwl4965_connection_init_rx_config(priv);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
}
- /* Configure BT coexistence */
- iwl_send_bt_config(priv);
+ /* Configure Bluetooth device coexistence support */
+ iwl4965_send_bt_config(priv);
/* Configure the adapter for unassociated operation */
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
/* At this point, the NIC is initialized and operational */
priv->notif_missed_beacons = 0;
set_bit(STATUS_READY, &priv->status);
iwl4965_rf_kill_ct_config(priv);
+
IWL_DEBUG_INFO("ALIVE processing complete.\n");
+ wake_up_interruptible(&priv->wait_command_queue);
if (priv->error_recovering)
- iwl_error_recovery(priv);
+ iwl4965_error_recovery(priv);
return;
@@ -6581,9 +6616,9 @@ static void iwl_alive_start(struct iwl_priv *priv)
queue_work(priv->workqueue, &priv->restart);
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv);
+static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv);
-static void __iwl_down(struct iwl_priv *priv)
+static void __iwl4965_down(struct iwl4965_priv *priv)
{
unsigned long flags;
int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -6596,7 +6631,7 @@ static void __iwl_down(struct iwl_priv *priv)
if (!exit_pending)
set_bit(STATUS_EXIT_PENDING, &priv->status);
- iwl_clear_stations_table(priv);
+ iwl4965_clear_stations_table(priv);
/* Unblock any waiting calls */
wake_up_interruptible_all(&priv->wait_command_queue);
@@ -6607,17 +6642,17 @@ static void __iwl_down(struct iwl_priv *priv)
clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* stop and reset the on-board processor */
- iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+ iwl4965_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
+ iwl4965_disable_interrupts(priv);
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
- /* If we have not previously called iwl_init() then
+ /* If we have not previously called iwl4965_init() then
* clear all bits but the RF Kill and SUSPEND bits and return */
- if (!iwl_is_init(priv)) {
+ if (!iwl4965_is_init(priv)) {
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
STATUS_RF_KILL_HW |
test_bit(STATUS_RF_KILL_SW, &priv->status) <<
@@ -6639,53 +6674,52 @@ static void __iwl_down(struct iwl_priv *priv)
STATUS_FW_ERROR;
spin_lock_irqsave(&priv->lock, flags);
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ iwl4965_clear_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&priv->lock, flags);
- iwl_hw_txq_ctx_stop(priv);
- iwl_hw_rxq_stop(priv);
+ iwl4965_hw_txq_ctx_stop(priv);
+ iwl4965_hw_rxq_stop(priv);
spin_lock_irqsave(&priv->lock, flags);
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
+ if (!iwl4965_grab_nic_access(priv)) {
+ iwl4965_write_prph(priv, APMG_CLK_DIS_REG,
APMG_CLK_VAL_DMA_CLK_RQT);
- iwl_release_restricted_access(priv);
+ iwl4965_release_nic_access(priv);
}
spin_unlock_irqrestore(&priv->lock, flags);
udelay(5);
- iwl_hw_nic_stop_master(priv);
- iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- iwl_hw_nic_reset(priv);
+ iwl4965_hw_nic_stop_master(priv);
+ iwl4965_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+ iwl4965_hw_nic_reset(priv);
exit:
- memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+ memset(&priv->card_alive, 0, sizeof(struct iwl4965_alive_resp));
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
priv->ibss_beacon = NULL;
/* clear out any free frames */
- iwl_clear_free_frames(priv);
+ iwl4965_clear_free_frames(priv);
}
-static void iwl_down(struct iwl_priv *priv)
+static void iwl4965_down(struct iwl4965_priv *priv)
{
mutex_lock(&priv->mutex);
- __iwl_down(priv);
+ __iwl4965_down(priv);
mutex_unlock(&priv->mutex);
- iwl_cancel_deferred_work(priv);
+ iwl4965_cancel_deferred_work(priv);
}
#define MAX_HW_RESTARTS 5
-static int __iwl_up(struct iwl_priv *priv)
+static int __iwl4965_up(struct iwl4965_priv *priv)
{
- DECLARE_MAC_BUF(mac);
int rc, i;
- u32 hw_rf_kill = 0;
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
IWL_WARNING("Exit pending; will not bring the NIC up\n");
@@ -6695,56 +6729,65 @@ static int __iwl_up(struct iwl_priv *priv)
if (test_bit(STATUS_RF_KILL_SW, &priv->status)) {
IWL_WARNING("Radio disabled by SW RF kill (module "
"parameter)\n");
- return 0;
+ return -ENODEV;
+ }
+
+ /* If platform's RF_KILL switch is NOT set to KILL */
+ if (iwl4965_read32(priv, CSR_GP_CNTRL) &
+ CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
+ clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ else {
+ set_bit(STATUS_RF_KILL_HW, &priv->status);
+ if (!test_bit(STATUS_IN_SUSPEND, &priv->status)) {
+ IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+ return -ENODEV;
+ }
+ }
+
+ if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+ IWL_ERROR("ucode not available for device bringup\n");
+ return -EIO;
}
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+ iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
- rc = iwl_hw_nic_init(priv);
+ rc = iwl4965_hw_nic_init(priv);
if (rc) {
IWL_ERROR("Unable to int nic\n");
return rc;
}
/* make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR,
CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
/* clear (again), then enable host interrupts */
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl_enable_interrupts(priv);
+ iwl4965_write32(priv, CSR_INT, 0xFFFFFFFF);
+ iwl4965_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+ iwl4965_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Copy original ucode data image from disk into backup cache.
* This will be used to initialize the on-board processor's
* data SRAM for a clean start when the runtime program first loads. */
memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
- priv->ucode_data.len);
-
- /* If platform's RF_KILL switch is set to KILL,
- * wait for BIT_INT_RF_KILL interrupt before loading uCode
- * and getting things started */
- if (!(iwl_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
+ priv->ucode_data.len);
- if (test_bit(STATUS_RF_KILL_HW, &priv->status) || hw_rf_kill) {
- IWL_WARNING("Radio disabled by HW RF Kill switch\n");
+ /* We return success when we resume from suspend and rf_kill is on. */
+ if (test_bit(STATUS_RF_KILL_HW, &priv->status))
return 0;
- }
for (i = 0; i < MAX_HW_RESTARTS; i++) {
- iwl_clear_stations_table(priv);
+ iwl4965_clear_stations_table(priv);
/* load bootstrap state machine,
* load bootstrap program into processor's memory,
* prepare to load the "initialize" uCode */
- rc = iwl_load_bsm(priv);
+ rc = iwl4965_load_bsm(priv);
if (rc) {
IWL_ERROR("Unable to set up bootstrap uCode: %d\n", rc);
@@ -6752,14 +6795,7 @@ static int __iwl_up(struct iwl_priv *priv)
}
/* start card; "initialize" will load runtime ucode */
- iwl_nic_start(priv);
-
- /* MAC Address location in EEPROM same for 3945/4965 */
- get_eeprom_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n",
- print_mac(mac, priv->mac_addr));
-
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ iwl4965_nic_start(priv);
IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
@@ -6767,7 +6803,7 @@ static int __iwl_up(struct iwl_priv *priv)
}
set_bit(STATUS_EXIT_PENDING, &priv->status);
- __iwl_down(priv);
+ __iwl4965_down(priv);
/* tried to restart and config the device for as long as our
* patience could withstand */
@@ -6782,35 +6818,35 @@ static int __iwl_up(struct iwl_priv *priv)
*
*****************************************************************************/
-static void iwl_bg_init_alive_start(struct work_struct *data)
+static void iwl4965_bg_init_alive_start(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, init_alive_start.work);
+ struct iwl4965_priv *priv =
+ container_of(data, struct iwl4965_priv, init_alive_start.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_init_alive_start(priv);
+ iwl4965_init_alive_start(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_alive_start(struct work_struct *data)
+static void iwl4965_bg_alive_start(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, alive_start.work);
+ struct iwl4965_priv *priv =
+ container_of(data, struct iwl4965_priv, alive_start.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_alive_start(priv);
+ iwl4965_alive_start(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_rf_kill(struct work_struct *work)
+static void iwl4965_bg_rf_kill(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, rf_kill);
wake_up_interruptible(&priv->wait_command_queue);
@@ -6819,7 +6855,7 @@ static void iwl_bg_rf_kill(struct work_struct *work)
mutex_lock(&priv->mutex);
- if (!iwl_is_rfkill(priv)) {
+ if (!iwl4965_is_rfkill(priv)) {
IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL,
"HW and/or SW RF Kill no longer active, restarting "
"device\n");
@@ -6840,10 +6876,10 @@ static void iwl_bg_rf_kill(struct work_struct *work)
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
-static void iwl_bg_scan_check(struct work_struct *data)
+static void iwl4965_bg_scan_check(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, scan_check.work);
+ struct iwl4965_priv *priv =
+ container_of(data, struct iwl4965_priv, scan_check.work);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -6856,22 +6892,22 @@ static void iwl_bg_scan_check(struct work_struct *data)
jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG));
if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
- iwl_send_scan_abort(priv);
+ iwl4965_send_scan_abort(priv);
}
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_request_scan(struct work_struct *data)
+static void iwl4965_bg_request_scan(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, request_scan);
- struct iwl_host_cmd cmd = {
+ struct iwl4965_priv *priv =
+ container_of(data, struct iwl4965_priv, request_scan);
+ struct iwl4965_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
- .len = sizeof(struct iwl_scan_cmd),
+ .len = sizeof(struct iwl4965_scan_cmd),
.meta.flags = CMD_SIZE_HUGE,
};
int rc = 0;
- struct iwl_scan_cmd *scan;
+ struct iwl4965_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
u8 direct_mask;
int phymode;
@@ -6880,7 +6916,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
mutex_lock(&priv->mutex);
- if (!iwl_is_ready(priv)) {
+ if (!iwl4965_is_ready(priv)) {
IWL_WARNING("request scan called when driver not ready.\n");
goto done;
}
@@ -6909,7 +6945,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
- if (iwl_is_rfkill(priv)) {
+ if (iwl4965_is_rfkill(priv)) {
IWL_DEBUG_HC("Aborting scan due to RF Kill activation\n");
goto done;
}
@@ -6925,7 +6961,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
}
if (!priv->scan) {
- priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) +
+ priv->scan = kmalloc(sizeof(struct iwl4965_scan_cmd) +
IWL_MAX_SCAN_SIZE, GFP_KERNEL);
if (!priv->scan) {
rc = -ENOMEM;
@@ -6933,12 +6969,12 @@ static void iwl_bg_request_scan(struct work_struct *data)
}
}
scan = priv->scan;
- memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+ memset(scan, 0, sizeof(struct iwl4965_scan_cmd) + IWL_MAX_SCAN_SIZE);
scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
- if (iwl_is_associated(priv)) {
+ if (iwl4965_is_associated(priv)) {
u16 interval = 0;
u32 extra;
u32 suspend_time = 100;
@@ -6968,14 +7004,14 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (priv->one_direct_scan) {
IWL_DEBUG_SCAN
("Kicking off one direct scan for '%s'\n",
- iwl_escape_essid(priv->direct_ssid,
+ iwl4965_escape_essid(priv->direct_ssid,
priv->direct_ssid_len));
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
direct_mask = 1;
- } else if (!iwl_is_associated(priv) && priv->essid_len) {
+ } else if (!iwl4965_is_associated(priv) && priv->essid_len) {
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->essid_len;
memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
@@ -6986,7 +7022,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
/* We don't build a direct scan probe request; the uCode will do
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.len = cpu_to_le16(
- iwl_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
+ iwl4965_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
IWL_MAX_SCAN_SIZE - sizeof(scan), 0));
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
@@ -7000,7 +7036,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
case 2:
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
scan->tx_cmd.rate_n_flags =
- iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
+ iwl4965_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
RATE_MCS_ANT_B_MSK|RATE_MCS_CCK_MSK);
scan->good_CRC_th = 0;
@@ -7009,7 +7045,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
case 1:
scan->tx_cmd.rate_n_flags =
- iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
+ iwl4965_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
RATE_MCS_ANT_B_MSK);
scan->good_CRC_th = IWL_GOOD_CRC_TH;
phymode = MODE_IEEE80211A;
@@ -7036,23 +7072,23 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (direct_mask)
IWL_DEBUG_SCAN
("Initiating direct scan for %s.\n",
- iwl_escape_essid(priv->essid, priv->essid_len));
+ iwl4965_escape_essid(priv->essid, priv->essid_len));
else
IWL_DEBUG_SCAN("Initiating indirect scan.\n");
scan->channel_count =
- iwl_get_channels_for_scan(
+ iwl4965_get_channels_for_scan(
priv, phymode, 1, /* active */
direct_mask,
(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
cmd.len += le16_to_cpu(scan->tx_cmd.len) +
- scan->channel_count * sizeof(struct iwl_scan_channel);
+ scan->channel_count * sizeof(struct iwl4965_scan_channel);
cmd.data = scan;
scan->len = cpu_to_le16(cmd.len);
set_bit(STATUS_SCAN_HW, &priv->status);
- rc = iwl_send_cmd_sync(priv, &cmd);
+ rc = iwl4965_send_cmd_sync(priv, &cmd);
if (rc)
goto done;
@@ -7063,50 +7099,52 @@ static void iwl_bg_request_scan(struct work_struct *data)
return;
done:
- /* inform mac80211 sacn aborted */
+ /* inform mac80211 scan aborted */
queue_work(priv->workqueue, &priv->scan_completed);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_up(struct work_struct *data)
+static void iwl4965_bg_up(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
+ struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, up);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- __iwl_up(priv);
+ __iwl4965_up(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_restart(struct work_struct *data)
+static void iwl4965_bg_restart(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+ struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv, restart);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- iwl_down(priv);
+ iwl4965_down(priv);
queue_work(priv->workqueue, &priv->up);
}
-static void iwl_bg_rx_replenish(struct work_struct *data)
+static void iwl4965_bg_rx_replenish(struct work_struct *data)
{
- struct iwl_priv *priv =
- container_of(data, struct iwl_priv, rx_replenish);
+ struct iwl4965_priv *priv =
+ container_of(data, struct iwl4965_priv, rx_replenish);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
mutex_lock(&priv->mutex);
- iwl_rx_replenish(priv);
+ iwl4965_rx_replenish(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_post_associate(struct work_struct *data)
+#define IWL_DELAY_NEXT_SCAN (HZ*2)
+
+static void iwl4965_bg_post_associate(struct work_struct *data)
{
- struct iwl_priv *priv = container_of(data, struct iwl_priv,
+ struct iwl4965_priv *priv = container_of(data, struct iwl4965_priv,
post_associate.work);
int rc = 0;
@@ -7128,20 +7166,20 @@ static void iwl_bg_post_associate(struct work_struct *data)
mutex_lock(&priv->mutex);
- if (!priv->interface_id || !priv->is_open) {
+ if (!priv->vif || !priv->is_open) {
mutex_unlock(&priv->mutex);
return;
}
- iwl_scan_cancel_timeout(priv, 200);
+ iwl4965_scan_cancel_timeout(priv, 200);
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ iwl4965_setup_rxon_timing(priv);
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
IWL_WARNING("REPLY_RXON_TIMING failed - "
@@ -7149,15 +7187,10 @@ static void iwl_bg_post_associate(struct work_struct *data)
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
-#ifdef CONFIG_IWLWIFI_HT
- if (priv->is_ht_enabled && priv->current_assoc_ht.is_ht)
- iwl4965_set_rxon_ht(priv, &priv->current_assoc_ht);
- else {
- priv->active_rate_ht[0] = 0;
- priv->active_rate_ht[1] = 0;
- priv->current_channel_width = IWL_CHANNEL_WIDTH_20MHZ;
- }
-#endif /* CONFIG_IWLWIFI_HT*/
+#ifdef CONFIG_IWL4965_HT
+ if (priv->current_ht_config.is_ht)
+ iwl4965_set_rxon_ht(priv, &priv->current_ht_config);
+#endif /* CONFIG_IWL4965_HT*/
iwl4965_set_rxon_chain(priv);
priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id);
@@ -7180,22 +7213,22 @@ static void iwl_bg_post_associate(struct work_struct *data)
}
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
switch (priv->iw_mode) {
case IEEE80211_IF_TYPE_STA:
- iwl_rate_scale_init(priv->hw, IWL_AP_ID);
+ iwl4965_rate_scale_init(priv->hw, IWL_AP_ID);
break;
case IEEE80211_IF_TYPE_IBSS:
/* clear out the station table */
- iwl_clear_stations_table(priv);
+ iwl4965_clear_stations_table(priv);
- iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
- iwl_rxon_add_station(priv, priv->bssid, 0);
- iwl_rate_scale_init(priv->hw, IWL_STA_ID);
- iwl_send_beacon_cmd(priv);
+ iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
+ iwl4965_rxon_add_station(priv, priv->bssid, 0);
+ iwl4965_rate_scale_init(priv->hw, IWL_STA_ID);
+ iwl4965_send_beacon_cmd(priv);
break;
@@ -7205,55 +7238,61 @@ static void iwl_bg_post_associate(struct work_struct *data)
break;
}
- iwl_sequence_reset(priv);
+ iwl4965_sequence_reset(priv);
-#ifdef CONFIG_IWLWIFI_SENSITIVITY
+#ifdef CONFIG_IWL4965_SENSITIVITY
/* Enable Rx differential gain and sensitivity calibrations */
iwl4965_chain_noise_reset(priv);
priv->start_calib = 1;
-#endif /* CONFIG_IWLWIFI_SENSITIVITY */
+#endif /* CONFIG_IWL4965_SENSITIVITY */
if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
priv->assoc_station_added = 1;
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_activate_qos(priv, 0);
-#endif /* CONFIG_IWLWIFI_QOS */
+#ifdef CONFIG_IWL4965_QOS
+ iwl4965_activate_qos(priv, 0);
+#endif /* CONFIG_IWL4965_QOS */
+ /* we have just associated, don't start scan too early */
+ priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_abort_scan(struct work_struct *work)
+static void iwl4965_bg_abort_scan(struct work_struct *work)
{
- struct iwl_priv *priv = container_of(work, struct iwl_priv,
- abort_scan);
+ struct iwl4965_priv *priv = container_of(work, struct iwl4965_priv, abort_scan);
- if (!iwl_is_ready(priv))
+ if (!iwl4965_is_ready(priv))
return;
mutex_lock(&priv->mutex);
set_bit(STATUS_SCAN_ABORTING, &priv->status);
- iwl_send_scan_abort(priv);
+ iwl4965_send_scan_abort(priv);
mutex_unlock(&priv->mutex);
}
-static void iwl_bg_scan_completed(struct work_struct *work)
+static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+
+static void iwl4965_bg_scan_completed(struct work_struct *work)
{
- struct iwl_priv *priv =
- container_of(work, struct iwl_priv, scan_completed);
+ struct iwl4965_priv *priv =
+ container_of(work, struct iwl4965_priv, scan_completed);
IWL_DEBUG(IWL_DL_INFO | IWL_DL_SCAN, "SCAN complete scan\n");
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
+ if (test_bit(STATUS_CONF_PENDING, &priv->status))
+ iwl4965_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+
ieee80211_scan_completed(priv->hw);
/* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */
mutex_lock(&priv->mutex);
- iwl_hw_reg_send_txpower(priv);
+ iwl4965_hw_reg_send_txpower(priv);
mutex_unlock(&priv->mutex);
}
@@ -7263,50 +7302,123 @@ static void iwl_bg_scan_completed(struct work_struct *work)
*
*****************************************************************************/
-static int iwl_mac_start(struct ieee80211_hw *hw)
+#define UCODE_READY_TIMEOUT (2 * HZ)
+
+static int iwl4965_mac_start(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
+ int ret;
IWL_DEBUG_MAC80211("enter\n");
+ if (pci_enable_device(priv->pci_dev)) {
+ IWL_ERROR("Fail to pci_enable_device\n");
+ return -ENODEV;
+ }
+ pci_restore_state(priv->pci_dev);
+ pci_enable_msi(priv->pci_dev);
+
+ ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
+ DRV_NAME, priv);
+ if (ret) {
+ IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
+ goto out_disable_msi;
+ }
+
/* we should be verifying the device is ready to be opened */
mutex_lock(&priv->mutex);
- priv->is_open = 1;
+ memset(&priv->staging_rxon, 0, sizeof(struct iwl4965_rxon_cmd));
+ /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+ * ucode filename and max sizes are card-specific. */
+
+ if (!priv->ucode_code.len) {
+ ret = iwl4965_read_ucode(priv);
+ if (ret) {
+ IWL_ERROR("Could not read microcode: %d\n", ret);
+ mutex_unlock(&priv->mutex);
+ goto out_release_irq;
+ }
+ }
- if (!iwl_is_rfkill(priv))
- ieee80211_start_queues(priv->hw);
+ ret = __iwl4965_up(priv);
mutex_unlock(&priv->mutex);
+
+ if (ret)
+ goto out_release_irq;
+
+ IWL_DEBUG_INFO("Start UP work done.\n");
+
+ if (test_bit(STATUS_IN_SUSPEND, &priv->status))
+ return 0;
+
+ /* Wait for START_ALIVE from ucode. Otherwise callbacks from
+ * mac80211 will not be run successfully. */
+ ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+ test_bit(STATUS_READY, &priv->status),
+ UCODE_READY_TIMEOUT);
+ if (!ret) {
+ if (!test_bit(STATUS_READY, &priv->status)) {
+ IWL_ERROR("Wait for START_ALIVE timeout after %dms.\n",
+ jiffies_to_msecs(UCODE_READY_TIMEOUT));
+ ret = -ETIMEDOUT;
+ goto out_release_irq;
+ }
+ }
+
+ priv->is_open = 1;
IWL_DEBUG_MAC80211("leave\n");
return 0;
+
+out_release_irq:
+ free_irq(priv->pci_dev->irq, priv);
+out_disable_msi:
+ pci_disable_msi(priv->pci_dev);
+ pci_disable_device(priv->pci_dev);
+ priv->is_open = 0;
+ IWL_DEBUG_MAC80211("leave - failed\n");
+ return ret;
}
-static void iwl_mac_stop(struct ieee80211_hw *hw)
+static void iwl4965_mac_stop(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
+ if (!priv->is_open) {
+ IWL_DEBUG_MAC80211("leave - skip\n");
+ return;
+ }
- mutex_lock(&priv->mutex);
- /* stop mac, cancel any scan request and clear
- * RXON_FILTER_ASSOC_MSK BIT
- */
priv->is_open = 0;
- iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
- mutex_unlock(&priv->mutex);
+
+ if (iwl4965_is_ready_rf(priv)) {
+ /* stop mac, cancel any scan request and clear
+ * RXON_FILTER_ASSOC_MSK BIT
+ */
+ mutex_lock(&priv->mutex);
+ iwl4965_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ mutex_unlock(&priv->mutex);
+ }
+
+ iwl4965_down(priv);
+
+ flush_workqueue(priv->workqueue);
+ free_irq(priv->pci_dev->irq, priv);
+ pci_disable_msi(priv->pci_dev);
+ pci_save_state(priv->pci_dev);
+ pci_disable_device(priv->pci_dev);
IWL_DEBUG_MAC80211("leave\n");
}
-static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *ctl)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
@@ -7318,29 +7430,29 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_TX("dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
ctl->tx_rate);
- if (iwl_tx_skb(priv, skb, ctl))
+ if (iwl4965_tx_skb(priv, skb, ctl))
dev_kfree_skb_any(skb);
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
-static int iwl_mac_add_interface(struct ieee80211_hw *hw,
+static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
unsigned long flags;
DECLARE_MAC_BUF(mac);
- IWL_DEBUG_MAC80211("enter: id %d, type %d\n", conf->if_id, conf->type);
+ IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
- if (priv->interface_id) {
- IWL_DEBUG_MAC80211("leave - interface_id != 0\n");
+ if (priv->vif) {
+ IWL_DEBUG_MAC80211("leave - vif != NULL\n");
return 0;
}
spin_lock_irqsave(&priv->lock, flags);
- priv->interface_id = conf->if_id;
+ priv->vif = conf->vif;
spin_unlock_irqrestore(&priv->lock, flags);
@@ -7350,58 +7462,62 @@ static int iwl_mac_add_interface(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr));
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
- iwl_set_mode(priv, conf->type);
- IWL_DEBUG_MAC80211("leave\n");
+ if (iwl4965_is_ready(priv))
+ iwl4965_set_mode(priv, conf->type);
+
mutex_unlock(&priv->mutex);
+ IWL_DEBUG_MAC80211("leave\n");
return 0;
}
/**
- * iwl_mac_config - mac80211 config callback
+ * iwl4965_mac_config - mac80211 config callback
*
* We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
* be set inappropriately and the driver currently sets the hardware up to
* use it whenever needed.
*/
-static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
- const struct iwl_channel_info *ch_info;
+ struct iwl4965_priv *priv = hw->priv;
+ const struct iwl4965_channel_info *ch_info;
unsigned long flags;
+ int ret = 0;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
- if (!iwl_is_ready(priv)) {
+ priv->add_radiotap = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
+ if (!iwl4965_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n");
- mutex_unlock(&priv->mutex);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
- * what is exposed through include/ declrations */
- if (unlikely(!iwl_param_disable_hw_scan &&
+ if (unlikely(!iwl4965_param_disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) {
IWL_DEBUG_MAC80211("leave - scanning\n");
+ set_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
return 0;
}
spin_lock_irqsave(&priv->lock, flags);
- ch_info = iwl_get_channel_info(priv, conf->phymode, conf->channel);
+ ch_info = iwl4965_get_channel_info(priv, conf->phymode, conf->channel);
if (!is_channel_valid(ch_info)) {
IWL_DEBUG_SCAN("Channel %d [%d] is INVALID for this SKU.\n",
conf->channel, conf->phymode);
IWL_DEBUG_MAC80211("leave - invalid channel\n");
spin_unlock_irqrestore(&priv->lock, flags);
- mutex_unlock(&priv->mutex);
- return -EINVAL;
+ ret = -EINVAL;
+ goto out;
}
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
/* if we are switching fron ht to 2.4 clear flags
* from any ht related info since 2.4 does not
* support ht */
@@ -7411,57 +7527,56 @@ static int iwl_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
#endif
)
priv->staging_rxon.flags = 0;
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT */
- iwl_set_rxon_channel(priv, conf->phymode, conf->channel);
+ iwl4965_set_rxon_channel(priv, conf->phymode, conf->channel);
- iwl_set_flags_for_phymode(priv, conf->phymode);
+ iwl4965_set_flags_for_phymode(priv, conf->phymode);
/* The list of supported rates and rate mask can be different
* for each phymode; since the phymode may have changed, reset
* the rate mask to what mac80211 lists */
- iwl_set_rate(priv);
+ iwl4965_set_rate(priv);
spin_unlock_irqrestore(&priv->lock, flags);
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
- iwl_hw_channel_switch(priv, conf->channel);
- mutex_unlock(&priv->mutex);
- return 0;
+ iwl4965_hw_channel_switch(priv, conf->channel);
+ goto out;
}
#endif
- iwl_radio_kill_sw(priv, !conf->radio_enabled);
+ iwl4965_radio_kill_sw(priv, !conf->radio_enabled);
if (!conf->radio_enabled) {
IWL_DEBUG_MAC80211("leave - radio disabled\n");
- mutex_unlock(&priv->mutex);
- return 0;
+ goto out;
}
- if (iwl_is_rfkill(priv)) {
+ if (iwl4965_is_rfkill(priv)) {
IWL_DEBUG_MAC80211("leave - RF kill\n");
- mutex_unlock(&priv->mutex);
- return -EIO;
+ ret = -EIO;
+ goto out;
}
- iwl_set_rate(priv);
+ iwl4965_set_rate(priv);
if (memcmp(&priv->active_rxon,
&priv->staging_rxon, sizeof(priv->staging_rxon)))
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
else
IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
IWL_DEBUG_MAC80211("leave\n");
+out:
+ clear_bit(STATUS_CONF_PENDING, &priv->status);
mutex_unlock(&priv->mutex);
-
- return 0;
+ return ret;
}
-static void iwl_config_ap(struct iwl_priv *priv)
+static void iwl4965_config_ap(struct iwl4965_priv *priv)
{
int rc = 0;
@@ -7473,12 +7588,12 @@ static void iwl_config_ap(struct iwl_priv *priv)
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
/* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd));
- iwl_setup_rxon_timing(priv);
- rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
+ memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
+ iwl4965_setup_rxon_timing(priv);
+ rc = iwl4965_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (rc)
IWL_WARNING("REPLY_RXON_TIMING failed - "
@@ -7510,23 +7625,24 @@ static void iwl_config_ap(struct iwl_priv *priv)
}
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_activate_qos(priv, 1);
+ iwl4965_commit_rxon(priv);
+#ifdef CONFIG_IWL4965_QOS
+ iwl4965_activate_qos(priv, 1);
#endif
- iwl_rxon_add_station(priv, BROADCAST_ADDR, 0);
+ iwl4965_rxon_add_station(priv, iwl4965_broadcast_addr, 0);
}
- iwl_send_beacon_cmd(priv);
+ iwl4965_send_beacon_cmd(priv);
/* FIXME - we need to add code here to detect a totally new
* configuration, reset the AP, unassoc, rxon timing, assoc,
* clear sta table, add BCAST sta... */
}
-static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
+static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
unsigned long flags;
int rc;
@@ -7541,9 +7657,11 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
+ if (!iwl4965_is_alive(priv))
+ return -EAGAIN;
+
mutex_lock(&priv->mutex);
- IWL_DEBUG_MAC80211("enter: interface id %d\n", if_id);
if (conf->bssid)
IWL_DEBUG_MAC80211("bssid: %s\n",
print_mac(mac, conf->bssid));
@@ -7560,8 +7678,8 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
- if (priv->interface_id != if_id) {
- IWL_DEBUG_MAC80211("leave - interface_id != if_id\n");
+ if (priv->vif != vif) {
+ IWL_DEBUG_MAC80211("leave - priv->vif != vif\n");
mutex_unlock(&priv->mutex);
return 0;
}
@@ -7579,11 +7697,14 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
priv->ibss_beacon = conf->beacon;
}
+ if (iwl4965_is_rfkill(priv))
+ goto done;
+
if (conf->bssid && !is_zero_ether_addr(conf->bssid) &&
!is_multicast_ether_addr(conf->bssid)) {
/* If there is currently a HW scan going on in the background
* then we need to cancel it else the RXON below will fail. */
- if (iwl_scan_cancel_timeout(priv, 100)) {
+ if (iwl4965_scan_cancel_timeout(priv, 100)) {
IWL_WARNING("Aborted scan still in progress "
"after 100ms\n");
IWL_DEBUG_MAC80211("leaving - scan abort failed.\n");
@@ -7599,20 +7720,21 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl_config_ap(priv);
+ iwl4965_config_ap(priv);
else {
- rc = iwl_commit_rxon(priv);
+ rc = iwl4965_commit_rxon(priv);
if ((priv->iw_mode == IEEE80211_IF_TYPE_STA) && rc)
- iwl_rxon_add_station(
+ iwl4965_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
}
} else {
- iwl_scan_cancel_timeout(priv, 100);
+ iwl4965_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
}
+ done:
spin_lock_irqsave(&priv->lock, flags);
if (!conf->ssid_len)
memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
@@ -7628,34 +7750,35 @@ static int iwl_mac_config_interface(struct ieee80211_hw *hw, int if_id,
return 0;
}
-static void iwl_configure_filter(struct ieee80211_hw *hw,
+static void iwl4965_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
/*
* XXX: dummy
- * see also iwl_connection_init_rx_config
+ * see also iwl4965_connection_init_rx_config
*/
*total_flags = 0;
}
-static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
- cancel_delayed_work(&priv->post_associate);
- priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
-
- if (priv->interface_id == conf->if_id) {
- priv->interface_id = 0;
+ if (iwl4965_is_ready_rf(priv)) {
+ iwl4965_scan_cancel_timeout(priv, 100);
+ cancel_delayed_work(&priv->post_associate);
+ priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+ iwl4965_commit_rxon(priv);
+ }
+ if (priv->vif == conf->vif) {
+ priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
priv->essid_len = 0;
@@ -7666,19 +7789,50 @@ static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
}
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
+static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
+{
+ struct iwl4965_priv *priv = hw->priv;
+
+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+ if (bss_conf->use_short_preamble)
+ priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+ else
+ priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+ }
+
+ if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+ if (bss_conf->use_cts_prot && (priv->phymode != MODE_IEEE80211A))
+ priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK;
+ else
+ priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+ }
+
+ if (changes & BSS_CHANGED_ASSOC) {
+ /*
+ * TODO:
+ * do stuff instead of sniffing assoc resp
+ */
+ }
+
+ if (iwl4965_is_associated(priv))
+ iwl4965_send_rxon_assoc(priv);
+}
+
+static int iwl4965_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
{
int rc = 0;
unsigned long flags;
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
mutex_lock(&priv->mutex);
spin_lock_irqsave(&priv->lock, flags);
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl4965_is_ready_rf(priv)) {
rc = -EIO;
IWL_DEBUG_MAC80211("leave - not ready or exit pending\n");
goto out_unlock;
@@ -7690,17 +7844,21 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
+ /* we don't schedule scan within next_scan_jiffies period */
+ if (priv->next_scan_jiffies &&
+ time_after(priv->next_scan_jiffies, jiffies)) {
+ rc = -EAGAIN;
+ goto out_unlock;
+ }
/* if we just finished scan ask for delay */
- if (priv->last_scan_jiffies &&
- time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN,
- jiffies)) {
+ if (priv->last_scan_jiffies && time_after(priv->last_scan_jiffies +
+ IWL_DELAY_NEXT_SCAN, jiffies)) {
rc = -EAGAIN;
goto out_unlock;
}
if (len) {
- IWL_DEBUG_SCAN("direct scan for "
- "%s [%d]\n ",
- iwl_escape_essid(ssid, len), (int)len);
+ IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
+ iwl4965_escape_essid(ssid, len), (int)len);
priv->one_direct_scan = 1;
priv->direct_ssid_len = (u8)
@@ -7709,7 +7867,7 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
} else
priv->one_direct_scan = 0;
- rc = iwl_scan_initiate(priv);
+ rc = iwl4965_scan_initiate(priv);
IWL_DEBUG_MAC80211("leave\n");
@@ -7720,18 +7878,18 @@ out_unlock:
return rc;
}
-static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
DECLARE_MAC_BUF(mac);
int rc = 0;
u8 sta_id;
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_param_hwcrypto) {
+ if (!iwl4965_param_hwcrypto) {
IWL_DEBUG_MAC80211("leave - hwcrypto disabled\n");
return -EOPNOTSUPP;
}
@@ -7740,7 +7898,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
/* only support pairwise keys */
return -EOPNOTSUPP;
- sta_id = iwl_hw_find_station(priv, addr);
+ sta_id = iwl4965_hw_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
print_mac(mac, addr));
@@ -7749,24 +7907,24 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
mutex_lock(&priv->mutex);
- iwl_scan_cancel_timeout(priv, 100);
+ iwl4965_scan_cancel_timeout(priv, 100);
switch (cmd) {
case SET_KEY:
- rc = iwl_update_sta_key_info(priv, key, sta_id);
+ rc = iwl4965_update_sta_key_info(priv, key, sta_id);
if (!rc) {
- iwl_set_rxon_hwcrypto(priv, 1);
- iwl_commit_rxon(priv);
+ iwl4965_set_rxon_hwcrypto(priv, 1);
+ iwl4965_commit_rxon(priv);
key->hw_key_idx = sta_id;
IWL_DEBUG_MAC80211("set_key success, using hwcrypto\n");
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
}
break;
case DISABLE_KEY:
- rc = iwl_clear_sta_key_info(priv, sta_id);
+ rc = iwl4965_clear_sta_key_info(priv, sta_id);
if (!rc) {
- iwl_set_rxon_hwcrypto(priv, 0);
- iwl_commit_rxon(priv);
+ iwl4965_set_rxon_hwcrypto(priv, 0);
+ iwl4965_commit_rxon(priv);
IWL_DEBUG_MAC80211("disable hwcrypto key\n");
}
break;
@@ -7780,18 +7938,18 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return rc;
}
-static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
+static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
{
- struct iwl_priv *priv = hw->priv;
-#ifdef CONFIG_IWLWIFI_QOS
+ struct iwl4965_priv *priv = hw->priv;
+#ifdef CONFIG_IWL4965_QOS
unsigned long flags;
int q;
-#endif /* CONFIG_IWL_QOS */
+#endif /* CONFIG_IWL4965_QOS */
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl4965_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
return -EIO;
}
@@ -7801,7 +7959,7 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
return 0;
}
-#ifdef CONFIG_IWLWIFI_QOS
+#ifdef CONFIG_IWL4965_QOS
if (!priv->qos_data.qos_enable) {
priv->qos_data.qos_active = 0;
IWL_DEBUG_MAC80211("leave - qos not enabled\n");
@@ -7824,30 +7982,30 @@ static int iwl_mac_conf_tx(struct ieee80211_hw *hw, int queue,
mutex_lock(&priv->mutex);
if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
- iwl_activate_qos(priv, 1);
- else if (priv->assoc_id && iwl_is_associated(priv))
- iwl_activate_qos(priv, 0);
+ iwl4965_activate_qos(priv, 1);
+ else if (priv->assoc_id && iwl4965_is_associated(priv))
+ iwl4965_activate_qos(priv, 0);
mutex_unlock(&priv->mutex);
-#endif /*CONFIG_IWLWIFI_QOS */
+#endif /*CONFIG_IWL4965_QOS */
IWL_DEBUG_MAC80211("leave\n");
return 0;
}
-static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
+static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
int i, avail;
- struct iwl_tx_queue *txq;
- struct iwl_queue *q;
+ struct iwl4965_tx_queue *txq;
+ struct iwl4965_queue *q;
unsigned long flags;
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl4965_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
return -EIO;
}
@@ -7857,7 +8015,7 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
for (i = 0; i < AC_NUM; i++) {
txq = &priv->txq[i];
q = &txq->q;
- avail = iwl_queue_space(q);
+ avail = iwl4965_queue_space(q);
stats->data[i].len = q->n_window - avail;
stats->data[i].limit = q->n_window - q->high_mark;
@@ -7871,7 +8029,7 @@ static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
return 0;
}
-static int iwl_mac_get_stats(struct ieee80211_hw *hw,
+static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
IWL_DEBUG_MAC80211("enter\n");
@@ -7880,7 +8038,7 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
+static u64 iwl4965_mac_get_tsf(struct ieee80211_hw *hw)
{
IWL_DEBUG_MAC80211("enter\n");
IWL_DEBUG_MAC80211("leave\n");
@@ -7888,35 +8046,35 @@ static u64 iwl_mac_get_tsf(struct ieee80211_hw *hw)
return 0;
}
-static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
+static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
unsigned long flags;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
priv->lq_mngr.lq_ready = 0;
-#ifdef CONFIG_IWLWIFI_HT
+#ifdef CONFIG_IWL4965_HT
spin_lock_irqsave(&priv->lock, flags);
- memset(&priv->current_assoc_ht, 0, sizeof(struct sta_ht_info));
+ memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info));
spin_unlock_irqrestore(&priv->lock, flags);
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT_AGG
/* if (priv->lq_mngr.agg_ctrl.granted_ba)
iwl4965_turn_off_agg(priv, TID_ALL_SPECIFIED);*/
- memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl_agg_control));
+ memset(&(priv->lq_mngr.agg_ctrl), 0, sizeof(struct iwl4965_agg_control));
priv->lq_mngr.agg_ctrl.tid_traffic_load_threshold = 10;
priv->lq_mngr.agg_ctrl.ba_timeout = 5000;
priv->lq_mngr.agg_ctrl.auto_agg = 1;
if (priv->lq_mngr.agg_ctrl.auto_agg)
priv->lq_mngr.agg_ctrl.requested_ba = TID_ALL_ENABLED;
-#endif /*CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /*CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_reset_qos(priv);
+#ifdef CONFIG_IWL4965_QOS
+ iwl4965_reset_qos(priv);
#endif
cancel_delayed_work(&priv->post_associate);
@@ -7941,13 +8099,19 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
spin_unlock_irqrestore(&priv->lock, flags);
+ if (!iwl4965_is_ready_rf(priv)) {
+ IWL_DEBUG_MAC80211("leave - not ready\n");
+ mutex_unlock(&priv->mutex);
+ return;
+ }
+
/* we are restarting association process
* clear RXON_FILTER_ASSOC_MSK bit
*/
if (priv->iw_mode != IEEE80211_IF_TYPE_AP) {
- iwl_scan_cancel_timeout(priv, 100);
+ iwl4965_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
}
/* Per mac80211.h: This is only used in IBSS mode... */
@@ -7958,32 +8122,25 @@ static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
return;
}
- if (!iwl_is_ready_rf(priv)) {
- IWL_DEBUG_MAC80211("leave - not ready\n");
- mutex_unlock(&priv->mutex);
- return;
- }
-
priv->only_active_channel = 0;
- iwl_set_rate(priv);
+ iwl4965_set_rate(priv);
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211("leave\n");
-
}
-static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
+static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
- struct iwl_priv *priv = hw->priv;
+ struct iwl4965_priv *priv = hw->priv;
unsigned long flags;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
- if (!iwl_is_ready_rf(priv)) {
+ if (!iwl4965_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
mutex_unlock(&priv->mutex);
return -EIO;
@@ -8007,8 +8164,8 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
IWL_DEBUG_MAC80211("leave\n");
spin_unlock_irqrestore(&priv->lock, flags);
-#ifdef CONFIG_IWLWIFI_QOS
- iwl_reset_qos(priv);
+#ifdef CONFIG_IWL4965_QOS
+ iwl4965_reset_qos(priv);
#endif
queue_work(priv->workqueue, &priv->post_associate.work);
@@ -8018,133 +8175,62 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
return 0;
}
-#ifdef CONFIG_IWLWIFI_HT
-union ht_cap_info {
- struct {
- u16 advanced_coding_cap :1;
- u16 supported_chan_width_set :1;
- u16 mimo_power_save_mode :2;
- u16 green_field :1;
- u16 short_GI20 :1;
- u16 short_GI40 :1;
- u16 tx_stbc :1;
- u16 rx_stbc :1;
- u16 beam_forming :1;
- u16 delayed_ba :1;
- u16 maximal_amsdu_size :1;
- u16 cck_mode_at_40MHz :1;
- u16 psmp_support :1;
- u16 stbc_ctrl_frame_support :1;
- u16 sig_txop_protection_support :1;
- };
- u16 val;
-} __attribute__ ((packed));
-
-union ht_param_info{
- struct {
- u8 max_rx_ampdu_factor :2;
- u8 mpdu_density :3;
- u8 reserved :3;
- };
- u8 val;
-} __attribute__ ((packed));
-
-union ht_exra_param_info {
- struct {
- u8 ext_chan_offset :2;
- u8 tx_chan_width :1;
- u8 rifs_mode :1;
- u8 controlled_access_only :1;
- u8 service_interval_granularity :3;
- };
- u8 val;
-} __attribute__ ((packed));
-
-union ht_operation_mode{
- struct {
- u16 op_mode :2;
- u16 non_GF :1;
- u16 reserved :13;
- };
- u16 val;
-} __attribute__ ((packed));
-
+#ifdef CONFIG_IWL4965_HT
-static int sta_ht_info_init(struct ieee80211_ht_capability *ht_cap,
- struct ieee80211_ht_additional_info *ht_extra,
- struct sta_ht_info *ht_info_ap,
- struct sta_ht_info *ht_info)
+static void iwl4965_ht_info_fill(struct ieee80211_conf *conf,
+ struct iwl4965_priv *priv)
{
- union ht_cap_info cap;
- union ht_operation_mode op_mode;
- union ht_param_info param_info;
- union ht_exra_param_info extra_param_info;
+ struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+ struct ieee80211_ht_info *ht_conf = &conf->ht_conf;
+ struct ieee80211_ht_bss_info *ht_bss_conf = &conf->ht_bss_conf;
IWL_DEBUG_MAC80211("enter: \n");
- if (!ht_info) {
- IWL_DEBUG_MAC80211("leave: ht_info is NULL\n");
- return -1;
+ if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) {
+ iwl_conf->is_ht = 0;
+ return;
}
- if (ht_cap) {
- cap.val = (u16) le16_to_cpu(ht_cap->capabilities_info);
- param_info.val = ht_cap->mac_ht_params_info;
- ht_info->is_ht = 1;
- if (cap.short_GI20)
- ht_info->sgf |= 0x1;
- if (cap.short_GI40)
- ht_info->sgf |= 0x2;
- ht_info->is_green_field = cap.green_field;
- ht_info->max_amsdu_size = cap.maximal_amsdu_size;
- ht_info->supported_chan_width = cap.supported_chan_width_set;
- ht_info->tx_mimo_ps_mode = cap.mimo_power_save_mode;
- memcpy(ht_info->supp_rates, ht_cap->supported_mcs_set, 16);
-
- ht_info->ampdu_factor = param_info.max_rx_ampdu_factor;
- ht_info->mpdu_density = param_info.mpdu_density;
-
- IWL_DEBUG_MAC80211("SISO mask 0x%X MIMO mask 0x%X \n",
- ht_cap->supported_mcs_set[0],
- ht_cap->supported_mcs_set[1]);
-
- if (ht_info_ap) {
- ht_info->control_channel = ht_info_ap->control_channel;
- ht_info->extension_chan_offset =
- ht_info_ap->extension_chan_offset;
- ht_info->tx_chan_width = ht_info_ap->tx_chan_width;
- ht_info->operating_mode = ht_info_ap->operating_mode;
- }
-
- if (ht_extra) {
- extra_param_info.val = ht_extra->ht_param;
- ht_info->control_channel = ht_extra->control_chan;
- ht_info->extension_chan_offset =
- extra_param_info.ext_chan_offset;
- ht_info->tx_chan_width = extra_param_info.tx_chan_width;
- op_mode.val = (u16)
- le16_to_cpu(ht_extra->operation_mode);
- ht_info->operating_mode = op_mode.op_mode;
- IWL_DEBUG_MAC80211("control channel %d\n",
- ht_extra->control_chan);
- }
- } else
- ht_info->is_ht = 0;
-
+ iwl_conf->is_ht = 1;
+ priv->ps_mode = (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+
+ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
+ iwl_conf->sgf |= 0x1;
+ if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
+ iwl_conf->sgf |= 0x2;
+
+ iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD);
+ iwl_conf->max_amsdu_size =
+ !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
+ iwl_conf->supported_chan_width =
+ !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
+ iwl_conf->tx_mimo_ps_mode =
+ (u8)((ht_conf->cap & IEEE80211_HT_CAP_MIMO_PS) >> 2);
+ memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
+
+ iwl_conf->control_channel = ht_bss_conf->primary_channel;
+ iwl_conf->extension_chan_offset =
+ ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
+ iwl_conf->tx_chan_width =
+ !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
+ iwl_conf->ht_protection =
+ ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
+ iwl_conf->non_GF_STA_present =
+ !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
+
+ IWL_DEBUG_MAC80211("control channel %d\n",
+ iwl_conf->control_channel);
IWL_DEBUG_MAC80211("leave\n");
- return 0;
}
-static int iwl_mac_conf_ht(struct ieee80211_hw *hw,
- struct ieee80211_ht_capability *ht_cap,
- struct ieee80211_ht_additional_info *ht_extra)
+static int iwl4965_mac_conf_ht(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
{
- struct iwl_priv *priv = hw->priv;
- int rs;
+ struct iwl4965_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter: \n");
- rs = sta_ht_info_init(ht_cap, ht_extra, NULL, &priv->current_assoc_ht);
+ iwl4965_ht_info_fill(conf, priv);
iwl4965_set_rxon_chain(priv);
if (priv && priv->assoc_id &&
@@ -8159,58 +8245,33 @@ static int iwl_mac_conf_ht(struct ieee80211_hw *hw,
spin_unlock_irqrestore(&priv->lock, flags);
}
- IWL_DEBUG_MAC80211("leave: control channel %d\n",
- ht_extra->control_chan);
- return rs;
-
+ IWL_DEBUG_MAC80211("leave:\n");
+ return 0;
}
-static void iwl_set_ht_capab(struct ieee80211_hw *hw,
- struct ieee80211_ht_capability *ht_cap,
- u8 use_wide_chan)
+static void iwl4965_set_ht_capab(struct ieee80211_hw *hw,
+ struct ieee80211_ht_cap *ht_cap,
+ u8 use_current_config)
{
- union ht_cap_info cap;
- union ht_param_info param_info;
-
- memset(&cap, 0, sizeof(union ht_cap_info));
- memset(&param_info, 0, sizeof(union ht_param_info));
-
- cap.maximal_amsdu_size = HT_IE_MAX_AMSDU_SIZE_4K;
- cap.green_field = 1;
- cap.short_GI20 = 1;
- cap.short_GI40 = 1;
- cap.supported_chan_width_set = use_wide_chan;
- cap.mimo_power_save_mode = 0x3;
-
- param_info.max_rx_ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
- param_info.mpdu_density = CFG_HT_MPDU_DENSITY_DEF;
- ht_cap->capabilities_info = (__le16) cpu_to_le16(cap.val);
- ht_cap->mac_ht_params_info = (u8) param_info.val;
+ struct ieee80211_conf *conf = &hw->conf;
+ struct ieee80211_hw_mode *mode = conf->mode;
- ht_cap->supported_mcs_set[0] = 0xff;
- ht_cap->supported_mcs_set[1] = 0xff;
- ht_cap->supported_mcs_set[4] =
- (cap.supported_chan_width_set) ? 0x1: 0x0;
+ if (use_current_config) {
+ ht_cap->cap_info = cpu_to_le16(conf->ht_conf.cap);
+ memcpy(ht_cap->supp_mcs_set,
+ conf->ht_conf.supp_mcs_set, 16);
+ } else {
+ ht_cap->cap_info = cpu_to_le16(mode->ht_info.cap);
+ memcpy(ht_cap->supp_mcs_set,
+ mode->ht_info.supp_mcs_set, 16);
+ }
+ ht_cap->ampdu_params_info =
+ (mode->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
+ ((mode->ht_info.ampdu_density << 2) &
+ IEEE80211_HT_CAP_AMPDU_DENSITY);
}
-static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw,
- struct ieee80211_ht_capability *ht_cap)
-{
- u8 use_wide_channel = 1;
- struct iwl_priv *priv = hw->priv;
-
- IWL_DEBUG_MAC80211("enter: \n");
- if (priv->channel_width != IWL_CHANNEL_WIDTH_40MHZ)
- use_wide_channel = 0;
-
- /* no fat tx allowed on 2.4GHZ */
- if (priv->phymode != MODE_IEEE80211A)
- use_wide_channel = 0;
-
- iwl_set_ht_capab(hw, ht_cap, use_wide_channel);
- IWL_DEBUG_MAC80211("leave: \n");
-}
-#endif /*CONFIG_IWLWIFI_HT*/
+#endif /*CONFIG_IWL4965_HT*/
/*****************************************************************************
*
@@ -8218,7 +8279,7 @@ static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw,
*
*****************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUG
+#ifdef CONFIG_IWL4965_DEBUG
/*
* The following adds a new attribute to the sysfs representation
@@ -8230,7 +8291,7 @@ static void iwl_mac_get_ht_capab(struct ieee80211_hw *hw,
static ssize_t show_debug_level(struct device_driver *d, char *buf)
{
- return sprintf(buf, "0x%08X\n", iwl_debug_level);
+ return sprintf(buf, "0x%08X\n", iwl4965_debug_level);
}
static ssize_t store_debug_level(struct device_driver *d,
const char *buf, size_t count)
@@ -8243,7 +8304,7 @@ static ssize_t store_debug_level(struct device_driver *d,
printk(KERN_INFO DRV_NAME
": %s is not in hex or decimal form.\n", buf);
else
- iwl_debug_level = val;
+ iwl4965_debug_level = val;
return strnlen(buf, count);
}
@@ -8251,7 +8312,7 @@ static ssize_t store_debug_level(struct device_driver *d,
static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO,
show_debug_level, store_debug_level);
-#endif /* CONFIG_IWLWIFI_DEBUG */
+#endif /* CONFIG_IWL4965_DEBUG */
static ssize_t show_rf_kill(struct device *d,
struct device_attribute *attr, char *buf)
@@ -8262,7 +8323,7 @@ static ssize_t show_rf_kill(struct device *d,
* 2 - HW based RF kill active
* 3 - Both HW and SW based RF kill active
*/
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
int val = (test_bit(STATUS_RF_KILL_SW, &priv->status) ? 0x1 : 0x0) |
(test_bit(STATUS_RF_KILL_HW, &priv->status) ? 0x2 : 0x0);
@@ -8273,10 +8334,10 @@ static ssize_t store_rf_kill(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
mutex_lock(&priv->mutex);
- iwl_radio_kill_sw(priv, buf[0] == '1');
+ iwl4965_radio_kill_sw(priv, buf[0] == '1');
mutex_unlock(&priv->mutex);
return count;
@@ -8287,12 +8348,12 @@ static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill);
static ssize_t show_temperature(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
- if (!iwl_is_alive(priv))
+ if (!iwl4965_is_alive(priv))
return -EAGAIN;
- return sprintf(buf, "%d\n", iwl_hw_get_temperature(priv));
+ return sprintf(buf, "%d\n", iwl4965_hw_get_temperature(priv));
}
static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
@@ -8301,15 +8362,15 @@ static ssize_t show_rs_window(struct device *d,
struct device_attribute *attr,
char *buf)
{
- struct iwl_priv *priv = d->driver_data;
- return iwl_fill_rs_info(priv->hw, buf, IWL_AP_ID);
+ struct iwl4965_priv *priv = d->driver_data;
+ return iwl4965_fill_rs_info(priv->hw, buf, IWL_AP_ID);
}
static DEVICE_ATTR(rs_window, S_IRUGO, show_rs_window, NULL);
static ssize_t show_tx_power(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
return sprintf(buf, "%d\n", priv->user_txpower_limit);
}
@@ -8317,7 +8378,7 @@ static ssize_t store_tx_power(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
char *p = (char *)buf;
u32 val;
@@ -8326,7 +8387,7 @@ static ssize_t store_tx_power(struct device *d,
printk(KERN_INFO DRV_NAME
": %s is not in decimal form.\n", buf);
else
- iwl_hw_reg_set_txpower(priv, val);
+ iwl4965_hw_reg_set_txpower(priv, val);
return count;
}
@@ -8336,7 +8397,7 @@ static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
static ssize_t show_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n", priv->active_rxon.flags);
}
@@ -8345,19 +8406,19 @@ static ssize_t store_flags(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
u32 flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.flags) != flags) {
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl4965_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing rxon.flags = 0x%04X\n",
flags);
priv->staging_rxon.flags = cpu_to_le32(flags);
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -8370,7 +8431,7 @@ static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
static ssize_t show_filter_flags(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n",
le32_to_cpu(priv->active_rxon.filter_flags));
@@ -8380,20 +8441,20 @@ static ssize_t store_filter_flags(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
u32 filter_flags = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) {
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl4965_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing rxon.filter_flags = "
"0x%04X\n", filter_flags);
priv->staging_rxon.filter_flags =
cpu_to_le32(filter_flags);
- iwl_commit_rxon(priv);
+ iwl4965_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -8407,20 +8468,20 @@ static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
static ssize_t show_tune(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
return sprintf(buf, "0x%04X\n",
(priv->phymode << 8) |
le16_to_cpu(priv->active_rxon.channel));
}
-static void iwl_set_flags_for_phymode(struct iwl_priv *priv, u8 phymode);
+static void iwl4965_set_flags_for_phymode(struct iwl4965_priv *priv, u8 phymode);
static ssize_t store_tune(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
char *p = (char *)buf;
u16 tune = simple_strtoul(p, &p, 0);
u8 phymode = (tune >> 8) & 0xff;
@@ -8431,9 +8492,9 @@ static ssize_t store_tune(struct device *d,
mutex_lock(&priv->mutex);
if ((le16_to_cpu(priv->staging_rxon.channel) != channel) ||
(priv->phymode != phymode)) {
- const struct iwl_channel_info *ch_info;
+ const struct iwl4965_channel_info *ch_info;
- ch_info = iwl_get_channel_info(priv, phymode, channel);
+ ch_info = iwl4965_get_channel_info(priv, phymode, channel);
if (!ch_info) {
IWL_WARNING("Requested invalid phymode/channel "
"combination: %d %d\n", phymode, channel);
@@ -8442,18 +8503,18 @@ static ssize_t store_tune(struct device *d,
}
/* Cancel any currently running scans... */
- if (iwl_scan_cancel_timeout(priv, 100))
+ if (iwl4965_scan_cancel_timeout(priv, 100))
IWL_WARNING("Could not cancel scan.\n");
else {
IWL_DEBUG_INFO("Committing phymode and "
"rxon.channel = %d %d\n",
phymode, channel);
- iwl_set_rxon_channel(priv, phymode, channel);
- iwl_set_flags_for_phymode(priv, phymode);
+ iwl4965_set_rxon_channel(priv, phymode, channel);
+ iwl4965_set_flags_for_phymode(priv, phymode);
- iwl_set_rate(priv);
- iwl_commit_rxon(priv);
+ iwl4965_set_rate(priv);
+ iwl4965_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -8463,13 +8524,13 @@ static ssize_t store_tune(struct device *d,
static DEVICE_ATTR(tune, S_IWUSR | S_IRUGO, show_tune, store_tune);
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
static ssize_t show_measurement(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl_spectrum_notification measure_report;
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_spectrum_notification measure_report;
u32 size = sizeof(measure_report), len = 0, ofs = 0;
u8 *data = (u8 *) & measure_report;
unsigned long flags;
@@ -8501,7 +8562,7 @@ static ssize_t store_measurement(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
struct ieee80211_measurement_params params = {
.channel = le16_to_cpu(priv->active_rxon.channel),
.start_time = cpu_to_le64(priv->last_tsf),
@@ -8527,20 +8588,20 @@ static ssize_t store_measurement(struct device *d,
IWL_DEBUG_INFO("Invoking measurement of type %d on "
"channel %d (for '%s')\n", type, params.channel, buf);
- iwl_get_measurement(priv, &params, type);
+ iwl4965_get_measurement(priv, &params, type);
return count;
}
static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
show_measurement, store_measurement);
-#endif /* CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT */
+#endif /* CONFIG_IWL4965_SPECTRUM_MEASUREMENT */
static ssize_t store_retry_rate(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
priv->retry_rate = simple_strtoul(buf, NULL, 0);
if (priv->retry_rate <= 0)
@@ -8552,7 +8613,7 @@ static ssize_t store_retry_rate(struct device *d,
static ssize_t show_retry_rate(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
return sprintf(buf, "%d", priv->retry_rate);
}
@@ -8563,14 +8624,14 @@ static ssize_t store_power_level(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
int rc;
int mode;
mode = simple_strtoul(buf, NULL, 0);
mutex_lock(&priv->mutex);
- if (!iwl_is_ready(priv)) {
+ if (!iwl4965_is_ready(priv)) {
rc = -EAGAIN;
goto out;
}
@@ -8581,7 +8642,7 @@ static ssize_t store_power_level(struct device *d,
mode |= IWL_POWER_ENABLED;
if (mode != priv->power_mode) {
- rc = iwl_send_power_mode(priv, IWL_POWER_LEVEL(mode));
+ rc = iwl4965_send_power_mode(priv, IWL_POWER_LEVEL(mode));
if (rc) {
IWL_DEBUG_MAC80211("failed setting power mode.\n");
goto out;
@@ -8617,7 +8678,7 @@ static const s32 period_duration[] = {
static ssize_t show_power_level(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
int level = IWL_POWER_LEVEL(priv->power_mode);
char *p = buf;
@@ -8652,18 +8713,18 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
static ssize_t show_channels(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
int len = 0, i;
struct ieee80211_channel *channels = NULL;
const struct ieee80211_hw_mode *hw_mode = NULL;
int count = 0;
- if (!iwl_is_ready(priv))
+ if (!iwl4965_is_ready(priv))
return -EAGAIN;
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211G);
+ hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211G);
if (!hw_mode)
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211B);
+ hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211B);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
@@ -8690,7 +8751,7 @@ static ssize_t show_channels(struct device *d,
flag & IEEE80211_CHAN_W_ACTIVE_SCAN ?
"active/passive" : "passive only");
- hw_mode = iwl_get_hw_mode(priv, MODE_IEEE80211A);
+ hw_mode = iwl4965_get_hw_mode(priv, MODE_IEEE80211A);
if (hw_mode) {
channels = hw_mode->channels;
count = hw_mode->num_channels;
@@ -8726,17 +8787,17 @@ static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
- u32 size = sizeof(struct iwl_notif_statistics);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
+ u32 size = sizeof(struct iwl4965_notif_statistics);
u32 len = 0, ofs = 0;
u8 *data = (u8 *) & priv->statistics;
int rc = 0;
- if (!iwl_is_alive(priv))
+ if (!iwl4965_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
- rc = iwl_send_statistics_request(priv);
+ rc = iwl4965_send_statistics_request(priv);
mutex_unlock(&priv->mutex);
if (rc) {
@@ -8764,9 +8825,9 @@ static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL);
static ssize_t show_antenna(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
- if (!iwl_is_alive(priv))
+ if (!iwl4965_is_alive(priv))
return -EAGAIN;
return sprintf(buf, "%d\n", priv->antenna);
@@ -8777,7 +8838,7 @@ static ssize_t store_antenna(struct device *d,
const char *buf, size_t count)
{
int ant;
- struct iwl_priv *priv = dev_get_drvdata(d);
+ struct iwl4965_priv *priv = dev_get_drvdata(d);
if (count == 0)
return 0;
@@ -8789,7 +8850,7 @@ static ssize_t store_antenna(struct device *d,
if ((ant >= 0) && (ant <= 2)) {
IWL_DEBUG_INFO("Setting antenna select to %d.\n", ant);
- priv->antenna = (enum iwl_antenna)ant;
+ priv->antenna = (enum iwl4965_antenna)ant;
} else
IWL_DEBUG_INFO("Bad antenna select value %d.\n", ant);
@@ -8802,8 +8863,8 @@ static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
static ssize_t show_status(struct device *d,
struct device_attribute *attr, char *buf)
{
- struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- if (!iwl_is_alive(priv))
+ struct iwl4965_priv *priv = (struct iwl4965_priv *)d->driver_data;
+ if (!iwl4965_is_alive(priv))
return -EAGAIN;
return sprintf(buf, "0x%08x\n", (int)priv->status);
}
@@ -8817,7 +8878,7 @@ static ssize_t dump_error_log(struct device *d,
char *p = (char *)buf;
if (p[0] == '1')
- iwl_dump_nic_error_log((struct iwl_priv *)d->driver_data);
+ iwl4965_dump_nic_error_log((struct iwl4965_priv *)d->driver_data);
return strnlen(buf, count);
}
@@ -8831,7 +8892,7 @@ static ssize_t dump_event_log(struct device *d,
char *p = (char *)buf;
if (p[0] == '1')
- iwl_dump_nic_event_log((struct iwl_priv *)d->driver_data);
+ iwl4965_dump_nic_event_log((struct iwl4965_priv *)d->driver_data);
return strnlen(buf, count);
}
@@ -8844,34 +8905,34 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
*
*****************************************************************************/
-static void iwl_setup_deferred_work(struct iwl_priv *priv)
+static void iwl4965_setup_deferred_work(struct iwl4965_priv *priv)
{
priv->workqueue = create_workqueue(DRV_NAME);
init_waitqueue_head(&priv->wait_command_queue);
- INIT_WORK(&priv->up, iwl_bg_up);
- INIT_WORK(&priv->restart, iwl_bg_restart);
- INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
- INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed);
- INIT_WORK(&priv->request_scan, iwl_bg_request_scan);
- INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan);
- INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
- INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
- INIT_DELAYED_WORK(&priv->post_associate, iwl_bg_post_associate);
- INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
- INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
- INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
-
- iwl_hw_setup_deferred_work(priv);
+ INIT_WORK(&priv->up, iwl4965_bg_up);
+ INIT_WORK(&priv->restart, iwl4965_bg_restart);
+ INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
+ INIT_WORK(&priv->scan_completed, iwl4965_bg_scan_completed);
+ INIT_WORK(&priv->request_scan, iwl4965_bg_request_scan);
+ INIT_WORK(&priv->abort_scan, iwl4965_bg_abort_scan);
+ INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
+ INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
+ INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
+ INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
+ INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
+ INIT_DELAYED_WORK(&priv->scan_check, iwl4965_bg_scan_check);
+
+ iwl4965_hw_setup_deferred_work(priv);
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
- iwl_irq_tasklet, (unsigned long)priv);
+ iwl4965_irq_tasklet, (unsigned long)priv);
}
-static void iwl_cancel_deferred_work(struct iwl_priv *priv)
+static void iwl4965_cancel_deferred_work(struct iwl4965_priv *priv)
{
- iwl_hw_cancel_deferred_work(priv);
+ iwl4965_hw_cancel_deferred_work(priv);
cancel_delayed_work_sync(&priv->init_alive_start);
cancel_delayed_work(&priv->scan_check);
@@ -8880,14 +8941,14 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
cancel_work_sync(&priv->beacon_update);
}
-static struct attribute *iwl_sysfs_entries[] = {
+static struct attribute *iwl4965_sysfs_entries[] = {
&dev_attr_antenna.attr,
&dev_attr_channels.attr,
&dev_attr_dump_errors.attr,
&dev_attr_dump_events.attr,
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
-#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT
+#ifdef CONFIG_IWL4965_SPECTRUM_MEASUREMENT
&dev_attr_measurement.attr,
#endif
&dev_attr_power_level.attr,
@@ -8903,54 +8964,56 @@ static struct attribute *iwl_sysfs_entries[] = {
NULL
};
-static struct attribute_group iwl_attribute_group = {
+static struct attribute_group iwl4965_attribute_group = {
.name = NULL, /* put in device directory */
- .attrs = iwl_sysfs_entries,
+ .attrs = iwl4965_sysfs_entries,
};
-static struct ieee80211_ops iwl_hw_ops = {
- .tx = iwl_mac_tx,
- .start = iwl_mac_start,
- .stop = iwl_mac_stop,
- .add_interface = iwl_mac_add_interface,
- .remove_interface = iwl_mac_remove_interface,
- .config = iwl_mac_config,
- .config_interface = iwl_mac_config_interface,
- .configure_filter = iwl_configure_filter,
- .set_key = iwl_mac_set_key,
- .get_stats = iwl_mac_get_stats,
- .get_tx_stats = iwl_mac_get_tx_stats,
- .conf_tx = iwl_mac_conf_tx,
- .get_tsf = iwl_mac_get_tsf,
- .reset_tsf = iwl_mac_reset_tsf,
- .beacon_update = iwl_mac_beacon_update,
-#ifdef CONFIG_IWLWIFI_HT
- .conf_ht = iwl_mac_conf_ht,
- .get_ht_capab = iwl_mac_get_ht_capab,
-#ifdef CONFIG_IWLWIFI_HT_AGG
- .ht_tx_agg_start = iwl_mac_ht_tx_agg_start,
- .ht_tx_agg_stop = iwl_mac_ht_tx_agg_stop,
- .ht_rx_agg_start = iwl_mac_ht_rx_agg_start,
- .ht_rx_agg_stop = iwl_mac_ht_rx_agg_stop,
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
- .hw_scan = iwl_mac_hw_scan
+static struct ieee80211_ops iwl4965_hw_ops = {
+ .tx = iwl4965_mac_tx,
+ .start = iwl4965_mac_start,
+ .stop = iwl4965_mac_stop,
+ .add_interface = iwl4965_mac_add_interface,
+ .remove_interface = iwl4965_mac_remove_interface,
+ .config = iwl4965_mac_config,
+ .config_interface = iwl4965_mac_config_interface,
+ .configure_filter = iwl4965_configure_filter,
+ .set_key = iwl4965_mac_set_key,
+ .get_stats = iwl4965_mac_get_stats,
+ .get_tx_stats = iwl4965_mac_get_tx_stats,
+ .conf_tx = iwl4965_mac_conf_tx,
+ .get_tsf = iwl4965_mac_get_tsf,
+ .reset_tsf = iwl4965_mac_reset_tsf,
+ .beacon_update = iwl4965_mac_beacon_update,
+ .bss_info_changed = iwl4965_bss_info_changed,
+#ifdef CONFIG_IWL4965_HT
+ .conf_ht = iwl4965_mac_conf_ht,
+ .ampdu_action = iwl4965_mac_ampdu_action,
+#ifdef CONFIG_IWL4965_HT_AGG
+ .ht_tx_agg_start = iwl4965_mac_ht_tx_agg_start,
+ .ht_tx_agg_stop = iwl4965_mac_ht_tx_agg_stop,
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
+ .hw_scan = iwl4965_mac_hw_scan
};
-static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int err = 0;
- struct iwl_priv *priv;
+ struct iwl4965_priv *priv;
struct ieee80211_hw *hw;
int i;
+ DECLARE_MAC_BUF(mac);
- if (iwl_param_disable_hw_scan) {
+ /* Disabling hardware scan means that mac80211 will perform scans
+ * "the hard way", rather than using device's scan. */
+ if (iwl4965_param_disable_hw_scan) {
IWL_DEBUG_INFO("Disabling hw_scan\n");
- iwl_hw_ops.hw_scan = NULL;
+ iwl4965_hw_ops.hw_scan = NULL;
}
- if ((iwl_param_queues_num > IWL_MAX_NUM_QUEUES) ||
- (iwl_param_queues_num < IWL_MIN_NUM_QUEUES)) {
+ if ((iwl4965_param_queues_num > IWL_MAX_NUM_QUEUES) ||
+ (iwl4965_param_queues_num < IWL_MIN_NUM_QUEUES)) {
IWL_ERROR("invalid queues_num, should be between %d and %d\n",
IWL_MIN_NUM_QUEUES, IWL_MAX_NUM_QUEUES);
err = -EINVAL;
@@ -8959,7 +9022,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* mac80211 allocates memory for this device instance, including
* space for this driver's private structure */
- hw = ieee80211_alloc_hw(sizeof(struct iwl_priv), &iwl_hw_ops);
+ hw = ieee80211_alloc_hw(sizeof(struct iwl4965_priv), &iwl4965_hw_ops);
if (hw == NULL) {
IWL_ERROR("Can not allocate network device\n");
err = -ENOMEM;
@@ -8974,9 +9037,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->hw = hw;
priv->pci_dev = pdev;
- priv->antenna = (enum iwl_antenna)iwl_param_antenna;
-#ifdef CONFIG_IWLWIFI_DEBUG
- iwl_debug_level = iwl_param_debug;
+ priv->antenna = (enum iwl4965_antenna)iwl4965_param_antenna;
+#ifdef CONFIG_IWL4965_DEBUG
+ iwl4965_debug_level = iwl4965_param_debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
priv->retry_rate = 1;
@@ -8995,12 +9058,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Tell mac80211 our Tx characteristics */
hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
+ /* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
+#ifdef CONFIG_IWL4965_HT
+#ifdef CONFIG_IWL4965_HT_AGG
+ /* Enhanced value; more queues, to support 11n aggregation */
hw->queues = 16;
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
+#endif /* CONFIG_IWL4965_HT_AGG */
+#endif /* CONFIG_IWL4965_HT */
spin_lock_init(&priv->lock);
spin_lock_init(&priv->power_data.lock);
@@ -9021,7 +9086,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
- iwl_clear_stations_table(priv);
+ /* Clear the driver's (not device's) station table */
+ iwl4965_clear_stations_table(priv);
priv->data_retry_limit = -1;
priv->ieee_channels = NULL;
@@ -9040,9 +9106,11 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = pci_request_regions(pdev, DRV_NAME);
if (err)
goto out_pci_disable_device;
+
/* We disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, 0x41, 0x00);
+
priv->hw_base = pci_iomap(pdev, 0, 0);
if (!priv->hw_base) {
err = -ENODEV;
@@ -9055,7 +9123,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Initialize module parameter values here */
- if (iwl_param_disable) {
+ /* Disable radio (SW RF KILL) via parameter when loading driver */
+ if (iwl4965_param_disable) {
set_bit(STATUS_RF_KILL_SW, &priv->status);
IWL_DEBUG_INFO("Radio disabled.\n");
}
@@ -9064,91 +9133,92 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
priv->ps_mode = 0;
priv->use_ant_b_for_management_frame = 1; /* start with ant B */
- priv->is_ht_enabled = 1;
- priv->channel_width = IWL_CHANNEL_WIDTH_40MHZ;
priv->valid_antenna = 0x7; /* assume all 3 connected */
priv->ps_mode = IWL_MIMO_PS_NONE;
- priv->cck_power_index_compensation = iwl_read32(
- priv, CSR_HW_REV_WA_REG);
+ /* Choose which receivers/antennas to use */
iwl4965_set_rxon_chain(priv);
printk(KERN_INFO DRV_NAME
": Detected Intel Wireless WiFi Link 4965AGN\n");
/* Device-specific setup */
- if (iwl_hw_set_hw_setting(priv)) {
+ if (iwl4965_hw_set_hw_setting(priv)) {
IWL_ERROR("failed to set hw settings\n");
- mutex_unlock(&priv->mutex);
goto out_iounmap;
}
-#ifdef CONFIG_IWLWIFI_QOS
- if (iwl_param_qos_enable)
+#ifdef CONFIG_IWL4965_QOS
+ if (iwl4965_param_qos_enable)
priv->qos_data.qos_enable = 1;
- iwl_reset_qos(priv);
+ iwl4965_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
-#endif /* CONFIG_IWLWIFI_QOS */
+#endif /* CONFIG_IWL4965_QOS */
- iwl_set_rxon_channel(priv, MODE_IEEE80211G, 6);
- iwl_setup_deferred_work(priv);
- iwl_setup_rx_handlers(priv);
+ iwl4965_set_rxon_channel(priv, MODE_IEEE80211G, 6);
+ iwl4965_setup_deferred_work(priv);
+ iwl4965_setup_rx_handlers(priv);
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
- pci_enable_msi(pdev);
-
- err = request_irq(pdev->irq, iwl_isr, IRQF_SHARED, DRV_NAME, priv);
- if (err) {
- IWL_ERROR("Error allocating IRQ %d\n", pdev->irq);
- goto out_disable_msi;
- }
-
- mutex_lock(&priv->mutex);
+ iwl4965_disable_interrupts(priv);
- err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
if (err) {
IWL_ERROR("failed to create sysfs device attributes\n");
- mutex_unlock(&priv->mutex);
goto out_release_irq;
}
- /* fetch ucode file from disk, alloc and copy to bus-master buffers ...
- * ucode filename and max sizes are card-specific. */
- err = iwl_read_ucode(priv);
+ /* nic init */
+ iwl4965_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+ iwl4965_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ err = iwl4965_poll_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ goto out_remove_sysfs;
+ }
+ /* Read the EEPROM */
+ err = iwl4965_eeprom_init(priv);
if (err) {
- IWL_ERROR("Could not read microcode: %d\n", err);
- mutex_unlock(&priv->mutex);
- goto out_pci_alloc;
+ IWL_ERROR("Unable to init EEPROM\n");
+ goto out_remove_sysfs;
}
+ /* MAC Address location in EEPROM same for 3945/4965 */
+ get_eeprom_mac(priv, priv->mac_addr);
+ IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
- mutex_unlock(&priv->mutex);
-
- IWL_DEBUG_INFO("Queing UP work.\n");
+ iwl4965_rate_control_register(priv->hw);
+ err = ieee80211_register_hw(priv->hw);
+ if (err) {
+ IWL_ERROR("Failed to register network device (error %d)\n", err);
+ goto out_remove_sysfs;
+ }
- queue_work(priv->workqueue, &priv->up);
+ priv->hw->conf.beacon_int = 100;
+ priv->mac80211_registered = 1;
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
return 0;
- out_pci_alloc:
- iwl_dealloc_ucode_pci(priv);
-
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ out_remove_sysfs:
+ sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
out_release_irq:
- free_irq(pdev->irq, priv);
-
- out_disable_msi:
- pci_disable_msi(pdev);
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- iwl_unset_hw_setting(priv);
+ iwl4965_unset_hw_setting(priv);
out_iounmap:
pci_iounmap(pdev, priv->hw_base);
@@ -9163,9 +9233,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
return err;
}
-static void iwl_pci_remove(struct pci_dev *pdev)
+static void iwl4965_pci_remove(struct pci_dev *pdev)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct iwl4965_priv *priv = pci_get_drvdata(pdev);
struct list_head *p, *q;
int i;
@@ -9176,43 +9246,41 @@ static void iwl_pci_remove(struct pci_dev *pdev)
set_bit(STATUS_EXIT_PENDING, &priv->status);
- iwl_down(priv);
+ iwl4965_down(priv);
/* Free MAC hash list for ADHOC */
for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
list_del(p);
- kfree(list_entry(p, struct iwl_ibss_seq, list));
+ kfree(list_entry(p, struct iwl4965_ibss_seq, list));
}
}
- sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+ sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
- iwl_dealloc_ucode_pci(priv);
+ iwl4965_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
- iwl_rx_queue_free(priv, &priv->rxq);
- iwl_hw_txq_ctx_free(priv);
+ iwl4965_rx_queue_free(priv, &priv->rxq);
+ iwl4965_hw_txq_ctx_free(priv);
- iwl_unset_hw_setting(priv);
- iwl_clear_stations_table(priv);
+ iwl4965_unset_hw_setting(priv);
+ iwl4965_clear_stations_table(priv);
if (priv->mac80211_registered) {
ieee80211_unregister_hw(priv->hw);
- iwl_rate_control_unregister(priv->hw);
+ iwl4965_rate_control_unregister(priv->hw);
}
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
- /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
+ /* ieee80211_unregister_hw calls iwl4965_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */
destroy_workqueue(priv->workqueue);
priv->workqueue = NULL;
- free_irq(pdev->irq, priv);
- pci_disable_msi(pdev);
pci_iounmap(pdev, priv->hw_base);
pci_release_regions(pdev);
pci_disable_device(pdev);
@@ -9231,93 +9299,31 @@ static void iwl_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
+ struct iwl4965_priv *priv = pci_get_drvdata(pdev);
- set_bit(STATUS_IN_SUSPEND, &priv->status);
-
- /* Take down the device; powers it off, etc. */
- iwl_down(priv);
-
- if (priv->mac80211_registered)
- ieee80211_stop_queues(priv->hw);
+ if (priv->is_open) {
+ set_bit(STATUS_IN_SUSPEND, &priv->status);
+ iwl4965_mac_stop(priv->hw);
+ priv->is_open = 1;
+ }
- pci_save_state(pdev);
- pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
return 0;
}
-static void iwl_resume(struct iwl_priv *priv)
+static int iwl4965_pci_resume(struct pci_dev *pdev)
{
- unsigned long flags;
-
- /* The following it a temporary work around due to the
- * suspend / resume not fully initializing the NIC correctly.
- * Without all of the following, resume will not attempt to take
- * down the NIC (it shouldn't really need to) and will just try
- * and bring the NIC back up. However that fails during the
- * ucode verification process. This then causes iwl_down to be
- * called *after* iwl_hw_nic_init() has succeeded -- which
- * then lets the next init sequence succeed. So, we've
- * replicated all of that NIC init code here... */
-
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
- iwl_hw_nic_init(priv);
-
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
- iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
- iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
- /* tell the device to stop sending interrupts */
- iwl_disable_interrupts(priv);
-
- spin_lock_irqsave(&priv->lock, flags);
- iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
- if (!iwl_grab_restricted_access(priv)) {
- iwl_write_restricted_reg(priv, APMG_CLK_DIS_REG,
- APMG_CLK_VAL_DMA_CLK_RQT);
- iwl_release_restricted_access(priv);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
-
- udelay(5);
-
- iwl_hw_nic_reset(priv);
-
- /* Bring the device back up */
- clear_bit(STATUS_IN_SUSPEND, &priv->status);
- queue_work(priv->workqueue, &priv->up);
-}
-
-static int iwl_pci_resume(struct pci_dev *pdev)
-{
- struct iwl_priv *priv = pci_get_drvdata(pdev);
- int err;
-
- printk(KERN_INFO "Coming out of suspend...\n");
+ struct iwl4965_priv *priv = pci_get_drvdata(pdev);
pci_set_power_state(pdev, PCI_D0);
- err = pci_enable_device(pdev);
- pci_restore_state(pdev);
-
- /*
- * Suspend/Resume resets the PCI configuration space, so we have to
- * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries
- * from interfering with C3 CPU state. pci_restore_state won't help
- * here since it only restores the first 64 bytes pci config header.
- */
- pci_write_config_byte(pdev, 0x41, 0x00);
- iwl_resume(priv);
+ if (priv->is_open)
+ iwl4965_mac_start(priv->hw);
+ clear_bit(STATUS_IN_SUSPEND, &priv->status);
return 0;
}
@@ -9329,33 +9335,33 @@ static int iwl_pci_resume(struct pci_dev *pdev)
*
*****************************************************************************/
-static struct pci_driver iwl_driver = {
+static struct pci_driver iwl4965_driver = {
.name = DRV_NAME,
- .id_table = iwl_hw_card_ids,
- .probe = iwl_pci_probe,
- .remove = __devexit_p(iwl_pci_remove),
+ .id_table = iwl4965_hw_card_ids,
+ .probe = iwl4965_pci_probe,
+ .remove = __devexit_p(iwl4965_pci_remove),
#ifdef CONFIG_PM
- .suspend = iwl_pci_suspend,
- .resume = iwl_pci_resume,
+ .suspend = iwl4965_pci_suspend,
+ .resume = iwl4965_pci_resume,
#endif
};
-static int __init iwl_init(void)
+static int __init iwl4965_init(void)
{
int ret;
printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
- ret = pci_register_driver(&iwl_driver);
+ ret = pci_register_driver(&iwl4965_driver);
if (ret) {
IWL_ERROR("Unable to initialize PCI module\n");
return ret;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
- ret = driver_create_file(&iwl_driver.driver, &driver_attr_debug_level);
+#ifdef CONFIG_IWL4965_DEBUG
+ ret = driver_create_file(&iwl4965_driver.driver, &driver_attr_debug_level);
if (ret) {
IWL_ERROR("Unable to create driver sysfs file\n");
- pci_unregister_driver(&iwl_driver);
+ pci_unregister_driver(&iwl4965_driver);
return ret;
}
#endif
@@ -9363,32 +9369,34 @@ static int __init iwl_init(void)
return ret;
}
-static void __exit iwl_exit(void)
+static void __exit iwl4965_exit(void)
{
-#ifdef CONFIG_IWLWIFI_DEBUG
- driver_remove_file(&iwl_driver.driver, &driver_attr_debug_level);
+#ifdef CONFIG_IWL4965_DEBUG
+ driver_remove_file(&iwl4965_driver.driver, &driver_attr_debug_level);
#endif
- pci_unregister_driver(&iwl_driver);
+ pci_unregister_driver(&iwl4965_driver);
}
-module_param_named(antenna, iwl_param_antenna, int, 0444);
+module_param_named(antenna, iwl4965_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl_param_disable, int, 0444);
+module_param_named(disable, iwl4965_param_disable, int, 0444);
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
-module_param_named(hwcrypto, iwl_param_hwcrypto, int, 0444);
+module_param_named(hwcrypto, iwl4965_param_hwcrypto, int, 0444);
MODULE_PARM_DESC(hwcrypto,
"using hardware crypto engine (default 0 [software])\n");
-module_param_named(debug, iwl_param_debug, int, 0444);
+module_param_named(debug, iwl4965_param_debug, int, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
-module_param_named(disable_hw_scan, iwl_param_disable_hw_scan, int, 0444);
+module_param_named(disable_hw_scan, iwl4965_param_disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
-module_param_named(queues_num, iwl_param_queues_num, int, 0444);
+module_param_named(queues_num, iwl4965_param_queues_num, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
/* QoS */
-module_param_named(qos_enable, iwl_param_qos_enable, int, 0444);
+module_param_named(qos_enable, iwl4965_param_qos_enable, int, 0444);
MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
+module_param_named(amsdu_size_8K, iwl4965_param_amsdu_size_8K, int, 0444);
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
-module_exit(iwl_exit);
-module_init(iwl_init);
+module_exit(iwl4965_exit);
+module_init(iwl4965_init);
diff --git a/drivers/net/wireless/iwlwifi/iwlwifi.h b/drivers/net/wireless/iwlwifi/iwlwifi.h
deleted file mode 100644
index 432ce887807f..000000000000
--- a/drivers/net/wireless/iwlwifi/iwlwifi.h
+++ /dev/null
@@ -1,708 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2007 Intel Corporation. All rights reserved.
- *
- * Portions of this file are derived from the ipw3945 project, as well
- * as portions of the ieee80211 subsystem header files.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
- *
- * The full GNU General Public License is included in this distribution in the
- * file called LICENSE.
- *
- * Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- *****************************************************************************/
-
-#ifndef __iwlwifi_h__
-#define __iwlwifi_h__
-
-#include <linux/pci.h> /* for struct pci_device_id */
-#include <linux/kernel.h>
-#include <net/ieee80211_radiotap.h>
-
-struct iwl_priv;
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-extern struct pci_device_id iwl_hw_card_ids[];
-
-#include "iwl-hw.h"
-#if IWL == 3945
-#define DRV_NAME "iwl3945"
-#include "iwl-3945-hw.h"
-#elif IWL == 4965
-#define DRV_NAME "iwl4965"
-#include "iwl-4965-hw.h"
-#endif
-
-#include "iwl-prph.h"
-
-/*
- * Driver implementation data structures, constants, inline
- * functions
- *
- * NOTE: DO NOT PUT HARDWARE/UCODE SPECIFIC DECLRATIONS HERE
- *
- * Hardware specific declrations go into iwl-*hw.h
- *
- */
-
-#include "iwl-debug.h"
-
-/* Default noise level to report when noise measurement is not available.
- * This may be because we're:
- * 1) Not associated (4965, no beacon statistics being sent to driver)
- * 2) Scanning (noise measurement does not apply to associated channel)
- * 3) Receiving CCK (3945 delivers noise info only for OFDM frames)
- * Use default noise value of -127 ... this is below the range of measurable
- * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
- * Also, -127 works better than 0 when averaging frames with/without
- * noise info (e.g. averaging might be done in app); measured dBm values are
- * always negative ... using a negative value as the default keeps all
- * averages within an s8's (used in some apps) range of negative values. */
-#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
-/* Module parameters accessible from iwl-*.c */
-extern int iwl_param_disable_hw_scan;
-extern int iwl_param_debug;
-extern int iwl_param_mode;
-extern int iwl_param_disable;
-extern int iwl_param_antenna;
-extern int iwl_param_hwcrypto;
-extern int iwl_param_qos_enable;
-extern int iwl_param_queues_num;
-
-enum iwl_antenna {
- IWL_ANTENNA_DIVERSITY,
- IWL_ANTENNA_MAIN,
- IWL_ANTENNA_AUX
-};
-
-/*
- * RTS threshold here is total size [2347] minus 4 FCS bytes
- * Per spec:
- * a value of 0 means RTS on all data/management packets
- * a value > max MSDU size means no RTS
- * else RTS for data/management frames where MPDU is larger
- * than RTS value.
- */
-#define DEFAULT_RTS_THRESHOLD 2347U
-#define MIN_RTS_THRESHOLD 0U
-#define MAX_RTS_THRESHOLD 2347U
-#define MAX_MSDU_SIZE 2304U
-#define MAX_MPDU_SIZE 2346U
-#define DEFAULT_BEACON_INTERVAL 100U
-#define DEFAULT_SHORT_RETRY_LIMIT 7U
-#define DEFAULT_LONG_RETRY_LIMIT 4U
-
-struct iwl_rx_mem_buffer {
- dma_addr_t dma_addr;
- struct sk_buff *skb;
- struct list_head list;
-};
-
-struct iwl_rt_rx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- __le64 rt_tsf; /* TSF */
- u8 rt_flags; /* radiotap packet flags */
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channelMHz; /* channel in MHz */
- __le16 rt_chbitmask; /* channel bitfield */
- s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
- s8 rt_dbmnoise;
- u8 rt_antenna; /* antenna number */
- u8 payload[0]; /* payload... */
-} __attribute__ ((packed));
-
-struct iwl_rt_tx_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- u8 rt_rate; /* rate in 500kb/s */
- __le16 rt_channel; /* channel in mHz */
- __le16 rt_chbitmask; /* channel bitfield */
- s8 rt_dbmsignal; /* signal in dBm, kluged to signed */
- u8 rt_antenna; /* antenna number */
- u8 payload[0]; /* payload... */
-} __attribute__ ((packed));
-
-/*
- * Generic queue structure
- *
- * Contains common data for Rx and Tx queues
- */
-struct iwl_queue {
- int n_bd; /* number of BDs in this queue */
- int first_empty; /* 1-st empty entry (index) host_w*/
- int last_used; /* last used entry (index) host_r*/
- dma_addr_t dma_addr; /* physical addr for BD's */
- int n_window; /* safe queue window */
- u32 id;
- int low_mark; /* low watermark, resume queue if free
- * space more than this */
- int high_mark; /* high watermark, stop queue if free
- * space less than this */
-} __attribute__ ((packed));
-
-#define MAX_NUM_OF_TBS (20)
-
-struct iwl_tx_info {
- struct ieee80211_tx_status status;
- struct sk_buff *skb[MAX_NUM_OF_TBS];
-};
-
-/**
- * struct iwl_tx_queue - Tx Queue for DMA
- * @need_update: need to update read/write index
- * @shed_retry: queue is HT AGG enabled
- *
- * Queue consists of circular buffer of BD's and required locking structures.
- */
-struct iwl_tx_queue {
- struct iwl_queue q;
- struct iwl_tfd_frame *bd;
- struct iwl_cmd *cmd;
- dma_addr_t dma_addr_cmd;
- struct iwl_tx_info *txb;
- int need_update;
- int sched_retry;
- int active;
-};
-
-#include "iwl-channel.h"
-
-#if IWL == 3945
-#include "iwl-3945-rs.h"
-#else
-#include "iwl-4965-rs.h"
-#endif
-
-#define IWL_TX_FIFO_AC0 0
-#define IWL_TX_FIFO_AC1 1
-#define IWL_TX_FIFO_AC2 2
-#define IWL_TX_FIFO_AC3 3
-#define IWL_TX_FIFO_HCCA_1 5
-#define IWL_TX_FIFO_HCCA_2 6
-#define IWL_TX_FIFO_NONE 7
-
-/* Minimum number of queues. MAX_NUM is defined in hw specific files */
-#define IWL_MIN_NUM_QUEUES 4
-
-/* Power management (not Tx power) structures */
-
-struct iwl_power_vec_entry {
- struct iwl_powertable_cmd cmd;
- u8 no_dtim;
-};
-#define IWL_POWER_RANGE_0 (0)
-#define IWL_POWER_RANGE_1 (1)
-
-#define IWL_POWER_MODE_CAM 0x00 /* Continuously Aware Mode, always on */
-#define IWL_POWER_INDEX_3 0x03
-#define IWL_POWER_INDEX_5 0x05
-#define IWL_POWER_AC 0x06
-#define IWL_POWER_BATTERY 0x07
-#define IWL_POWER_LIMIT 0x07
-#define IWL_POWER_MASK 0x0F
-#define IWL_POWER_ENABLED 0x10
-#define IWL_POWER_LEVEL(x) ((x) & IWL_POWER_MASK)
-
-struct iwl_power_mgr {
- spinlock_t lock;
- struct iwl_power_vec_entry pwr_range_0[IWL_POWER_AC];
- struct iwl_power_vec_entry pwr_range_1[IWL_POWER_AC];
- u8 active_index;
- u32 dtim_val;
-};
-
-#define IEEE80211_DATA_LEN 2304
-#define IEEE80211_4ADDR_LEN 30
-#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct iwl_frame {
- union {
- struct ieee80211_hdr frame;
- struct iwl_tx_beacon_cmd beacon;
- u8 raw[IEEE80211_FRAME_LEN];
- u8 cmd[360];
- } u;
- struct list_head list;
-};
-
-#define SEQ_TO_QUEUE(x) ((x >> 8) & 0xbf)
-#define QUEUE_TO_SEQ(x) ((x & 0xbf) << 8)
-#define SEQ_TO_INDEX(x) (x & 0xff)
-#define INDEX_TO_SEQ(x) (x & 0xff)
-#define SEQ_HUGE_FRAME (0x4000)
-#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-enum {
- /* CMD_SIZE_NORMAL = 0, */
- CMD_SIZE_HUGE = (1 << 0),
- /* CMD_SYNC = 0, */
- CMD_ASYNC = (1 << 1),
- /* CMD_NO_SKB = 0, */
- CMD_WANT_SKB = (1 << 2),
-};
-
-struct iwl_cmd;
-struct iwl_priv;
-
-struct iwl_cmd_meta {
- struct iwl_cmd_meta *source;
- union {
- struct sk_buff *skb;
- int (*callback)(struct iwl_priv *priv,
- struct iwl_cmd *cmd, struct sk_buff *skb);
- } __attribute__ ((packed)) u;
-
- /* The CMD_SIZE_HUGE flag bit indicates that the command
- * structure is stored at the end of the shared queue memory. */
- u32 flags;
-
-} __attribute__ ((packed));
-
-struct iwl_cmd {
- struct iwl_cmd_meta meta;
- struct iwl_cmd_header hdr;
- union {
- struct iwl_addsta_cmd addsta;
- struct iwl_led_cmd led;
- u32 flags;
- u8 val8;
- u16 val16;
- u32 val32;
- struct iwl_bt_cmd bt;
- struct iwl_rxon_time_cmd rxon_time;
- struct iwl_powertable_cmd powertable;
- struct iwl_qosparam_cmd qosparam;
- struct iwl_tx_cmd tx;
- struct iwl_tx_beacon_cmd tx_beacon;
- struct iwl_rxon_assoc_cmd rxon_assoc;
- u8 *indirect;
- u8 payload[360];
- } __attribute__ ((packed)) cmd;
-} __attribute__ ((packed));
-
-struct iwl_host_cmd {
- u8 id;
- u16 len;
- struct iwl_cmd_meta meta;
- const void *data;
-};
-
-#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_cmd) - \
- sizeof(struct iwl_cmd_meta))
-
-/*
- * RX related structures and functions
- */
-#define RX_FREE_BUFFERS 64
-#define RX_LOW_WATERMARK 8
-
-#define SUP_RATE_11A_MAX_NUM_CHANNELS 8
-#define SUP_RATE_11B_MAX_NUM_CHANNELS 4
-#define SUP_RATE_11G_MAX_NUM_CHANNELS 12
-
-/**
- * struct iwl_rx_queue - Rx queue
- * @processed: Internal index to last handled Rx packet
- * @read: Shared index to newest available Rx buffer
- * @write: Shared index to oldest written Rx packet
- * @free_count: Number of pre-allocated buffers in rx_free
- * @rx_free: list of free SKBs for use
- * @rx_used: List of Rx buffers with no SKB
- * @need_update: flag to indicate we need to update read/write index
- *
- * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
- */
-struct iwl_rx_queue {
- __le32 *bd;
- dma_addr_t dma_addr;
- struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
- struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
- u32 processed;
- u32 read;
- u32 write;
- u32 free_count;
- struct list_head rx_free;
- struct list_head rx_used;
- int need_update;
- spinlock_t lock;
-};
-
-#define IWL_SUPPORTED_RATES_IE_LEN 8
-
-#define SCAN_INTERVAL 100
-
-#define MAX_A_CHANNELS 252
-#define MIN_A_CHANNELS 7
-
-#define MAX_B_CHANNELS 14
-#define MIN_B_CHANNELS 1
-
-#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
-#define STATUS_INT_ENABLED 1
-#define STATUS_RF_KILL_HW 2
-#define STATUS_RF_KILL_SW 3
-#define STATUS_INIT 4
-#define STATUS_ALIVE 5
-#define STATUS_READY 6
-#define STATUS_TEMPERATURE 7
-#define STATUS_GEO_CONFIGURED 8
-#define STATUS_EXIT_PENDING 9
-#define STATUS_IN_SUSPEND 10
-#define STATUS_STATISTICS 11
-#define STATUS_SCANNING 12
-#define STATUS_SCAN_ABORTING 13
-#define STATUS_SCAN_HW 14
-#define STATUS_POWER_PMI 15
-#define STATUS_FW_ERROR 16
-
-#define MAX_TID_COUNT 9
-
-#define IWL_INVALID_RATE 0xFF
-#define IWL_INVALID_VALUE -1
-
-#if IWL == 4965
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
-struct iwl_ht_agg {
- u16 txq_id;
- u16 frame_count;
- u16 wait_for_ba;
- u16 start_idx;
- u32 bitmap0;
- u32 bitmap1;
- u32 rate_n_flags;
-};
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
-#endif
-
-struct iwl_tid_data {
- u16 seq_number;
-#if IWL == 4965
-#ifdef CONFIG_IWLWIFI_HT
-#ifdef CONFIG_IWLWIFI_HT_AGG
- struct iwl_ht_agg agg;
-#endif /* CONFIG_IWLWIFI_HT_AGG */
-#endif /* CONFIG_IWLWIFI_HT */
-#endif
-};
-
-struct iwl_hw_key {
- enum ieee80211_key_alg alg;
- int keylen;
- u8 key[32];
-};
-
-union iwl_ht_rate_supp {
- u16 rates;
- struct {
- u8 siso_rate;
- u8 mimo_rate;
- };
-};
-
-#ifdef CONFIG_IWLWIFI_HT
-#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3)
-#define HT_IE_MAX_AMSDU_SIZE_4K (0)
-#define CFG_HT_MPDU_DENSITY_2USEC (0x5)
-#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_2USEC
-
-struct sta_ht_info {
- u8 is_ht;
- u16 rx_mimo_ps_mode;
- u16 tx_mimo_ps_mode;
- u16 control_channel;
- u8 max_amsdu_size;
- u8 ampdu_factor;
- u8 mpdu_density;
- u8 operating_mode;
- u8 supported_chan_width;
- u8 extension_chan_offset;
- u8 is_green_field;
- u8 sgf;
- u8 supp_rates[16];
- u8 tx_chan_width;
- u8 chan_width_cap;
-};
-#endif /*CONFIG_IWLWIFI_HT */
-
-#ifdef CONFIG_IWLWIFI_QOS
-
-union iwl_qos_capabity {
- struct {
- u8 edca_count:4; /* bit 0-3 */
- u8 q_ack:1; /* bit 4 */
- u8 queue_request:1; /* bit 5 */
- u8 txop_request:1; /* bit 6 */
- u8 reserved:1; /* bit 7 */
- } q_AP;
- struct {
- u8 acvo_APSD:1; /* bit 0 */
- u8 acvi_APSD:1; /* bit 1 */
- u8 ac_bk_APSD:1; /* bit 2 */
- u8 ac_be_APSD:1; /* bit 3 */
- u8 q_ack:1; /* bit 4 */
- u8 max_len:2; /* bit 5-6 */
- u8 more_data_ack:1; /* bit 7 */
- } q_STA;
- u8 val;
-};
-
-/* QoS sturctures */
-struct iwl_qos_info {
- int qos_enable;
- int qos_active;
- union iwl_qos_capabity qos_cap;
- struct iwl_qosparam_cmd def_qos_parm;
-};
-#endif /*CONFIG_IWLWIFI_QOS */
-
-#define STA_PS_STATUS_WAKE 0
-#define STA_PS_STATUS_SLEEP 1
-
-struct iwl_station_entry {
- struct iwl_addsta_cmd sta;
- struct iwl_tid_data tid[MAX_TID_COUNT];
-#if IWL == 3945
- union {
- struct {
- u8 rate;
- u8 flags;
- } s;
- u16 rate_n_flags;
- } current_rate;
-#endif
- u8 used;
- u8 ps_status;
- struct iwl_hw_key keyinfo;
-};
-
-/* one for each uCode image (inst/data, boot/init/runtime) */
-struct fw_image_desc {
- void *v_addr; /* access by driver */
- dma_addr_t p_addr; /* access by card's busmaster DMA */
- u32 len; /* bytes */
-};
-
-/* uCode file layout */
-struct iwl_ucode {
- __le32 ver; /* major/minor/subminor */
- __le32 inst_size; /* bytes of runtime instructions */
- __le32 data_size; /* bytes of runtime data */
- __le32 init_size; /* bytes of initialization instructions */
- __le32 init_data_size; /* bytes of initialization data */
- __le32 boot_size; /* bytes of bootstrap instructions */
- u8 data[0]; /* data in same order as "size" elements */
-};
-
-#define IWL_IBSS_MAC_HASH_SIZE 32
-
-struct iwl_ibss_seq {
- u8 mac[ETH_ALEN];
- u16 seq_num;
- u16 frag_num;
- unsigned long packet_time;
- struct list_head list;
-};
-
-struct iwl_driver_hw_info {
- u16 max_txq_num;
- u16 ac_queue_count;
- u32 rx_buffer_size;
- u16 tx_cmd_len;
- u16 max_rxq_size;
- u16 max_rxq_log;
- u32 cck_flag;
- u8 max_stations;
- u8 bcast_sta_id;
- void *shared_virt;
- dma_addr_t shared_phys;
-};
-
-
-#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17)
-#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18)
-#define STA_FLG_MAX_AGG_SIZE_POS (19)
-#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19)
-#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21)
-#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22)
-#define STA_FLG_AGG_MPDU_DENSITY_POS (23)
-#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23)
-#define HT_SHORT_GI_20MHZ_ONLY (1 << 0)
-#define HT_SHORT_GI_40MHZ_ONLY (1 << 1)
-
-
-#include "iwl-priv.h"
-
-/* Requires full declaration of iwl_priv before including */
-#include "iwl-io.h"
-
-#define IWL_RX_HDR(x) ((struct iwl_rx_frame_hdr *)(\
- x->u.rx_frame.stats.payload + \
- x->u.rx_frame.stats.phy_count))
-#define IWL_RX_END(x) ((struct iwl_rx_frame_end *)(\
- IWL_RX_HDR(x)->payload + \
- le16_to_cpu(IWL_RX_HDR(x)->len)))
-#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
-#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
-
-
-/******************************************************************************
- *
- * Functions implemented in iwl-base.c which are forward declared here
- * for use by iwl-*.c
- *
- *****************************************************************************/
-struct iwl_addsta_cmd;
-extern int iwl_send_add_station(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags);
-extern const char *iwl_get_tx_fail_reason(u32 status);
-extern u8 iwl_add_station(struct iwl_priv *priv, const u8 *bssid,
- int is_ap, u8 flags);
-extern int iwl_is_network_packet(struct iwl_priv *priv,
- struct ieee80211_hdr *header);
-extern int iwl_power_init_handle(struct iwl_priv *priv);
-extern int iwl_eeprom_init(struct iwl_priv *priv);
-#ifdef CONFIG_IWLWIFI_DEBUG
-extern void iwl_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
- struct ieee80211_hdr *header, int group100);
-#else
-static inline void iwl_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
- struct ieee80211_hdr *header,
- int group100) {}
-#endif
-extern int iwl_tx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);
-extern void iwl_handle_data_packet_monitor(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb,
- void *data, short len,
- struct ieee80211_rx_status *stats,
- u16 phy_flags);
-extern int is_duplicate_packet(struct iwl_priv *priv, struct ieee80211_hdr
- *header);
-extern void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-extern int iwl_rx_queue_alloc(struct iwl_priv *priv);
-extern void iwl_rx_queue_reset(struct iwl_priv *priv,
- struct iwl_rx_queue *rxq);
-extern int iwl_calc_db_from_ratio(int sig_ratio);
-extern int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm);
-extern int iwl_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq, int count, u32 id);
-extern int iwl_rx_queue_restock(struct iwl_priv *priv);
-extern void iwl_rx_replenish(void *data);
-extern void iwl_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-extern int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len,
- const void *data);
-extern int __must_check iwl_send_cmd_async(struct iwl_priv *priv,
- struct iwl_host_cmd *cmd);
-extern int __must_check iwl_send_cmd_sync(struct iwl_priv *priv,
- struct iwl_host_cmd *cmd);
-extern int __must_check iwl_send_cmd(struct iwl_priv *priv,
- struct iwl_host_cmd *cmd);
-extern unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left);
-extern int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
- struct iwl_rx_queue *q);
-extern int iwl_send_statistics_request(struct iwl_priv *priv);
-extern void iwl_set_decrypted_flag(struct iwl_priv *priv, struct sk_buff *skb,
- u32 decrypt_res,
- struct ieee80211_rx_status *stats);
-extern __le16 *ieee80211_get_qos_ctrl(struct ieee80211_hdr *hdr);
-
-extern const u8 BROADCAST_ADDR[ETH_ALEN];
-
-/*
- * Currently used by iwl-3945-rs... look at restructuring so that it doesn't
- * call this... todo... fix that.
-*/
-extern u8 iwl_sync_station(struct iwl_priv *priv, int sta_id,
- u16 tx_rate, u8 flags);
-
-static inline int iwl_is_associated(struct iwl_priv *priv)
-{
- return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
-}
-
-/******************************************************************************
- *
- * Functions implemented in iwl-[34]*.c which are forward declared here
- * for use by iwl-base.c
- *
- * NOTE: The implementation of these functions are hardware specific
- * which is why they are in the hardware specific files (vs. iwl-base.c)
- *
- * Naming convention --
- * iwl_ <-- Its part of iwlwifi (should be changed to iwl_)
- * iwl_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
- * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
- * iwl_bg_ <-- Called from work queue context
- * iwl_mac_ <-- mac80211 callback
- *
- ****************************************************************************/
-extern void iwl_hw_rx_handler_setup(struct iwl_priv *priv);
-extern void iwl_hw_setup_deferred_work(struct iwl_priv *priv);
-extern void iwl_hw_cancel_deferred_work(struct iwl_priv *priv);
-extern int iwl_hw_rxq_stop(struct iwl_priv *priv);
-extern int iwl_hw_set_hw_setting(struct iwl_priv *priv);
-extern int iwl_hw_nic_init(struct iwl_priv *priv);
-extern void iwl_hw_card_show_info(struct iwl_priv *priv);
-extern int iwl_hw_nic_stop_master(struct iwl_priv *priv);
-extern void iwl_hw_txq_ctx_free(struct iwl_priv *priv);
-extern void iwl_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl_hw_nic_reset(struct iwl_priv *priv);
-extern int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *tfd,
- dma_addr_t addr, u16 len);
-extern int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
-extern int iwl_hw_get_temperature(struct iwl_priv *priv);
-extern int iwl_hw_tx_queue_init(struct iwl_priv *priv,
- struct iwl_tx_queue *txq);
-extern unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
- struct iwl_frame *frame, u8 rate);
-extern int iwl_hw_get_rx_read(struct iwl_priv *priv);
-extern void iwl_hw_build_tx_cmd_rate(struct iwl_priv *priv,
- struct iwl_cmd *cmd,
- struct ieee80211_tx_control *ctrl,
- struct ieee80211_hdr *hdr,
- int sta_id, int tx_id);
-extern int iwl_hw_reg_send_txpower(struct iwl_priv *priv);
-extern int iwl_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
-extern void iwl_hw_rx_statistics(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb);
-extern void iwl_disable_events(struct iwl_priv *priv);
-extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-
-/**
- * iwl_hw_find_station - Find station id for a given BSSID
- * @bssid: MAC address of station ID to find
- *
- * NOTE: This should not be hardware specific but the code has
- * not yet been merged into a single common layer for managing the
- * station tables.
- */
-extern u8 iwl_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
-
-extern int iwl_hw_channel_switch(struct iwl_priv *priv, u16 channel);
-extern int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
-#endif
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
index 9cf0211de67f..5e10ce0d351c 100644
--- a/drivers/net/wireless/libertas/11d.c
+++ b/drivers/net/wireless/libertas/11d.c
@@ -43,16 +43,14 @@ static struct chan_freq_power channel_freq_power_UN_BG[] = {
{14, 2484, TX_PWR_DEFAULT}
};
-static u8 wlan_region_2_code(u8 * region)
+static u8 lbs_region_2_code(u8 *region)
{
u8 i;
- u8 size = sizeof(region_code_mapping)/
- sizeof(struct region_code_mapping);
for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
region[i] = toupper(region[i]);
- for (i = 0; i < size; i++) {
+ for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
if (!memcmp(region, region_code_mapping[i].region,
COUNTRY_CODE_LEN))
return (region_code_mapping[i].code);
@@ -62,12 +60,11 @@ static u8 wlan_region_2_code(u8 * region)
return (region_code_mapping[0].code);
}
-static u8 *wlan_code_2_region(u8 code)
+static u8 *lbs_code_2_region(u8 code)
{
u8 i;
- u8 size = sizeof(region_code_mapping)
- / sizeof(struct region_code_mapping);
- for (i = 0; i < size; i++) {
+
+ for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
if (region_code_mapping[i].code == code)
return (region_code_mapping[i].region);
}
@@ -82,7 +79,7 @@ static u8 *wlan_code_2_region(u8 code)
* @param nrchan number of channels
* @return the nrchan-th chan number
*/
-static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
+static u8 lbs_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 *chan)
/*find the nrchan-th chan after the firstchan*/
{
u8 i;
@@ -90,8 +87,7 @@ static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
u8 cfp_no;
cfp = channel_freq_power_UN_BG;
- cfp_no = sizeof(channel_freq_power_UN_BG) /
- sizeof(struct chan_freq_power);
+ cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG);
for (i = 0; i < cfp_no; i++) {
if ((cfp + i)->channel == firstchan) {
@@ -117,7 +113,7 @@ static u8 wlan_get_chan_11d(u8 band, u8 firstchan, u8 nrchan, u8 * chan)
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return TRUE; FALSE
*/
-static u8 wlan_channel_known_11d(u8 chan,
+static u8 lbs_channel_known_11d(u8 chan,
struct parsed_region_chan_11d * parsed_region_chan)
{
struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
@@ -138,19 +134,15 @@ static u8 wlan_channel_known_11d(u8 chan,
return 0;
}
-u32 libertas_chan_2_freq(u8 chan, u8 band)
+u32 lbs_chan_2_freq(u8 chan, u8 band)
{
struct chan_freq_power *cf;
- u16 cnt;
u16 i;
u32 freq = 0;
cf = channel_freq_power_UN_BG;
- cnt =
- sizeof(channel_freq_power_UN_BG) /
- sizeof(struct chan_freq_power);
- for (i = 0; i < cnt; i++) {
+ for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
if (chan == cf[i].channel)
freq = cf[i].freq;
}
@@ -160,7 +152,7 @@ u32 libertas_chan_2_freq(u8 chan, u8 band)
static int generate_domain_info_11d(struct parsed_region_chan_11d
*parsed_region_chan,
- struct wlan_802_11d_domain_reg * domaininfo)
+ struct lbs_802_11d_domain_reg *domaininfo)
{
u8 nr_subband = 0;
@@ -225,7 +217,7 @@ static int generate_domain_info_11d(struct parsed_region_chan_11d
* @param *parsed_region_chan pointer to parsed_region_chan_11d
* @return N/A
*/
-static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_chan,
+static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan,
struct parsed_region_chan_11d *
parsed_region_chan)
{
@@ -246,7 +238,7 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_
parsed_region_chan->band = region_chan->band;
parsed_region_chan->region = region_chan->region;
memcpy(parsed_region_chan->countrycode,
- wlan_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
+ lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region,
parsed_region_chan->band);
@@ -272,7 +264,7 @@ static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_
* @param chan chan
* @return TRUE;FALSE
*/
-static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
+static u8 lbs_region_chan_supported_11d(u8 region, u8 band, u8 chan)
{
struct chan_freq_power *cfp;
int cfp_no;
@@ -281,7 +273,7 @@ static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
lbs_deb_enter(LBS_DEB_11D);
- cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
+ cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
if (cfp == NULL)
return 0;
@@ -346,7 +338,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
/*Step1: check region_code */
parsed_region_chan->region = region =
- wlan_region_2_code(countryinfo->countrycode);
+ lbs_region_2_code(countryinfo->countrycode);
lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode,
@@ -375,7 +367,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
/*step4: channel is supported? */
- if (!wlan_get_chan_11d(band, firstchan, i, &curchan)) {
+ if (!lbs_get_chan_11d(band, firstchan, i, &curchan)) {
/* Chan is not found in UN table */
lbs_deb_11d("chan is not supported: %d \n", i);
break;
@@ -383,7 +375,7 @@ static int parse_domain_info_11d(struct ieeetypes_countryinfofullset*
lastchan = curchan;
- if (wlan_region_chan_supported_11d
+ if (lbs_region_chan_supported_11d
(region, band, curchan)) {
/*step5: Check if curchan is supported by mrvl in region */
parsed_region_chan->chanpwr[idx].chan = curchan;
@@ -419,14 +411,14 @@ done:
* @param parsed_region_chan pointer to parsed_region_chan_11d
* @return PASSIVE if chan is unknown; ACTIVE if chan is known
*/
-u8 libertas_get_scan_type_11d(u8 chan,
+u8 lbs_get_scan_type_11d(u8 chan,
struct parsed_region_chan_11d * parsed_region_chan)
{
u8 scan_type = CMD_SCAN_TYPE_PASSIVE;
lbs_deb_enter(LBS_DEB_11D);
- if (wlan_channel_known_11d(chan, parsed_region_chan)) {
+ if (lbs_channel_known_11d(chan, parsed_region_chan)) {
lbs_deb_11d("found, do active scan\n");
scan_type = CMD_SCAN_TYPE_ACTIVE;
} else {
@@ -438,29 +430,29 @@ u8 libertas_get_scan_type_11d(u8 chan,
}
-void libertas_init_11d(wlan_private * priv)
+void lbs_init_11d(struct lbs_private *priv)
{
- priv->adapter->enable11d = 0;
- memset(&(priv->adapter->parsed_region_chan), 0,
+ priv->enable11d = 0;
+ memset(&(priv->parsed_region_chan), 0,
sizeof(struct parsed_region_chan_11d));
return;
}
/**
* @brief This function sets DOMAIN INFO to FW
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @return 0; -1
*/
-static int set_domain_info_11d(wlan_private * priv)
+static int set_domain_info_11d(struct lbs_private *priv)
{
int ret;
- if (!priv->adapter->enable11d) {
+ if (!priv->enable11d) {
lbs_deb_11d("dnld domain Info with 11d disabled\n");
return 0;
}
- ret = libertas_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP, 0, NULL);
if (ret)
@@ -471,28 +463,27 @@ static int set_domain_info_11d(wlan_private * priv)
/**
* @brief This function setups scan channels
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @param band band
* @return 0
*/
-int libertas_set_universaltable(wlan_private * priv, u8 band)
+int lbs_set_universaltable(struct lbs_private *priv, u8 band)
{
- wlan_adapter *adapter = priv->adapter;
u16 size = sizeof(struct chan_freq_power);
u16 i = 0;
- memset(adapter->universal_channel, 0,
- sizeof(adapter->universal_channel));
+ memset(priv->universal_channel, 0,
+ sizeof(priv->universal_channel));
- adapter->universal_channel[i].nrcfp =
+ priv->universal_channel[i].nrcfp =
sizeof(channel_freq_power_UN_BG) / size;
lbs_deb_11d("BG-band nrcfp %d\n",
- adapter->universal_channel[i].nrcfp);
+ priv->universal_channel[i].nrcfp);
- adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
- adapter->universal_channel[i].valid = 1;
- adapter->universal_channel[i].region = UNIVERSAL_REGION_CODE;
- adapter->universal_channel[i].band = band;
+ priv->universal_channel[i].CFP = channel_freq_power_UN_BG;
+ priv->universal_channel[i].valid = 1;
+ priv->universal_channel[i].region = UNIVERSAL_REGION_CODE;
+ priv->universal_channel[i].band = band;
i++;
return 0;
@@ -500,21 +491,20 @@ int libertas_set_universaltable(wlan_private * priv, u8 band)
/**
* @brief This function implements command CMD_802_11D_DOMAIN_INFO
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @param cmd pointer to cmd buffer
* @param cmdno cmd ID
* @param cmdOption cmd action
* @return 0
*/
-int libertas_cmd_802_11d_domain_info(wlan_private * priv,
+int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *cmd, u16 cmdno,
u16 cmdoption)
{
struct cmd_ds_802_11d_domain_info *pdomaininfo =
&cmd->params.domaininfo;
struct mrvlietypes_domainparamset *domain = &pdomaininfo->domain;
- wlan_adapter *adapter = priv->adapter;
- u8 nr_subband = adapter->domainreg.nr_subband;
+ u8 nr_subband = priv->domainreg.nr_subband;
lbs_deb_enter(LBS_DEB_11D);
@@ -526,12 +516,12 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv,
cmd->size =
cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
- (int)(cmd->size));
+ le16_to_cpu(cmd->size));
goto done;
}
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
- memcpy(domain->countrycode, adapter->domainreg.countrycode,
+ memcpy(domain->countrycode, priv->domainreg.countrycode,
sizeof(domain->countrycode));
domain->header.len =
@@ -539,7 +529,7 @@ int libertas_cmd_802_11d_domain_info(wlan_private * priv,
sizeof(domain->countrycode));
if (nr_subband) {
- memcpy(domain->subband, adapter->domainreg.subband,
+ memcpy(domain->subband, priv->domainreg.subband,
nr_subband * sizeof(struct ieeetypes_subbandset));
cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
@@ -560,11 +550,11 @@ done:
/**
* @brief This function parses countryinfo from AP and download country info to FW
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @param resp pointer to command response buffer
* @return 0; -1
*/
-int libertas_ret_802_11d_domain_info(wlan_private * priv,
+int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
@@ -606,31 +596,30 @@ int libertas_ret_802_11d_domain_info(wlan_private * priv,
/**
* @brief This function parses countryinfo from AP and download country info to FW
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @return 0; -1
*/
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
struct bss_descriptor * bss)
{
int ret;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_11D);
- if (priv->adapter->enable11d) {
- memset(&adapter->parsed_region_chan, 0,
+ if (priv->enable11d) {
+ memset(&priv->parsed_region_chan, 0,
sizeof(struct parsed_region_chan_11d));
ret = parse_domain_info_11d(&bss->countryinfo, 0,
- &adapter->parsed_region_chan);
+ &priv->parsed_region_chan);
if (ret == -1) {
lbs_deb_11d("error parsing domain_info from AP\n");
goto done;
}
- memset(&adapter->domainreg, 0,
- sizeof(struct wlan_802_11d_domain_reg));
- generate_domain_info_11d(&adapter->parsed_region_chan,
- &adapter->domainreg);
+ memset(&priv->domainreg, 0,
+ sizeof(struct lbs_802_11d_domain_reg));
+ generate_domain_info_11d(&priv->parsed_region_chan,
+ &priv->domainreg);
ret = set_domain_info_11d(priv);
@@ -648,25 +637,23 @@ done:
/**
* @brief This function generates 11D info from user specified regioncode and download to FW
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @return 0; -1
*/
-int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
+int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv)
{
int ret;
- wlan_adapter *adapter = priv->adapter;
struct region_channel *region_chan;
u8 j;
lbs_deb_enter(LBS_DEB_11D);
- lbs_deb_11d("curbssparams.band %d\n", adapter->curbssparams.band);
+ lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band);
- if (priv->adapter->enable11d) {
+ if (priv->enable11d) {
/* update parsed_region_chan_11; dnld domaininf to FW */
- for (j = 0; j < sizeof(adapter->region_channel) /
- sizeof(adapter->region_channel[0]); j++) {
- region_chan = &adapter->region_channel[j];
+ for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) {
+ region_chan = &priv->region_channel[j];
lbs_deb_11d("%d region_chan->band %d\n", j,
region_chan->band);
@@ -674,29 +661,28 @@ int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
if (!region_chan || !region_chan->valid
|| !region_chan->CFP)
continue;
- if (region_chan->band != adapter->curbssparams.band)
+ if (region_chan->band != priv->curbssparams.band)
continue;
break;
}
- if (j >= sizeof(adapter->region_channel) /
- sizeof(adapter->region_channel[0])) {
+ if (j >= ARRAY_SIZE(priv->region_channel)) {
lbs_deb_11d("region_chan not found, band %d\n",
- adapter->curbssparams.band);
+ priv->curbssparams.band);
ret = -1;
goto done;
}
- memset(&adapter->parsed_region_chan, 0,
+ memset(&priv->parsed_region_chan, 0,
sizeof(struct parsed_region_chan_11d));
- wlan_generate_parsed_region_chan_11d(region_chan,
- &adapter->
+ lbs_generate_parsed_region_chan_11d(region_chan,
+ &priv->
parsed_region_chan);
- memset(&adapter->domainreg, 0,
- sizeof(struct wlan_802_11d_domain_reg));
- generate_domain_info_11d(&adapter->parsed_region_chan,
- &adapter->domainreg);
+ memset(&priv->domainreg, 0,
+ sizeof(struct lbs_802_11d_domain_reg));
+ generate_domain_info_11d(&priv->parsed_region_chan,
+ &priv->domainreg);
ret = set_domain_info_11d(priv);
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
index 3a6d1f8db78f..811eea2cfba3 100644
--- a/drivers/net/wireless/libertas/11d.h
+++ b/drivers/net/wireless/libertas/11d.h
@@ -2,8 +2,8 @@
* This header file contains data structures and
* function declarations of 802.11d
*/
-#ifndef _WLAN_11D_
-#define _WLAN_11D_
+#ifndef _LBS_11D_
+#define _LBS_11D_
#include "types.h"
#include "defs.h"
@@ -52,7 +52,7 @@ struct cmd_ds_802_11d_domain_info {
} __attribute__ ((packed));
/** domain regulatory information */
-struct wlan_802_11d_domain_reg {
+struct lbs_802_11d_domain_reg {
/** country Code*/
u8 countrycode[COUNTRY_CODE_LEN];
/** No. of subband*/
@@ -78,26 +78,28 @@ struct region_code_mapping {
u8 code;
};
-u8 libertas_get_scan_type_11d(u8 chan,
+struct lbs_private;
+
+u8 lbs_get_scan_type_11d(u8 chan,
struct parsed_region_chan_11d *parsed_region_chan);
-u32 libertas_chan_2_freq(u8 chan, u8 band);
+u32 lbs_chan_2_freq(u8 chan, u8 band);
-void libertas_init_11d(wlan_private * priv);
+void lbs_init_11d(struct lbs_private *priv);
-int libertas_set_universaltable(wlan_private * priv, u8 band);
+int lbs_set_universaltable(struct lbs_private *priv, u8 band);
-int libertas_cmd_802_11d_domain_info(wlan_private * priv,
+int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *cmd, u16 cmdno,
u16 cmdOption);
-int libertas_ret_802_11d_domain_info(wlan_private * priv,
+int lbs_ret_802_11d_domain_info(struct lbs_private *priv,
struct cmd_ds_command *resp);
struct bss_descriptor;
-int libertas_parse_dnld_countryinfo_11d(wlan_private * priv,
+int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
struct bss_descriptor * bss);
-int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
+int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv);
-#endif /* _WLAN_11D_ */
+#endif
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 0b133ce63805..d860fc375752 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -195,45 +195,33 @@ setuserscan
where [ARGS]:
- chan=[chan#][band][mode] where band is [a,b,g] and mode is
- blank for active or 'p' for passive
bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan
ssid="[SSID]" specify a SSID filter for the scan
keep=[0 or 1] keep the previous scan results (1), discard (0)
dur=[scan time] time to scan for each channel in milliseconds
- probes=[#] number of probe requests to send on each chan
type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any)
- Any combination of the above arguments can be supplied on the command line.
- If the chan token is absent, a full channel scan will be completed by
- the driver. If the dur or probes tokens are absent, the driver default
- setting will be used. The bssid and ssid fields, if blank,
- will produce an unfiltered scan. The type field will default to 3 (Any)
- and the keep field will default to 0 (Discard).
+ Any combination of the above arguments can be supplied on the command
+ line. If dur tokens are absent, the driver default setting will be used.
+ The bssid and ssid fields, if blank, will produce an unfiltered scan.
+ The type field will default to 3 (Any) and the keep field will default
+ to 0 (Discard).
Examples:
- 1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
- echo "chan=1g,6g,11g" > setuserscan
+ 1) Perform a passive scan on all channels for 20 ms per channel:
+ echo "dur=20" > setuserscan
- 2) Perform a passive scan on channel 11 for 20 ms:
- echo "chan=11gp dur=20" > setuserscan
+ 2) Perform an active scan for a specific SSID:
+ echo "ssid="TestAP"" > setuserscan
- 3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
- channel 36 in the 'a' band:
-
- echo "chan=1g,6g,11g,36ap" > setuserscan
-
- 4) Perform an active scan on channel 6 and 36 for a specific SSID:
- echo "chan=6g,36a ssid="TestAP"" > setuserscan
-
- 5) Scan all available channels (B/G, A bands) for a specific BSSID, keep
+ 3) Scan all available channels (B/G, A bands) for a specific BSSID, keep
the current scan table intact, update existing or append new scan data:
echo "bssid=00:50:43:20:12:82 keep=1" > setuserscan
- 6) Scan channel 6, for all infrastructure networks, sending two probe
- requests. Keep the previous scan table intact. Update any duplicate
- BSSID/SSID matches with the new scan data:
- echo "chan=6g type=1 probes=2 keep=1" > setuserscan
+ 4) Scan for all infrastructure networks.
+ Keep the previous scan table intact. Update any duplicate BSSID/SSID
+ matches with the new scan data:
+ echo "type=1 keep=1" > setuserscan
All entries in the scan table (not just the new scan data when keep=1)
will be displayed upon completion by use of the getscantable ioctl.
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index b61b176e9d07..c622e9b63cd1 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -9,39 +9,16 @@
#include "decl.h"
#include "hostcmd.h"
#include "host.h"
+#include "cmd.h"
static const u8 bssid_any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const u8 bssid_off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-static void print_assoc_req(const char * extra, struct assoc_request * assoc_req)
-{
- DECLARE_MAC_BUF(mac);
- lbs_deb_assoc(
- "#### Association Request: %s\n"
- " flags: 0x%08lX\n"
- " SSID: '%s'\n"
- " channel: %d\n"
- " band: %d\n"
- " mode: %d\n"
- " BSSID: %s\n"
- " Encryption:%s%s%s\n"
- " auth: %d\n",
- extra, assoc_req->flags,
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
- assoc_req->channel, assoc_req->band, assoc_req->mode,
- print_mac(mac, assoc_req->bssid),
- assoc_req->secinfo.WPAenabled ? " WPA" : "",
- assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
- assoc_req->secinfo.wep_enabled ? " WEP" : "",
- assoc_req->secinfo.auth_mode);
-}
-
-static int assoc_helper_essid(wlan_private *priv,
+static int assoc_helper_essid(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct bss_descriptor * bss;
int channel = -1;
@@ -55,18 +32,17 @@ static int assoc_helper_essid(wlan_private *priv,
if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
channel = assoc_req->channel;
- lbs_deb_assoc("New SSID requested: '%s'\n",
+ lbs_deb_assoc("SSID '%s' requested\n",
escape_essid(assoc_req->ssid, assoc_req->ssid_len));
if (assoc_req->mode == IW_MODE_INFRA) {
- libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+ lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
assoc_req->ssid_len, 0);
- bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+ bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
if (bss != NULL) {
- lbs_deb_assoc("SSID found in scan list, associating\n");
memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- ret = wlan_associate(priv, assoc_req);
+ ret = lbs_associate(priv, assoc_req);
} else {
lbs_deb_assoc("SSID not found; cannot associate\n");
}
@@ -74,23 +50,23 @@ static int assoc_helper_essid(wlan_private *priv,
/* Scan for the network, do not save previous results. Stale
* scan data will cause us to join a non-existant adhoc network
*/
- libertas_send_specific_ssid_scan(priv, assoc_req->ssid,
+ lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
assoc_req->ssid_len, 1);
/* Search for the requested SSID in the scan table */
- bss = libertas_find_ssid_in_list(adapter, assoc_req->ssid,
+ bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
if (bss != NULL) {
lbs_deb_assoc("SSID found, will join\n");
memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
- libertas_join_adhoc_network(priv, assoc_req);
+ lbs_join_adhoc_network(priv, assoc_req);
} else {
/* else send START command */
lbs_deb_assoc("SSID not found, creating adhoc network\n");
memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
IW_ESSID_MAX_SIZE);
assoc_req->bss.ssid_len = assoc_req->ssid_len;
- libertas_start_adhoc_network(priv, assoc_req);
+ lbs_start_adhoc_network(priv, assoc_req);
}
}
@@ -99,10 +75,9 @@ static int assoc_helper_essid(wlan_private *priv,
}
-static int assoc_helper_bssid(wlan_private *priv,
+static int assoc_helper_bssid(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct bss_descriptor * bss;
DECLARE_MAC_BUF(mac);
@@ -111,7 +86,7 @@ static int assoc_helper_bssid(wlan_private *priv,
print_mac(mac, assoc_req->bssid));
/* Search for index position in list for requested MAC */
- bss = libertas_find_bssid_in_list(adapter, assoc_req->bssid,
+ bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
assoc_req->mode);
if (bss == NULL) {
lbs_deb_assoc("ASSOC: WAP: BSSID %s not found, "
@@ -121,10 +96,10 @@ static int assoc_helper_bssid(wlan_private *priv,
memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
if (assoc_req->mode == IW_MODE_INFRA) {
- ret = wlan_associate(priv, assoc_req);
- lbs_deb_assoc("ASSOC: wlan_associate(bssid) returned %d\n", ret);
+ ret = lbs_associate(priv, assoc_req);
+ lbs_deb_assoc("ASSOC: lbs_associate(bssid) returned %d\n", ret);
} else if (assoc_req->mode == IW_MODE_ADHOC) {
- libertas_join_adhoc_network(priv, assoc_req);
+ lbs_join_adhoc_network(priv, assoc_req);
}
out:
@@ -133,11 +108,13 @@ out:
}
-static int assoc_helper_associate(wlan_private *priv,
+static int assoc_helper_associate(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
int ret = 0, done = 0;
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
/* If we're given and 'any' BSSID, try associating based on SSID */
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
@@ -145,42 +122,36 @@ static int assoc_helper_associate(wlan_private *priv,
&& compare_ether_addr(bssid_off, assoc_req->bssid)) {
ret = assoc_helper_bssid(priv, assoc_req);
done = 1;
- if (ret) {
- lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
- }
}
}
if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
ret = assoc_helper_essid(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC: bssid: ret = %d\n", ret);
- }
}
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-static int assoc_helper_mode(wlan_private *priv,
+static int assoc_helper_mode(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
- if (assoc_req->mode == adapter->mode)
+ if (assoc_req->mode == priv->mode)
goto done;
if (assoc_req->mode == IW_MODE_INFRA) {
- if (adapter->psstate != PS_STATE_FULL_POWER)
- libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
- adapter->psmode = WLAN802_11POWERMODECAM;
+ if (priv->psstate != PS_STATE_FULL_POWER)
+ lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
+ priv->psmode = LBS802_11POWERMODECAM;
}
- adapter->mode = assoc_req->mode;
- ret = libertas_prepare_and_send_command(priv,
+ priv->mode = assoc_req->mode;
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
0, CMD_OPTION_WAITFORRSP,
OID_802_11_INFRASTRUCTURE_MODE,
@@ -192,57 +163,76 @@ done:
}
-static int update_channel(wlan_private * priv)
+int lbs_update_channel(struct lbs_private *priv)
{
- /* the channel in f/w could be out of sync, get the current channel */
- return libertas_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL,
- CMD_OPT_802_11_RF_CHANNEL_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+ int ret;
+
+ /* the channel in f/w could be out of sync; get the current channel */
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ ret = lbs_get_channel(priv);
+ if (ret > 0) {
+ priv->curbssparams.channel = ret;
+ ret = 0;
+ }
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
+ return ret;
}
-void libertas_sync_channel(struct work_struct *work)
+void lbs_sync_channel(struct work_struct *work)
{
- wlan_private *priv = container_of(work, wlan_private, sync_channel);
+ struct lbs_private *priv = container_of(work, struct lbs_private,
+ sync_channel);
- if (update_channel(priv) != 0)
+ lbs_deb_enter(LBS_DEB_ASSOC);
+ if (lbs_update_channel(priv))
lbs_pr_info("Channel synchronization failed.");
+ lbs_deb_leave(LBS_DEB_ASSOC);
}
-static int assoc_helper_channel(wlan_private *priv,
+static int assoc_helper_channel(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
- ret = update_channel(priv);
- if (ret < 0) {
- lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ ret = lbs_update_channel(priv);
+ if (ret) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
+ goto done;
}
- if (assoc_req->channel == adapter->curbssparams.channel)
+ if (assoc_req->channel == priv->curbssparams.channel)
goto done;
+ if (priv->mesh_dev) {
+ /* Change mesh channel first; 21.p21 firmware won't let
+ you change channel otherwise (even though it'll return
+ an error to this */
+ lbs_mesh_config(priv, 0, assoc_req->channel);
+ }
+
lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
- adapter->curbssparams.channel, assoc_req->channel);
+ priv->curbssparams.channel, assoc_req->channel);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_RF_CHANNEL,
- CMD_OPT_802_11_RF_CHANNEL_SET,
- CMD_OPTION_WAITFORRSP, 0, &assoc_req->channel);
- if (ret < 0) {
- lbs_deb_assoc("ASSOC: channel: error setting channel.");
- }
+ ret = lbs_set_channel(priv, assoc_req->channel);
+ if (ret < 0)
+ lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
- ret = update_channel(priv);
- if (ret < 0) {
- lbs_deb_assoc("ASSOC: channel: error getting channel.");
+ /* FIXME: shouldn't need to grab the channel _again_ after setting
+ * it since the firmware is supposed to return the new channel, but
+ * whatever... */
+ ret = lbs_update_channel(priv);
+ if (ret) {
+ lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
+ goto done;
}
- if (assoc_req->channel != adapter->curbssparams.channel) {
- lbs_deb_assoc("ASSOC: channel: failed to update channel to %d",
+ if (assoc_req->channel != priv->curbssparams.channel) {
+ lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
assoc_req->channel);
- goto done;
+ goto restore_mesh;
}
if ( assoc_req->secinfo.wep_enabled
@@ -255,83 +245,75 @@ static int assoc_helper_channel(wlan_private *priv,
}
/* Must restart/rejoin adhoc networks after channel change */
- set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
+ set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
-done:
+ restore_mesh:
+ if (priv->mesh_dev)
+ lbs_mesh_config(priv, 1, priv->curbssparams.channel);
+
+ done:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-static int assoc_helper_wep_keys(wlan_private *priv,
- struct assoc_request * assoc_req)
+static int assoc_helper_wep_keys(struct lbs_private *priv,
+ struct assoc_request *assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int i;
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
/* Set or remove WEP keys */
- if ( assoc_req->wep_keys[0].len
- || assoc_req->wep_keys[1].len
- || assoc_req->wep_keys[2].len
- || assoc_req->wep_keys[3].len) {
- ret = libertas_prepare_and_send_command(priv,
- CMD_802_11_SET_WEP,
- CMD_ACT_ADD,
- CMD_OPTION_WAITFORRSP,
- 0, assoc_req);
- } else {
- ret = libertas_prepare_and_send_command(priv,
- CMD_802_11_SET_WEP,
- CMD_ACT_REMOVE,
- CMD_OPTION_WAITFORRSP,
- 0, NULL);
- }
+ if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
+ assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
+ ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
+ else
+ ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
if (ret)
goto out;
/* enable/disable the MAC's WEP packet filter */
if (assoc_req->secinfo.wep_enabled)
- adapter->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
+ priv->currentpacketfilter |= CMD_ACT_MAC_WEP_ENABLE;
else
- adapter->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
- ret = libertas_set_mac_packet_filter(priv);
+ priv->currentpacketfilter &= ~CMD_ACT_MAC_WEP_ENABLE;
+
+ ret = lbs_set_mac_packet_filter(priv);
if (ret)
goto out;
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
- /* Copy WEP keys into adapter wep key fields */
+ /* Copy WEP keys into priv wep key fields */
for (i = 0; i < 4; i++) {
- memcpy(&adapter->wep_keys[i], &assoc_req->wep_keys[i],
- sizeof(struct enc_key));
+ memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
+ sizeof(struct enc_key));
}
- adapter->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
+ priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-static int assoc_helper_secinfo(wlan_private *priv,
+static int assoc_helper_secinfo(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
- u32 do_wpa;
- u32 rsn = 0;
+ uint16_t do_wpa;
+ uint16_t rsn = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
- memcpy(&adapter->secinfo, &assoc_req->secinfo,
- sizeof(struct wlan_802_11_security));
+ memcpy(&priv->secinfo, &assoc_req->secinfo,
+ sizeof(struct lbs_802_11_security));
- ret = libertas_set_mac_packet_filter(priv);
+ ret = lbs_set_mac_packet_filter(priv);
if (ret)
goto out;
@@ -341,28 +323,19 @@ static int assoc_helper_secinfo(wlan_private *priv,
*/
/* Get RSN enabled/disabled */
- ret = libertas_prepare_and_send_command(priv,
- CMD_802_11_ENABLE_RSN,
- CMD_ACT_GET,
- CMD_OPTION_WAITFORRSP,
- 0, &rsn);
+ ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
if (ret) {
- lbs_deb_assoc("Failed to get RSN status: %d", ret);
+ lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
goto out;
}
/* Don't re-enable RSN if it's already enabled */
- do_wpa = (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled);
+ do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
if (do_wpa == rsn)
goto out;
/* Set RSN enabled/disabled */
- rsn = do_wpa;
- ret = libertas_prepare_and_send_command(priv,
- CMD_802_11_ENABLE_RSN,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP,
- 0, &rsn);
+ ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
out:
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -370,7 +343,7 @@ out:
}
-static int assoc_helper_wpa_keys(wlan_private *priv,
+static int assoc_helper_wpa_keys(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
int ret = 0;
@@ -385,7 +358,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_KEY_MATERIAL,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP,
@@ -399,7 +372,7 @@ static int assoc_helper_wpa_keys(wlan_private *priv,
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_KEY_MATERIAL,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP,
@@ -413,20 +386,19 @@ out:
}
-static int assoc_helper_wpa_ie(wlan_private *priv,
+static int assoc_helper_wpa_ie(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
- memcpy(&adapter->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
- adapter->wpa_ie_len = assoc_req->wpa_ie_len;
+ memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
+ priv->wpa_ie_len = assoc_req->wpa_ie_len;
} else {
- memset(&adapter->wpa_ie, 0, MAX_WPA_IE_LEN);
- adapter->wpa_ie_len = 0;
+ memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
+ priv->wpa_ie_len = 0;
}
lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -434,55 +406,68 @@ static int assoc_helper_wpa_ie(wlan_private *priv,
}
-static int should_deauth_infrastructure(wlan_adapter *adapter,
+static int should_deauth_infrastructure(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- if (adapter->connect_status != LIBERTAS_CONNECTED)
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ if (priv->connect_status != LBS_CONNECTED)
return 0;
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to new SSID in "
- " configuration request.\n");
- return 1;
+ lbs_deb_assoc("Deauthenticating due to new SSID\n");
+ ret = 1;
+ goto out;
}
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
- if (adapter->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
- lbs_deb_assoc("Deauthenticating due to updated security "
- "info in configuration request.\n");
- return 1;
+ if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
+ lbs_deb_assoc("Deauthenticating due to new security\n");
+ ret = 1;
+ goto out;
}
}
if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to new BSSID in "
- " configuration request.\n");
- return 1;
+ lbs_deb_assoc("Deauthenticating due to new BSSID\n");
+ ret = 1;
+ goto out;
}
if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
- lbs_deb_assoc("Deauthenticating due to channel switch.\n");
- return 1;
+ lbs_deb_assoc("Deauthenticating due to channel switch\n");
+ ret = 1;
+ goto out;
}
/* FIXME: deal with 'auto' mode somehow */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
- if (assoc_req->mode != IW_MODE_INFRA)
- return 1;
+ if (assoc_req->mode != IW_MODE_INFRA) {
+ lbs_deb_assoc("Deauthenticating due to leaving "
+ "infra mode\n");
+ ret = 1;
+ goto out;
+ }
}
+out:
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return 0;
}
-static int should_stop_adhoc(wlan_adapter *adapter,
+static int should_stop_adhoc(struct lbs_private *priv,
struct assoc_request * assoc_req)
{
- if (adapter->connect_status != LIBERTAS_CONNECTED)
+ lbs_deb_enter(LBS_DEB_ASSOC);
+
+ if (priv->connect_status != LBS_CONNECTED)
return 0;
- if (libertas_ssid_cmp(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len,
+ if (lbs_ssid_cmp(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len,
assoc_req->ssid, assoc_req->ssid_len) != 0)
return 1;
@@ -493,18 +478,19 @@ static int should_stop_adhoc(wlan_adapter *adapter,
}
if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
- if (assoc_req->channel != adapter->curbssparams.channel)
+ if (assoc_req->channel != priv->curbssparams.channel)
return 1;
}
+ lbs_deb_leave(LBS_DEB_ASSOC);
return 0;
}
-void libertas_association_worker(struct work_struct *work)
+void lbs_association_worker(struct work_struct *work)
{
- wlan_private *priv = container_of(work, wlan_private, assoc_work.work);
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = container_of(work, struct lbs_private,
+ assoc_work.work);
struct assoc_request * assoc_req = NULL;
int ret = 0;
int find_any_ssid = 0;
@@ -512,16 +498,33 @@ void libertas_association_worker(struct work_struct *work)
lbs_deb_enter(LBS_DEB_ASSOC);
- mutex_lock(&adapter->lock);
- assoc_req = adapter->pending_assoc_req;
- adapter->pending_assoc_req = NULL;
- adapter->in_progress_assoc_req = assoc_req;
- mutex_unlock(&adapter->lock);
+ mutex_lock(&priv->lock);
+ assoc_req = priv->pending_assoc_req;
+ priv->pending_assoc_req = NULL;
+ priv->in_progress_assoc_req = assoc_req;
+ mutex_unlock(&priv->lock);
if (!assoc_req)
goto done;
- print_assoc_req(__func__, assoc_req);
+ lbs_deb_assoc(
+ "Association Request:\n"
+ " flags: 0x%08lx\n"
+ " SSID: '%s'\n"
+ " chann: %d\n"
+ " band: %d\n"
+ " mode: %d\n"
+ " BSSID: %s\n"
+ " secinfo: %s%s%s\n"
+ " auth_mode: %d\n",
+ assoc_req->flags,
+ escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ assoc_req->channel, assoc_req->band, assoc_req->mode,
+ print_mac(mac, assoc_req->bssid),
+ assoc_req->secinfo.WPAenabled ? " WPA" : "",
+ assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
+ assoc_req->secinfo.wep_enabled ? " WEP" : "",
+ assoc_req->secinfo.auth_mode);
/* If 'any' SSID was specified, find an SSID to associate with */
if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)
@@ -538,7 +541,7 @@ void libertas_association_worker(struct work_struct *work)
if (find_any_ssid) {
u8 new_mode;
- ret = libertas_find_best_network_ssid(priv, assoc_req->ssid,
+ ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
&assoc_req->ssid_len, assoc_req->mode, &new_mode);
if (ret) {
lbs_deb_assoc("Could not find best network\n");
@@ -557,18 +560,18 @@ void libertas_association_worker(struct work_struct *work)
* Check if the attributes being changing require deauthentication
* from the currently associated infrastructure access point.
*/
- if (adapter->mode == IW_MODE_INFRA) {
- if (should_deauth_infrastructure(adapter, assoc_req)) {
- ret = libertas_send_deauthentication(priv);
+ if (priv->mode == IW_MODE_INFRA) {
+ if (should_deauth_infrastructure(priv, assoc_req)) {
+ ret = lbs_send_deauthentication(priv);
if (ret) {
lbs_deb_assoc("Deauthentication due to new "
"configuration request failed: %d\n",
ret);
}
}
- } else if (adapter->mode == IW_MODE_ADHOC) {
- if (should_stop_adhoc(adapter, assoc_req)) {
- ret = libertas_stop_adhoc_network(priv);
+ } else if (priv->mode == IW_MODE_ADHOC) {
+ if (should_stop_adhoc(priv, assoc_req)) {
+ ret = lbs_stop_adhoc_network(priv);
if (ret) {
lbs_deb_assoc("Teardown of AdHoc network due to "
"new configuration request failed: %d\n",
@@ -581,58 +584,40 @@ void libertas_association_worker(struct work_struct *work)
/* Send the various configuration bits to the firmware */
if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
ret = assoc_helper_mode(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) mode: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
ret = assoc_helper_channel(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) channel: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
ret = assoc_helper_wep_keys(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) wep_keys: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
ret = assoc_helper_secinfo(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) secinfo: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
ret = assoc_helper_wpa_ie(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) wpa_ie: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)
|| test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
ret = assoc_helper_wpa_keys(priv, assoc_req);
- if (ret) {
- lbs_deb_assoc("ASSOC(:%d) wpa_keys: ret = %d\n",
- __LINE__, ret);
+ if (ret)
goto out;
- }
}
/* SSID/BSSID should be the _last_ config option set, because they
@@ -644,28 +629,27 @@ void libertas_association_worker(struct work_struct *work)
ret = assoc_helper_associate(priv, assoc_req);
if (ret) {
- lbs_deb_assoc("ASSOC: association attempt unsuccessful: %d\n",
+ lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
ret);
success = 0;
}
- if (adapter->connect_status != LIBERTAS_CONNECTED) {
- lbs_deb_assoc("ASSOC: association attempt unsuccessful, "
- "not connected.\n");
+ if (priv->connect_status != LBS_CONNECTED) {
+ lbs_deb_assoc("ASSOC: association unsuccessful, "
+ "not connected\n");
success = 0;
}
if (success) {
- lbs_deb_assoc("ASSOC: association attempt successful. "
- "Associated to '%s' (%s)\n",
- escape_essid(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len),
- print_mac(mac, adapter->curbssparams.bssid));
- libertas_prepare_and_send_command(priv,
+ lbs_deb_assoc("ASSOC: associated to '%s', %s\n",
+ escape_essid(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len),
+ print_mac(mac, priv->curbssparams.bssid));
+ lbs_prepare_and_send_command(priv,
CMD_802_11_RSSI,
0, CMD_OPTION_WAITFORRSP, 0, NULL);
- libertas_prepare_and_send_command(priv,
+ lbs_prepare_and_send_command(priv,
CMD_802_11_GET_LOG,
0, CMD_OPTION_WAITFORRSP, 0, NULL);
} else {
@@ -679,9 +663,9 @@ out:
ret);
}
- mutex_lock(&adapter->lock);
- adapter->in_progress_assoc_req = NULL;
- mutex_unlock(&adapter->lock);
+ mutex_lock(&priv->lock);
+ priv->in_progress_assoc_req = NULL;
+ mutex_unlock(&priv->lock);
kfree(assoc_req);
done:
@@ -692,14 +676,15 @@ done:
/*
* Caller MUST hold any necessary locks
*/
-struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
+struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
{
struct assoc_request * assoc_req;
- if (!adapter->pending_assoc_req) {
- adapter->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
+ lbs_deb_enter(LBS_DEB_ASSOC);
+ if (!priv->pending_assoc_req) {
+ priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
GFP_KERNEL);
- if (!adapter->pending_assoc_req) {
+ if (!priv->pending_assoc_req) {
lbs_pr_info("Not enough memory to allocate association"
" request!\n");
return NULL;
@@ -709,60 +694,59 @@ struct assoc_request * wlan_get_association_request(wlan_adapter *adapter)
/* Copy current configuration attributes to the association request,
* but don't overwrite any that are already set.
*/
- assoc_req = adapter->pending_assoc_req;
+ assoc_req = priv->pending_assoc_req;
if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
- memcpy(&assoc_req->ssid, &adapter->curbssparams.ssid,
+ memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
IW_ESSID_MAX_SIZE);
- assoc_req->ssid_len = adapter->curbssparams.ssid_len;
+ assoc_req->ssid_len = priv->curbssparams.ssid_len;
}
if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
- assoc_req->channel = adapter->curbssparams.channel;
+ assoc_req->channel = priv->curbssparams.channel;
if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
- assoc_req->band = adapter->curbssparams.band;
+ assoc_req->band = priv->curbssparams.band;
if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
- assoc_req->mode = adapter->mode;
+ assoc_req->mode = priv->mode;
if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
- memcpy(&assoc_req->bssid, adapter->curbssparams.bssid,
+ memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
ETH_ALEN);
}
if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
int i;
for (i = 0; i < 4; i++) {
- memcpy(&assoc_req->wep_keys[i], &adapter->wep_keys[i],
+ memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
sizeof(struct enc_key));
}
}
if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
- assoc_req->wep_tx_keyidx = adapter->wep_tx_keyidx;
+ assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_mcast_key, &adapter->wpa_mcast_key,
+ memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
sizeof(struct enc_key));
}
if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_unicast_key, &adapter->wpa_unicast_key,
+ memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
sizeof(struct enc_key));
}
if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
- memcpy(&assoc_req->secinfo, &adapter->secinfo,
- sizeof(struct wlan_802_11_security));
+ memcpy(&assoc_req->secinfo, &priv->secinfo,
+ sizeof(struct lbs_802_11_security));
}
if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
- memcpy(&assoc_req->wpa_ie, &adapter->wpa_ie,
+ memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
MAX_WPA_IE_LEN);
- assoc_req->wpa_ie_len = adapter->wpa_ie_len;
+ assoc_req->wpa_ie_len = priv->wpa_ie_len;
}
- print_assoc_req(__func__, assoc_req);
-
+ lbs_deb_leave(LBS_DEB_ASSOC);
return assoc_req;
}
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index e09b7490abbd..08372bbf3761 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -1,32 +1,12 @@
/* Copyright (C) 2006, Red Hat, Inc. */
-#ifndef _WLAN_ASSOC_H_
-#define _WLAN_ASSOC_H_
+#ifndef _LBS_ASSOC_H_
+#define _LBS_ASSOC_H_
#include "dev.h"
-void libertas_association_worker(struct work_struct *work);
+void lbs_association_worker(struct work_struct *work);
+struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
+void lbs_sync_channel(struct work_struct *work);
-struct assoc_request * wlan_get_association_request(wlan_adapter *adapter);
-
-void libertas_sync_channel(struct work_struct *work);
-
-#define ASSOC_DELAY (HZ / 2)
-static inline void wlan_postpone_association_work(wlan_private *priv)
-{
- if (priv->adapter->surpriseremoved)
- return;
- cancel_delayed_work(&priv->assoc_work);
- queue_delayed_work(priv->work_thread, &priv->assoc_work, ASSOC_DELAY);
-}
-
-static inline void wlan_cancel_association_work(wlan_private *priv)
-{
- cancel_delayed_work(&priv->assoc_work);
- if (priv->adapter->pending_assoc_req) {
- kfree(priv->adapter->pending_assoc_req);
- priv->adapter->pending_assoc_req = NULL;
- }
-}
-
-#endif /* _WLAN_ASSOC_H */
+#endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index be5cfd8402c7..eab020338fde 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -11,47 +11,139 @@
#include "dev.h"
#include "join.h"
#include "wext.h"
+#include "cmd.h"
-static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode);
+static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
+static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+ struct cmd_ctrl_node *ptempnode,
+ void *pdata_buf);
-static u16 commands_allowed_in_ps[] = {
- CMD_802_11_RSSI,
-};
/**
- * @brief This function checks if the commans is allowed
- * in PS mode not.
+ * @brief Checks whether a command is allowed in Power Save mode
*
* @param command the command ID
- * @return TRUE or FALSE
+ * @return 1 if allowed, 0 if not allowed
*/
-static u8 is_command_allowed_in_ps(__le16 command)
+static u8 is_command_allowed_in_ps(u16 cmd)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(commands_allowed_in_ps); i++) {
- if (command == cpu_to_le16(commands_allowed_in_ps[i]))
- return 1;
+ switch (cmd) {
+ case CMD_802_11_RSSI:
+ return 1;
+ default:
+ break;
}
-
return 0;
}
-static int wlan_cmd_hw_spec(wlan_private * priv, struct cmd_ds_command *cmd)
+/**
+ * @brief Updates the hardware details like MAC address and regulatory region
+ *
+ * @param priv A pointer to struct lbs_private structure
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_update_hw_spec(struct lbs_private *priv)
{
- struct cmd_ds_get_hw_spec *hwspec = &cmd->params.hwspec;
+ struct cmd_ds_get_hw_spec cmd;
+ int ret = -1;
+ u32 i;
+ DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_GET_HW_SPEC);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_get_hw_spec) + S_DS_GEN);
- memcpy(hwspec->permanentaddr, priv->adapter->current_addr, ETH_ALEN);
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
+ ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd);
+ if (ret)
+ goto out;
+
+ priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
+
+ /* The firmware release is in an interesting format: the patch
+ * level is in the most significant nibble ... so fix that: */
+ priv->fwrelease = le32_to_cpu(cmd.fwrelease);
+ priv->fwrelease = (priv->fwrelease << 8) |
+ (priv->fwrelease >> 24 & 0xff);
+
+ /* Some firmware capabilities:
+ * CF card firmware 5.0.16p0: cap 0x00000303
+ * USB dongle firmware 5.110.17p2: cap 0x00000303
+ */
+ printk("libertas: %s, fw %u.%u.%up%u, cap 0x%08x\n",
+ print_mac(mac, cmd.permanentaddr),
+ priv->fwrelease >> 24 & 0xff,
+ priv->fwrelease >> 16 & 0xff,
+ priv->fwrelease >> 8 & 0xff,
+ priv->fwrelease & 0xff,
+ priv->fwcapinfo);
+ lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
+ cmd.hwifversion, cmd.version);
+
+ /* Clamp region code to 8-bit since FW spec indicates that it should
+ * only ever be 8-bit, even though the field size is 16-bit. Some firmware
+ * returns non-zero high 8 bits here.
+ */
+ priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+
+ for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+ /* use the region code to search for the index */
+ if (priv->regioncode == lbs_region_code_to_index[i])
+ break;
+ }
+
+ /* if it's unidentified region code, use the default (USA) */
+ if (i >= MRVDRV_MAX_REGION_CODE) {
+ priv->regioncode = 0x10;
+ lbs_pr_info("unidentified region code; using the default (USA)\n");
+ }
+
+ if (priv->current_addr[0] == 0xff)
+ memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
+
+ memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
+ if (priv->mesh_dev)
+ memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
+
+ if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
+ ret = -1;
+ goto out;
+ }
+ if (lbs_set_universaltable(priv, 0)) {
+ ret = -1;
+ goto out;
+ }
+
+out:
lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ return ret;
}
-static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
+int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
+{
+ struct cmd_ds_host_sleep cmd_config;
+ int ret;
+
+ cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config));
+ cmd_config.criteria = cpu_to_le32(criteria);
+ cmd_config.gpio = priv->wol_gpio;
+ cmd_config.gap = priv->wol_gap;
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
+ if (!ret) {
+ lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
+ priv->wol_criteria = criteria;
+ } else {
+ lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
+
+static int lbs_cmd_802_11_ps_mode(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action)
{
@@ -90,161 +182,161 @@ static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
+ uint16_t cmd_action, uint16_t *timeout)
{
- u16 *timeout = pdata_buf;
+ struct cmd_ds_802_11_inactivity_timeout cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
- cmd->size =
- cpu_to_le16(sizeof(struct cmd_ds_802_11_inactivity_timeout)
- + S_DS_GEN);
+ cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- cmd->params.inactivity_timeout.action = cpu_to_le16(cmd_action);
+ cmd.action = cpu_to_le16(cmd_action);
- if (cmd_action)
- cmd->params.inactivity_timeout.timeout = cpu_to_le16(*timeout);
+ if (cmd_action == CMD_ACT_SET)
+ cmd.timeout = cpu_to_le16(*timeout);
else
- cmd->params.inactivity_timeout.timeout = 0;
+ cmd.timeout = 0;
- lbs_deb_leave(LBS_DEB_CMD);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
+
+ if (!ret)
+ *timeout = le16_to_cpu(cmd.timeout);
+
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return 0;
}
-static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action)
+int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
+ struct sleep_params *sp)
{
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ds_802_11_sleep_params *sp = &cmd->params.sleep_params;
+ struct cmd_ds_802_11_sleep_params cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->size = cpu_to_le16((sizeof(struct cmd_ds_802_11_sleep_params)) +
- S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_SLEEP_PARAMS);
-
if (cmd_action == CMD_ACT_GET) {
- memset(&adapter->sp, 0, sizeof(struct sleep_params));
- memset(sp, 0, sizeof(struct cmd_ds_802_11_sleep_params));
- sp->action = cpu_to_le16(cmd_action);
- } else if (cmd_action == CMD_ACT_SET) {
- sp->action = cpu_to_le16(cmd_action);
- sp->error = cpu_to_le16(adapter->sp.sp_error);
- sp->offset = cpu_to_le16(adapter->sp.sp_offset);
- sp->stabletime = cpu_to_le16(adapter->sp.sp_stabletime);
- sp->calcontrol = (u8) adapter->sp.sp_calcontrol;
- sp->externalsleepclk = (u8) adapter->sp.sp_extsleepclk;
- sp->reserved = cpu_to_le16(adapter->sp.sp_reserved);
+ memset(&cmd, 0, sizeof(cmd));
+ } else {
+ cmd.error = cpu_to_le16(sp->sp_error);
+ cmd.offset = cpu_to_le16(sp->sp_offset);
+ cmd.stabletime = cpu_to_le16(sp->sp_stabletime);
+ cmd.calcontrol = sp->sp_calcontrol;
+ cmd.externalsleepclk = sp->sp_extsleepclk;
+ cmd.reserved = cpu_to_le16(sp->sp_reserved);
+ }
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(cmd_action);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd);
+
+ if (!ret) {
+ lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
+ "calcontrol 0x%x extsleepclk 0x%x\n",
+ le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
+ le16_to_cpu(cmd.stabletime), cmd.calcontrol,
+ cmd.externalsleepclk);
+
+ sp->sp_error = le16_to_cpu(cmd.error);
+ sp->sp_offset = le16_to_cpu(cmd.offset);
+ sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
+ sp->sp_calcontrol = cmd.calcontrol;
+ sp->sp_extsleepclk = cmd.externalsleepclk;
+ sp->sp_reserved = le16_to_cpu(cmd.reserved);
}
- lbs_deb_leave(LBS_DEB_CMD);
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return 0;
}
-static int wlan_cmd_802_11_set_wep(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u32 cmd_act,
- void * pdata_buf)
+int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+ struct assoc_request *assoc)
{
- struct cmd_ds_802_11_set_wep *wep = &cmd->params.wep;
- wlan_adapter *adapter = priv->adapter;
+ struct cmd_ds_802_11_set_wep cmd;
int ret = 0;
- struct assoc_request * assoc_req = pdata_buf;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_SET_WEP);
- cmd->size = cpu_to_le16(sizeof(*wep) + S_DS_GEN);
-
- if (cmd_act == CMD_ACT_ADD) {
- int i;
+ cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
- if (!assoc_req) {
- lbs_deb_cmd("Invalid association request!");
- ret = -1;
- goto done;
- }
+ cmd.action = cpu_to_le16(cmd_action);
- wep->action = cpu_to_le16(CMD_ACT_ADD);
+ if (cmd_action == CMD_ACT_ADD) {
+ int i;
/* default tx key index */
- wep->keyindex = cpu_to_le16((u16)(assoc_req->wep_tx_keyidx &
- (u32)CMD_WEP_KEY_INDEX_MASK));
+ cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
+ CMD_WEP_KEY_INDEX_MASK);
/* Copy key types and material to host command structure */
for (i = 0; i < 4; i++) {
- struct enc_key * pkey = &assoc_req->wep_keys[i];
+ struct enc_key *pkey = &assoc->wep_keys[i];
switch (pkey->len) {
case KEY_LEN_WEP_40:
- wep->keytype[i] = CMD_TYPE_WEP_40_BIT;
- memmove(&wep->keymaterial[i], pkey->key,
- pkey->len);
+ cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
+ memmove(cmd.keymaterial[i], pkey->key, pkey->len);
lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
break;
case KEY_LEN_WEP_104:
- wep->keytype[i] = CMD_TYPE_WEP_104_BIT;
- memmove(&wep->keymaterial[i], pkey->key,
- pkey->len);
+ cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
+ memmove(cmd.keymaterial[i], pkey->key, pkey->len);
lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
break;
case 0:
break;
default:
lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
- i, pkey->len);
+ i, pkey->len);
ret = -1;
goto done;
break;
}
}
- } else if (cmd_act == CMD_ACT_REMOVE) {
+ } else if (cmd_action == CMD_ACT_REMOVE) {
/* ACT_REMOVE clears _all_ WEP keys */
- wep->action = cpu_to_le16(CMD_ACT_REMOVE);
/* default tx key index */
- wep->keyindex = cpu_to_le16((u16)(adapter->wep_tx_keyidx &
- (u32)CMD_WEP_KEY_INDEX_MASK));
- lbs_deb_cmd("SET_WEP: remove key %d\n", adapter->wep_tx_keyidx);
+ cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
+ CMD_WEP_KEY_INDEX_MASK);
+ lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
}
- ret = 0;
-
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
done:
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
-static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action,
- void * pdata_buf)
+int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ uint16_t *enable)
{
- struct cmd_ds_802_11_enable_rsn *penableRSN = &cmd->params.enbrsn;
- u32 * enable = pdata_buf;
+ struct cmd_ds_802_11_enable_rsn cmd;
+ int ret;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_ENABLE_RSN);
- cmd->size = cpu_to_le16(sizeof(*penableRSN) + S_DS_GEN);
- penableRSN->action = cpu_to_le16(cmd_action);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(cmd_action);
if (cmd_action == CMD_ACT_SET) {
if (*enable)
- penableRSN->enable = cpu_to_le16(CMD_ENABLE_RSN);
+ cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
else
- penableRSN->enable = cpu_to_le16(CMD_DISABLE_RSN);
+ cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
}
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
+ ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
+ if (!ret && cmd_action == CMD_ACT_GET)
+ *enable = le16_to_cpu(cmd.enable);
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
struct enc_key * pkey)
@@ -272,7 +364,7 @@ static void set_one_wpa_key(struct MrvlIEtype_keyParamSet * pkeyparamset,
lbs_deb_leave(LBS_DEB_CMD);
}
-static int wlan_cmd_802_11_key_material(wlan_private * priv,
+static int lbs_cmd_802_11_key_material(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action,
u32 cmd_oid, void *pdata_buf)
@@ -319,7 +411,7 @@ done:
return ret;
}
-static int wlan_cmd_802_11_reset(wlan_private * priv,
+static int lbs_cmd_802_11_reset(struct lbs_private *priv,
struct cmd_ds_command *cmd, int cmd_action)
{
struct cmd_ds_802_11_reset *reset = &cmd->params.reset;
@@ -334,7 +426,7 @@ static int wlan_cmd_802_11_reset(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_get_log(wlan_private * priv,
+static int lbs_cmd_802_11_get_log(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
lbs_deb_enter(LBS_DEB_CMD);
@@ -346,7 +438,7 @@ static int wlan_cmd_802_11_get_log(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_get_stat(wlan_private * priv,
+static int lbs_cmd_802_11_get_stat(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
lbs_deb_enter(LBS_DEB_CMD);
@@ -358,13 +450,12 @@ static int wlan_cmd_802_11_get_stat(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
+static int lbs_cmd_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *cmd,
int cmd_action,
int cmd_oid, void *pdata_buf)
{
struct cmd_ds_802_11_snmp_mib *pSNMPMIB = &cmd->params.smib;
- wlan_adapter *adapter = priv->adapter;
u8 ucTemp;
lbs_deb_enter(LBS_DEB_CMD);
@@ -380,7 +471,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
u8 mode = (u8) (size_t) pdata_buf;
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->oid = cpu_to_le16((u16) DESIRED_BSSTYPE_I);
- pSNMPMIB->bufsize = sizeof(u8);
+ pSNMPMIB->bufsize = cpu_to_le16(sizeof(u8));
if (mode == IW_MODE_ADHOC) {
ucTemp = SNMP_MIB_VALUE_ADHOC;
} else {
@@ -400,8 +491,8 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->oid = cpu_to_le16((u16) DOT11D_I);
if (cmd_action == CMD_ACT_SET) {
- pSNMPMIB->querytype = CMD_ACT_SET;
- pSNMPMIB->bufsize = sizeof(u16);
+ pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
+ pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
ulTemp = *(u32 *)pdata_buf;
*((__le16 *)(pSNMPMIB->value)) =
cpu_to_le16((u16) ulTemp);
@@ -433,7 +524,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
{
u32 ulTemp;
- pSNMPMIB->oid = le16_to_cpu((u16) RTSTHRESH_I);
+ pSNMPMIB->oid = cpu_to_le16(RTSTHRESH_I);
if (cmd_action == CMD_ACT_GET) {
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_GET);
@@ -456,7 +547,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
pSNMPMIB->querytype = cpu_to_le16(CMD_ACT_SET);
pSNMPMIB->bufsize = cpu_to_le16(sizeof(u16));
*((__le16 *)(pSNMPMIB->value)) =
- cpu_to_le16((u16) adapter->txretrycount);
+ cpu_to_le16((u16) priv->txretrycount);
}
break;
@@ -479,47 +570,7 @@ static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_radio_control(wlan_private * priv,
- struct cmd_ds_command *cmd,
- int cmd_action)
-{
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ds_802_11_radio_control *pradiocontrol = &cmd->params.radio;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- cmd->size =
- cpu_to_le16((sizeof(struct cmd_ds_802_11_radio_control)) +
- S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_RADIO_CONTROL);
-
- pradiocontrol->action = cpu_to_le16(cmd_action);
-
- switch (adapter->preamble) {
- case CMD_TYPE_SHORT_PREAMBLE:
- pradiocontrol->control = cpu_to_le16(SET_SHORT_PREAMBLE);
- break;
-
- case CMD_TYPE_LONG_PREAMBLE:
- pradiocontrol->control = cpu_to_le16(SET_LONG_PREAMBLE);
- break;
-
- case CMD_TYPE_AUTO_PREAMBLE:
- default:
- pradiocontrol->control = cpu_to_le16(SET_AUTO_PREAMBLE);
- break;
- }
-
- if (adapter->radioon)
- pradiocontrol->control |= cpu_to_le16(TURN_ON_RF);
- else
- pradiocontrol->control &= cpu_to_le16(~TURN_ON_RF);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
+static int lbs_cmd_802_11_rf_tx_power(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
@@ -563,7 +614,7 @@ static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_monitor_mode(wlan_private * priv,
+static int lbs_cmd_802_11_monitor_mode(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
@@ -583,13 +634,12 @@ static int wlan_cmd_802_11_monitor_mode(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
+static int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action)
{
struct cmd_ds_802_11_rate_adapt_rateset
*rateadapt = &cmd->params.rateset;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
cmd->size =
@@ -598,46 +648,100 @@ static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
cmd->command = cpu_to_le16(CMD_802_11_RATE_ADAPT_RATESET);
rateadapt->action = cpu_to_le16(cmd_action);
- rateadapt->enablehwauto = cpu_to_le16(adapter->enablehwauto);
- rateadapt->bitmap = cpu_to_le16(adapter->ratebitmap);
+ rateadapt->enablehwauto = cpu_to_le16(priv->enablehwauto);
+ rateadapt->bitmap = cpu_to_le16(priv->ratebitmap);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_cmd_802_11_data_rate(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action)
+/**
+ * @brief Get the current data rate
+ *
+ * @param priv A pointer to struct lbs_private structure
+ *
+ * @return The data rate on success, error on failure
+ */
+int lbs_get_data_rate(struct lbs_private *priv)
{
- struct cmd_ds_802_11_data_rate *pdatarate = &cmd->params.drate;
- wlan_adapter *adapter = priv->adapter;
+ struct cmd_ds_802_11_data_rate cmd;
+ int ret = -1;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_data_rate) +
- S_DS_GEN);
- cmd->command = cpu_to_le16(CMD_802_11_DATA_RATE);
- memset(pdatarate, 0, sizeof(struct cmd_ds_802_11_data_rate));
- pdatarate->action = cpu_to_le16(cmd_action);
-
- if (cmd_action == CMD_ACT_SET_TX_FIX_RATE) {
- pdatarate->rates[0] = libertas_data_rate_to_fw_index(adapter->cur_rate);
- lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n",
- adapter->cur_rate);
- } else if (cmd_action == CMD_ACT_SET_TX_AUTO) {
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_GET_TX_RATE);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
+ if (ret)
+ goto out;
+
+ lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
+
+ ret = (int) lbs_fw_index_to_data_rate(cmd.rates[0]);
+ lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", ret);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Set the data rate
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param rate The desired data rate, or 0 to clear a locked rate
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
+{
+ struct cmd_ds_802_11_data_rate cmd;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+ if (rate > 0) {
+ cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
+ cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
+ if (cmd.rates[0] == 0) {
+ lbs_deb_cmd("DATA_RATE: invalid requested rate of"
+ " 0x%02X\n", rate);
+ ret = 0;
+ goto out;
+ }
+ lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
+ } else {
+ cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
lbs_deb_cmd("DATA_RATE: setting auto\n");
}
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
+ if (ret)
+ goto out;
+
+ lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
+
+ /* FIXME: get actual rates FW can do if this command actually returns
+ * all data rates supported.
+ */
+ priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
+ lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
-static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
+static int lbs_cmd_mac_multicast_adr(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action)
{
struct cmd_ds_mac_multicast_adr *pMCastAdr = &cmd->params.madr;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_multicast_adr) +
@@ -647,39 +751,79 @@ static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
lbs_deb_cmd("MULTICAST_ADR: setting %d addresses\n", pMCastAdr->nr_of_adrs);
pMCastAdr->action = cpu_to_le16(cmd_action);
pMCastAdr->nr_of_adrs =
- cpu_to_le16((u16) adapter->nr_of_multicastmacaddr);
- memcpy(pMCastAdr->maclist, adapter->multicastlist,
- adapter->nr_of_multicastmacaddr * ETH_ALEN);
+ cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
+ memcpy(pMCastAdr->maclist, priv->multicastlist,
+ priv->nr_of_multicastmacaddr * ETH_ALEN);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
- struct cmd_ds_command *cmd,
- int option, void *pdata_buf)
+/**
+ * @brief Get the radio channel
+ *
+ * @param priv A pointer to struct lbs_private structure
+ *
+ * @return The channel on success, error on failure
+ */
+int lbs_get_channel(struct lbs_private *priv)
{
- struct cmd_ds_802_11_rf_channel *rfchan = &cmd->params.rfchannel;
+ struct cmd_ds_802_11_rf_channel cmd;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
- cmd->command = cpu_to_le16(CMD_802_11_RF_CHANNEL);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rf_channel) +
- S_DS_GEN);
- if (option == CMD_OPT_802_11_RF_CHANNEL_SET) {
- rfchan->currentchannel = cpu_to_le16(*((u16 *) pdata_buf));
- }
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET);
- rfchan->action = cpu_to_le16(option);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+ if (ret)
+ goto out;
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ ret = le16_to_cpu(cmd.channel);
+ lbs_deb_cmd("current radio channel is %d\n", ret);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
+}
+
+/**
+ * @brief Set the radio channel
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param channel The desired channel, or 0 to clear a locked channel
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_set_channel(struct lbs_private *priv, u8 channel)
+{
+ struct cmd_ds_802_11_rf_channel cmd;
+ u8 old_channel = priv->curbssparams.channel;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
+ cmd.channel = cpu_to_le16(channel);
+
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+ if (ret)
+ goto out;
+
+ priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
+ lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
+ priv->curbssparams.channel);
+
+out:
+ lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+ return ret;
}
-static int wlan_cmd_802_11_rssi(wlan_private * priv,
+static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_RSSI);
@@ -687,28 +831,28 @@ static int wlan_cmd_802_11_rssi(wlan_private * priv,
cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
/* reset Beacon SNR/NF/RSSI values */
- adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
- adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
- adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
- adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
- adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
- adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
+ priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
+ priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
+ priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
+ priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
+ priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
+ priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_cmd_reg_access(wlan_private * priv,
+static int lbs_cmd_reg_access(struct lbs_private *priv,
struct cmd_ds_command *cmdptr,
u8 cmd_action, void *pdata_buf)
{
- struct wlan_offset_value *offval;
+ struct lbs_offset_value *offval;
lbs_deb_enter(LBS_DEB_CMD);
- offval = (struct wlan_offset_value *)pdata_buf;
+ offval = (struct lbs_offset_value *)pdata_buf;
- switch (cmdptr->command) {
+ switch (le16_to_cpu(cmdptr->command)) {
case CMD_MAC_REG_ACCESS:
{
struct cmd_ds_mac_reg_access *macreg;
@@ -773,11 +917,10 @@ static int wlan_cmd_reg_access(wlan_private * priv,
return 0;
}
-static int wlan_cmd_802_11_mac_address(wlan_private * priv,
+static int lbs_cmd_802_11_mac_address(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action)
{
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
cmd->command = cpu_to_le16(CMD_802_11_MAC_ADDRESS);
@@ -789,19 +932,19 @@ static int wlan_cmd_802_11_mac_address(wlan_private * priv,
if (cmd_action == CMD_ACT_SET) {
memcpy(cmd->params.macadd.macadd,
- adapter->current_addr, ETH_ALEN);
- lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", adapter->current_addr, 6);
+ priv->current_addr, ETH_ALEN);
+ lbs_deb_hex(LBS_DEB_CMD, "SET_CMD: MAC addr", priv->current_addr, 6);
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
+static int lbs_cmd_802_11_eeprom_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
int cmd_action, void *pdata_buf)
{
- struct wlan_ioctl_regrdwr *ea = pdata_buf;
+ struct lbs_ioctl_regrdwr *ea = pdata_buf;
lbs_deb_enter(LBS_DEB_CMD);
@@ -819,7 +962,7 @@ static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
return 0;
}
-static int wlan_cmd_bt_access(wlan_private * priv,
+static int lbs_cmd_bt_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
@@ -857,7 +1000,7 @@ static int wlan_cmd_bt_access(wlan_private * priv,
return 0;
}
-static int wlan_cmd_fwt_access(wlan_private * priv,
+static int lbs_cmd_fwt_access(struct lbs_private *priv,
struct cmd_ds_command *cmd,
u16 cmd_action, void *pdata_buf)
{
@@ -879,47 +1022,72 @@ static int wlan_cmd_fwt_access(wlan_private * priv,
return 0;
}
-static int wlan_cmd_mesh_access(wlan_private * priv,
- struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+ struct cmd_ds_mesh_access *cmd)
{
- struct cmd_ds_mesh_access *mesh_access = &cmd->params.mesh;
+ int ret;
+
lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
- cmd->command = cpu_to_le16(CMD_MESH_ACCESS);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mesh_access) + S_DS_GEN);
- cmd->result = 0;
+ cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+ cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+ cmd->hdr.result = 0;
- if (pdata_buf)
- memcpy(mesh_access, pdata_buf, sizeof(*mesh_access));
- else
- memset(mesh_access, 0, sizeof(*mesh_access));
+ cmd->action = cpu_to_le16(cmd_action);
- mesh_access->action = cpu_to_le16(cmd_action);
+ ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
lbs_deb_leave(LBS_DEB_CMD);
- return 0;
+ return ret;
}
+EXPORT_SYMBOL_GPL(lbs_mesh_access);
-static int wlan_cmd_set_boot2_ver(wlan_private * priv,
+int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan)
+{
+ struct cmd_ds_mesh_config cmd;
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.action = cpu_to_le16(enable);
+ cmd.channel = cpu_to_le16(chan);
+ cmd.type = cpu_to_le16(priv->mesh_tlv);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+ if (enable) {
+ cmd.length = cpu_to_le16(priv->mesh_ssid_len);
+ memcpy(cmd.data, priv->mesh_ssid, priv->mesh_ssid_len);
+ }
+ lbs_deb_cmd("mesh config enable %d TLV %x channel %d SSID %s\n",
+ enable, priv->mesh_tlv, chan,
+ escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
+ return lbs_cmd_with_response(priv, CMD_MESH_CONFIG, &cmd);
+}
+
+static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
struct cmd_ds_command *cmd,
- u16 cmd_action, void *pdata_buf)
+ u16 cmd_action)
{
- struct cmd_ds_set_boot2_ver *boot2_ver = &cmd->params.boot2_ver;
- cmd->command = cpu_to_le16(CMD_SET_BOOT2_VER);
- cmd->size = cpu_to_le16(sizeof(struct cmd_ds_set_boot2_ver) + S_DS_GEN);
- boot2_ver->version = priv->boot2_version;
+ struct cmd_ds_802_11_beacon_control
+ *bcn_ctrl = &cmd->params.bcn_ctrl;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+ cmd->size =
+ cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
+ + S_DS_GEN);
+ cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
+
+ bcn_ctrl->action = cpu_to_le16(cmd_action);
+ bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
+ bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
+
+ lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-/*
- * Note: NEVER use libertas_queue_cmd() with addtail==0 other than for
- * the command timer, because it does not account for queued commands.
- */
-void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail)
+static void lbs_queue_cmd(struct lbs_private *priv,
+ struct cmd_ctrl_node *cmdnode)
{
unsigned long flags;
- struct cmd_ds_command *cmdptr;
+ int addtail = 1;
lbs_deb_enter(LBS_DEB_HOST);
@@ -927,118 +1095,87 @@ void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u
lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n");
goto done;
}
-
- cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
- if (!cmdptr) {
- lbs_deb_host("QUEUE_CMD: cmdptr is NULL\n");
+ if (!cmdnode->cmdbuf->size) {
+ lbs_deb_host("DNLD_CMD: cmd size is zero\n");
goto done;
}
+ cmdnode->result = 0;
/* Exit_PS command needs to be queued in the header always. */
- if (cmdptr->command == CMD_802_11_PS_MODE) {
- struct cmd_ds_802_11_ps_mode *psm = &cmdptr->params.psmode;
+ if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
+ struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
+
if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
- if (adapter->psstate != PS_STATE_FULL_POWER)
+ if (priv->psstate != PS_STATE_FULL_POWER)
addtail = 0;
}
}
- spin_lock_irqsave(&adapter->driver_lock, flags);
+ spin_lock_irqsave(&priv->driver_lock, flags);
- if (addtail) {
- list_add_tail((struct list_head *)cmdnode,
- &adapter->cmdpendingq);
- adapter->nr_cmd_pending++;
- } else
- list_add((struct list_head *)cmdnode, &adapter->cmdpendingq);
+ if (addtail)
+ list_add_tail(&cmdnode->list, &priv->cmdpendingq);
+ else
+ list_add(&cmdnode->list, &priv->cmdpendingq);
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
- le16_to_cpu(((struct cmd_ds_gen*)cmdnode->bufvirtualaddr)->command));
+ le16_to_cpu(cmdnode->cmdbuf->command));
done:
lbs_deb_leave(LBS_DEB_HOST);
}
-/*
- * TODO: Fix the issue when DownloadcommandToStation is being called the
- * second time when the command times out. All the cmdptr->xxx are in little
- * endian and therefore all the comparissions will fail.
- * For now - we are not performing the endian conversion the second time - but
- * for PS and DEEP_SLEEP we need to worry
- */
-static int DownloadcommandToStation(wlan_private * priv,
- struct cmd_ctrl_node *cmdnode)
+static void lbs_submit_command(struct lbs_private *priv,
+ struct cmd_ctrl_node *cmdnode)
{
unsigned long flags;
- struct cmd_ds_command *cmdptr;
- wlan_adapter *adapter = priv->adapter;
- int ret = -1;
- u16 cmdsize;
- u16 command;
+ struct cmd_header *cmd;
+ uint16_t cmdsize;
+ uint16_t command;
+ int timeo = 5 * HZ;
+ int ret;
lbs_deb_enter(LBS_DEB_HOST);
- if (!adapter || !cmdnode) {
- lbs_deb_host("DNLD_CMD: adapter or cmdmode is NULL\n");
- goto done;
- }
+ cmd = cmdnode->cmdbuf;
- cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->cur_cmd = cmdnode;
+ priv->cur_cmd_retcode = 0;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (!cmdptr || !cmdptr->size) {
- lbs_deb_host("DNLD_CMD: cmdptr is NULL or zero\n");
- __libertas_cleanup_and_insert_cmd(priv, cmdnode);
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
- goto done;
- }
+ cmdsize = le16_to_cpu(cmd->size);
+ command = le16_to_cpu(cmd->command);
- adapter->cur_cmd = cmdnode;
- adapter->cur_cmd_retcode = 0;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ /* These commands take longer */
+ if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
+ command == CMD_802_11_AUTHENTICATE)
+ timeo = 10 * HZ;
- cmdsize = cmdptr->size;
- command = cpu_to_le16(cmdptr->command);
+ lbs_deb_host("DNLD_CMD: command 0x%04x, seq %d, size %d, jiffies %lu\n",
+ command, le16_to_cpu(cmd->seqnum), cmdsize, jiffies);
+ lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
- lbs_deb_host("DNLD_CMD: command 0x%04x, size %d, jiffies %lu\n",
- command, le16_to_cpu(cmdptr->size), jiffies);
- lbs_deb_hex(LBS_DEB_HOST, "DNLD_CMD", cmdnode->bufvirtualaddr, cmdsize);
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
- cmdnode->cmdwaitqwoken = 0;
- cmdsize = cpu_to_le16(cmdsize);
-
- ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmdptr, cmdsize);
-
- if (ret != 0) {
- lbs_deb_host("DNLD_CMD: hw_host_to_card failed\n");
- spin_lock_irqsave(&adapter->driver_lock, flags);
- adapter->cur_cmd_retcode = ret;
- __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
- adapter->nr_cmd_pending--;
- adapter->cur_cmd = NULL;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
- goto done;
- }
-
- lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n", command, jiffies);
+ if (ret) {
+ lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
+ /* Let the timer kick in and retry, and potentially reset
+ the whole thing if the condition persists */
+ timeo = HZ;
+ } else
+ lbs_deb_cmd("DNLD_CMD: sent command 0x%04x, jiffies %lu\n",
+ command, jiffies);
/* Setup the timer after transmit command */
- if (command == CMD_802_11_SCAN || command == CMD_802_11_AUTHENTICATE
- || command == CMD_802_11_ASSOCIATE)
- mod_timer(&adapter->command_timer, jiffies + (10*HZ));
- else
- mod_timer(&adapter->command_timer, jiffies + (5*HZ));
-
- ret = 0;
+ mod_timer(&priv->command_timer, jiffies + timeo);
-done:
- lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
- return ret;
+ lbs_deb_leave(LBS_DEB_HOST);
}
-static int wlan_cmd_mac_control(wlan_private * priv,
+static int lbs_cmd_mac_control(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
struct cmd_ds_mac_control *mac = &cmd->params.macctrl;
@@ -1047,7 +1184,7 @@ static int wlan_cmd_mac_control(wlan_private * priv,
cmd->command = cpu_to_le16(CMD_MAC_CONTROL);
cmd->size = cpu_to_le16(sizeof(struct cmd_ds_mac_control) + S_DS_GEN);
- mac->action = cpu_to_le16(priv->adapter->currentpacketfilter);
+ mac->action = cpu_to_le16(priv->currentpacketfilter);
lbs_deb_cmd("MAC_CONTROL: action 0x%x, size %d\n",
le16_to_cpu(mac->action), le16_to_cpu(cmd->size));
@@ -1058,54 +1195,98 @@ static int wlan_cmd_mac_control(wlan_private * priv,
/**
* This function inserts command node to cmdfreeq
- * after cleans it. Requires adapter->driver_lock held.
+ * after cleans it. Requires priv->driver_lock held.
*/
-void __libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
+static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
+ struct cmd_ctrl_node *cmdnode)
{
- wlan_adapter *adapter = priv->adapter;
+ lbs_deb_enter(LBS_DEB_HOST);
- if (!ptempcmd)
- return;
+ if (!cmdnode)
+ goto out;
+
+ cmdnode->callback = NULL;
+ cmdnode->callback_arg = 0;
- cleanup_cmdnode(ptempcmd);
- list_add_tail((struct list_head *)ptempcmd, &adapter->cmdfreeq);
+ memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
+
+ list_add_tail(&cmdnode->list, &priv->cmdfreeq);
+ out:
+ lbs_deb_leave(LBS_DEB_HOST);
}
-static void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct cmd_ctrl_node *ptempcmd)
+static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
+ struct cmd_ctrl_node *ptempcmd)
{
unsigned long flags;
- spin_lock_irqsave(&priv->adapter->driver_lock, flags);
- __libertas_cleanup_and_insert_cmd(priv, ptempcmd);
- spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ __lbs_cleanup_and_insert_cmd(priv, ptempcmd);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
}
-int libertas_set_radio_control(wlan_private * priv)
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result)
+{
+ if (cmd == priv->cur_cmd)
+ priv->cur_cmd_retcode = result;
+
+ cmd->result = result;
+ cmd->cmdwaitqwoken = 1;
+ wake_up_interruptible(&cmd->cmdwait_q);
+
+ if (!cmd->callback)
+ __lbs_cleanup_and_insert_cmd(priv, cmd);
+ priv->cur_cmd = NULL;
+}
+
+int lbs_set_radio_control(struct lbs_private *priv)
{
int ret = 0;
+ struct cmd_ds_802_11_radio_control cmd;
lbs_deb_enter(LBS_DEB_CMD);
- ret = libertas_prepare_and_send_command(priv,
- CMD_802_11_RADIO_CONTROL,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+ cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+ cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+ switch (priv->preamble) {
+ case CMD_TYPE_SHORT_PREAMBLE:
+ cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE);
+ break;
+
+ case CMD_TYPE_LONG_PREAMBLE:
+ cmd.control = cpu_to_le16(SET_LONG_PREAMBLE);
+ break;
+
+ case CMD_TYPE_AUTO_PREAMBLE:
+ default:
+ cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE);
+ break;
+ }
+
+ if (priv->radioon)
+ cmd.control |= cpu_to_le16(TURN_ON_RF);
+ else
+ cmd.control &= cpu_to_le16(~TURN_ON_RF);
+
+ lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
+ priv->preamble);
- lbs_deb_cmd("RADIO_SET: radio %d, preamble %d\n",
- priv->adapter->radioon, priv->adapter->preamble);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
}
-int libertas_set_mac_packet_filter(wlan_private * priv)
+int lbs_set_mac_packet_filter(struct lbs_private *priv)
{
int ret = 0;
lbs_deb_enter(LBS_DEB_CMD);
/* Send MAC control command to station */
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_MAC_CONTROL, 0, 0, 0, NULL);
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
@@ -1115,7 +1296,7 @@ int libertas_set_mac_packet_filter(wlan_private * priv)
/**
* @brief This function prepare the command before send to firmware.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param cmd_no command number
* @param cmd_action command action: GET or SET
* @param wait_option wait option: wait response or not
@@ -1123,32 +1304,31 @@ int libertas_set_mac_packet_filter(wlan_private * priv)
* @param pdata_buf A pointer to informaion buffer
* @return 0 or -1
*/
-int libertas_prepare_and_send_command(wlan_private * priv,
+int lbs_prepare_and_send_command(struct lbs_private *priv,
u16 cmd_no,
u16 cmd_action,
u16 wait_option, u32 cmd_oid, void *pdata_buf)
{
int ret = 0;
- wlan_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmdnode;
struct cmd_ds_command *cmdptr;
unsigned long flags;
lbs_deb_enter(LBS_DEB_HOST);
- if (!adapter) {
- lbs_deb_host("PREP_CMD: adapter is NULL\n");
+ if (!priv) {
+ lbs_deb_host("PREP_CMD: priv is NULL\n");
ret = -1;
goto done;
}
- if (adapter->surpriseremoved) {
+ if (priv->surpriseremoved) {
lbs_deb_host("PREP_CMD: card removed\n");
ret = -1;
goto done;
}
- cmdnode = libertas_get_free_cmd_ctrl_node(priv);
+ cmdnode = lbs_get_cmd_ctrl_node(priv);
if (cmdnode == NULL) {
lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
@@ -1159,138 +1339,107 @@ int libertas_prepare_and_send_command(wlan_private * priv,
goto done;
}
- libertas_set_cmd_ctrl_node(priv, cmdnode, cmd_oid, wait_option, pdata_buf);
+ lbs_set_cmd_ctrl_node(priv, cmdnode, pdata_buf);
- cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
+ cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
- if (!cmdptr) {
- lbs_deb_host("PREP_CMD: cmdptr is NULL\n");
- libertas_cleanup_and_insert_cmd(priv, cmdnode);
- ret = -1;
- goto done;
- }
-
/* Set sequence number, command and INT option */
- adapter->seqnum++;
- cmdptr->seqnum = cpu_to_le16(adapter->seqnum);
+ priv->seqnum++;
+ cmdptr->seqnum = cpu_to_le16(priv->seqnum);
cmdptr->command = cpu_to_le16(cmd_no);
cmdptr->result = 0;
switch (cmd_no) {
- case CMD_GET_HW_SPEC:
- ret = wlan_cmd_hw_spec(priv, cmdptr);
- break;
case CMD_802_11_PS_MODE:
- ret = wlan_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
+ ret = lbs_cmd_802_11_ps_mode(priv, cmdptr, cmd_action);
break;
case CMD_802_11_SCAN:
- ret = libertas_cmd_80211_scan(priv, cmdptr, pdata_buf);
+ ret = lbs_cmd_80211_scan(priv, cmdptr, pdata_buf);
break;
case CMD_MAC_CONTROL:
- ret = wlan_cmd_mac_control(priv, cmdptr);
+ ret = lbs_cmd_mac_control(priv, cmdptr);
break;
case CMD_802_11_ASSOCIATE:
case CMD_802_11_REASSOCIATE:
- ret = libertas_cmd_80211_associate(priv, cmdptr, pdata_buf);
+ ret = lbs_cmd_80211_associate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_DEAUTHENTICATE:
- ret = libertas_cmd_80211_deauthenticate(priv, cmdptr);
- break;
-
- case CMD_802_11_SET_WEP:
- ret = wlan_cmd_802_11_set_wep(priv, cmdptr, cmd_action, pdata_buf);
+ ret = lbs_cmd_80211_deauthenticate(priv, cmdptr);
break;
case CMD_802_11_AD_HOC_START:
- ret = libertas_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
+ ret = lbs_cmd_80211_ad_hoc_start(priv, cmdptr, pdata_buf);
break;
case CMD_CODE_DNLD:
break;
case CMD_802_11_RESET:
- ret = wlan_cmd_802_11_reset(priv, cmdptr, cmd_action);
+ ret = lbs_cmd_802_11_reset(priv, cmdptr, cmd_action);
break;
case CMD_802_11_GET_LOG:
- ret = wlan_cmd_802_11_get_log(priv, cmdptr);
+ ret = lbs_cmd_802_11_get_log(priv, cmdptr);
break;
case CMD_802_11_AUTHENTICATE:
- ret = libertas_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
+ ret = lbs_cmd_80211_authenticate(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_GET_STAT:
- ret = wlan_cmd_802_11_get_stat(priv, cmdptr);
+ ret = lbs_cmd_802_11_get_stat(priv, cmdptr);
break;
case CMD_802_11_SNMP_MIB:
- ret = wlan_cmd_802_11_snmp_mib(priv, cmdptr,
+ ret = lbs_cmd_802_11_snmp_mib(priv, cmdptr,
cmd_action, cmd_oid, pdata_buf);
break;
case CMD_MAC_REG_ACCESS:
case CMD_BBP_REG_ACCESS:
case CMD_RF_REG_ACCESS:
- ret = wlan_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_802_11_RF_CHANNEL:
- ret = wlan_cmd_802_11_rf_channel(priv, cmdptr,
- cmd_action, pdata_buf);
+ ret = lbs_cmd_reg_access(priv, cmdptr, cmd_action, pdata_buf);
break;
case CMD_802_11_RF_TX_POWER:
- ret = wlan_cmd_802_11_rf_tx_power(priv, cmdptr,
+ ret = lbs_cmd_802_11_rf_tx_power(priv, cmdptr,
cmd_action, pdata_buf);
break;
- case CMD_802_11_RADIO_CONTROL:
- ret = wlan_cmd_802_11_radio_control(priv, cmdptr, cmd_action);
- break;
-
- case CMD_802_11_DATA_RATE:
- ret = wlan_cmd_802_11_data_rate(priv, cmdptr, cmd_action);
- break;
case CMD_802_11_RATE_ADAPT_RATESET:
- ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
+ ret = lbs_cmd_802_11_rate_adapt_rateset(priv,
cmdptr, cmd_action);
break;
case CMD_MAC_MULTICAST_ADR:
- ret = wlan_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
+ ret = lbs_cmd_mac_multicast_adr(priv, cmdptr, cmd_action);
break;
case CMD_802_11_MONITOR_MODE:
- ret = wlan_cmd_802_11_monitor_mode(priv, cmdptr,
+ ret = lbs_cmd_802_11_monitor_mode(priv, cmdptr,
cmd_action, pdata_buf);
break;
case CMD_802_11_AD_HOC_JOIN:
- ret = libertas_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
+ ret = lbs_cmd_80211_ad_hoc_join(priv, cmdptr, pdata_buf);
break;
case CMD_802_11_RSSI:
- ret = wlan_cmd_802_11_rssi(priv, cmdptr);
+ ret = lbs_cmd_802_11_rssi(priv, cmdptr);
break;
case CMD_802_11_AD_HOC_STOP:
- ret = libertas_cmd_80211_ad_hoc_stop(priv, cmdptr);
- break;
-
- case CMD_802_11_ENABLE_RSN:
- ret = wlan_cmd_802_11_enable_rsn(priv, cmdptr, cmd_action,
- pdata_buf);
+ ret = lbs_cmd_80211_ad_hoc_stop(priv, cmdptr);
break;
case CMD_802_11_KEY_MATERIAL:
- ret = wlan_cmd_802_11_key_material(priv, cmdptr, cmd_action,
+ ret = lbs_cmd_802_11_key_material(priv, cmdptr, cmd_action,
cmd_oid, pdata_buf);
break;
@@ -1300,11 +1449,11 @@ int libertas_prepare_and_send_command(wlan_private * priv,
break;
case CMD_802_11_MAC_ADDRESS:
- ret = wlan_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
+ ret = lbs_cmd_802_11_mac_address(priv, cmdptr, cmd_action);
break;
case CMD_802_11_EEPROM_ACCESS:
- ret = wlan_cmd_802_11_eeprom_access(priv, cmdptr,
+ ret = lbs_cmd_802_11_eeprom_access(priv, cmdptr,
cmd_action, pdata_buf);
break;
@@ -1322,19 +1471,10 @@ int libertas_prepare_and_send_command(wlan_private * priv,
goto done;
case CMD_802_11D_DOMAIN_INFO:
- ret = libertas_cmd_802_11d_domain_info(priv, cmdptr,
+ ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
cmd_no, cmd_action);
break;
- case CMD_802_11_SLEEP_PARAMS:
- ret = wlan_cmd_802_11_sleep_params(priv, cmdptr, cmd_action);
- break;
- case CMD_802_11_INACTIVITY_TIMEOUT:
- ret = wlan_cmd_802_11_inactivity_timeout(priv, cmdptr,
- cmd_action, pdata_buf);
- libertas_set_cmd_ctrl_node(priv, cmdnode, 0, 0, pdata_buf);
- break;
-
case CMD_802_11_TPC_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
cmdptr->size =
@@ -1361,13 +1501,15 @@ int libertas_prepare_and_send_command(wlan_private * priv,
#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
cmdptr->size =
- cpu_to_le16(gpio->header.len + S_DS_GEN +
- ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
- gpio->header.len = cpu_to_le16(gpio->header.len);
+ cpu_to_le16(le16_to_cpu(gpio->header.len)
+ + S_DS_GEN
+ + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
+ gpio->header.len = gpio->header.len;
ret = 0;
break;
}
+
case CMD_802_11_PWR_CFG:
cmdptr->command = cpu_to_le16(CMD_802_11_PWR_CFG);
cmdptr->size =
@@ -1379,19 +1521,11 @@ int libertas_prepare_and_send_command(wlan_private * priv,
ret = 0;
break;
case CMD_BT_ACCESS:
- ret = wlan_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
+ ret = lbs_cmd_bt_access(priv, cmdptr, cmd_action, pdata_buf);
break;
case CMD_FWT_ACCESS:
- ret = wlan_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_MESH_ACCESS:
- ret = wlan_cmd_mesh_access(priv, cmdptr, cmd_action, pdata_buf);
- break;
-
- case CMD_SET_BOOT2_VER:
- ret = wlan_cmd_set_boot2_ver(priv, cmdptr, cmd_action, pdata_buf);
+ ret = lbs_cmd_fwt_access(priv, cmdptr, cmd_action, pdata_buf);
break;
case CMD_GET_TSF:
@@ -1400,6 +1534,9 @@ int libertas_prepare_and_send_command(wlan_private * priv,
S_DS_GEN);
ret = 0;
break;
+ case CMD_802_11_BEACON_CTRL:
+ ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
+ break;
default:
lbs_deb_host("PREP_CMD: unknown command 0x%04x\n", cmd_no);
ret = -1;
@@ -1409,14 +1546,14 @@ int libertas_prepare_and_send_command(wlan_private * priv,
/* return error, since the command preparation failed */
if (ret != 0) {
lbs_deb_host("PREP_CMD: command preparation failed\n");
- libertas_cleanup_and_insert_cmd(priv, cmdnode);
+ lbs_cleanup_and_insert_cmd(priv, cmdnode);
ret = -1;
goto done;
}
cmdnode->cmdwaitqwoken = 0;
- libertas_queue_cmd(adapter, cmdnode, 1);
+ lbs_queue_cmd(priv, cmdnode);
wake_up_interruptible(&priv->waitq);
if (wait_option & CMD_OPTION_WAITFORRSP) {
@@ -1426,67 +1563,60 @@ int libertas_prepare_and_send_command(wlan_private * priv,
cmdnode->cmdwaitqwoken);
}
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->cur_cmd_retcode) {
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->cur_cmd_retcode) {
lbs_deb_host("PREP_CMD: command failed with return code %d\n",
- adapter->cur_cmd_retcode);
- adapter->cur_cmd_retcode = 0;
+ priv->cur_cmd_retcode);
+ priv->cur_cmd_retcode = 0;
ret = -1;
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
done:
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_prepare_and_send_command);
+EXPORT_SYMBOL_GPL(lbs_prepare_and_send_command);
/**
* @brief This function allocates the command buffer and link
* it to command free queue.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return 0 or -1
*/
-int libertas_allocate_cmd_buffer(wlan_private * priv)
+int lbs_allocate_cmd_buffer(struct lbs_private *priv)
{
int ret = 0;
- u32 ulbufsize;
+ u32 bufsize;
u32 i;
- struct cmd_ctrl_node *tempcmd_array;
- u8 *ptempvirtualaddr;
- wlan_adapter *adapter = priv->adapter;
+ struct cmd_ctrl_node *cmdarray;
lbs_deb_enter(LBS_DEB_HOST);
- /* Allocate and initialize cmdCtrlNode */
- ulbufsize = sizeof(struct cmd_ctrl_node) * MRVDRV_NUM_OF_CMD_BUFFER;
-
- if (!(tempcmd_array = kzalloc(ulbufsize, GFP_KERNEL))) {
+ /* Allocate and initialize the command array */
+ bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
+ if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) {
lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
ret = -1;
goto done;
}
- adapter->cmd_array = tempcmd_array;
+ priv->cmd_array = cmdarray;
- /* Allocate and initialize command buffers */
- ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
- for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
- if (!(ptempvirtualaddr = kzalloc(ulbufsize, GFP_KERNEL))) {
+ /* Allocate and initialize each command buffer in the command array */
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
+ if (!cmdarray[i].cmdbuf) {
lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
ret = -1;
goto done;
}
-
- /* Update command buffer virtual */
- tempcmd_array[i].bufvirtualaddr = ptempvirtualaddr;
}
- for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
- init_waitqueue_head(&tempcmd_array[i].cmdwait_q);
- libertas_cleanup_and_insert_cmd(priv, &tempcmd_array[i]);
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ init_waitqueue_head(&cmdarray[i].cmdwait_q);
+ lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]);
}
-
ret = 0;
done:
@@ -1497,39 +1627,36 @@ done:
/**
* @brief This function frees the command buffer.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return 0 or -1
*/
-int libertas_free_cmd_buffer(wlan_private * priv)
+int lbs_free_cmd_buffer(struct lbs_private *priv)
{
- u32 ulbufsize; /* Someone needs to die for this. Slowly and painfully */
+ struct cmd_ctrl_node *cmdarray;
unsigned int i;
- struct cmd_ctrl_node *tempcmd_array;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_HOST);
/* need to check if cmd array is allocated or not */
- if (adapter->cmd_array == NULL) {
+ if (priv->cmd_array == NULL) {
lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
goto done;
}
- tempcmd_array = adapter->cmd_array;
+ cmdarray = priv->cmd_array;
/* Release shared memory buffers */
- ulbufsize = MRVDRV_SIZE_OF_CMD_BUFFER;
- for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
- if (tempcmd_array[i].bufvirtualaddr) {
- kfree(tempcmd_array[i].bufvirtualaddr);
- tempcmd_array[i].bufvirtualaddr = NULL;
+ for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
+ if (cmdarray[i].cmdbuf) {
+ kfree(cmdarray[i].cmdbuf);
+ cmdarray[i].cmdbuf = NULL;
}
}
/* Release cmd_ctrl_node */
- if (adapter->cmd_array) {
- kfree(adapter->cmd_array);
- adapter->cmd_array = NULL;
+ if (priv->cmd_array) {
+ kfree(priv->cmd_array);
+ priv->cmd_array = NULL;
}
done:
@@ -1541,34 +1668,31 @@ done:
* @brief This function gets a free command node if available in
* command free queue.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
*/
-struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
+static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
{
struct cmd_ctrl_node *tempnode;
- wlan_adapter *adapter = priv->adapter;
unsigned long flags;
lbs_deb_enter(LBS_DEB_HOST);
- if (!adapter)
+ if (!priv)
return NULL;
- spin_lock_irqsave(&adapter->driver_lock, flags);
+ spin_lock_irqsave(&priv->driver_lock, flags);
- if (!list_empty(&adapter->cmdfreeq)) {
- tempnode = (struct cmd_ctrl_node *)adapter->cmdfreeq.next;
- list_del((struct list_head *)tempnode);
+ if (!list_empty(&priv->cmdfreeq)) {
+ tempnode = list_first_entry(&priv->cmdfreeq,
+ struct cmd_ctrl_node, list);
+ list_del(&tempnode->list);
} else {
lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
tempnode = NULL;
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
-
- if (tempnode)
- cleanup_cmdnode(tempnode);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_leave(LBS_DEB_HOST);
return tempnode;
@@ -1580,47 +1704,26 @@ struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
* @param ptempnode A pointer to cmdCtrlNode structure
* @return n/a
*/
-static void cleanup_cmdnode(struct cmd_ctrl_node *ptempnode)
-{
- lbs_deb_enter(LBS_DEB_HOST);
-
- if (!ptempnode)
- return;
- ptempnode->cmdwaitqwoken = 1;
- wake_up_interruptible(&ptempnode->cmdwait_q);
- ptempnode->status = 0;
- ptempnode->cmd_oid = (u32) 0;
- ptempnode->wait_option = 0;
- ptempnode->pdata_buf = NULL;
-
- if (ptempnode->bufvirtualaddr != NULL)
- memset(ptempnode->bufvirtualaddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
-
- lbs_deb_leave(LBS_DEB_HOST);
-}
/**
* @brief This function initializes the command node.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param ptempnode A pointer to cmd_ctrl_node structure
- * @param cmd_oid cmd oid: treated as sub command
- * @param wait_option wait option: wait response or not
* @param pdata_buf A pointer to informaion buffer
* @return 0 or -1
*/
-void libertas_set_cmd_ctrl_node(wlan_private * priv,
- struct cmd_ctrl_node *ptempnode,
- u32 cmd_oid, u16 wait_option, void *pdata_buf)
+static void lbs_set_cmd_ctrl_node(struct lbs_private *priv,
+ struct cmd_ctrl_node *ptempnode,
+ void *pdata_buf)
{
lbs_deb_enter(LBS_DEB_HOST);
if (!ptempnode)
return;
- ptempnode->cmd_oid = cmd_oid;
- ptempnode->wait_option = wait_option;
- ptempnode->pdata_buf = pdata_buf;
+ ptempnode->callback = NULL;
+ ptempnode->callback_arg = (unsigned long)pdata_buf;
lbs_deb_leave(LBS_DEB_HOST);
}
@@ -1630,60 +1733,58 @@ void libertas_set_cmd_ctrl_node(wlan_private * priv,
* pending queue. It will put fimware back to PS mode
* if applicable.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return 0 or -1
*/
-int libertas_execute_next_command(wlan_private * priv)
+int lbs_execute_next_command(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmdnode = NULL;
- struct cmd_ds_command *cmdptr;
+ struct cmd_header *cmd;
unsigned long flags;
int ret = 0;
// Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
- // only caller to us is libertas_thread() and we get even when a
+ // only caller to us is lbs_thread() and we get even when a
// data packet is received
lbs_deb_enter(LBS_DEB_THREAD);
- spin_lock_irqsave(&adapter->driver_lock, flags);
+ spin_lock_irqsave(&priv->driver_lock, flags);
- if (adapter->cur_cmd) {
+ if (priv->cur_cmd) {
lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n");
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
- if (!list_empty(&adapter->cmdpendingq)) {
- cmdnode = (struct cmd_ctrl_node *)
- adapter->cmdpendingq.next;
+ if (!list_empty(&priv->cmdpendingq)) {
+ cmdnode = list_first_entry(&priv->cmdpendingq,
+ struct cmd_ctrl_node, list);
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
if (cmdnode) {
- cmdptr = (struct cmd_ds_command *)cmdnode->bufvirtualaddr;
+ cmd = cmdnode->cmdbuf;
- if (is_command_allowed_in_ps(cmdptr->command)) {
- if ((adapter->psstate == PS_STATE_SLEEP) ||
- (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+ if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
+ if ((priv->psstate == PS_STATE_SLEEP) ||
+ (priv->psstate == PS_STATE_PRE_SLEEP)) {
lbs_deb_host(
"EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
- le16_to_cpu(cmdptr->command),
- adapter->psstate);
+ le16_to_cpu(cmd->command),
+ priv->psstate);
ret = -1;
goto done;
}
lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
- "0x%04x in psstate %d\n",
- le16_to_cpu(cmdptr->command),
- adapter->psstate);
- } else if (adapter->psstate != PS_STATE_FULL_POWER) {
+ "0x%04x in psstate %d\n",
+ le16_to_cpu(cmd->command), priv->psstate);
+ } else if (priv->psstate != PS_STATE_FULL_POWER) {
/*
* 1. Non-PS command:
* Queue it. set needtowakeup to TRUE if current state
- * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
+ * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
* 2. PS command but not Exit_PS:
* Ignore it.
* 3. PS command Exit_PS:
@@ -1691,18 +1792,17 @@ int libertas_execute_next_command(wlan_private * priv)
* otherwise send this command down to firmware
* immediately.
*/
- if (cmdptr->command !=
- cpu_to_le16(CMD_802_11_PS_MODE)) {
+ if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) {
/* Prepare to send Exit PS,
* this non PS command will be sent later */
- if ((adapter->psstate == PS_STATE_SLEEP)
- || (adapter->psstate == PS_STATE_PRE_SLEEP)
+ if ((priv->psstate == PS_STATE_SLEEP)
+ || (priv->psstate == PS_STATE_PRE_SLEEP)
) {
/* w/ new scheme, it will not reach here.
since it is blocked in main_thread. */
- adapter->needtowakeup = 1;
+ priv->needtowakeup = 1;
} else
- libertas_ps_wakeup(priv, 0);
+ lbs_ps_wakeup(priv, 0);
ret = 0;
goto done;
@@ -1711,8 +1811,7 @@ int libertas_execute_next_command(wlan_private * priv)
* PS command. Ignore it if it is not Exit_PS.
* otherwise send it down immediately.
*/
- struct cmd_ds_802_11_ps_mode *psm =
- &cmdptr->params.psmode;
+ struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1];
lbs_deb_host(
"EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
@@ -1721,20 +1820,24 @@ int libertas_execute_next_command(wlan_private * priv)
cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
- list_del((struct list_head *)cmdnode);
- libertas_cleanup_and_insert_cmd(priv, cmdnode);
+ list_del(&cmdnode->list);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ lbs_complete_command(priv, cmdnode, 0);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
goto done;
}
- if ((adapter->psstate == PS_STATE_SLEEP) ||
- (adapter->psstate == PS_STATE_PRE_SLEEP)) {
+ if ((priv->psstate == PS_STATE_SLEEP) ||
+ (priv->psstate == PS_STATE_PRE_SLEEP)) {
lbs_deb_host(
"EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
- list_del((struct list_head *)cmdnode);
- libertas_cleanup_and_insert_cmd(priv, cmdnode);
- adapter->needtowakeup = 1;
+ list_del(&cmdnode->list);
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ lbs_complete_command(priv, cmdnode, 0);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ priv->needtowakeup = 1;
ret = 0;
goto done;
@@ -1744,33 +1847,34 @@ int libertas_execute_next_command(wlan_private * priv)
"EXEC_NEXT_CMD: sending EXIT_PS\n");
}
}
- list_del((struct list_head *)cmdnode);
+ list_del(&cmdnode->list);
lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
- le16_to_cpu(cmdptr->command));
- DownloadcommandToStation(priv, cmdnode);
+ le16_to_cpu(cmd->command));
+ lbs_submit_command(priv, cmdnode);
} else {
/*
* check if in power save mode, if yes, put the device back
* to PS mode
*/
- if ((adapter->psmode != WLAN802_11POWERMODECAM) &&
- (adapter->psstate == PS_STATE_FULL_POWER) &&
- (adapter->connect_status == LIBERTAS_CONNECTED)) {
- if (adapter->secinfo.WPAenabled ||
- adapter->secinfo.WPA2enabled) {
+ if ((priv->psmode != LBS802_11POWERMODECAM) &&
+ (priv->psstate == PS_STATE_FULL_POWER) &&
+ ((priv->connect_status == LBS_CONNECTED) ||
+ (priv->mesh_connect_status == LBS_CONNECTED))) {
+ if (priv->secinfo.WPAenabled ||
+ priv->secinfo.WPA2enabled) {
/* check for valid WPA group keys */
- if (adapter->wpa_mcast_key.len ||
- adapter->wpa_unicast_key.len) {
+ if (priv->wpa_mcast_key.len ||
+ priv->wpa_unicast_key.len) {
lbs_deb_host(
"EXEC_NEXT_CMD: WPA enabled and GTK_SET"
" go back to PS_SLEEP");
- libertas_ps_sleep(priv, 0);
+ lbs_ps_sleep(priv, 0);
}
} else {
lbs_deb_host(
"EXEC_NEXT_CMD: cmdpendingq empty, "
"go back to PS_SLEEP");
- libertas_ps_sleep(priv, 0);
+ lbs_ps_sleep(priv, 0);
}
}
}
@@ -1781,7 +1885,7 @@ done:
return ret;
}
-void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
+void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
{
union iwreq_data iwrq;
u8 buf[50];
@@ -1805,10 +1909,9 @@ void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
lbs_deb_leave(LBS_DEB_WEXT);
}
-static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
+static int sendconfirmsleep(struct lbs_private *priv, u8 *cmdptr, u16 size)
{
unsigned long flags;
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
lbs_deb_enter(LBS_DEB_HOST);
@@ -1819,26 +1922,25 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
lbs_deb_hex(LBS_DEB_HOST, "sleep confirm command", cmdptr, size);
ret = priv->hw_host_to_card(priv, MVMS_CMD, cmdptr, size);
- priv->dnld_sent = DNLD_RES_RECEIVED;
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->intcounter || adapter->currenttxskb)
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->intcounter || priv->currenttxskb)
lbs_deb_host("SEND_SLEEPC_CMD: intcounter %d, currenttxskb %p\n",
- adapter->intcounter, adapter->currenttxskb);
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ priv->intcounter, priv->currenttxskb);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
if (ret) {
lbs_pr_alert(
"SEND_SLEEPC_CMD: Host to Card failed for Confirm Sleep\n");
} else {
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (!adapter->intcounter) {
- adapter->psstate = PS_STATE_SLEEP;
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (!priv->intcounter) {
+ priv->psstate = PS_STATE_SLEEP;
} else {
lbs_deb_host("SEND_SLEEPC_CMD: after sent, intcounter %d\n",
- adapter->intcounter);
+ priv->intcounter);
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
lbs_deb_host("SEND_SLEEPC_CMD: sent confirm sleep\n");
}
@@ -1847,7 +1949,7 @@ static int sendconfirmsleep(wlan_private * priv, u8 * cmdptr, u16 size)
return ret;
}
-void libertas_ps_sleep(wlan_private * priv, int wait_option)
+void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
{
lbs_deb_enter(LBS_DEB_HOST);
@@ -1856,7 +1958,7 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option)
* Remove this check if it is to be supported in IBSS mode also
*/
- libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
+ lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
lbs_deb_leave(LBS_DEB_HOST);
@@ -1865,19 +1967,19 @@ void libertas_ps_sleep(wlan_private * priv, int wait_option)
/**
* @brief This function sends Exit_PS command to firmware.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param wait_option wait response or not
* @return n/a
*/
-void libertas_ps_wakeup(wlan_private * priv, int wait_option)
+void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
{
__le32 Localpsmode;
lbs_deb_enter(LBS_DEB_HOST);
- Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
+ Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
- libertas_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
+ lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
CMD_SUBCMD_EXIT_PS,
wait_option, 0, &Localpsmode);
@@ -1888,37 +1990,36 @@ void libertas_ps_wakeup(wlan_private * priv, int wait_option)
* @brief This function checks condition and prepares to
* send sleep confirm command to firmware if ok.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param psmode Power Saving mode
* @return n/a
*/
-void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
+void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode)
{
unsigned long flags =0;
- wlan_adapter *adapter = priv->adapter;
u8 allowed = 1;
lbs_deb_enter(LBS_DEB_HOST);
if (priv->dnld_sent) {
allowed = 0;
- lbs_deb_host("dnld_sent was set");
+ lbs_deb_host("dnld_sent was set\n");
}
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->cur_cmd) {
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->cur_cmd) {
allowed = 0;
- lbs_deb_host("cur_cmd was set");
+ lbs_deb_host("cur_cmd was set\n");
}
- if (adapter->intcounter > 0) {
+ if (priv->intcounter > 0) {
allowed = 0;
- lbs_deb_host("intcounter %d", adapter->intcounter);
+ lbs_deb_host("intcounter %d\n", priv->intcounter);
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
if (allowed) {
- lbs_deb_host("sending libertas_ps_confirm_sleep\n");
- sendconfirmsleep(priv, (u8 *) & adapter->libertas_ps_confirm_sleep,
+ lbs_deb_host("sending lbs_ps_confirm_sleep\n");
+ sendconfirmsleep(priv, (u8 *) & priv->lbs_ps_confirm_sleep,
sizeof(struct PS_CMD_ConfirmSleep));
} else {
lbs_deb_host("sleep confirm has been delayed\n");
@@ -1926,3 +2027,123 @@ void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode)
lbs_deb_leave(LBS_DEB_HOST);
}
+
+
+/**
+ * @brief Simple callback that copies response back into command
+ *
+ * @param priv A pointer to struct lbs_private structure
+ * @param extra A pointer to the original command structure for which
+ * 'resp' is a response
+ * @param resp A pointer to the command response
+ *
+ * @return 0 on success, error on failure
+ */
+int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
+ struct cmd_header *resp)
+{
+ struct cmd_header *buf = (void *)extra;
+ uint16_t copy_len;
+
+ lbs_deb_enter(LBS_DEB_CMD);
+
+ copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+ lbs_deb_cmd("Copying back %u bytes; command response was %u bytes, "
+ "copy back buffer was %u bytes\n", copy_len,
+ le16_to_cpu(resp->size), le16_to_cpu(buf->size));
+ memcpy(buf, resp, copy_len);
+
+ lbs_deb_leave(LBS_DEB_CMD);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbs_cmd_copyback);
+
+struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+ unsigned long callback_arg)
+{
+ struct cmd_ctrl_node *cmdnode;
+
+ lbs_deb_enter(LBS_DEB_HOST);
+
+ if (priv->surpriseremoved) {
+ lbs_deb_host("PREP_CMD: card removed\n");
+ cmdnode = ERR_PTR(-ENOENT);
+ goto done;
+ }
+
+ cmdnode = lbs_get_cmd_ctrl_node(priv);
+ if (cmdnode == NULL) {
+ lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
+
+ /* Wake up main thread to execute next command */
+ wake_up_interruptible(&priv->waitq);
+ cmdnode = ERR_PTR(-ENOBUFS);
+ goto done;
+ }
+
+ cmdnode->callback = callback;
+ cmdnode->callback_arg = callback_arg;
+
+ /* Copy the incoming command to the buffer */
+ memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size);
+
+ /* Set sequence number, clean result, move to buffer */
+ priv->seqnum++;
+ cmdnode->cmdbuf->command = cpu_to_le16(command);
+ cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size);
+ cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum);
+ cmdnode->cmdbuf->result = 0;
+
+ lbs_deb_host("PREP_CMD: command 0x%04x\n", command);
+
+ /* here was the big old switch() statement, which is now obsolete,
+ * because the caller of lbs_cmd() sets up all of *cmd for us. */
+
+ cmdnode->cmdwaitqwoken = 0;
+ lbs_queue_cmd(priv, cmdnode);
+ wake_up_interruptible(&priv->waitq);
+
+ done:
+ lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
+ return cmdnode;
+}
+
+int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+ unsigned long callback_arg)
+{
+ struct cmd_ctrl_node *cmdnode;
+ unsigned long flags;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_HOST);
+
+ cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size,
+ callback, callback_arg);
+ if (IS_ERR(cmdnode)) {
+ ret = PTR_ERR(cmdnode);
+ goto done;
+ }
+
+ might_sleep();
+ wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken);
+
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ ret = cmdnode->result;
+ if (ret)
+ lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n",
+ command, ret);
+
+ __lbs_cleanup_and_insert_cmd(priv, cmdnode);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+done:
+ lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(__lbs_cmd);
+
+
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
new file mode 100644
index 000000000000..b9ab85cc7913
--- /dev/null
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2007, Red Hat, Inc. */
+
+#ifndef _LBS_CMD_H_
+#define _LBS_CMD_H_
+
+#include "hostcmd.h"
+#include "dev.h"
+
+/* lbs_cmd() infers the size of the buffer to copy data back into, from
+ the size of the target of the pointer. Since the command to be sent
+ may often be smaller, that size is set in cmd->size by the caller.*/
+#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \
+ uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \
+ (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \
+ __lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \
+})
+
+#define lbs_cmd_with_response(priv, cmdnr, cmd) \
+ lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
+
+/* __lbs_cmd() will free the cmdnode and return success/failure.
+ __lbs_cmd_async() requires that the callback free the cmdnode */
+struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+ unsigned long callback_arg);
+int __lbs_cmd(struct lbs_private *priv, uint16_t command,
+ struct cmd_header *in_cmd, int in_cmd_size,
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+ unsigned long callback_arg);
+
+int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
+ struct cmd_header *resp);
+
+int lbs_update_hw_spec(struct lbs_private *priv);
+
+int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+ struct cmd_ds_mesh_access *cmd);
+
+int lbs_get_data_rate(struct lbs_private *priv);
+int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
+
+int lbs_get_channel(struct lbs_private *priv);
+int lbs_set_channel(struct lbs_private *priv, u8 channel);
+
+int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
+
+int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
+int lbs_suspend(struct lbs_private *priv);
+int lbs_resume(struct lbs_private *priv);
+
+int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
+ uint16_t cmd_action, uint16_t *timeout);
+int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
+ struct sleep_params *sp);
+int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+ struct assoc_request *assoc);
+int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+ uint16_t *enable);
+
+#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 8f90892ea22e..159216a91903 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -20,18 +20,17 @@
* reports disconnect to upper layer, clean tx/rx packets,
* reset link state etc.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return n/a
*/
-void libertas_mac_event_disconnected(wlan_private * priv)
+void lbs_mac_event_disconnected(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
union iwreq_data wrqu;
- if (adapter->connect_status != LIBERTAS_CONNECTED)
+ if (priv->connect_status != LBS_CONNECTED)
return;
- lbs_deb_enter(LBS_DEB_CMD);
+ lbs_deb_enter(LBS_DEB_ASSOC);
memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -44,40 +43,36 @@ void libertas_mac_event_disconnected(wlan_private * priv)
msleep_interruptible(1000);
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- /* Free Tx and Rx packets */
- kfree_skb(priv->adapter->currenttxskb);
- priv->adapter->currenttxskb = NULL;
-
/* report disconnect to upper layer */
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
+ /* Free Tx and Rx packets */
+ kfree_skb(priv->currenttxskb);
+ priv->currenttxskb = NULL;
+ priv->tx_pending_len = 0;
+
/* reset SNR/NF/RSSI values */
- memset(adapter->SNR, 0x00, sizeof(adapter->SNR));
- memset(adapter->NF, 0x00, sizeof(adapter->NF));
- memset(adapter->RSSI, 0x00, sizeof(adapter->RSSI));
- memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
- memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
- adapter->nextSNRNF = 0;
- adapter->numSNRNF = 0;
- lbs_deb_cmd("current SSID '%s', length %u\n",
- escape_essid(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len),
- adapter->curbssparams.ssid_len);
-
- adapter->connect_status = LIBERTAS_DISCONNECTED;
+ memset(priv->SNR, 0x00, sizeof(priv->SNR));
+ memset(priv->NF, 0x00, sizeof(priv->NF));
+ memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
+ memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
+ memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
+ priv->nextSNRNF = 0;
+ priv->numSNRNF = 0;
+ priv->connect_status = LBS_DISCONNECTED;
/* Clear out associated SSID and BSSID since connection is
* no longer valid.
*/
- memset(&adapter->curbssparams.bssid, 0, ETH_ALEN);
- memset(&adapter->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
- adapter->curbssparams.ssid_len = 0;
+ memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
+ memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
+ priv->curbssparams.ssid_len = 0;
- if (adapter->psstate != PS_STATE_FULL_POWER) {
+ if (priv->psstate != PS_STATE_FULL_POWER) {
/* make firmware to exit PS mode */
lbs_deb_cmd("disconnected, so exit PS mode\n");
- libertas_ps_wakeup(priv, 0);
+ lbs_ps_wakeup(priv, 0);
}
lbs_deb_leave(LBS_DEB_CMD);
}
@@ -85,11 +80,11 @@ void libertas_mac_event_disconnected(wlan_private * priv)
/**
* @brief This function handles MIC failure event.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @para event the event id
* @return n/a
*/
-static void handle_mic_failureevent(wlan_private * priv, u32 event)
+static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
{
char buf[50];
@@ -104,15 +99,14 @@ static void handle_mic_failureevent(wlan_private * priv, u32 event)
strcat(buf, "multicast ");
}
- libertas_send_iwevcustom_event(priv, buf);
+ lbs_send_iwevcustom_event(priv, buf);
lbs_deb_leave(LBS_DEB_CMD);
}
-static int wlan_ret_reg_access(wlan_private * priv,
+static int lbs_ret_reg_access(struct lbs_private *priv,
u16 type, struct cmd_ds_command *resp)
{
int ret = 0;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
@@ -121,8 +115,8 @@ static int wlan_ret_reg_access(wlan_private * priv,
{
struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
- adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- adapter->offsetvalue.value = le32_to_cpu(reg->value);
+ priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+ priv->offsetvalue.value = le32_to_cpu(reg->value);
break;
}
@@ -130,8 +124,8 @@ static int wlan_ret_reg_access(wlan_private * priv,
{
struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
- adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- adapter->offsetvalue.value = reg->value;
+ priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+ priv->offsetvalue.value = reg->value;
break;
}
@@ -139,8 +133,8 @@ static int wlan_ret_reg_access(wlan_private * priv,
{
struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
- adapter->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
- adapter->offsetvalue.value = reg->value;
+ priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+ priv->offsetvalue.value = reg->value;
break;
}
@@ -152,112 +146,23 @@ static int wlan_ret_reg_access(wlan_private * priv,
return ret;
}
-static int wlan_ret_get_hw_spec(wlan_private * priv,
- struct cmd_ds_command *resp)
-{
- u32 i;
- struct cmd_ds_get_hw_spec *hwspec = &resp->params.hwspec;
- wlan_adapter *adapter = priv->adapter;
- int ret = 0;
- DECLARE_MAC_BUF(mac);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- adapter->fwcapinfo = le32_to_cpu(hwspec->fwcapinfo);
-
- memcpy(adapter->fwreleasenumber, hwspec->fwreleasenumber, 4);
-
- lbs_deb_cmd("GET_HW_SPEC: firmware release %u.%u.%up%u\n",
- adapter->fwreleasenumber[2], adapter->fwreleasenumber[1],
- adapter->fwreleasenumber[0], adapter->fwreleasenumber[3]);
- lbs_deb_cmd("GET_HW_SPEC: MAC addr %s\n",
- print_mac(mac, hwspec->permanentaddr));
- lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
- hwspec->hwifversion, hwspec->version);
-
- /* Clamp region code to 8-bit since FW spec indicates that it should
- * only ever be 8-bit, even though the field size is 16-bit. Some firmware
- * returns non-zero high 8 bits here.
- */
- adapter->regioncode = le16_to_cpu(hwspec->regioncode) & 0xFF;
-
- for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
- /* use the region code to search for the index */
- if (adapter->regioncode == libertas_region_code_to_index[i]) {
- break;
- }
- }
-
- /* if it's unidentified region code, use the default (USA) */
- if (i >= MRVDRV_MAX_REGION_CODE) {
- adapter->regioncode = 0x10;
- lbs_pr_info("unidentified region code; using the default (USA)\n");
- }
-
- if (adapter->current_addr[0] == 0xff)
- memmove(adapter->current_addr, hwspec->permanentaddr, ETH_ALEN);
-
- memcpy(priv->dev->dev_addr, adapter->current_addr, ETH_ALEN);
- if (priv->mesh_dev)
- memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
-
- if (libertas_set_regiontable(priv, adapter->regioncode, 0)) {
- ret = -1;
- goto done;
- }
-
- if (libertas_set_universaltable(priv, 0)) {
- ret = -1;
- goto done;
- }
-
-done:
- lbs_deb_enter_args(LBS_DEB_CMD, "ret %d", ret);
- return ret;
-}
-
-static int wlan_ret_802_11_sleep_params(wlan_private * priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_sleep_params *sp = &resp->params.sleep_params;
- wlan_adapter *adapter = priv->adapter;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, calcontrol 0x%x "
- "extsleepclk 0x%x\n", le16_to_cpu(sp->error),
- le16_to_cpu(sp->offset), le16_to_cpu(sp->stabletime),
- sp->calcontrol, sp->externalsleepclk);
-
- adapter->sp.sp_error = le16_to_cpu(sp->error);
- adapter->sp.sp_offset = le16_to_cpu(sp->offset);
- adapter->sp.sp_stabletime = le16_to_cpu(sp->stabletime);
- adapter->sp.sp_calcontrol = sp->calcontrol;
- adapter->sp.sp_extsleepclk = sp->externalsleepclk;
- adapter->sp.sp_reserved = le16_to_cpu(sp->reserved);
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
-static int wlan_ret_802_11_stat(wlan_private * priv,
+static int lbs_ret_802_11_stat(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
lbs_deb_enter(LBS_DEB_CMD);
-/* currently adapter->wlan802_11Stat is unused
+/* currently priv->wlan802_11Stat is unused
struct cmd_ds_802_11_get_stat *p11Stat = &resp->params.gstat;
- wlan_adapter *adapter = priv->adapter;
// TODO Convert it to Big endian befor copy
- memcpy(&adapter->wlan802_11Stat,
+ memcpy(&priv->wlan802_11Stat,
p11Stat, sizeof(struct cmd_ds_802_11_get_stat));
*/
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
+static int lbs_ret_802_11_snmp_mib(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_snmp_mib *smib = &resp->params.smib;
@@ -273,22 +178,22 @@ static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
if (querytype == CMD_ACT_GET) {
switch (oid) {
case FRAGTHRESH_I:
- priv->adapter->fragthsd =
+ priv->fragthsd =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: frag threshold %u\n",
- priv->adapter->fragthsd);
+ priv->fragthsd);
break;
case RTSTHRESH_I:
- priv->adapter->rtsthsd =
+ priv->rtsthsd =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: rts threshold %u\n",
- priv->adapter->rtsthsd);
+ priv->rtsthsd);
break;
case SHORT_RETRYLIM_I:
- priv->adapter->txretrycount =
+ priv->txretrycount =
le16_to_cpu(*((__le16 *)(smib->value)));
lbs_deb_cmd("SNMP_RESP: tx retry count %u\n",
- priv->adapter->rtsthsd);
+ priv->rtsthsd);
break;
default:
break;
@@ -299,12 +204,11 @@ static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
return 0;
}
-static int wlan_ret_802_11_key_material(wlan_private * priv,
+static int lbs_ret_802_11_key_material(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_key_material *pkeymaterial =
&resp->params.keymaterial;
- wlan_adapter *adapter = priv->adapter;
u16 action = le16_to_cpu(pkeymaterial->action);
lbs_deb_enter(LBS_DEB_CMD);
@@ -332,9 +236,9 @@ static int wlan_ret_802_11_key_material(wlan_private * priv,
break;
if (key_flags & KEY_INFO_WPA_UNICAST)
- pkey = &adapter->wpa_unicast_key;
+ pkey = &priv->wpa_unicast_key;
else if (key_flags & KEY_INFO_WPA_MCAST)
- pkey = &adapter->wpa_mcast_key;
+ pkey = &priv->wpa_mcast_key;
else
break;
@@ -355,134 +259,85 @@ static int wlan_ret_802_11_key_material(wlan_private * priv,
return 0;
}
-static int wlan_ret_802_11_mac_address(wlan_private * priv,
+static int lbs_ret_802_11_mac_address(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_mac_address *macadd = &resp->params.macadd;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
- memcpy(adapter->current_addr, macadd->macadd, ETH_ALEN);
+ memcpy(priv->current_addr, macadd->macadd, ETH_ALEN);
lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
-static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
+static int lbs_ret_802_11_rf_tx_power(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_rf_tx_power *rtp = &resp->params.txp;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
- adapter->txpowerlevel = le16_to_cpu(rtp->currentlevel);
+ priv->txpowerlevel = le16_to_cpu(rtp->currentlevel);
- lbs_deb_cmd("TX power currently %d\n", adapter->txpowerlevel);
+ lbs_deb_cmd("TX power currently %d\n", priv->txpowerlevel);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
+static int lbs_ret_802_11_rate_adapt_rateset(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_rate_adapt_rateset *rates = &resp->params.rateset;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
if (rates->action == CMD_ACT_GET) {
- adapter->enablehwauto = le16_to_cpu(rates->enablehwauto);
- adapter->ratebitmap = le16_to_cpu(rates->bitmap);
+ priv->enablehwauto = le16_to_cpu(rates->enablehwauto);
+ priv->ratebitmap = le16_to_cpu(rates->bitmap);
}
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_ret_802_11_data_rate(wlan_private * priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_data_rate *pdatarate = &resp->params.drate;
- wlan_adapter *adapter = priv->adapter;
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) pdatarate,
- sizeof(struct cmd_ds_802_11_data_rate));
-
- /* FIXME: get actual rates FW can do if this command actually returns
- * all data rates supported.
- */
- adapter->cur_rate = libertas_fw_index_to_data_rate(pdatarate->rates[0]);
- lbs_deb_cmd("DATA_RATE: current rate 0x%02x\n", adapter->cur_rate);
-
- lbs_deb_leave(LBS_DEB_CMD);
- return 0;
-}
-
-static int wlan_ret_802_11_rf_channel(wlan_private * priv,
- struct cmd_ds_command *resp)
-{
- struct cmd_ds_802_11_rf_channel *rfchannel = &resp->params.rfchannel;
- wlan_adapter *adapter = priv->adapter;
- u16 action = le16_to_cpu(rfchannel->action);
- u16 newchannel = le16_to_cpu(rfchannel->currentchannel);
-
- lbs_deb_enter(LBS_DEB_CMD);
-
- if (action == CMD_OPT_802_11_RF_CHANNEL_GET
- && adapter->curbssparams.channel != newchannel) {
- lbs_deb_cmd("channel switch from %d to %d\n",
- adapter->curbssparams.channel, newchannel);
-
- /* Update the channel again */
- adapter->curbssparams.channel = newchannel;
- }
-
- lbs_deb_enter(LBS_DEB_CMD);
- return 0;
-}
-
-static int wlan_ret_802_11_rssi(wlan_private * priv,
+static int lbs_ret_802_11_rssi(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
/* store the non average value */
- adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
- adapter->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
+ priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
+ priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
- adapter->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
- adapter->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
+ priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
+ priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
- adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
- CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
- adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+ priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
+ CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
+ priv->NF[TYPE_BEACON][TYPE_NOAVG]);
- adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
- CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
- adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
+ priv->RSSI[TYPE_BEACON][TYPE_AVG] =
+ CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
+ priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
- adapter->RSSI[TYPE_BEACON][TYPE_NOAVG],
- adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
+ priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
+ priv->RSSI[TYPE_BEACON][TYPE_AVG]);
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
+static int lbs_ret_802_11_eeprom_access(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
- wlan_adapter *adapter = priv->adapter;
- struct wlan_ioctl_regrdwr *pbuf;
- pbuf = (struct wlan_ioctl_regrdwr *) adapter->prdeeprom;
+ struct lbs_ioctl_regrdwr *pbuf;
+ pbuf = (struct lbs_ioctl_regrdwr *) priv->prdeeprom;
lbs_deb_enter_args(LBS_DEB_CMD, "len %d",
le16_to_cpu(resp->params.rdeeprom.bytecount));
@@ -503,46 +358,45 @@ static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
return 0;
}
-static int wlan_ret_get_log(wlan_private * priv,
+static int lbs_ret_get_log(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
struct cmd_ds_802_11_get_log *logmessage = &resp->params.glog;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_CMD);
/* Stored little-endian */
- memcpy(&adapter->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
+ memcpy(&priv->logmsg, logmessage, sizeof(struct cmd_ds_802_11_get_log));
lbs_deb_leave(LBS_DEB_CMD);
return 0;
}
-static int libertas_ret_802_11_enable_rsn(wlan_private * priv,
- struct cmd_ds_command *resp)
+static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
+ struct cmd_ds_command *resp)
{
- struct cmd_ds_802_11_enable_rsn *enable_rsn = &resp->params.enbrsn;
- wlan_adapter *adapter = priv->adapter;
- u32 * pdata_buf = adapter->cur_cmd->pdata_buf;
+ struct cmd_ds_802_11_beacon_control *bcn_ctrl =
+ &resp->params.bcn_ctrl;
lbs_deb_enter(LBS_DEB_CMD);
- if (enable_rsn->action == cpu_to_le16(CMD_ACT_GET)) {
- if (pdata_buf)
- *pdata_buf = (u32) le16_to_cpu(enable_rsn->enable);
+ if (bcn_ctrl->action == CMD_ACT_GET) {
+ priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
+ priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
}
- lbs_deb_leave(LBS_DEB_CMD);
+ lbs_deb_enter(LBS_DEB_CMD);
return 0;
}
-static inline int handle_cmd_response(u16 respcmd,
- struct cmd_ds_command *resp,
- wlan_private *priv)
+static inline int handle_cmd_response(struct lbs_private *priv,
+ unsigned long dummy,
+ struct cmd_header *cmd_response)
{
+ struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
int ret = 0;
unsigned long flags;
- wlan_adapter *adapter = priv->adapter;
+ uint16_t respcmd = le16_to_cpu(resp->command);
lbs_deb_enter(LBS_DEB_HOST);
@@ -550,218 +404,213 @@ static inline int handle_cmd_response(u16 respcmd,
case CMD_RET(CMD_MAC_REG_ACCESS):
case CMD_RET(CMD_BBP_REG_ACCESS):
case CMD_RET(CMD_RF_REG_ACCESS):
- ret = wlan_ret_reg_access(priv, respcmd, resp);
- break;
-
- case CMD_RET(CMD_GET_HW_SPEC):
- ret = wlan_ret_get_hw_spec(priv, resp);
+ ret = lbs_ret_reg_access(priv, respcmd, resp);
break;
case CMD_RET(CMD_802_11_SCAN):
- ret = libertas_ret_80211_scan(priv, resp);
+ ret = lbs_ret_80211_scan(priv, resp);
break;
case CMD_RET(CMD_802_11_GET_LOG):
- ret = wlan_ret_get_log(priv, resp);
+ ret = lbs_ret_get_log(priv, resp);
break;
case CMD_RET_802_11_ASSOCIATE:
case CMD_RET(CMD_802_11_ASSOCIATE):
case CMD_RET(CMD_802_11_REASSOCIATE):
- ret = libertas_ret_80211_associate(priv, resp);
+ ret = lbs_ret_80211_associate(priv, resp);
break;
case CMD_RET(CMD_802_11_DISASSOCIATE):
case CMD_RET(CMD_802_11_DEAUTHENTICATE):
- ret = libertas_ret_80211_disassociate(priv, resp);
+ ret = lbs_ret_80211_disassociate(priv, resp);
break;
case CMD_RET(CMD_802_11_AD_HOC_START):
case CMD_RET(CMD_802_11_AD_HOC_JOIN):
- ret = libertas_ret_80211_ad_hoc_start(priv, resp);
+ ret = lbs_ret_80211_ad_hoc_start(priv, resp);
break;
case CMD_RET(CMD_802_11_GET_STAT):
- ret = wlan_ret_802_11_stat(priv, resp);
+ ret = lbs_ret_802_11_stat(priv, resp);
break;
case CMD_RET(CMD_802_11_SNMP_MIB):
- ret = wlan_ret_802_11_snmp_mib(priv, resp);
+ ret = lbs_ret_802_11_snmp_mib(priv, resp);
break;
case CMD_RET(CMD_802_11_RF_TX_POWER):
- ret = wlan_ret_802_11_rf_tx_power(priv, resp);
+ ret = lbs_ret_802_11_rf_tx_power(priv, resp);
break;
case CMD_RET(CMD_802_11_SET_AFC):
case CMD_RET(CMD_802_11_GET_AFC):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf, &resp->params.afc,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
sizeof(struct cmd_ds_802_11_afc));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_MAC_MULTICAST_ADR):
case CMD_RET(CMD_MAC_CONTROL):
- case CMD_RET(CMD_802_11_SET_WEP):
case CMD_RET(CMD_802_11_RESET):
case CMD_RET(CMD_802_11_AUTHENTICATE):
- case CMD_RET(CMD_802_11_RADIO_CONTROL):
case CMD_RET(CMD_802_11_BEACON_STOP):
break;
- case CMD_RET(CMD_802_11_ENABLE_RSN):
- ret = libertas_ret_802_11_enable_rsn(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_DATA_RATE):
- ret = wlan_ret_802_11_data_rate(priv, resp);
- break;
case CMD_RET(CMD_802_11_RATE_ADAPT_RATESET):
- ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
- break;
- case CMD_RET(CMD_802_11_RF_CHANNEL):
- ret = wlan_ret_802_11_rf_channel(priv, resp);
+ ret = lbs_ret_802_11_rate_adapt_rateset(priv, resp);
break;
case CMD_RET(CMD_802_11_RSSI):
- ret = wlan_ret_802_11_rssi(priv, resp);
+ ret = lbs_ret_802_11_rssi(priv, resp);
break;
case CMD_RET(CMD_802_11_MAC_ADDRESS):
- ret = wlan_ret_802_11_mac_address(priv, resp);
+ ret = lbs_ret_802_11_mac_address(priv, resp);
break;
case CMD_RET(CMD_802_11_AD_HOC_STOP):
- ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
+ ret = lbs_ret_80211_ad_hoc_stop(priv, resp);
break;
case CMD_RET(CMD_802_11_KEY_MATERIAL):
- ret = wlan_ret_802_11_key_material(priv, resp);
+ ret = lbs_ret_802_11_key_material(priv, resp);
break;
case CMD_RET(CMD_802_11_EEPROM_ACCESS):
- ret = wlan_ret_802_11_eeprom_access(priv, resp);
+ ret = lbs_ret_802_11_eeprom_access(priv, resp);
break;
case CMD_RET(CMD_802_11D_DOMAIN_INFO):
- ret = libertas_ret_802_11d_domain_info(priv, resp);
- break;
-
- case CMD_RET(CMD_802_11_SLEEP_PARAMS):
- ret = wlan_ret_802_11_sleep_params(priv, resp);
- break;
- case CMD_RET(CMD_802_11_INACTIVITY_TIMEOUT):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- *((u16 *) adapter->cur_cmd->pdata_buf) =
- le16_to_cpu(resp->params.inactivity_timeout.timeout);
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ ret = lbs_ret_802_11d_domain_info(priv, resp);
break;
case CMD_RET(CMD_802_11_TPC_CFG):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf, &resp->params.tpccfg,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
sizeof(struct cmd_ds_802_11_tpc_cfg));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf, &resp->params.ledgpio,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
sizeof(struct cmd_ds_802_11_led_ctrl));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
+
case CMD_RET(CMD_802_11_PWR_CFG):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- memmove(adapter->cur_cmd->pdata_buf, &resp->params.pwrcfg,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memmove((void *)priv->cur_cmd->callback_arg, &resp->params.pwrcfg,
sizeof(struct cmd_ds_802_11_pwr_cfg));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_GET_TSF):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- memcpy(priv->adapter->cur_cmd->pdata_buf,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ memcpy((void *)priv->cur_cmd->callback_arg,
&resp->params.gettsf.tsfvalue, sizeof(u64));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_BT_ACCESS):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->cur_cmd->pdata_buf)
- memcpy(adapter->cur_cmd->pdata_buf,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->cur_cmd->callback_arg)
+ memcpy((void *)priv->cur_cmd->callback_arg,
&resp->params.bt.addr1, 2 * ETH_ALEN);
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
case CMD_RET(CMD_FWT_ACCESS):
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->cur_cmd->pdata_buf)
- memcpy(adapter->cur_cmd->pdata_buf, &resp->params.fwt,
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ if (priv->cur_cmd->callback_arg)
+ memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
sizeof(resp->params.fwt));
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
break;
- case CMD_RET(CMD_MESH_ACCESS):
- if (adapter->cur_cmd->pdata_buf)
- memcpy(adapter->cur_cmd->pdata_buf, &resp->params.mesh,
- sizeof(resp->params.mesh));
+ case CMD_RET(CMD_802_11_BEACON_CTRL):
+ ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
break;
+
default:
lbs_deb_host("CMD_RESP: unknown cmd response 0x%04x\n",
- resp->command);
+ le16_to_cpu(resp->command));
break;
}
lbs_deb_leave(LBS_DEB_HOST);
return ret;
}
-int libertas_process_rx_command(wlan_private * priv)
+int lbs_process_rx_command(struct lbs_private *priv)
{
- u16 respcmd;
- struct cmd_ds_command *resp;
- wlan_adapter *adapter = priv->adapter;
+ uint16_t respcmd, curcmd;
+ struct cmd_header *resp;
int ret = 0;
- ulong flags;
- u16 result;
+ unsigned long flags;
+ uint16_t result;
lbs_deb_enter(LBS_DEB_HOST);
- /* Now we got response from FW, cancel the command timer */
- del_timer(&adapter->command_timer);
-
- mutex_lock(&adapter->lock);
- spin_lock_irqsave(&adapter->driver_lock, flags);
+ mutex_lock(&priv->lock);
+ spin_lock_irqsave(&priv->driver_lock, flags);
- if (!adapter->cur_cmd) {
+ if (!priv->cur_cmd) {
lbs_deb_host("CMD_RESP: cur_cmd is NULL\n");
ret = -1;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
goto done;
}
- resp = (struct cmd_ds_command *)(adapter->cur_cmd->bufvirtualaddr);
+
+ resp = (void *)priv->upld_buf;
+
+ curcmd = le16_to_cpu(resp->command);
respcmd = le16_to_cpu(resp->command);
result = le16_to_cpu(resp->result);
- lbs_deb_host("CMD_RESP: response 0x%04x, size %d, jiffies %lu\n",
- respcmd, priv->upld_len, jiffies);
- lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", adapter->cur_cmd->bufvirtualaddr,
- priv->upld_len);
-
- if (!(respcmd & 0x8000)) {
- lbs_deb_host("invalid response!\n");
- adapter->cur_cmd_retcode = -1;
- __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
- adapter->nr_cmd_pending--;
- adapter->cur_cmd = NULL;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ lbs_deb_host("CMD_RESP: response 0x%04x, seq %d, size %d, jiffies %lu\n",
+ respcmd, le16_to_cpu(resp->seqnum), priv->upld_len, jiffies);
+ lbs_deb_hex(LBS_DEB_HOST, "CMD_RESP", (void *) resp, priv->upld_len);
+
+ if (resp->seqnum != resp->seqnum) {
+ lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
+ le16_to_cpu(resp->seqnum), le16_to_cpu(resp->seqnum));
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ ret = -1;
+ goto done;
+ }
+ if (respcmd != CMD_RET(curcmd) &&
+ respcmd != CMD_802_11_ASSOCIATE && curcmd != CMD_RET_802_11_ASSOCIATE) {
+ lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ ret = -1;
+ goto done;
+ }
+
+ if (resp->result == cpu_to_le16(0x0004)) {
+ /* 0x0004 means -EAGAIN. Drop the response, let it time out
+ and be resubmitted */
+ lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
+ le16_to_cpu(resp->command));
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
+ /* Now we got response from FW, cancel the command timer */
+ del_timer(&priv->command_timer);
+ priv->cmd_timed_out = 0;
+ if (priv->nr_retries) {
+ lbs_pr_info("Received result %x to command %x after %d retries\n",
+ result, curcmd, priv->nr_retries);
+ priv->nr_retries = 0;
+ }
+
/* Store the response code to cur_cmd_retcode. */
- adapter->cur_cmd_retcode = result;;
+ priv->cur_cmd_retcode = result;
if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
- struct cmd_ds_802_11_ps_mode *psmode = &resp->params.psmode;
+ struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
u16 action = le16_to_cpu(psmode->action);
lbs_deb_host(
@@ -774,54 +623,45 @@ int libertas_process_rx_command(wlan_private * priv)
/*
* We should not re-try enter-ps command in
* ad-hoc mode. It takes place in
- * libertas_execute_next_command().
+ * lbs_execute_next_command().
*/
- if (adapter->mode == IW_MODE_ADHOC &&
+ if (priv->mode == IW_MODE_ADHOC &&
action == CMD_SUBCMD_ENTER_PS)
- adapter->psmode = WLAN802_11POWERMODECAM;
+ priv->psmode = LBS802_11POWERMODECAM;
} else if (action == CMD_SUBCMD_ENTER_PS) {
- adapter->needtowakeup = 0;
- adapter->psstate = PS_STATE_AWAKE;
+ priv->needtowakeup = 0;
+ priv->psstate = PS_STATE_AWAKE;
lbs_deb_host("CMD_RESP: ENTER_PS command response\n");
- if (adapter->connect_status != LIBERTAS_CONNECTED) {
+ if (priv->connect_status != LBS_CONNECTED) {
/*
* When Deauth Event received before Enter_PS command
* response, We need to wake up the firmware.
*/
lbs_deb_host(
- "disconnected, invoking libertas_ps_wakeup\n");
+ "disconnected, invoking lbs_ps_wakeup\n");
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
- mutex_unlock(&adapter->lock);
- libertas_ps_wakeup(priv, 0);
- mutex_lock(&adapter->lock);
- spin_lock_irqsave(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ mutex_unlock(&priv->lock);
+ lbs_ps_wakeup(priv, 0);
+ mutex_lock(&priv->lock);
+ spin_lock_irqsave(&priv->driver_lock, flags);
}
} else if (action == CMD_SUBCMD_EXIT_PS) {
- adapter->needtowakeup = 0;
- adapter->psstate = PS_STATE_FULL_POWER;
+ priv->needtowakeup = 0;
+ priv->psstate = PS_STATE_FULL_POWER;
lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
} else {
lbs_deb_host("CMD_RESP: PS action 0x%X\n", action);
}
- __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
- adapter->nr_cmd_pending--;
- adapter->cur_cmd = NULL;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ lbs_complete_command(priv, priv->cur_cmd, result);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
goto done;
}
- if (adapter->cur_cmd->cmdflags & CMD_F_HOSTCMD) {
- /* Copy the response back to response buffer */
- memcpy(adapter->cur_cmd->pdata_buf, resp,
- le16_to_cpu(resp->size));
- adapter->cur_cmd->cmdflags &= ~CMD_F_HOSTCMD;
- }
-
/* If the command is not successful, cleanup and return failure */
if ((result != 0 || !(respcmd & 0x8000))) {
lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n",
@@ -836,106 +676,132 @@ int libertas_process_rx_command(wlan_private * priv)
break;
}
-
- __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
- adapter->nr_cmd_pending--;
- adapter->cur_cmd = NULL;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ lbs_complete_command(priv, priv->cur_cmd, result);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = -1;
goto done;
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
- ret = handle_cmd_response(respcmd, resp, priv);
+ if (priv->cur_cmd && priv->cur_cmd->callback) {
+ ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
+ resp);
+ } else
+ ret = handle_cmd_response(priv, 0, resp);
- spin_lock_irqsave(&adapter->driver_lock, flags);
- if (adapter->cur_cmd) {
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (priv->cur_cmd) {
/* Clean up and Put current command back to cmdfreeq */
- __libertas_cleanup_and_insert_cmd(priv, adapter->cur_cmd);
- adapter->nr_cmd_pending--;
- WARN_ON(adapter->nr_cmd_pending > 128);
- adapter->cur_cmd = NULL;
+ lbs_complete_command(priv, priv->cur_cmd, result);
}
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
done:
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
return ret;
}
-int libertas_process_event(wlan_private * priv)
+static int lbs_send_confirmwake(struct lbs_private *priv)
+{
+ struct cmd_header *cmd = &priv->lbs_ps_confirm_wake;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_HOST);
+
+ cmd->command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
+ cmd->size = cpu_to_le16(sizeof(*cmd));
+ cmd->seqnum = cpu_to_le16(++priv->seqnum);
+ cmd->result = 0;
+
+ lbs_deb_host("SEND_WAKEC_CMD: before download\n");
+
+ lbs_deb_hex(LBS_DEB_HOST, "wake confirm command", (void *)cmd, sizeof(*cmd));
+
+ ret = priv->hw_host_to_card(priv, MVMS_CMD, (void *)cmd, sizeof(*cmd));
+ if (ret)
+ lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
+
+ lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
+ return ret;
+}
+
+int lbs_process_event(struct lbs_private *priv)
{
int ret = 0;
- wlan_adapter *adapter = priv->adapter;
u32 eventcause;
lbs_deb_enter(LBS_DEB_CMD);
- spin_lock_irq(&adapter->driver_lock);
- eventcause = adapter->eventcause;
- spin_unlock_irq(&adapter->driver_lock);
+ spin_lock_irq(&priv->driver_lock);
+ eventcause = priv->eventcause >> SBI_EVENT_CAUSE_SHIFT;
+ spin_unlock_irq(&priv->driver_lock);
- lbs_deb_cmd("event cause 0x%x\n", eventcause);
+ lbs_deb_cmd("event cause %d\n", eventcause);
- switch (eventcause >> SBI_EVENT_CAUSE_SHIFT) {
+ switch (eventcause) {
case MACREG_INT_CODE_LINK_SENSED:
lbs_deb_cmd("EVENT: MACREG_INT_CODE_LINK_SENSED\n");
break;
case MACREG_INT_CODE_DEAUTHENTICATED:
lbs_deb_cmd("EVENT: deauthenticated\n");
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_DISASSOCIATED:
lbs_deb_cmd("EVENT: disassociated\n");
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
break;
- case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
+ case MACREG_INT_CODE_LINK_LOST_NO_SCAN:
lbs_deb_cmd("EVENT: link lost\n");
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
break;
case MACREG_INT_CODE_PS_SLEEP:
lbs_deb_cmd("EVENT: sleep\n");
/* handle unexpected PS SLEEP event */
- if (adapter->psstate == PS_STATE_FULL_POWER) {
+ if (priv->psstate == PS_STATE_FULL_POWER) {
lbs_deb_cmd(
"EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n");
break;
}
- adapter->psstate = PS_STATE_PRE_SLEEP;
+ priv->psstate = PS_STATE_PRE_SLEEP;
- libertas_ps_confirm_sleep(priv, (u16) adapter->psmode);
+ lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
break;
+ case MACREG_INT_CODE_HOST_AWAKE:
+ lbs_deb_cmd("EVENT: HOST_AWAKE\n");
+ lbs_send_confirmwake(priv);
+ break;
+
case MACREG_INT_CODE_PS_AWAKE:
lbs_deb_cmd("EVENT: awake\n");
-
/* handle unexpected PS AWAKE event */
- if (adapter->psstate == PS_STATE_FULL_POWER) {
+ if (priv->psstate == PS_STATE_FULL_POWER) {
lbs_deb_cmd(
"EVENT: In FULL POWER mode - ignore PS AWAKE\n");
break;
}
- adapter->psstate = PS_STATE_AWAKE;
+ priv->psstate = PS_STATE_AWAKE;
- if (adapter->needtowakeup) {
+ if (priv->needtowakeup) {
/*
* wait for the command processing to finish
* before resuming sending
- * adapter->needtowakeup will be set to FALSE
- * in libertas_ps_wakeup()
+ * priv->needtowakeup will be set to FALSE
+ * in lbs_ps_wakeup()
*/
lbs_deb_cmd("waking up ...\n");
- libertas_ps_wakeup(priv, 0);
+ lbs_ps_wakeup(priv, 0);
}
break;
@@ -979,24 +845,24 @@ int libertas_process_event(wlan_private * priv)
break;
}
lbs_pr_info("EVENT: MESH_AUTO_STARTED\n");
- adapter->connect_status = LIBERTAS_CONNECTED;
- if (priv->mesh_open == 1) {
- netif_wake_queue(priv->mesh_dev);
+ priv->mesh_connect_status = LBS_CONNECTED;
+ if (priv->mesh_open) {
netif_carrier_on(priv->mesh_dev);
+ if (!priv->tx_pending_len)
+ netif_wake_queue(priv->mesh_dev);
}
- adapter->mode = IW_MODE_ADHOC;
+ priv->mode = IW_MODE_ADHOC;
schedule_work(&priv->sync_channel);
break;
default:
- lbs_pr_alert("EVENT: unknown event id 0x%04x\n",
- eventcause >> SBI_EVENT_CAUSE_SHIFT);
+ lbs_pr_alert("EVENT: unknown event id %d\n", eventcause);
break;
}
- spin_lock_irq(&adapter->driver_lock);
- adapter->eventcause = 0;
- spin_unlock_irq(&adapter->driver_lock);
+ spin_lock_irq(&priv->driver_lock);
+ priv->eventcause = 0;
+ spin_unlock_irq(&priv->driver_lock);
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return ret;
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 0bda0b511910..fd67b770dd78 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -10,15 +10,16 @@
#include "decl.h"
#include "host.h"
#include "debugfs.h"
+#include "cmd.h"
-static struct dentry *libertas_dir = NULL;
+static struct dentry *lbs_dir;
static char *szStates[] = {
"Connected",
"Disconnected"
};
#ifdef PROC_DEBUG
-static void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev);
#endif
static int open_file_generic(struct inode *inode, struct file *file)
@@ -35,19 +36,19 @@ static ssize_t write_file_dummy(struct file *file, const char __user *buf,
static const size_t len = PAGE_SIZE;
-static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
+static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
size_t pos = 0;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
ssize_t res;
pos += snprintf(buf+pos, len-pos, "state = %s\n",
- szStates[priv->adapter->connect_status]);
+ szStates[priv->connect_status]);
pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
- (u32) priv->adapter->regioncode);
+ (u32) priv->regioncode);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
@@ -56,10 +57,10 @@ static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
}
-static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
+static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
size_t pos = 0;
int numscansdone = 0, res;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
@@ -70,8 +71,8 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
pos += snprintf(buf+pos, len-pos,
"# | ch | rssi | bssid | cap | Qual | SSID \n");
- mutex_lock(&priv->adapter->lock);
- list_for_each_entry (iter_bss, &priv->adapter->network_list, list) {
+ mutex_lock(&priv->lock);
+ list_for_each_entry (iter_bss, &priv->network_list, list) {
u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
@@ -90,7 +91,7 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
numscansdone++;
}
- mutex_unlock(&priv->adapter->lock);
+ mutex_unlock(&priv->lock);
res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
@@ -98,83 +99,75 @@ static ssize_t libertas_getscantable(struct file *file, char __user *userbuf,
return res;
}
-static ssize_t libertas_sleepparams_write(struct file *file,
+static ssize_t lbs_sleepparams_write(struct file *file,
const char __user *user_buf, size_t count,
loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- ssize_t buf_size, res;
+ struct lbs_private *priv = file->private_data;
+ ssize_t buf_size, ret;
+ struct sleep_params sp;
int p1, p2, p3, p4, p5, p6;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
buf_size = min(count, len - 1);
if (copy_from_user(buf, user_buf, buf_size)) {
- res = -EFAULT;
+ ret = -EFAULT;
goto out_unlock;
}
- res = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
- if (res != 6) {
- res = -EFAULT;
+ ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6);
+ if (ret != 6) {
+ ret = -EINVAL;
goto out_unlock;
}
- priv->adapter->sp.sp_error = p1;
- priv->adapter->sp.sp_offset = p2;
- priv->adapter->sp.sp_stabletime = p3;
- priv->adapter->sp.sp_calcontrol = p4;
- priv->adapter->sp.sp_extsleepclk = p5;
- priv->adapter->sp.sp_reserved = p6;
-
- res = libertas_prepare_and_send_command(priv,
- CMD_802_11_SLEEP_PARAMS,
- CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
-
- if (!res)
- res = count;
- else
- res = -EINVAL;
+ sp.sp_error = p1;
+ sp.sp_offset = p2;
+ sp.sp_stabletime = p3;
+ sp.sp_calcontrol = p4;
+ sp.sp_extsleepclk = p5;
+ sp.sp_reserved = p6;
+
+ ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp);
+ if (!ret)
+ ret = count;
+ else if (ret > 0)
+ ret = -EINVAL;
out_unlock:
free_page(addr);
- return res;
+ return ret;
}
-static ssize_t libertas_sleepparams_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res;
+ struct lbs_private *priv = file->private_data;
+ ssize_t ret;
size_t pos = 0;
+ struct sleep_params sp;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
- res = libertas_prepare_and_send_command(priv,
- CMD_802_11_SLEEP_PARAMS,
- CMD_ACT_GET,
- CMD_OPTION_WAITFORRSP, 0, NULL);
- if (res) {
- res = -EFAULT;
+ ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp);
+ if (ret)
goto out_unlock;
- }
- pos += snprintf(buf, len, "%d %d %d %d %d %d\n", adapter->sp.sp_error,
- adapter->sp.sp_offset, adapter->sp.sp_stabletime,
- adapter->sp.sp_calcontrol, adapter->sp.sp_extsleepclk,
- adapter->sp.sp_reserved);
+ pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error,
+ sp.sp_offset, sp.sp_stabletime,
+ sp.sp_calcontrol, sp.sp_extsleepclk,
+ sp.sp_reserved);
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
out_unlock:
free_page(addr);
- return res;
+ return ret;
}
-static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
+static ssize_t lbs_extscan(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
union iwreq_data wrqu;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
@@ -186,7 +179,7 @@ static ssize_t libertas_extscan(struct file *file, const char __user *userbuf,
goto out_unlock;
}
- libertas_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
+ lbs_send_specific_ssid_scan(priv, buf, strlen(buf)-1, 0);
memset(&wrqu, 0, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
@@ -196,45 +189,8 @@ out_unlock:
return count;
}
-static int libertas_parse_chan(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg, int dur)
-{
- char *start, *end, *hold, *str;
- int i = 0;
-
- start = strstr(buf, "chan=");
- if (!start)
- return -EINVAL;
- start += 5;
- end = strchr(start, ' ');
- if (!end)
- end = buf + count;
- hold = kzalloc((end - start)+1, GFP_KERNEL);
- if (!hold)
- return -ENOMEM;
- strncpy(hold, start, end - start);
- hold[(end-start)+1] = '\0';
- while(hold && (str = strsep(&hold, ","))) {
- int chan;
- char band, passive = 0;
- sscanf(str, "%d%c%c", &chan, &band, &passive);
- scan_cfg->chanlist[i].channumber = chan;
- scan_cfg->chanlist[i].scantype = passive ? 1 : 0;
- if (band == 'b' || band == 'g')
- scan_cfg->chanlist[i].radiotype = 0;
- else if (band == 'a')
- scan_cfg->chanlist[i].radiotype = 1;
-
- scan_cfg->chanlist[i].scantime = dur;
- i++;
- }
-
- kfree(hold);
- return i;
-}
-
-static void libertas_parse_bssid(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static void lbs_parse_bssid(char *buf, size_t count,
+ struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
unsigned int mac[ETH_ALEN];
@@ -243,12 +199,13 @@ static void libertas_parse_bssid(char *buf, size_t count,
if (!hold)
return;
hold += 6;
- sscanf(hold, MAC_FMT, mac, mac+1, mac+2, mac+3, mac+4, mac+5);
+ sscanf(hold, "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac, mac+1, mac+2, mac+3, mac+4, mac+5);
memcpy(scan_cfg->bssid, mac, ETH_ALEN);
}
-static void libertas_parse_ssid(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static void lbs_parse_ssid(char *buf, size_t count,
+ struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold, *end;
ssize_t size;
@@ -267,7 +224,7 @@ static void libertas_parse_ssid(char *buf, size_t count,
return;
}
-static int libertas_parse_clear(char *buf, size_t count, const char *tag)
+static int lbs_parse_clear(char *buf, size_t count, const char *tag)
{
char *hold;
int val;
@@ -284,8 +241,8 @@ static int libertas_parse_clear(char *buf, size_t count, const char *tag)
return val;
}
-static int libertas_parse_dur(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static int lbs_parse_dur(char *buf, size_t count,
+ struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
@@ -299,25 +256,8 @@ static int libertas_parse_dur(char *buf, size_t count,
return val;
}
-static void libertas_parse_probes(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
-{
- char *hold;
- int val;
-
- hold = strstr(buf, "probes=");
- if (!hold)
- return;
- hold += 7;
- sscanf(hold, "%d", &val);
-
- scan_cfg->numprobes = val;
-
- return;
-}
-
-static void libertas_parse_type(char *buf, size_t count,
- struct wlan_ioctl_user_scan_cfg *scan_cfg)
+static void lbs_parse_type(char *buf, size_t count,
+ struct lbs_ioctl_user_scan_cfg *scan_cfg)
{
char *hold;
int val;
@@ -337,1036 +277,324 @@ static void libertas_parse_type(char *buf, size_t count,
return;
}
-static ssize_t libertas_setuserscan(struct file *file,
+static ssize_t lbs_setuserscan(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
- struct wlan_ioctl_user_scan_cfg *scan_cfg;
+ struct lbs_ioctl_user_scan_cfg *scan_cfg;
union iwreq_data wrqu;
int dur;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
+ char *buf = (char *)get_zeroed_page(GFP_KERNEL);
- scan_cfg = kzalloc(sizeof(struct wlan_ioctl_user_scan_cfg), GFP_KERNEL);
- if (!scan_cfg)
+ if (!buf)
return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
res = -EFAULT;
- goto out_unlock;
+ goto out_buf;
+ }
+
+ scan_cfg = kzalloc(sizeof(struct lbs_ioctl_user_scan_cfg), GFP_KERNEL);
+ if (!scan_cfg) {
+ res = -ENOMEM;
+ goto out_buf;
}
+ res = count;
+
+ scan_cfg->bsstype = LBS_SCAN_BSS_TYPE_ANY;
- scan_cfg->bsstype = WLAN_SCAN_BSS_TYPE_ANY;
+ dur = lbs_parse_dur(buf, count, scan_cfg);
+ lbs_parse_bssid(buf, count, scan_cfg);
+ scan_cfg->clear_bssid = lbs_parse_clear(buf, count, "clear_bssid=");
+ lbs_parse_ssid(buf, count, scan_cfg);
+ scan_cfg->clear_ssid = lbs_parse_clear(buf, count, "clear_ssid=");
+ lbs_parse_type(buf, count, scan_cfg);
- dur = libertas_parse_dur(buf, count, scan_cfg);
- libertas_parse_chan(buf, count, scan_cfg, dur);
- libertas_parse_bssid(buf, count, scan_cfg);
- scan_cfg->clear_bssid = libertas_parse_clear(buf, count, "clear_bssid=");
- libertas_parse_ssid(buf, count, scan_cfg);
- scan_cfg->clear_ssid = libertas_parse_clear(buf, count, "clear_ssid=");
- libertas_parse_probes(buf, count, scan_cfg);
- libertas_parse_type(buf, count, scan_cfg);
+ lbs_scan_networks(priv, scan_cfg, 1);
+ wait_event_interruptible(priv->cmd_pending,
+ priv->surpriseremoved || !priv->last_scanned_channel);
- wlan_scan_networks(priv, scan_cfg, 1);
- wait_event_interruptible(priv->adapter->cmd_pending,
- !priv->adapter->nr_cmd_pending);
+ if (priv->surpriseremoved)
+ goto out_scan_cfg;
memset(&wrqu, 0x00, sizeof(union iwreq_data));
wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
-out_unlock:
- free_page(addr);
+ out_scan_cfg:
kfree(scan_cfg);
- return count;
+ out_buf:
+ free_page((unsigned long)buf);
+ return res;
}
-static int libertas_event_initcmd(wlan_private *priv, void **response_buf,
- struct cmd_ctrl_node **cmdnode,
- struct cmd_ds_command **cmd)
-{
- u16 wait_option = CMD_OPTION_WAITFORRSP;
-
- if (!(*cmdnode = libertas_get_free_cmd_ctrl_node(priv))) {
- lbs_deb_debugfs("failed libertas_get_free_cmd_ctrl_node\n");
- return -ENOMEM;
- }
- if (!(*response_buf = kmalloc(3000, GFP_KERNEL))) {
- lbs_deb_debugfs("failed to allocate response buffer!\n");
- return -ENOMEM;
- }
- libertas_set_cmd_ctrl_node(priv, *cmdnode, 0, wait_option, NULL);
- init_waitqueue_head(&(*cmdnode)->cmdwait_q);
- (*cmdnode)->pdata_buf = *response_buf;
- (*cmdnode)->cmdflags |= CMD_F_HOSTCMD;
- (*cmdnode)->cmdwaitqwoken = 0;
- *cmd = (struct cmd_ds_command *)(*cmdnode)->bufvirtualaddr;
- (*cmd)->command = cpu_to_le16(CMD_802_11_SUBSCRIBE_EVENT);
- (*cmd)->seqnum = cpu_to_le16(++priv->adapter->seqnum);
- (*cmd)->result = 0;
- return 0;
-}
-static ssize_t libertas_lowrssi_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
+/*
+ * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
+ * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
+ * firmware. Here's an example:
+ * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00
+ * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03
+ * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ *
+ * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length,
+ * 00 00 are the data bytes of this TLV. For this TLV, their meaning is
+ * defined in mrvlietypes_thresholds
+ *
+ * This function searches in this TLV data chunk for a given TLV type
+ * and returns a pointer to the first data byte of the TLV, or to NULL
+ * if the TLV hasn't been found.
+ */
+static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
+ struct mrvlietypesheader *tlv_h;
+ uint16_t length;
ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_rssithreshold *Lowrssi;
- case __constant_cpu_to_le16(TLV_TYPE_RSSI_LOW):
- Lowrssi = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- Lowrssi->rssivalue,
- Lowrssi->rssifreq,
- (event->events & cpu_to_le16(0x0001))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_snrthreshold);
- break;
- }
- }
-
- kfree(response_buf);
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
-}
-
-static u16 libertas_get_events_bitmap(wlan_private *priv)
-{
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res;
- u16 event_bitmap;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- return res;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- return 0;
- }
-
- if (le16_to_cpu(pcmdptr->command) != CMD_RET(CMD_802_11_SUBSCRIBE_EVENT)) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- return 0;
- }
-
- event = (struct cmd_ds_802_11_subscribe_event *)(response_buf + S_DS_GEN);
- event_bitmap = le16_to_cpu(event->events);
- kfree(response_buf);
- return event_bitmap;
+ while (pos < size) {
+ tlv_h = (struct mrvlietypesheader *) tlv;
+ if (!tlv_h->len)
+ return NULL;
+ if (tlv_h->type == cpu_to_le16(tlv_type))
+ return tlv_h;
+ length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
+ pos += length;
+ tlv += length;
+ }
+ return NULL;
}
-static ssize_t libertas_lowrssi_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_rssithreshold *rssi_threshold;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- event_bitmap = libertas_get_events_bitmap(priv);
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_rssithreshold));
-
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
- rssi_threshold->header.type = cpu_to_le16(0x0104);
- rssi_threshold->header.len = cpu_to_le16(2);
- rssi_threshold->rssivalue = value;
- rssi_threshold->rssifreq = freq;
- event_bitmap |= subscribed ? 0x0001 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t libertas_lowsnr_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
+ struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
- ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
+ struct cmd_ds_802_11_subscribe_event *subscribed;
+ struct mrvlietypes_thresholds *got;
+ struct lbs_private *priv = file->private_data;
+ ssize_t ret = 0;
+ size_t pos = 0;
+ char *buf;
+ u8 value;
+ u8 freq;
+ int events = 0;
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
+ buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
+ subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL);
+ if (!subscribed) {
+ ret = -ENOMEM;
+ goto out_page;
}
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_snrthreshold *LowSnr;
- case __constant_cpu_to_le16(TLV_TYPE_SNR_LOW):
- LowSnr = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- LowSnr->snrvalue,
- LowSnr->snrfreq,
- (event->events & cpu_to_le16(0x0002))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_snrthreshold);
- break;
- }
- }
+ subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed));
+ subscribed->action = cpu_to_le16(CMD_ACT_GET);
- kfree(response_buf);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed);
+ if (ret)
+ goto out_cmd;
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
-}
+ got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv));
+ if (got) {
+ value = got->value;
+ freq = got->freq;
+ events = le16_to_cpu(subscribed->events);
-static ssize_t libertas_lowsnr_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_snrthreshold *snr_threshold;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
- }
-
- event_bitmap = libertas_get_events_bitmap(priv);
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_snrthreshold));
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
- snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_LOW);
- snr_threshold->header.len = cpu_to_le16(2);
- snr_threshold->snrvalue = value;
- snr_threshold->snrfreq = freq;
- event_bitmap |= subscribed ? 0x0002 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
+ pos += snprintf(buf, len, "%d %d %d\n", value, freq,
+ !!(events & event_mask));
}
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
+ ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- res = count;
+ out_cmd:
+ kfree(subscribed);
-out_unlock:
- free_page(addr);
- return res;
+ out_page:
+ free_page((unsigned long)buf);
+ return ret;
}
-static ssize_t libertas_failcount_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
- ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_failurecount *failcount;
- case __constant_cpu_to_le16(TLV_TYPE_FAILCOUNT):
- failcount = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- failcount->failvalue,
- failcount->Failfreq,
- (event->events & cpu_to_le16(0x0004))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_failurecount);
- break;
- }
- }
-
- kfree(response_buf);
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
-}
-static ssize_t libertas_failcount_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
+static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
+ struct file *file,
+ const char __user *userbuf, size_t count,
+ loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_failurecount *failcount;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
+ struct cmd_ds_802_11_subscribe_event *events;
+ struct mrvlietypes_thresholds *tlv;
+ struct lbs_private *priv = file->private_data;
+ ssize_t buf_size;
+ int value, freq, new_mask;
+ uint16_t curr_mask;
+ char *buf;
+ int ret;
+
+ buf = (char *)get_zeroed_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
buf_size = min(count, len - 1);
if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
+ ret = -EFAULT;
+ goto out_page;
}
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
+ ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask);
+ if (ret != 3) {
+ ret = -EINVAL;
+ goto out_page;
}
-
- event_bitmap = libertas_get_events_bitmap(priv);
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_failurecount));
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- failcount = (struct mrvlietypes_failurecount *)(ptr);
- failcount->header.type = cpu_to_le16(TLV_TYPE_FAILCOUNT);
- failcount->header.len = cpu_to_le16(2);
- failcount->failvalue = value;
- failcount->Failfreq = freq;
- event_bitmap |= subscribed ? 0x0004 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = (struct cmd_ds_command *)response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
+ events = kzalloc(sizeof(*events), GFP_KERNEL);
+ if (!events) {
+ ret = -ENOMEM;
+ goto out_page;
}
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
+ events->hdr.size = cpu_to_le16(sizeof(*events));
+ events->action = cpu_to_le16(CMD_ACT_GET);
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-
-static ssize_t libertas_bcnmiss_read(struct file *file, char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
- ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
+ if (ret)
+ goto out_events;
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
+ curr_mask = le16_to_cpu(events->events);
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
+ if (new_mask)
+ new_mask = curr_mask | event_mask;
+ else
+ new_mask = curr_mask & ~event_mask;
- pcmdptr = response_buf;
+ /* Now everything is set and we can send stuff down to the firmware */
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- free_page(addr);
- kfree(response_buf);
- return 0;
- }
+ tlv = (void *)events->tlv;
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- free_page(addr);
- kfree(response_buf);
- return 0;
- }
+ events->action = cpu_to_le16(CMD_ACT_SET);
+ events->events = cpu_to_le16(new_mask);
+ tlv->header.type = cpu_to_le16(tlv_type);
+ tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header));
+ tlv->value = value;
+ if (tlv_type != TLV_TYPE_BCNMISS)
+ tlv->freq = freq;
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_beaconsmissed *bcnmiss;
- case __constant_cpu_to_le16(TLV_TYPE_BCNMISS):
- bcnmiss = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d N/A %d\n",
- bcnmiss->beaconmissed,
- (event->events & cpu_to_le16(0x0008))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_beaconsmissed);
- break;
- }
- }
+ /* The command header, the event mask, and the one TLV */
+ events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 2 + sizeof(*tlv));
- kfree(response_buf);
+ ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events);
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
+ if (!ret)
+ ret = count;
+ out_events:
+ kfree(events);
+ out_page:
+ free_page((unsigned long)buf);
+ return ret;
}
-static ssize_t libertas_bcnmiss_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
+
+static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_beaconsmissed *bcnmiss;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
+ return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
+ file, userbuf, count, ppos);
+}
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
- }
- event_bitmap = libertas_get_events_bitmap(priv);
+static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW,
+ file, userbuf, count, ppos);
+}
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_beaconsmissed));
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- bcnmiss = (struct mrvlietypes_beaconsmissed *)(ptr);
- bcnmiss->header.type = cpu_to_le16(TLV_TYPE_BCNMISS);
- bcnmiss->header.len = cpu_to_le16(2);
- bcnmiss->beaconmissed = value;
- event_bitmap |= subscribed ? 0x0008 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
+static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
+ file, userbuf, count, ppos);
+}
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- free_page(addr);
- kfree(response_buf);
- return 0;
- }
- res = count;
-out_unlock:
- free_page(addr);
- return res;
+static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW,
+ file, userbuf, count, ppos);
}
-static ssize_t libertas_highrssi_read(struct file *file, char __user *userbuf,
+
+static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
- ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_rssithreshold *Highrssi;
- case __constant_cpu_to_le16(TLV_TYPE_RSSI_HIGH):
- Highrssi = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- Highrssi->rssivalue,
- Highrssi->rssifreq,
- (event->events & cpu_to_le16(0x0010))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_snrthreshold);
- break;
- }
- }
-
- kfree(response_buf);
-
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
+ return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
+ file, userbuf, count, ppos);
}
-static ssize_t libertas_highrssi_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
-{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_rssithreshold *rssi_threshold;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
- }
- event_bitmap = libertas_get_events_bitmap(priv);
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_rssithreshold));
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- rssi_threshold = (struct mrvlietypes_rssithreshold *)(ptr);
- rssi_threshold->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH);
- rssi_threshold->header.len = cpu_to_le16(2);
- rssi_threshold->rssivalue = value;
- rssi_threshold->rssifreq = freq;
- event_bitmap |= subscribed ? 0x0010 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- return 0;
- }
+static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT,
+ file, userbuf, count, ppos);
+}
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- return 0;
- }
- res = count;
-out_unlock:
- free_page(addr);
- return res;
+static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
+ file, userbuf, count, ppos);
}
-static ssize_t libertas_highsnr_read(struct file *file, char __user *userbuf,
+
+static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- void *response_buf;
- int res, cmd_len;
- ssize_t pos = 0;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0) {
- free_page(addr);
- return res;
- }
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_GET);
- pcmdptr->size = cpu_to_le16(sizeof(*event) + S_DS_GEN);
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
+ return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH,
+ file, userbuf, count, ppos);
+}
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
-
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- event = (void *)(response_buf + S_DS_GEN);
- while (cmd_len < le16_to_cpu(pcmdptr->size)) {
- struct mrvlietypesheader *header = (void *)(response_buf + cmd_len);
- switch (header->type) {
- struct mrvlietypes_snrthreshold *HighSnr;
- case __constant_cpu_to_le16(TLV_TYPE_SNR_HIGH):
- HighSnr = (void *)(response_buf + cmd_len);
- pos += snprintf(buf+pos, len-pos, "%d %d %d\n",
- HighSnr->snrvalue,
- HighSnr->snrfreq,
- (event->events & cpu_to_le16(0x0020))?1:0);
- default:
- cmd_len += sizeof(struct mrvlietypes_snrthreshold);
- break;
- }
- }
+static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
+ file, userbuf, count, ppos);
+}
- kfree(response_buf);
- res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
- free_page(addr);
- return res;
+static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH,
+ file, userbuf, count, ppos);
}
-static ssize_t libertas_highsnr_write(struct file *file,
- const char __user *userbuf,
- size_t count, loff_t *ppos)
+static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf,
+ size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- ssize_t res, buf_size;
- int value, freq, subscribed, cmd_len;
- struct cmd_ctrl_node *pcmdnode;
- struct cmd_ds_command *pcmdptr;
- struct cmd_ds_802_11_subscribe_event *event;
- struct mrvlietypes_snrthreshold *snr_threshold;
- void *response_buf;
- u16 event_bitmap;
- u8 *ptr;
- unsigned long addr = get_zeroed_page(GFP_KERNEL);
- char *buf = (char *)addr;
-
- buf_size = min(count, len - 1);
- if (copy_from_user(buf, userbuf, buf_size)) {
- res = -EFAULT;
- goto out_unlock;
- }
- res = sscanf(buf, "%d %d %d", &value, &freq, &subscribed);
- if (res != 3) {
- res = -EFAULT;
- goto out_unlock;
- }
+ return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
+ file, userbuf, count, ppos);
+}
- event_bitmap = libertas_get_events_bitmap(priv);
- res = libertas_event_initcmd(priv, &response_buf, &pcmdnode, &pcmdptr);
- if (res < 0)
- goto out_unlock;
-
- event = &pcmdptr->params.subscribe_event;
- event->action = cpu_to_le16(CMD_ACT_SET);
- pcmdptr->size = cpu_to_le16(S_DS_GEN +
- sizeof(struct cmd_ds_802_11_subscribe_event) +
- sizeof(struct mrvlietypes_snrthreshold));
- cmd_len = S_DS_GEN + sizeof(struct cmd_ds_802_11_subscribe_event);
- ptr = (u8*) pcmdptr+cmd_len;
- snr_threshold = (struct mrvlietypes_snrthreshold *)(ptr);
- snr_threshold->header.type = cpu_to_le16(TLV_TYPE_SNR_HIGH);
- snr_threshold->header.len = cpu_to_le16(2);
- snr_threshold->snrvalue = value;
- snr_threshold->snrfreq = freq;
- event_bitmap |= subscribed ? 0x0020 : 0x0;
- event->events = cpu_to_le16(event_bitmap);
-
- libertas_queue_cmd(adapter, pcmdnode, 1);
- wake_up_interruptible(&priv->waitq);
-
- /* Sleep until response is generated by FW */
- wait_event_interruptible(pcmdnode->cmdwait_q,
- pcmdnode->cmdwaitqwoken);
-
- pcmdptr = response_buf;
-
- if (pcmdptr->result) {
- lbs_pr_err("%s: fail, result=%d\n", __func__,
- le16_to_cpu(pcmdptr->result));
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
+static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *ppos)
+{
+ return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS,
+ file, userbuf, count, ppos);
+}
- if (pcmdptr->command != cpu_to_le16(CMD_RET(CMD_802_11_SUBSCRIBE_EVENT))) {
- lbs_pr_err("command response incorrect!\n");
- kfree(response_buf);
- free_page(addr);
- return 0;
- }
- res = count;
-out_unlock:
- free_page(addr);
- return res;
-}
-static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct wlan_offset_value offval;
+ struct lbs_private *priv = file->private_data;
+ struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
@@ -1375,23 +603,23 @@ static ssize_t libertas_rdmac_read(struct file *file, char __user *userbuf,
offval.offset = priv->mac_offset;
offval.value = 0;
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_MAC_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
- priv->mac_offset, adapter->offsetvalue.value);
+ priv->mac_offset, priv->offsetvalue.value);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
return ret;
}
-static ssize_t libertas_rdmac_write(struct file *file,
+static ssize_t lbs_rdmac_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1408,15 +636,15 @@ out_unlock:
return res;
}
-static ssize_t libertas_wrmac_write(struct file *file,
+static ssize_t lbs_wrmac_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct wlan_offset_value offval;
+ struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1433,7 +661,7 @@ static ssize_t libertas_wrmac_write(struct file *file,
offval.offset = offset;
offval.value = value;
- res = libertas_prepare_and_send_command(priv,
+ res = lbs_prepare_and_send_command(priv,
CMD_MAC_REG_ACCESS, 1,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
@@ -1444,12 +672,11 @@ out_unlock:
return res;
}
-static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct wlan_offset_value offval;
+ struct lbs_private *priv = file->private_data;
+ struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
@@ -1458,12 +685,12 @@ static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
offval.offset = priv->bbp_offset;
offval.value = 0;
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_BBP_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
- priv->bbp_offset, adapter->offsetvalue.value);
+ priv->bbp_offset, priv->offsetvalue.value);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
@@ -1471,11 +698,11 @@ static ssize_t libertas_rdbbp_read(struct file *file, char __user *userbuf,
return ret;
}
-static ssize_t libertas_rdbbp_write(struct file *file,
+static ssize_t lbs_rdbbp_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1492,15 +719,15 @@ out_unlock:
return res;
}
-static ssize_t libertas_wrbbp_write(struct file *file,
+static ssize_t lbs_wrbbp_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct wlan_offset_value offval;
+ struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1517,7 +744,7 @@ static ssize_t libertas_wrbbp_write(struct file *file,
offval.offset = offset;
offval.value = value;
- res = libertas_prepare_and_send_command(priv,
+ res = lbs_prepare_and_send_command(priv,
CMD_BBP_REG_ACCESS, 1,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
@@ -1528,12 +755,11 @@ out_unlock:
return res;
}
-static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
- wlan_adapter *adapter = priv->adapter;
- struct wlan_offset_value offval;
+ struct lbs_private *priv = file->private_data;
+ struct lbs_offset_value offval;
ssize_t pos = 0;
int ret;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
@@ -1542,12 +768,12 @@ static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
offval.offset = priv->rf_offset;
offval.value = 0;
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_RF_REG_ACCESS, 0,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
- priv->rf_offset, adapter->offsetvalue.value);
+ priv->rf_offset, priv->offsetvalue.value);
ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
free_page(addr);
@@ -1555,11 +781,11 @@ static ssize_t libertas_rdrf_read(struct file *file, char __user *userbuf,
return ret;
}
-static ssize_t libertas_rdrf_write(struct file *file,
+static ssize_t lbs_rdrf_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1576,15 +802,15 @@ out_unlock:
return res;
}
-static ssize_t libertas_wrrf_write(struct file *file,
+static ssize_t lbs_wrrf_write(struct file *file,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
- wlan_private *priv = file->private_data;
+ struct lbs_private *priv = file->private_data;
ssize_t res, buf_size;
u32 offset, value;
- struct wlan_offset_value offval;
+ struct lbs_offset_value offval;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
@@ -1601,7 +827,7 @@ static ssize_t libertas_wrrf_write(struct file *file,
offval.offset = offset;
offval.value = value;
- res = libertas_prepare_and_send_command(priv,
+ res = lbs_prepare_and_send_command(priv,
CMD_RF_REG_ACCESS, 1,
CMD_OPTION_WAITFORRSP, 0, &offval);
mdelay(10);
@@ -1619,69 +845,69 @@ out_unlock:
.write = (fwrite), \
}
-struct libertas_debugfs_files {
+struct lbs_debugfs_files {
char *name;
int perm;
struct file_operations fops;
};
-static struct libertas_debugfs_files debugfs_files[] = {
- { "info", 0444, FOPS(libertas_dev_info, write_file_dummy), },
- { "getscantable", 0444, FOPS(libertas_getscantable,
+static struct lbs_debugfs_files debugfs_files[] = {
+ { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
+ { "getscantable", 0444, FOPS(lbs_getscantable,
write_file_dummy), },
- { "sleepparams", 0644, FOPS(libertas_sleepparams_read,
- libertas_sleepparams_write), },
- { "extscan", 0600, FOPS(NULL, libertas_extscan), },
- { "setuserscan", 0600, FOPS(NULL, libertas_setuserscan), },
+ { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
+ lbs_sleepparams_write), },
+ { "extscan", 0600, FOPS(NULL, lbs_extscan), },
+ { "setuserscan", 0600, FOPS(NULL, lbs_setuserscan), },
};
-static struct libertas_debugfs_files debugfs_events_files[] = {
- {"low_rssi", 0644, FOPS(libertas_lowrssi_read,
- libertas_lowrssi_write), },
- {"low_snr", 0644, FOPS(libertas_lowsnr_read,
- libertas_lowsnr_write), },
- {"failure_count", 0644, FOPS(libertas_failcount_read,
- libertas_failcount_write), },
- {"beacon_missed", 0644, FOPS(libertas_bcnmiss_read,
- libertas_bcnmiss_write), },
- {"high_rssi", 0644, FOPS(libertas_highrssi_read,
- libertas_highrssi_write), },
- {"high_snr", 0644, FOPS(libertas_highsnr_read,
- libertas_highsnr_write), },
+static struct lbs_debugfs_files debugfs_events_files[] = {
+ {"low_rssi", 0644, FOPS(lbs_lowrssi_read,
+ lbs_lowrssi_write), },
+ {"low_snr", 0644, FOPS(lbs_lowsnr_read,
+ lbs_lowsnr_write), },
+ {"failure_count", 0644, FOPS(lbs_failcount_read,
+ lbs_failcount_write), },
+ {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read,
+ lbs_bcnmiss_write), },
+ {"high_rssi", 0644, FOPS(lbs_highrssi_read,
+ lbs_highrssi_write), },
+ {"high_snr", 0644, FOPS(lbs_highsnr_read,
+ lbs_highsnr_write), },
};
-static struct libertas_debugfs_files debugfs_regs_files[] = {
- {"rdmac", 0644, FOPS(libertas_rdmac_read, libertas_rdmac_write), },
- {"wrmac", 0600, FOPS(NULL, libertas_wrmac_write), },
- {"rdbbp", 0644, FOPS(libertas_rdbbp_read, libertas_rdbbp_write), },
- {"wrbbp", 0600, FOPS(NULL, libertas_wrbbp_write), },
- {"rdrf", 0644, FOPS(libertas_rdrf_read, libertas_rdrf_write), },
- {"wrrf", 0600, FOPS(NULL, libertas_wrrf_write), },
+static struct lbs_debugfs_files debugfs_regs_files[] = {
+ {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), },
+ {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), },
+ {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), },
+ {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), },
+ {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), },
+ {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), },
};
-void libertas_debugfs_init(void)
+void lbs_debugfs_init(void)
{
- if (!libertas_dir)
- libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
+ if (!lbs_dir)
+ lbs_dir = debugfs_create_dir("lbs_wireless", NULL);
return;
}
-void libertas_debugfs_remove(void)
+void lbs_debugfs_remove(void)
{
- if (libertas_dir)
- debugfs_remove(libertas_dir);
+ if (lbs_dir)
+ debugfs_remove(lbs_dir);
return;
}
-void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
+void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev)
{
int i;
- struct libertas_debugfs_files *files;
- if (!libertas_dir)
+ struct lbs_debugfs_files *files;
+ if (!lbs_dir)
goto exit;
- priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
+ priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir);
if (!priv->debugfs_dir)
goto exit;
@@ -1721,13 +947,13 @@ void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
}
#ifdef PROC_DEBUG
- libertas_debug_init(priv, dev);
+ lbs_debug_init(priv, dev);
#endif
exit:
return;
}
-void libertas_debugfs_remove_one(wlan_private *priv)
+void lbs_debugfs_remove_one(struct lbs_private *priv)
{
int i;
@@ -1754,8 +980,8 @@ void libertas_debugfs_remove_one(wlan_private *priv)
#ifdef PROC_DEBUG
-#define item_size(n) (FIELD_SIZEOF(wlan_adapter, n))
-#define item_addr(n) (offsetof(wlan_adapter, n))
+#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n))
+#define item_addr(n) (offsetof(struct lbs_private, n))
struct debug_data {
@@ -1764,7 +990,7 @@ struct debug_data {
size_t addr;
};
-/* To debug any member of wlan_adapter, simply add one line here.
+/* To debug any member of struct lbs_private, simply add one line here.
*/
static struct debug_data items[] = {
{"intcounter", item_size(intcounter), item_addr(intcounter)},
@@ -1785,7 +1011,7 @@ static int num_of_items = ARRAY_SIZE(items);
* @param data data to output
* @return number of output data
*/
-static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
+static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
size_t count, loff_t *ppos)
{
int val = 0;
@@ -1829,7 +1055,7 @@ static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf,
* @param data data to write
* @return number of data
*/
-static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
+static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
size_t cnt, loff_t *ppos)
{
int r, i;
@@ -1881,21 +1107,21 @@ static ssize_t wlan_debugfs_write(struct file *f, const char __user *buf,
return (ssize_t)cnt;
}
-static struct file_operations libertas_debug_fops = {
+static struct file_operations lbs_debug_fops = {
.owner = THIS_MODULE,
.open = open_file_generic,
- .write = wlan_debugfs_write,
- .read = wlan_debugfs_read,
+ .write = lbs_debugfs_write,
+ .read = lbs_debugfs_read,
};
/**
* @brief create debug proc file
*
- * @param priv pointer wlan_private
+ * @param priv pointer struct lbs_private
* @param dev pointer net_device
* @return N/A
*/
-static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
+static void lbs_debug_init(struct lbs_private *priv, struct net_device *dev)
{
int i;
@@ -1903,11 +1129,10 @@ static void libertas_debug_init(wlan_private * priv, struct net_device *dev)
return;
for (i = 0; i < num_of_items; i++)
- items[i].addr += (size_t) priv->adapter;
+ items[i].addr += (size_t) priv;
priv->debugfs_debug = debugfs_create_file("debug", 0644,
priv->debugfs_dir, &items[0],
- &libertas_debug_fops);
+ &lbs_debug_fops);
}
#endif
-
diff --git a/drivers/net/wireless/libertas/debugfs.h b/drivers/net/wireless/libertas/debugfs.h
index 880a11b95d26..f2b9c7ffe0fd 100644
--- a/drivers/net/wireless/libertas/debugfs.h
+++ b/drivers/net/wireless/libertas/debugfs.h
@@ -1,6 +1,10 @@
-void libertas_debugfs_init(void);
-void libertas_debugfs_remove(void);
+#ifndef _LBS_DEBUGFS_H_
+#define _LBS_DEBUGFS_H_
-void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev);
-void libertas_debugfs_remove_one(wlan_private *priv);
+void lbs_debugfs_init(void);
+void lbs_debugfs_remove(void);
+void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev);
+void lbs_debugfs_remove_one(struct lbs_private *priv);
+
+#endif
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 87fea9d5b90a..aaacd9bd6bd2 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -3,80 +3,74 @@
* functions defined in other source files
*/
-#ifndef _WLAN_DECL_H_
-#define _WLAN_DECL_H_
+#ifndef _LBS_DECL_H_
+#define _LBS_DECL_H_
#include <linux/device.h>
#include "defs.h"
/** Function Prototype Declaration */
-struct wlan_private;
+struct lbs_private;
struct sk_buff;
struct net_device;
-
-int libertas_set_mac_packet_filter(wlan_private * priv);
-
-void libertas_send_tx_feedback(wlan_private * priv);
-
-int libertas_free_cmd_buffer(wlan_private * priv);
struct cmd_ctrl_node;
-struct cmd_ctrl_node *libertas_get_free_cmd_ctrl_node(wlan_private * priv);
+struct cmd_ds_command;
-void libertas_set_cmd_ctrl_node(wlan_private * priv,
- struct cmd_ctrl_node *ptempnode,
- u32 cmd_oid, u16 wait_option, void *pdata_buf);
+int lbs_set_mac_packet_filter(struct lbs_private *priv);
-int libertas_prepare_and_send_command(wlan_private * priv,
- u16 cmd_no,
- u16 cmd_action,
- u16 wait_option, u32 cmd_oid, void *pdata_buf);
+void lbs_send_tx_feedback(struct lbs_private *priv);
-void libertas_queue_cmd(wlan_adapter * adapter, struct cmd_ctrl_node *cmdnode, u8 addtail);
+int lbs_free_cmd_buffer(struct lbs_private *priv);
-int libertas_allocate_cmd_buffer(wlan_private * priv);
-int libertas_execute_next_command(wlan_private * priv);
-int libertas_process_event(wlan_private * priv);
-void libertas_interrupt(struct net_device *);
-int libertas_set_radio_control(wlan_private * priv);
-u32 libertas_fw_index_to_data_rate(u8 index);
-u8 libertas_data_rate_to_fw_index(u32 rate);
-void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen);
+int lbs_prepare_and_send_command(struct lbs_private *priv,
+ u16 cmd_no,
+ u16 cmd_action,
+ u16 wait_option, u32 cmd_oid, void *pdata_buf);
-void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
+int lbs_allocate_cmd_buffer(struct lbs_private *priv);
+int lbs_execute_next_command(struct lbs_private *priv);
+int lbs_process_event(struct lbs_private *priv);
+void lbs_interrupt(struct lbs_private *priv);
+int lbs_set_radio_control(struct lbs_private *priv);
+u32 lbs_fw_index_to_data_rate(u8 index);
+u8 lbs_data_rate_to_fw_index(u32 rate);
+void lbs_get_fwversion(struct lbs_private *priv,
+ char *fwversion,
+ int maxlen);
/** The proc fs interface */
-int libertas_process_rx_command(wlan_private * priv);
-int libertas_process_tx(wlan_private * priv, struct sk_buff *skb);
-void __libertas_cleanup_and_insert_cmd(wlan_private * priv,
- struct cmd_ctrl_node *ptempcmd);
-
-int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band);
-
-int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *);
+int lbs_process_rx_command(struct lbs_private *priv);
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+ int result);
+int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
-void libertas_ps_sleep(wlan_private * priv, int wait_option);
-void libertas_ps_confirm_sleep(wlan_private * priv, u16 psmode);
-void libertas_ps_wakeup(wlan_private * priv, int wait_option);
+int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
-void libertas_tx_runqueue(wlan_private *priv);
+void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
+void lbs_ps_confirm_sleep(struct lbs_private *priv, u16 psmode);
+void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
- wlan_adapter * adapter, u8 band, u16 channel);
+struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
+ struct lbs_private *priv,
+ u8 band,
+ u16 channel);
-void libertas_mac_event_disconnected(wlan_private * priv);
+void lbs_mac_event_disconnected(struct lbs_private *priv);
-void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
+void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
/* main.c */
-struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band,
- int *cfp_no);
-wlan_private *libertas_add_card(void *card, struct device *dmdev);
-int libertas_remove_card(wlan_private *priv);
-int libertas_start_card(wlan_private *priv);
-int libertas_stop_card(wlan_private *priv);
-int libertas_add_mesh(wlan_private *priv, struct device *dev);
-void libertas_remove_mesh(wlan_private *priv);
-int libertas_reset_device(wlan_private *priv);
-
-#endif /* _WLAN_DECL_H_ */
+struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
+ u8 band,
+ int *cfp_no);
+struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
+int lbs_remove_card(struct lbs_private *priv);
+int lbs_start_card(struct lbs_private *priv);
+int lbs_stop_card(struct lbs_private *priv);
+int lbs_reset_device(struct lbs_private *priv);
+void lbs_host_to_card_done(struct lbs_private *priv);
+
+int lbs_update_channel(struct lbs_private *priv);
+#endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 3a0c9beefcf8..3053cc2160bc 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -2,8 +2,8 @@
* This header file contains global constant/enum definitions,
* global variable declaration.
*/
-#ifndef _WLAN_DEFS_H_
-#define _WLAN_DEFS_H_
+#ifndef _LBS_DEFS_H_
+#define _LBS_DEFS_H_
#include <linux/spinlock.h>
@@ -41,11 +41,11 @@
#define LBS_DEB_HEX 0x00200000
#define LBS_DEB_SDIO 0x00400000
-extern unsigned int libertas_debug;
+extern unsigned int lbs_debug;
#ifdef DEBUG
#define LBS_DEB_LL(grp, grpnam, fmt, args...) \
-do { if ((libertas_debug & (grp)) == (grp)) \
+do { if ((lbs_debug & (grp)) == (grp)) \
printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
in_interrupt() ? " (INT)" : "", ## args); } while (0)
#else
@@ -96,8 +96,8 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
int i = 0;
if (len &&
- (libertas_debug & LBS_DEB_HEX) &&
- (libertas_debug & grp))
+ (lbs_debug & LBS_DEB_HEX) &&
+ (lbs_debug & grp))
{
for (i = 1; i <= len; i++) {
if ((i & 0xf) == 1) {
@@ -132,15 +132,22 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
*/
#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32
-#define MRVDRV_NUM_OF_CMD_BUFFER 10
-#define MRVDRV_SIZE_OF_CMD_BUFFER (2 * 1024)
+#define LBS_NUM_CMD_BUFFERS 10
+#define LBS_CMD_BUFFER_SIZE (2 * 1024)
#define MRVDRV_MAX_CHANNEL_SIZE 14
#define MRVDRV_ASSOCIATION_TIME_OUT 255
#define MRVDRV_SNAP_HEADER_LEN 8
-#define WLAN_UPLD_SIZE 2312
+#define LBS_UPLD_SIZE 2312
#define DEV_NAME_LEN 32
+/* Wake criteria for HOST_SLEEP_CFG command */
+#define EHS_WAKE_ON_BROADCAST_DATA 0x0001
+#define EHS_WAKE_ON_UNICAST_DATA 0x0002
+#define EHS_WAKE_ON_MAC_EVENT 0x0004
+#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
+#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
+
/** Misc constants */
/* This section defines 802.11 specific contants */
@@ -257,17 +264,11 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define MAX_LEDS 8
-#define IS_MESH_FRAME(x) (x->cb[6])
-#define SET_MESH_FRAME(x) (x->cb[6]=1)
-#define UNSET_MESH_FRAME(x) (x->cb[6]=0)
-
/** Global Variable Declaration */
-typedef struct _wlan_private wlan_private;
-typedef struct _wlan_adapter wlan_adapter;
-extern const char libertas_driver_version[];
-extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
+extern const char lbs_driver_version[];
+extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
-extern u8 libertas_bg_rates[MAX_RATES];
+extern u8 lbs_bg_rates[MAX_RATES];
/** ENUM definition*/
/** SNRNF_TYPE */
@@ -284,13 +285,13 @@ enum SNRNF_DATA {
MAX_TYPE_AVG
};
-/** WLAN_802_11_POWER_MODE */
-enum WLAN_802_11_POWER_MODE {
- WLAN802_11POWERMODECAM,
- WLAN802_11POWERMODEMAX_PSP,
- WLAN802_11POWERMODEFAST_PSP,
+/** LBS_802_11_POWER_MODE */
+enum LBS_802_11_POWER_MODE {
+ LBS802_11POWERMODECAM,
+ LBS802_11POWERMODEMAX_PSP,
+ LBS802_11POWERMODEFAST_PSP,
/*not a real mode, defined as an upper bound */
- WLAN802_11POWEMODEMAX
+ LBS802_11POWEMODEMAX
};
/** PS_STATE */
@@ -308,16 +309,16 @@ enum DNLD_STATE {
DNLD_CMD_SENT
};
-/** WLAN_MEDIA_STATE */
-enum WLAN_MEDIA_STATE {
- LIBERTAS_CONNECTED,
- LIBERTAS_DISCONNECTED
+/** LBS_MEDIA_STATE */
+enum LBS_MEDIA_STATE {
+ LBS_CONNECTED,
+ LBS_DISCONNECTED
};
-/** WLAN_802_11_PRIVACY_FILTER */
-enum WLAN_802_11_PRIVACY_FILTER {
- WLAN802_11PRIVFILTERACCEPTALL,
- WLAN802_11PRIVFILTER8021XWEP
+/** LBS_802_11_PRIVACY_FILTER */
+enum LBS_802_11_PRIVACY_FILTER {
+ LBS802_11PRIVFILTERACCEPTALL,
+ LBS802_11PRIVFILTER8021XWEP
};
/** mv_ms_type */
@@ -382,4 +383,4 @@ enum SNMP_MIB_VALUE_e {
#define FWT_DEFAULT_SLEEPMODE 0
#define FWT_DEFAULT_SNR 0
-#endif /* _WLAN_DEFS_H_ */
+#endif
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 1fb807aa91b9..58d7ef6b5ff5 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -1,21 +1,20 @@
/**
* This file contains definitions and data structures specific
* to Marvell 802.11 NIC. It contains the Device Information
- * structure wlan_adapter.
+ * structure struct lbs_private..
*/
-#ifndef _WLAN_DEV_H_
-#define _WLAN_DEV_H_
+#ifndef _LBS_DEV_H_
+#define _LBS_DEV_H_
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <linux/ethtool.h>
#include <linux/debugfs.h>
-#include <net/ieee80211.h>
#include "defs.h"
#include "scan.h"
-extern struct ethtool_ops libertas_ethtool_ops;
+extern struct ethtool_ops lbs_ethtool_ops;
#define MAX_BSSID_PER_CHANNEL 16
@@ -53,7 +52,7 @@ struct region_channel {
struct chan_freq_power *CFP;
};
-struct wlan_802_11_security {
+struct lbs_802_11_security {
u8 WPAenabled;
u8 WPA2enabled;
u8 wep_enabled;
@@ -78,16 +77,16 @@ struct current_bss_params {
/** sleep_params */
struct sleep_params {
- u16 sp_error;
- u16 sp_offset;
- u16 sp_stabletime;
- u8 sp_calcontrol;
- u8 sp_extsleepclk;
- u16 sp_reserved;
+ uint16_t sp_error;
+ uint16_t sp_offset;
+ uint16_t sp_stabletime;
+ uint8_t sp_calcontrol;
+ uint8_t sp_extsleepclk;
+ uint16_t sp_reserved;
};
/* Mesh statistics */
-struct wlan_mesh_stats {
+struct lbs_mesh_stats {
u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
u32 fwd_drop_ttl; /* Fwd: TTL zero */
@@ -99,26 +98,22 @@ struct wlan_mesh_stats {
};
/** Private structure for the MV device */
-struct _wlan_private {
- int open;
+struct lbs_private {
int mesh_open;
int infra_open;
int mesh_autostart_enabled;
- __le16 boot2_version;
char name[DEV_NAME_LEN];
void *card;
- wlan_adapter *adapter;
struct net_device *dev;
struct net_device_stats stats;
struct net_device *mesh_dev; /* Virtual device */
struct net_device *rtap_net_dev;
- struct ieee80211_device *ieee;
struct iw_statistics wstats;
- struct wlan_mesh_stats mstats;
+ struct lbs_mesh_stats mstats;
struct dentry *debugfs_dir;
struct dentry *debugfs_debug;
struct dentry *debugfs_files[6];
@@ -136,15 +131,13 @@ struct _wlan_private {
/** Upload length */
u32 upld_len;
/* Upload buffer */
- u8 upld_buf[WLAN_UPLD_SIZE];
+ u8 upld_buf[LBS_UPLD_SIZE];
/* Download sent:
bit0 1/0=data_sent/data_tx_done,
bit1 1/0=cmd_sent/cmd_tx_done,
all other bits reserved 0 */
u8 dnld_sent;
- struct device *hotplug_device;
-
/** thread to service interrupts */
struct task_struct *main_thread;
wait_queue_head_t waitq;
@@ -155,65 +148,29 @@ struct _wlan_private {
struct work_struct sync_channel;
/** Hardware access */
- int (*hw_host_to_card) (wlan_private * priv, u8 type, u8 * payload, u16 nb);
- int (*hw_get_int_status) (wlan_private * priv, u8 *);
- int (*hw_read_event_cause) (wlan_private *);
-};
+ int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
+ int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
+ int (*hw_read_event_cause) (struct lbs_private *);
-/** Association request
- *
- * Encapsulates all the options that describe a specific assocation request
- * or configuration of the wireless card's radio, mode, and security settings.
- */
-struct assoc_request {
-#define ASSOC_FLAG_SSID 1
-#define ASSOC_FLAG_CHANNEL 2
-#define ASSOC_FLAG_BAND 3
-#define ASSOC_FLAG_MODE 4
-#define ASSOC_FLAG_BSSID 5
-#define ASSOC_FLAG_WEP_KEYS 6
-#define ASSOC_FLAG_WEP_TX_KEYIDX 7
-#define ASSOC_FLAG_WPA_MCAST_KEY 8
-#define ASSOC_FLAG_WPA_UCAST_KEY 9
-#define ASSOC_FLAG_SECINFO 10
-#define ASSOC_FLAG_WPA_IE 11
- unsigned long flags;
+ /* Wake On LAN */
+ uint32_t wol_criteria;
+ uint8_t wol_gpio;
+ uint8_t wol_gap;
- u8 ssid[IW_ESSID_MAX_SIZE + 1];
- u8 ssid_len;
- u8 channel;
- u8 band;
- u8 mode;
- u8 bssid[ETH_ALEN];
-
- /** WEP keys */
- struct enc_key wep_keys[4];
- u16 wep_tx_keyidx;
-
- /** WPA keys */
- struct enc_key wpa_mcast_key;
- struct enc_key wpa_unicast_key;
+ /* was struct lbs_adapter from here... */
- struct wlan_802_11_security secinfo;
-
- /** WPA Information Elements*/
- u8 wpa_ie[MAX_WPA_IE_LEN];
- u8 wpa_ie_len;
-
- /* BSS to associate with for infrastructure of Ad-Hoc join */
- struct bss_descriptor bss;
-};
-
-/** Wlan adapter data structure*/
-struct _wlan_adapter {
+ /** Wlan adapter data structure*/
/** STATUS variables */
- u8 fwreleasenumber[4];
+ u32 fwrelease;
u32 fwcapinfo;
/* protected with big lock */
struct mutex lock;
- u8 tmptxbuf[WLAN_UPLD_SIZE];
+ /* TX packet ready to be sent... */
+ int tx_pending_len; /* -1 while building packet */
+
+ u8 tx_pending_buf[LBS_UPLD_SIZE];
/* protected by hard_start_xmit serialization */
/** command-related variables */
@@ -231,8 +188,7 @@ struct _wlan_adapter {
struct list_head cmdpendingq;
wait_queue_head_t cmd_pending;
- u8 nr_cmd_pending;
- /* command related variables protected by adapter->driver_lock */
+ /* command related variables protected by priv->driver_lock */
/** Async and Sync Event variables */
u32 intcounter;
@@ -244,17 +200,18 @@ struct _wlan_adapter {
/** Timers */
struct timer_list command_timer;
-
- /* TX queue used in PS mode */
- spinlock_t txqueue_lock;
- struct sk_buff *tx_queue_ps[NR_TX_QUEUE];
- unsigned int tx_queue_idx;
+ int nr_retries;
+ int cmd_timed_out;
u8 hisregcpy;
/** current ssid/bssid related parameters*/
struct current_bss_params curbssparams;
+ uint16_t mesh_tlv;
+ u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 mesh_ssid_len;
+
/* IW_MODE_* */
u8 mode;
@@ -263,6 +220,8 @@ struct _wlan_adapter {
struct list_head network_free_list;
struct bss_descriptor *networks;
+ u16 beacon_period;
+ u8 beacon_enable;
u8 adhoccreate;
/** capability Info used in Association, start, join */
@@ -286,11 +245,11 @@ struct _wlan_adapter {
/** Tx-related variables (for single packet tx) */
struct sk_buff *currenttxskb;
- u16 TxLockFlag;
/** NIC Operation characteristics */
u16 currentpacketfilter;
u32 connect_status;
+ u32 mesh_connect_status;
u16 regioncode;
u16 txpowerlevel;
@@ -300,15 +259,17 @@ struct _wlan_adapter {
u16 psmode; /* Wlan802_11PowermodeCAM=disable
Wlan802_11PowermodeMAX_PSP=enable */
u32 psstate;
+ char ps_supported;
u8 needtowakeup;
- struct PS_CMD_ConfirmSleep libertas_ps_confirm_sleep;
+ struct PS_CMD_ConfirmSleep lbs_ps_confirm_sleep;
+ struct cmd_header lbs_ps_confirm_wake;
struct assoc_request * pending_assoc_req;
struct assoc_request * in_progress_assoc_req;
/** Encryption parameter */
- struct wlan_802_11_security secinfo;
+ struct lbs_802_11_security secinfo;
/** WEP keys */
struct enc_key wep_keys[4];
@@ -338,9 +299,6 @@ struct _wlan_adapter {
u8 cur_rate;
u8 auto_rate;
- /** sleep_params */
- struct sleep_params sp;
-
/** RF calibration data */
#define MAX_REGION_CHANNEL_NUM 2
@@ -350,7 +308,7 @@ struct _wlan_adapter {
struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
/** 11D and Domain Regulatory Data */
- struct wlan_802_11d_domain_reg domainreg;
+ struct lbs_802_11d_domain_reg domainreg;
struct parsed_region_chan_11d parsed_region_chan;
/** FSM variable for 11d support */
@@ -358,14 +316,57 @@ struct _wlan_adapter {
/** MISCELLANEOUS */
u8 *prdeeprom;
- struct wlan_offset_value offsetvalue;
+ struct lbs_offset_value offsetvalue;
struct cmd_ds_802_11_get_log logmsg;
u32 monitormode;
+ int last_scanned_channel;
u8 fw_ready;
+};
+
+/** Association request
+ *
+ * Encapsulates all the options that describe a specific assocation request
+ * or configuration of the wireless card's radio, mode, and security settings.
+ */
+struct assoc_request {
+#define ASSOC_FLAG_SSID 1
+#define ASSOC_FLAG_CHANNEL 2
+#define ASSOC_FLAG_BAND 3
+#define ASSOC_FLAG_MODE 4
+#define ASSOC_FLAG_BSSID 5
+#define ASSOC_FLAG_WEP_KEYS 6
+#define ASSOC_FLAG_WEP_TX_KEYIDX 7
+#define ASSOC_FLAG_WPA_MCAST_KEY 8
+#define ASSOC_FLAG_WPA_UCAST_KEY 9
+#define ASSOC_FLAG_SECINFO 10
+#define ASSOC_FLAG_WPA_IE 11
+ unsigned long flags;
- u8 last_scanned_channel;
+ u8 ssid[IW_ESSID_MAX_SIZE + 1];
+ u8 ssid_len;
+ u8 channel;
+ u8 band;
+ u8 mode;
+ u8 bssid[ETH_ALEN];
+
+ /** WEP keys */
+ struct enc_key wep_keys[4];
+ u16 wep_tx_keyidx;
+
+ /** WPA keys */
+ struct enc_key wpa_mcast_key;
+ struct enc_key wpa_unicast_key;
+
+ struct lbs_802_11_security secinfo;
+
+ /** WPA Information Elements*/
+ u8 wpa_ie[MAX_WPA_IE_LEN];
+ u8 wpa_ie_len;
+
+ /* BSS to associate with for infrastructure of Ad-Hoc join */
+ struct bss_descriptor bss;
};
-#endif /* _WLAN_DEV_H_ */
+#endif
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 3dae15211b6a..21e6f988ea81 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -8,6 +8,8 @@
#include "dev.h"
#include "join.h"
#include "wext.h"
+#include "cmd.h"
+
static const char * mesh_stat_strings[]= {
"drop_duplicate_bcast",
"drop_ttl_zero",
@@ -19,35 +21,34 @@ static const char * mesh_stat_strings[]= {
"tx_failed_cnt"
};
-static void libertas_ethtool_get_drvinfo(struct net_device *dev,
+static void lbs_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- wlan_private *priv = (wlan_private *) dev->priv;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
char fwver[32];
- libertas_get_fwversion(priv->adapter, fwver, sizeof(fwver) - 1);
+ lbs_get_fwversion(priv, fwver, sizeof(fwver) - 1);
strcpy(info->driver, "libertas");
- strcpy(info->version, libertas_driver_version);
+ strcpy(info->version, lbs_driver_version);
strcpy(info->fw_version, fwver);
}
/* All 8388 parts have 16KiB EEPROM size at the time of writing.
* In case that changes this needs fixing.
*/
-#define LIBERTAS_EEPROM_LEN 16384
+#define LBS_EEPROM_LEN 16384
-static int libertas_ethtool_get_eeprom_len(struct net_device *dev)
+static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
{
- return LIBERTAS_EEPROM_LEN;
+ return LBS_EEPROM_LEN;
}
-static int libertas_ethtool_get_eeprom(struct net_device *dev,
+static int lbs_ethtool_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * bytes)
{
- wlan_private *priv = (wlan_private *) dev->priv;
- wlan_adapter *adapter = priv->adapter;
- struct wlan_ioctl_regrdwr regctrl;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_ioctl_regrdwr regctrl;
char *ptr;
int ret;
@@ -55,47 +56,47 @@ static int libertas_ethtool_get_eeprom(struct net_device *dev,
regctrl.offset = eeprom->offset;
regctrl.NOB = eeprom->len;
- if (eeprom->offset + eeprom->len > LIBERTAS_EEPROM_LEN)
+ if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN)
return -EINVAL;
// mutex_lock(&priv->mutex);
- adapter->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
- if (!adapter->prdeeprom)
+ priv->prdeeprom = kmalloc(eeprom->len+sizeof(regctrl), GFP_KERNEL);
+ if (!priv->prdeeprom)
return -ENOMEM;
- memcpy(adapter->prdeeprom, &regctrl, sizeof(regctrl));
+ memcpy(priv->prdeeprom, &regctrl, sizeof(regctrl));
/* +14 is for action, offset, and NOB in
* response */
lbs_deb_ethtool("action:%d offset: %x NOB: %02x\n",
regctrl.action, regctrl.offset, regctrl.NOB);
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_EEPROM_ACCESS,
regctrl.action,
CMD_OPTION_WAITFORRSP, 0,
&regctrl);
if (ret) {
- if (adapter->prdeeprom)
- kfree(adapter->prdeeprom);
+ if (priv->prdeeprom)
+ kfree(priv->prdeeprom);
goto done;
}
mdelay(10);
- ptr = (char *)adapter->prdeeprom;
+ ptr = (char *)priv->prdeeprom;
/* skip the command header, but include the "value" u32 variable */
- ptr = ptr + sizeof(struct wlan_ioctl_regrdwr) - 4;
+ ptr = ptr + sizeof(struct lbs_ioctl_regrdwr) - 4;
/*
* Return the result back to the user
*/
memcpy(bytes, ptr, eeprom->len);
- if (adapter->prdeeprom)
- kfree(adapter->prdeeprom);
+ if (priv->prdeeprom)
+ kfree(priv->prdeeprom);
// mutex_unlock(&priv->mutex);
ret = 0;
@@ -105,17 +106,17 @@ done:
return ret;
}
-static void libertas_ethtool_get_stats(struct net_device * dev,
+static void lbs_ethtool_get_stats(struct net_device * dev,
struct ethtool_stats * stats, u64 * data)
{
- wlan_private *priv = dev->priv;
+ struct lbs_private *priv = dev->priv;
struct cmd_ds_mesh_access mesh_access;
int ret;
lbs_deb_enter(LBS_DEB_ETHTOOL);
/* Get Mesh Statistics */
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_MESH_ACCESS, CMD_ACT_MESH_GET_STATS,
CMD_OPTION_WAITFORRSP, 0, &mesh_access);
@@ -143,7 +144,7 @@ static void libertas_ethtool_get_stats(struct net_device * dev,
lbs_deb_enter(LBS_DEB_ETHTOOL);
}
-static int libertas_ethtool_get_sset_count(struct net_device * dev, int sset)
+static int lbs_ethtool_get_sset_count(struct net_device * dev, int sset)
{
switch (sset) {
case ETH_SS_STATS:
@@ -153,7 +154,7 @@ static int libertas_ethtool_get_sset_count(struct net_device * dev, int sset)
}
}
-static void libertas_ethtool_get_strings (struct net_device * dev,
+static void lbs_ethtool_get_strings(struct net_device *dev,
u32 stringset,
u8 * s)
{
@@ -173,12 +174,57 @@ static void libertas_ethtool_get_strings (struct net_device * dev,
lbs_deb_enter(LBS_DEB_ETHTOOL);
}
-struct ethtool_ops libertas_ethtool_ops = {
- .get_drvinfo = libertas_ethtool_get_drvinfo,
- .get_eeprom = libertas_ethtool_get_eeprom,
- .get_eeprom_len = libertas_ethtool_get_eeprom_len,
- .get_sset_count = libertas_ethtool_get_sset_count,
- .get_ethtool_stats = libertas_ethtool_get_stats,
- .get_strings = libertas_ethtool_get_strings,
+static void lbs_ethtool_get_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct lbs_private *priv = dev->priv;
+
+ if (priv->wol_criteria == 0xffffffff) {
+ /* Interface driver didn't configure wake */
+ wol->supported = wol->wolopts = 0;
+ return;
+ }
+
+ wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
+
+ if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
+ wol->wolopts |= WAKE_UCAST;
+ if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
+ wol->wolopts |= WAKE_MCAST;
+ if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
+ wol->wolopts |= WAKE_BCAST;
+ if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
+ wol->wolopts |= WAKE_PHY;
+}
+
+static int lbs_ethtool_set_wol(struct net_device *dev,
+ struct ethtool_wolinfo *wol)
+{
+ struct lbs_private *priv = dev->priv;
+ uint32_t criteria = 0;
+
+ if (priv->wol_criteria == 0xffffffff && wol->wolopts)
+ return -EOPNOTSUPP;
+
+ if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
+ return -EOPNOTSUPP;
+
+ if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA;
+ if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA;
+ if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA;
+ if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT;
+
+ return lbs_host_sleep_cfg(priv, criteria);
+}
+
+struct ethtool_ops lbs_ethtool_ops = {
+ .get_drvinfo = lbs_ethtool_get_drvinfo,
+ .get_eeprom = lbs_ethtool_get_eeprom,
+ .get_eeprom_len = lbs_ethtool_get_eeprom_len,
+ .get_sset_count = lbs_ethtool_get_sset_count,
+ .get_ethtool_stats = lbs_ethtool_get_stats,
+ .get_strings = lbs_ethtool_get_strings,
+ .get_wol = lbs_ethtool_get_wol,
+ .set_wol = lbs_ethtool_set_wol,
};
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index b37ddbca969f..1aa04076b1ac 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -2,25 +2,25 @@
* This file contains definitions of WLAN commands.
*/
-#ifndef _HOST_H_
-#define _HOST_H_
+#ifndef _LBS_HOST_H_
+#define _LBS_HOST_H_
/** PUBLIC DEFINITIONS */
-#define DEFAULT_AD_HOC_CHANNEL 6
-#define DEFAULT_AD_HOC_CHANNEL_A 36
+#define DEFAULT_AD_HOC_CHANNEL 6
+#define DEFAULT_AD_HOC_CHANNEL_A 36
/** IEEE 802.11 oids */
-#define OID_802_11_SSID 0x00008002
-#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
-#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
-#define OID_802_11_RTS_THRESHOLD 0x0000800A
-#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
-#define OID_802_11_SUPPORTED_RATES 0x0000800E
-#define OID_802_11_STATISTICS 0x00008012
-#define OID_802_11_TX_RETRYCOUNT 0x0000801D
-#define OID_802_11D_ENABLE 0x00008020
-
-#define CMD_OPTION_WAITFORRSP 0x0002
+#define OID_802_11_SSID 0x00008002
+#define OID_802_11_INFRASTRUCTURE_MODE 0x00008008
+#define OID_802_11_FRAGMENTATION_THRESHOLD 0x00008009
+#define OID_802_11_RTS_THRESHOLD 0x0000800A
+#define OID_802_11_TX_ANTENNA_SELECTED 0x0000800D
+#define OID_802_11_SUPPORTED_RATES 0x0000800E
+#define OID_802_11_STATISTICS 0x00008012
+#define OID_802_11_TX_RETRYCOUNT 0x0000801D
+#define OID_802_11D_ENABLE 0x00008020
+
+#define CMD_OPTION_WAITFORRSP 0x0002
/** Host command IDs */
@@ -30,192 +30,189 @@
#define CMD_RET(cmd) (0x8000 | cmd)
/* Return command convention exceptions: */
-#define CMD_RET_802_11_ASSOCIATE 0x8012
+#define CMD_RET_802_11_ASSOCIATE 0x8012
/* Command codes */
-#define CMD_CODE_DNLD 0x0002
-#define CMD_GET_HW_SPEC 0x0003
-#define CMD_EEPROM_UPDATE 0x0004
-#define CMD_802_11_RESET 0x0005
-#define CMD_802_11_SCAN 0x0006
-#define CMD_802_11_GET_LOG 0x000b
-#define CMD_MAC_MULTICAST_ADR 0x0010
-#define CMD_802_11_AUTHENTICATE 0x0011
-#define CMD_802_11_EEPROM_ACCESS 0x0059
-#define CMD_802_11_ASSOCIATE 0x0050
-#define CMD_802_11_SET_WEP 0x0013
-#define CMD_802_11_GET_STAT 0x0014
-#define CMD_802_3_GET_STAT 0x0015
-#define CMD_802_11_SNMP_MIB 0x0016
-#define CMD_MAC_REG_MAP 0x0017
-#define CMD_BBP_REG_MAP 0x0018
-#define CMD_MAC_REG_ACCESS 0x0019
-#define CMD_BBP_REG_ACCESS 0x001a
-#define CMD_RF_REG_ACCESS 0x001b
-#define CMD_802_11_RADIO_CONTROL 0x001c
-#define CMD_802_11_RF_CHANNEL 0x001d
-#define CMD_802_11_RF_TX_POWER 0x001e
-#define CMD_802_11_RSSI 0x001f
-#define CMD_802_11_RF_ANTENNA 0x0020
-
-#define CMD_802_11_PS_MODE 0x0021
-
-#define CMD_802_11_DATA_RATE 0x0022
-#define CMD_RF_REG_MAP 0x0023
-#define CMD_802_11_DEAUTHENTICATE 0x0024
-#define CMD_802_11_REASSOCIATE 0x0025
-#define CMD_802_11_DISASSOCIATE 0x0026
-#define CMD_MAC_CONTROL 0x0028
-#define CMD_802_11_AD_HOC_START 0x002b
-#define CMD_802_11_AD_HOC_JOIN 0x002c
-
-#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
-#define CMD_802_11_ENABLE_RSN 0x002f
-#define CMD_802_11_PAIRWISE_TSC 0x0036
-#define CMD_802_11_GROUP_TSC 0x0037
-#define CMD_802_11_KEY_MATERIAL 0x005e
-
-#define CMD_802_11_SET_AFC 0x003c
-#define CMD_802_11_GET_AFC 0x003d
-
-#define CMD_802_11_AD_HOC_STOP 0x0040
-
-#define CMD_802_11_BEACON_STOP 0x0049
-
-#define CMD_802_11_MAC_ADDRESS 0x004D
-#define CMD_802_11_EEPROM_ACCESS 0x0059
-
-#define CMD_802_11_BAND_CONFIG 0x0058
-
-#define CMD_802_11D_DOMAIN_INFO 0x005b
-
-#define CMD_802_11_SLEEP_PARAMS 0x0066
-
-#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
-
-#define CMD_802_11_TPC_CFG 0x0072
-#define CMD_802_11_PWR_CFG 0x0073
-
-#define CMD_802_11_LED_GPIO_CTRL 0x004e
-
-#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
-
-#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
-
-#define CMD_802_11_TX_RATE_QUERY 0x007f
-
-#define CMD_GET_TSF 0x0080
-
-#define CMD_BT_ACCESS 0x0087
-
-#define CMD_FWT_ACCESS 0x0095
-
-#define CMD_802_11_MONITOR_MODE 0x0098
-
-#define CMD_MESH_ACCESS 0x009b
-
-#define CMD_SET_BOOT2_VER 0x00a5
+#define CMD_CODE_DNLD 0x0002
+#define CMD_GET_HW_SPEC 0x0003
+#define CMD_EEPROM_UPDATE 0x0004
+#define CMD_802_11_RESET 0x0005
+#define CMD_802_11_SCAN 0x0006
+#define CMD_802_11_GET_LOG 0x000b
+#define CMD_MAC_MULTICAST_ADR 0x0010
+#define CMD_802_11_AUTHENTICATE 0x0011
+#define CMD_802_11_EEPROM_ACCESS 0x0059
+#define CMD_802_11_ASSOCIATE 0x0050
+#define CMD_802_11_SET_WEP 0x0013
+#define CMD_802_11_GET_STAT 0x0014
+#define CMD_802_3_GET_STAT 0x0015
+#define CMD_802_11_SNMP_MIB 0x0016
+#define CMD_MAC_REG_MAP 0x0017
+#define CMD_BBP_REG_MAP 0x0018
+#define CMD_MAC_REG_ACCESS 0x0019
+#define CMD_BBP_REG_ACCESS 0x001a
+#define CMD_RF_REG_ACCESS 0x001b
+#define CMD_802_11_RADIO_CONTROL 0x001c
+#define CMD_802_11_RF_CHANNEL 0x001d
+#define CMD_802_11_RF_TX_POWER 0x001e
+#define CMD_802_11_RSSI 0x001f
+#define CMD_802_11_RF_ANTENNA 0x0020
+#define CMD_802_11_PS_MODE 0x0021
+#define CMD_802_11_DATA_RATE 0x0022
+#define CMD_RF_REG_MAP 0x0023
+#define CMD_802_11_DEAUTHENTICATE 0x0024
+#define CMD_802_11_REASSOCIATE 0x0025
+#define CMD_802_11_DISASSOCIATE 0x0026
+#define CMD_MAC_CONTROL 0x0028
+#define CMD_802_11_AD_HOC_START 0x002b
+#define CMD_802_11_AD_HOC_JOIN 0x002c
+#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e
+#define CMD_802_11_ENABLE_RSN 0x002f
+#define CMD_802_11_PAIRWISE_TSC 0x0036
+#define CMD_802_11_GROUP_TSC 0x0037
+#define CMD_802_11_SET_AFC 0x003c
+#define CMD_802_11_GET_AFC 0x003d
+#define CMD_802_11_AD_HOC_STOP 0x0040
+#define CMD_802_11_HOST_SLEEP_CFG 0x0043
+#define CMD_802_11_WAKEUP_CONFIRM 0x0044
+#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045
+#define CMD_802_11_BEACON_STOP 0x0049
+#define CMD_802_11_MAC_ADDRESS 0x004d
+#define CMD_802_11_LED_GPIO_CTRL 0x004e
+#define CMD_802_11_EEPROM_ACCESS 0x0059
+#define CMD_802_11_BAND_CONFIG 0x0058
+#define CMD_802_11D_DOMAIN_INFO 0x005b
+#define CMD_802_11_KEY_MATERIAL 0x005e
+#define CMD_802_11_SLEEP_PARAMS 0x0066
+#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067
+#define CMD_802_11_SLEEP_PERIOD 0x0068
+#define CMD_802_11_TPC_CFG 0x0072
+#define CMD_802_11_PWR_CFG 0x0073
+#define CMD_802_11_FW_WAKE_METHOD 0x0074
+#define CMD_802_11_SUBSCRIBE_EVENT 0x0075
+#define CMD_802_11_RATE_ADAPT_RATESET 0x0076
+#define CMD_802_11_TX_RATE_QUERY 0x007f
+#define CMD_GET_TSF 0x0080
+#define CMD_BT_ACCESS 0x0087
+#define CMD_FWT_ACCESS 0x0095
+#define CMD_802_11_MONITOR_MODE 0x0098
+#define CMD_MESH_ACCESS 0x009b
+#define CMD_MESH_CONFIG 0x00a3
+#define CMD_SET_BOOT2_VER 0x00a5
+#define CMD_802_11_BEACON_CTRL 0x00b0
/* For the IEEE Power Save */
-#define CMD_SUBCMD_ENTER_PS 0x0030
-#define CMD_SUBCMD_EXIT_PS 0x0031
-#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034
-#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
-#define CMD_SUBCMD_FULL_POWERUP 0x0036
-
-#define CMD_ENABLE_RSN 0x0001
-#define CMD_DISABLE_RSN 0x0000
+#define CMD_SUBCMD_ENTER_PS 0x0030
+#define CMD_SUBCMD_EXIT_PS 0x0031
+#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034
+#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
+#define CMD_SUBCMD_FULL_POWERUP 0x0036
-#define CMD_ACT_SET 0x0001
-#define CMD_ACT_GET 0x0000
+#define CMD_ENABLE_RSN 0x0001
+#define CMD_DISABLE_RSN 0x0000
-#define CMD_ACT_GET_AES (CMD_ACT_GET + 2)
-#define CMD_ACT_SET_AES (CMD_ACT_SET + 2)
-#define CMD_ACT_REMOVE_AES (CMD_ACT_SET + 3)
+#define CMD_ACT_GET 0x0000
+#define CMD_ACT_SET 0x0001
+#define CMD_ACT_GET_AES 0x0002
+#define CMD_ACT_SET_AES 0x0003
+#define CMD_ACT_REMOVE_AES 0x0004
/* Define action or option for CMD_802_11_SET_WEP */
-#define CMD_ACT_ADD 0x0002
-#define CMD_ACT_REMOVE 0x0004
-#define CMD_ACT_USE_DEFAULT 0x0008
+#define CMD_ACT_ADD 0x0002
+#define CMD_ACT_REMOVE 0x0004
+#define CMD_ACT_USE_DEFAULT 0x0008
-#define CMD_TYPE_WEP_40_BIT 0x01
-#define CMD_TYPE_WEP_104_BIT 0x02
+#define CMD_TYPE_WEP_40_BIT 0x01
+#define CMD_TYPE_WEP_104_BIT 0x02
-#define CMD_NUM_OF_WEP_KEYS 4
+#define CMD_NUM_OF_WEP_KEYS 4
-#define CMD_WEP_KEY_INDEX_MASK 0x3fff
+#define CMD_WEP_KEY_INDEX_MASK 0x3fff
/* Define action or option for CMD_802_11_RESET */
-#define CMD_ACT_HALT 0x0003
+#define CMD_ACT_HALT 0x0003
/* Define action or option for CMD_802_11_SCAN */
-#define CMD_BSS_TYPE_BSS 0x0001
-#define CMD_BSS_TYPE_IBSS 0x0002
-#define CMD_BSS_TYPE_ANY 0x0003
+#define CMD_BSS_TYPE_BSS 0x0001
+#define CMD_BSS_TYPE_IBSS 0x0002
+#define CMD_BSS_TYPE_ANY 0x0003
/* Define action or option for CMD_802_11_SCAN */
-#define CMD_SCAN_TYPE_ACTIVE 0x0000
-#define CMD_SCAN_TYPE_PASSIVE 0x0001
+#define CMD_SCAN_TYPE_ACTIVE 0x0000
+#define CMD_SCAN_TYPE_PASSIVE 0x0001
#define CMD_SCAN_RADIO_TYPE_BG 0
-#define CMD_SCAN_PROBE_DELAY_TIME 0
+#define CMD_SCAN_PROBE_DELAY_TIME 0
/* Define action or option for CMD_MAC_CONTROL */
-#define CMD_ACT_MAC_RX_ON 0x0001
-#define CMD_ACT_MAC_TX_ON 0x0002
-#define CMD_ACT_MAC_LOOPBACK_ON 0x0004
-#define CMD_ACT_MAC_WEP_ENABLE 0x0008
-#define CMD_ACT_MAC_INT_ENABLE 0x0010
-#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
-#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
-#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
-#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
-#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
+#define CMD_ACT_MAC_RX_ON 0x0001
+#define CMD_ACT_MAC_TX_ON 0x0002
+#define CMD_ACT_MAC_LOOPBACK_ON 0x0004
+#define CMD_ACT_MAC_WEP_ENABLE 0x0008
+#define CMD_ACT_MAC_INT_ENABLE 0x0010
+#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020
+#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040
+#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080
+#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100
+#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400
/* Define action or option for CMD_802_11_RADIO_CONTROL */
-#define CMD_TYPE_AUTO_PREAMBLE 0x0001
-#define CMD_TYPE_SHORT_PREAMBLE 0x0002
-#define CMD_TYPE_LONG_PREAMBLE 0x0003
-
-#define TURN_ON_RF 0x01
-#define RADIO_ON 0x01
-#define RADIO_OFF 0x00
-
-#define SET_AUTO_PREAMBLE 0x05
-#define SET_SHORT_PREAMBLE 0x03
-#define SET_LONG_PREAMBLE 0x01
+#define CMD_TYPE_AUTO_PREAMBLE 0x0001
+#define CMD_TYPE_SHORT_PREAMBLE 0x0002
+#define CMD_TYPE_LONG_PREAMBLE 0x0003
+
+/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
+#define CMD_SUBSCRIBE_RSSI_LOW 0x0001
+#define CMD_SUBSCRIBE_SNR_LOW 0x0002
+#define CMD_SUBSCRIBE_FAILCOUNT 0x0004
+#define CMD_SUBSCRIBE_BCNMISS 0x0008
+#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010
+#define CMD_SUBSCRIBE_SNR_HIGH 0x0020
+
+#define TURN_ON_RF 0x01
+#define RADIO_ON 0x01
+#define RADIO_OFF 0x00
+
+#define SET_AUTO_PREAMBLE 0x05
+#define SET_SHORT_PREAMBLE 0x03
+#define SET_LONG_PREAMBLE 0x01
/* Define action or option for CMD_802_11_RF_CHANNEL */
-#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
-#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
+#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00
+#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01
/* Define action or option for CMD_802_11_RF_TX_POWER */
-#define CMD_ACT_TX_POWER_OPT_GET 0x0000
-#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
-#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
-#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
+#define CMD_ACT_TX_POWER_OPT_GET 0x0000
+#define CMD_ACT_TX_POWER_OPT_SET_HIGH 0x8007
+#define CMD_ACT_TX_POWER_OPT_SET_MID 0x8004
+#define CMD_ACT_TX_POWER_OPT_SET_LOW 0x8000
-#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
-#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
-#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
+#define CMD_ACT_TX_POWER_INDEX_HIGH 0x0007
+#define CMD_ACT_TX_POWER_INDEX_MID 0x0004
+#define CMD_ACT_TX_POWER_INDEX_LOW 0x0000
/* Define action or option for CMD_802_11_DATA_RATE */
-#define CMD_ACT_SET_TX_AUTO 0x0000
-#define CMD_ACT_SET_TX_FIX_RATE 0x0001
-#define CMD_ACT_GET_TX_RATE 0x0002
+#define CMD_ACT_SET_TX_AUTO 0x0000
+#define CMD_ACT_SET_TX_FIX_RATE 0x0001
+#define CMD_ACT_GET_TX_RATE 0x0002
-#define CMD_ACT_SET_RX 0x0001
-#define CMD_ACT_SET_TX 0x0002
-#define CMD_ACT_SET_BOTH 0x0003
-#define CMD_ACT_GET_RX 0x0004
-#define CMD_ACT_GET_TX 0x0008
-#define CMD_ACT_GET_BOTH 0x000c
+#define CMD_ACT_SET_RX 0x0001
+#define CMD_ACT_SET_TX 0x0002
+#define CMD_ACT_SET_BOTH 0x0003
+#define CMD_ACT_GET_RX 0x0004
+#define CMD_ACT_GET_TX 0x0008
+#define CMD_ACT_GET_BOTH 0x000c
/* Define action or option for CMD_802_11_PS_MODE */
-#define CMD_TYPE_CAM 0x0000
-#define CMD_TYPE_MAX_PSP 0x0001
-#define CMD_TYPE_FAST_PSP 0x0002
+#define CMD_TYPE_CAM 0x0000
+#define CMD_TYPE_MAX_PSP 0x0001
+#define CMD_TYPE_FAST_PSP 0x0002
+
+/* Options for CMD_802_11_FW_WAKE_METHOD */
+#define CMD_WAKE_METHOD_UNCHANGED 0x0000
+#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
+#define CMD_WAKE_METHOD_GPIO 0x0002
/* Define action or option for CMD_BT_ACCESS */
enum cmd_bt_access_opts {
@@ -237,8 +234,8 @@ enum cmd_fwt_access_opts {
CMD_ACT_FWT_ACCESS_DEL,
CMD_ACT_FWT_ACCESS_LOOKUP,
CMD_ACT_FWT_ACCESS_LIST,
- CMD_ACT_FWT_ACCESS_LIST_route,
- CMD_ACT_FWT_ACCESS_LIST_neighbor,
+ CMD_ACT_FWT_ACCESS_LIST_ROUTE,
+ CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR,
CMD_ACT_FWT_ACCESS_RESET,
CMD_ACT_FWT_ACCESS_CLEANUP,
CMD_ACT_FWT_ACCESS_TIME,
@@ -264,27 +261,36 @@ enum cmd_mesh_access_opts {
};
/** Card Event definition */
-#define MACREG_INT_CODE_TX_PPA_FREE 0x00000000
-#define MACREG_INT_CODE_TX_DMA_DONE 0x00000001
-#define MACREG_INT_CODE_LINK_LOSE_W_SCAN 0x00000002
-#define MACREG_INT_CODE_LINK_LOSE_NO_SCAN 0x00000003
-#define MACREG_INT_CODE_LINK_SENSED 0x00000004
-#define MACREG_INT_CODE_CMD_FINISHED 0x00000005
-#define MACREG_INT_CODE_MIB_CHANGED 0x00000006
-#define MACREG_INT_CODE_INIT_DONE 0x00000007
-#define MACREG_INT_CODE_DEAUTHENTICATED 0x00000008
-#define MACREG_INT_CODE_DISASSOCIATED 0x00000009
-#define MACREG_INT_CODE_PS_AWAKE 0x0000000a
-#define MACREG_INT_CODE_PS_SLEEP 0x0000000b
-#define MACREG_INT_CODE_MIC_ERR_MULTICAST 0x0000000d
-#define MACREG_INT_CODE_MIC_ERR_UNICAST 0x0000000e
-#define MACREG_INT_CODE_WM_AWAKE 0x0000000f
-#define MACREG_INT_CODE_ADHOC_BCN_LOST 0x00000011
-#define MACREG_INT_CODE_RSSI_LOW 0x00000019
-#define MACREG_INT_CODE_SNR_LOW 0x0000001a
-#define MACREG_INT_CODE_MAX_FAIL 0x0000001b
-#define MACREG_INT_CODE_RSSI_HIGH 0x0000001c
-#define MACREG_INT_CODE_SNR_HIGH 0x0000001d
-#define MACREG_INT_CODE_MESH_AUTO_STARTED 0x00000023
-
-#endif /* _HOST_H_ */
+#define MACREG_INT_CODE_TX_PPA_FREE 0
+#define MACREG_INT_CODE_TX_DMA_DONE 1
+#define MACREG_INT_CODE_LINK_LOST_W_SCAN 2
+#define MACREG_INT_CODE_LINK_LOST_NO_SCAN 3
+#define MACREG_INT_CODE_LINK_SENSED 4
+#define MACREG_INT_CODE_CMD_FINISHED 5
+#define MACREG_INT_CODE_MIB_CHANGED 6
+#define MACREG_INT_CODE_INIT_DONE 7
+#define MACREG_INT_CODE_DEAUTHENTICATED 8
+#define MACREG_INT_CODE_DISASSOCIATED 9
+#define MACREG_INT_CODE_PS_AWAKE 10
+#define MACREG_INT_CODE_PS_SLEEP 11
+#define MACREG_INT_CODE_MIC_ERR_MULTICAST 13
+#define MACREG_INT_CODE_MIC_ERR_UNICAST 14
+#define MACREG_INT_CODE_WM_AWAKE 15
+#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 16
+#define MACREG_INT_CODE_ADHOC_BCN_LOST 17
+#define MACREG_INT_CODE_HOST_AWAKE 18
+#define MACREG_INT_CODE_STOP_TX 19
+#define MACREG_INT_CODE_START_TX 20
+#define MACREG_INT_CODE_CHANNEL_SWITCH 21
+#define MACREG_INT_CODE_MEASUREMENT_RDY 22
+#define MACREG_INT_CODE_WMM_CHANGE 23
+#define MACREG_INT_CODE_BG_SCAN_REPORT 24
+#define MACREG_INT_CODE_RSSI_LOW 25
+#define MACREG_INT_CODE_SNR_LOW 26
+#define MACREG_INT_CODE_MAX_FAIL 27
+#define MACREG_INT_CODE_RSSI_HIGH 28
+#define MACREG_INT_CODE_SNR_HIGH 29
+#define MACREG_INT_CODE_MESH_AUTO_STARTED 35
+#define MACREG_INT_CODE_FIRMWARE_READY 48
+
+#endif
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index e1045dc02cce..d35b015b6657 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -2,8 +2,8 @@
* This file contains the function prototypes, data structure
* and defines for all the host/station commands
*/
-#ifndef __HOSTCMD__H
-#define __HOSTCMD__H
+#ifndef _LBS_HOSTCMD_H
+#define _LBS_HOSTCMD_H
#include <linux/wireless.h>
#include "11d.h"
@@ -65,19 +65,21 @@ struct rxpd {
u8 reserved[3];
};
+struct cmd_header {
+ __le16 command;
+ __le16 size;
+ __le16 seqnum;
+ __le16 result;
+} __attribute__ ((packed));
+
struct cmd_ctrl_node {
- /* CMD link list */
struct list_head list;
- u32 status;
- /* CMD ID */
- u32 cmd_oid;
- /*CMD wait option: wait for finish or no wait */
- u16 wait_option;
- /* command parameter */
- void *pdata_buf;
- /*command data */
- u8 *bufvirtualaddr;
- u16 cmdflags;
+ int result;
+ /* command response */
+ int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *);
+ unsigned long callback_arg;
+ /* command data */
+ struct cmd_header *cmdbuf;
/* wait queue */
u16 cmdwaitqwoken;
wait_queue_head_t cmdwait_q;
@@ -86,13 +88,13 @@ struct cmd_ctrl_node {
/* Generic structure to hold all key types. */
struct enc_key {
u16 len;
- u16 flags; /* KEY_INFO_* from wlan_defs.h */
- u16 type; /* KEY_TYPE_* from wlan_defs.h */
+ u16 flags; /* KEY_INFO_* from defs.h */
+ u16 type; /* KEY_TYPE_* from defs.h */
u8 key[32];
};
-/* wlan_offset_value */
-struct wlan_offset_value {
+/* lbs_offset_value */
+struct lbs_offset_value {
u32 offset;
u32 value;
};
@@ -104,14 +106,19 @@ struct cmd_ds_gen {
__le16 size;
__le16 seqnum;
__le16 result;
+ void *cmdresp[0];
};
#define S_DS_GEN sizeof(struct cmd_ds_gen)
+
+
/*
* Define data structure for CMD_GET_HW_SPEC
* This structure defines the response for the GET_HW_SPEC command
*/
struct cmd_ds_get_hw_spec {
+ struct cmd_header hdr;
+
/* HW Interface version number */
__le16 hwifversion;
/* HW version number */
@@ -129,8 +136,8 @@ struct cmd_ds_get_hw_spec {
/* Number of antenna used */
__le16 nr_antenna;
- /* FW release number, example 1,2,3,4 = 3.2.1p4 */
- u8 fwreleasenumber[4];
+ /* FW release number, example 0x01030304 = 2.3.4p1 */
+ __le32 fwrelease;
/* Base Address of TxPD queue */
__le32 wcb_base;
@@ -149,8 +156,17 @@ struct cmd_ds_802_11_reset {
};
struct cmd_ds_802_11_subscribe_event {
+ struct cmd_header hdr;
+
__le16 action;
__le16 events;
+
+ /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
+ * number of TLVs. From the v5.1 manual, those TLVs would add up to
+ * 40 bytes. However, future firmware might add additional TLVs, so I
+ * bump this up a bit.
+ */
+ uint8_t tlv[128];
};
/*
@@ -242,6 +258,8 @@ struct cmd_ds_802_11_ad_hoc_result {
};
struct cmd_ds_802_11_set_wep {
+ struct cmd_header hdr;
+
/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
__le16 action;
@@ -249,8 +267,8 @@ struct cmd_ds_802_11_set_wep {
__le16 keyindex;
/* 40, 128bit or TXWEP */
- u8 keytype[4];
- u8 keymaterial[4][16];
+ uint8_t keytype[4];
+ uint8_t keymaterial[4][16];
};
struct cmd_ds_802_3_get_stat {
@@ -328,11 +346,21 @@ struct cmd_ds_rf_reg_access {
};
struct cmd_ds_802_11_radio_control {
+ struct cmd_header hdr;
+
__le16 action;
__le16 control;
};
+struct cmd_ds_802_11_beacon_control {
+ __le16 action;
+ __le16 beacon_enable;
+ __le16 beacon_period;
+};
+
struct cmd_ds_802_11_sleep_params {
+ struct cmd_header hdr;
+
/* ACT_GET/ACT_SET */
__le16 action;
@@ -346,16 +374,18 @@ struct cmd_ds_802_11_sleep_params {
__le16 stabletime;
/* control periodic calibration */
- u8 calcontrol;
+ uint8_t calcontrol;
/* control the use of external sleep clock */
- u8 externalsleepclk;
+ uint8_t externalsleepclk;
/* reserved field, should be set to zero */
__le16 reserved;
};
struct cmd_ds_802_11_inactivity_timeout {
+ struct cmd_header hdr;
+
/* ACT_GET/ACT_SET */
__le16 action;
@@ -364,11 +394,13 @@ struct cmd_ds_802_11_inactivity_timeout {
};
struct cmd_ds_802_11_rf_channel {
+ struct cmd_header hdr;
+
__le16 action;
- __le16 currentchannel;
- __le16 rftype;
- __le16 reserved;
- u8 channellist[32];
+ __le16 channel;
+ __le16 rftype; /* unused */
+ __le16 reserved; /* unused */
+ u8 channellist[32]; /* unused */
};
struct cmd_ds_802_11_rssi {
@@ -406,13 +438,29 @@ struct cmd_ds_802_11_rf_antenna {
};
struct cmd_ds_802_11_monitor_mode {
- u16 action;
- u16 mode;
+ __le16 action;
+ __le16 mode;
};
struct cmd_ds_set_boot2_ver {
- u16 action;
- u16 version;
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 version;
+};
+
+struct cmd_ds_802_11_fw_wake_method {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 method;
+};
+
+struct cmd_ds_802_11_sleep_period {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 period;
};
struct cmd_ds_802_11_ps_mode {
@@ -437,6 +485,8 @@ struct PS_CMD_ConfirmSleep {
};
struct cmd_ds_802_11_data_rate {
+ struct cmd_header hdr;
+
__le16 action;
__le16 reserved;
u8 rates[MAX_RATES];
@@ -488,6 +538,8 @@ struct cmd_ds_802_11_ad_hoc_join {
} __attribute__ ((packed));
struct cmd_ds_802_11_enable_rsn {
+ struct cmd_header hdr;
+
__le16 action;
__le16 enable;
} __attribute__ ((packed));
@@ -512,6 +564,13 @@ struct MrvlIEtype_keyParamSet {
u8 key[32];
};
+struct cmd_ds_host_sleep {
+ struct cmd_header hdr;
+ __le32 criteria;
+ uint8_t gpio;
+ uint8_t gap;
+} __attribute__ ((packed));
+
struct cmd_ds_802_11_key_material {
__le16 action;
struct MrvlIEtype_keyParamSet keyParamSet[2];
@@ -598,7 +657,21 @@ struct cmd_ds_fwt_access {
u8 prec[ETH_ALEN];
} __attribute__ ((packed));
+
+struct cmd_ds_mesh_config {
+ struct cmd_header hdr;
+
+ __le16 action;
+ __le16 channel;
+ __le16 type;
+ __le16 length;
+ u8 data[128]; /* last position reserved */
+} __attribute__ ((packed));
+
+
struct cmd_ds_mesh_access {
+ struct cmd_header hdr;
+
__le16 action;
__le32 data[32]; /* last position reserved */
} __attribute__ ((packed));
@@ -615,14 +688,12 @@ struct cmd_ds_command {
/* command Body */
union {
- struct cmd_ds_get_hw_spec hwspec;
struct cmd_ds_802_11_ps_mode psmode;
struct cmd_ds_802_11_scan scan;
struct cmd_ds_802_11_scan_rsp scanresp;
struct cmd_ds_mac_control macctrl;
struct cmd_ds_802_11_associate associate;
struct cmd_ds_802_11_deauthenticate deauth;
- struct cmd_ds_802_11_set_wep wep;
struct cmd_ds_802_11_ad_hoc_start ads;
struct cmd_ds_802_11_reset reset;
struct cmd_ds_802_11_ad_hoc_result result;
@@ -634,17 +705,13 @@ struct cmd_ds_command {
struct cmd_ds_802_11_rf_tx_power txp;
struct cmd_ds_802_11_rf_antenna rant;
struct cmd_ds_802_11_monitor_mode monitor;
- struct cmd_ds_802_11_data_rate drate;
struct cmd_ds_802_11_rate_adapt_rateset rateset;
struct cmd_ds_mac_multicast_adr madr;
struct cmd_ds_802_11_ad_hoc_join adj;
- struct cmd_ds_802_11_radio_control radio;
- struct cmd_ds_802_11_rf_channel rfchannel;
struct cmd_ds_802_11_rssi rssi;
struct cmd_ds_802_11_rssi_rsp rssirsp;
struct cmd_ds_802_11_disassociate dassociate;
struct cmd_ds_802_11_mac_address macadd;
- struct cmd_ds_802_11_enable_rsn enbrsn;
struct cmd_ds_802_11_key_material keymaterial;
struct cmd_ds_mac_reg_access macreg;
struct cmd_ds_bbp_reg_access bbpreg;
@@ -654,8 +721,6 @@ struct cmd_ds_command {
struct cmd_ds_802_11d_domain_info domaininfo;
struct cmd_ds_802_11d_domain_info domaininforesp;
- struct cmd_ds_802_11_sleep_params sleep_params;
- struct cmd_ds_802_11_inactivity_timeout inactivity_timeout;
struct cmd_ds_802_11_tpc_cfg tpccfg;
struct cmd_ds_802_11_pwr_cfg pwrcfg;
struct cmd_ds_802_11_afc afc;
@@ -664,10 +729,8 @@ struct cmd_ds_command {
struct cmd_tx_rate_query txrate;
struct cmd_ds_bt_access bt;
struct cmd_ds_fwt_access fwt;
- struct cmd_ds_mesh_access mesh;
- struct cmd_ds_set_boot2_ver boot2_ver;
struct cmd_ds_get_tsf gettsf;
- struct cmd_ds_802_11_subscribe_event subscribe_event;
+ struct cmd_ds_802_11_beacon_control bcn_ctrl;
} params;
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index ba4fc2b3bf0a..4b5ab9a6b97b 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -57,7 +57,7 @@ MODULE_LICENSE("GPL");
struct if_cs_card {
struct pcmcia_device *p_dev;
- wlan_private *priv;
+ struct lbs_private *priv;
void __iomem *iobase;
};
@@ -243,7 +243,7 @@ static inline void if_cs_disable_ints(struct if_cs_card *card)
static irqreturn_t if_cs_interrupt(int irq, void *data)
{
- struct if_cs_card *card = (struct if_cs_card *)data;
+ struct if_cs_card *card = data;
u16 int_cause;
lbs_deb_enter(LBS_DEB_CS);
@@ -253,25 +253,20 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
/* Not for us */
return IRQ_NONE;
- } else if(int_cause == 0xffff) {
+ } else if (int_cause == 0xffff) {
/* Read in junk, the card has probably been removed */
- card->priv->adapter->surpriseremoved = 1;
+ card->priv->surpriseremoved = 1;
} else {
- if(int_cause & IF_CS_H_IC_TX_OVER) {
- card->priv->dnld_sent = DNLD_RES_RECEIVED;
- if (!card->priv->adapter->cur_cmd)
- wake_up_interruptible(&card->priv->waitq);
-
- if (card->priv->adapter->connect_status == LIBERTAS_CONNECTED)
- netif_wake_queue(card->priv->dev);
- }
+ if (int_cause & IF_CS_H_IC_TX_OVER)
+ lbs_host_to_card_done(card->priv);
/* clear interrupt */
if_cs_write16(card, IF_CS_C_INT_CAUSE, int_cause & IF_CS_C_IC_MASK);
}
-
- libertas_interrupt(card->priv->dev);
+ spin_lock(&card->priv->driver_lock);
+ lbs_interrupt(card->priv);
+ spin_unlock(&card->priv->driver_lock);
return IRQ_HANDLED;
}
@@ -286,7 +281,7 @@ static irqreturn_t if_cs_interrupt(int irq, void *data)
/*
* Called from if_cs_host_to_card to send a command to the hardware
*/
-static int if_cs_send_cmd(wlan_private *priv, u8 *buf, u16 nb)
+static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
int ret = -1;
@@ -331,7 +326,7 @@ done:
/*
* Called from if_cs_host_to_card to send a data to the hardware
*/
-static void if_cs_send_data(wlan_private *priv, u8 *buf, u16 nb)
+static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
@@ -354,7 +349,7 @@ static void if_cs_send_data(wlan_private *priv, u8 *buf, u16 nb)
/*
* Get the command result out of the card.
*/
-static int if_cs_receive_cmdres(wlan_private *priv, u8* data, u32 *len)
+static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len)
{
int ret = -1;
u16 val;
@@ -369,7 +364,7 @@ static int if_cs_receive_cmdres(wlan_private *priv, u8* data, u32 *len)
}
*len = if_cs_read16(priv->card, IF_CS_C_CMD_LEN);
- if ((*len == 0) || (*len > MRVDRV_SIZE_OF_CMD_BUFFER)) {
+ if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) {
lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len);
goto out;
}
@@ -379,6 +374,9 @@ static int if_cs_receive_cmdres(wlan_private *priv, u8* data, u32 *len)
if (*len & 1)
data[*len-1] = if_cs_read8(priv->card, IF_CS_C_CMD);
+ /* This is a workaround for a firmware that reports too much
+ * bytes */
+ *len -= 8;
ret = 0;
out:
lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len);
@@ -386,7 +384,7 @@ out:
}
-static struct sk_buff *if_cs_receive_data(wlan_private *priv)
+static struct sk_buff *if_cs_receive_data(struct lbs_private *priv)
{
struct sk_buff *skb = NULL;
u16 len;
@@ -616,7 +614,10 @@ done:
/********************************************************************/
/* Send commands or data packets to the card */
-static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
+static int if_cs_host_to_card(struct lbs_private *priv,
+ u8 type,
+ u8 *buf,
+ u16 nb)
{
int ret = -1;
@@ -641,18 +642,16 @@ static int if_cs_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
}
-static int if_cs_get_int_status(wlan_private *priv, u8 *ireg)
+static int if_cs_get_int_status(struct lbs_private *priv, u8 *ireg)
{
struct if_cs_card *card = (struct if_cs_card *)priv->card;
- //wlan_adapter *adapter = priv->adapter;
int ret = 0;
u16 int_cause;
- u8 *cmdbuf;
*ireg = 0;
lbs_deb_enter(LBS_DEB_CS);
- if (priv->adapter->surpriseremoved)
+ if (priv->surpriseremoved)
goto out;
int_cause = if_cs_read16(card, IF_CS_C_INT_CAUSE) & IF_CS_C_IC_MASK;
@@ -668,7 +667,7 @@ sbi_get_int_status_exit:
/* is there a data packet for us? */
if (*ireg & IF_CS_C_S_RX_UPLD_RDY) {
struct sk_buff *skb = if_cs_receive_data(priv);
- libertas_process_rxed_packet(priv, skb);
+ lbs_process_rxed_packet(priv, skb);
*ireg &= ~IF_CS_C_S_RX_UPLD_RDY;
}
@@ -678,31 +677,24 @@ sbi_get_int_status_exit:
/* Card has a command result for us */
if (*ireg & IF_CS_C_S_CMD_UPLD_RDY) {
- spin_lock(&priv->adapter->driver_lock);
- if (!priv->adapter->cur_cmd) {
- cmdbuf = priv->upld_buf;
- priv->adapter->hisregcpy &= ~IF_CS_C_S_RX_UPLD_RDY;
- } else {
- cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
- }
-
- ret = if_cs_receive_cmdres(priv, cmdbuf, &priv->upld_len);
- spin_unlock(&priv->adapter->driver_lock);
+ spin_lock(&priv->driver_lock);
+ ret = if_cs_receive_cmdres(priv, priv->upld_buf, &priv->upld_len);
+ spin_unlock(&priv->driver_lock);
if (ret < 0)
lbs_pr_err("could not receive cmd from card\n");
}
out:
- lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->adapter->hisregcpy);
+ lbs_deb_leave_args(LBS_DEB_CS, "ret %d, ireg 0x%x, hisregcpy 0x%x", ret, *ireg, priv->hisregcpy);
return ret;
}
-static int if_cs_read_event_cause(wlan_private *priv)
+static int if_cs_read_event_cause(struct lbs_private *priv)
{
lbs_deb_enter(LBS_DEB_CS);
- priv->adapter->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
+ priv->eventcause = (if_cs_read16(priv->card, IF_CS_C_STATUS) & IF_CS_C_S_STATUS_MASK) >> 5;
if_cs_write16(priv->card, IF_CS_H_INT_CAUSE, IF_CS_H_IC_HOST_EVENT);
return 0;
@@ -746,7 +738,7 @@ static void if_cs_release(struct pcmcia_device *p_dev)
static int if_cs_probe(struct pcmcia_device *p_dev)
{
int ret = -ENOMEM;
- wlan_private *priv;
+ struct lbs_private *priv;
struct if_cs_card *card;
/* CIS parsing */
tuple_t tuple;
@@ -856,7 +848,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out2;
/* Make this card known to the libertas driver */
- priv = libertas_add_card(card, &p_dev->dev);
+ priv = lbs_add_card(card, &p_dev->dev);
if (!priv) {
ret = -ENOMEM;
goto out2;
@@ -869,7 +861,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
priv->hw_get_int_status = if_cs_get_int_status;
priv->hw_read_event_cause = if_cs_read_event_cause;
- priv->adapter->fw_ready = 1;
+ priv->fw_ready = 1;
/* Now actually get the IRQ */
ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt,
@@ -885,7 +877,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
if_cs_enable_ints(card);
/* And finally bring the card up */
- if (libertas_start_card(priv) != 0) {
+ if (lbs_start_card(priv) != 0) {
lbs_pr_err("could not activate card\n");
goto out3;
}
@@ -894,7 +886,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
goto out;
out3:
- libertas_remove_card(priv);
+ lbs_remove_card(priv);
out2:
ioport_unmap(card->iobase);
out1:
@@ -917,8 +909,8 @@ static void if_cs_detach(struct pcmcia_device *p_dev)
lbs_deb_enter(LBS_DEB_CS);
- libertas_stop_card(card->priv);
- libertas_remove_card(card->priv);
+ lbs_stop_card(card->priv);
+ lbs_remove_card(card->priv);
if_cs_disable_ints(card);
if_cs_release(p_dev);
kfree(card);
@@ -939,7 +931,7 @@ static struct pcmcia_device_id if_cs_ids[] = {
MODULE_DEVICE_TABLE(pcmcia, if_cs_ids);
-static struct pcmcia_driver libertas_driver = {
+static struct pcmcia_driver lbs_driver = {
.owner = THIS_MODULE,
.drv = {
.name = DRV_NAME,
@@ -955,7 +947,7 @@ static int __init if_cs_init(void)
int ret;
lbs_deb_enter(LBS_DEB_CS);
- ret = pcmcia_register_driver(&libertas_driver);
+ ret = pcmcia_register_driver(&lbs_driver);
lbs_deb_leave(LBS_DEB_CS);
return ret;
}
@@ -964,7 +956,7 @@ static int __init if_cs_init(void)
static void __exit if_cs_exit(void)
{
lbs_deb_enter(LBS_DEB_CS);
- pcmcia_unregister_driver(&libertas_driver);
+ pcmcia_unregister_driver(&lbs_driver);
lbs_deb_leave(LBS_DEB_CS);
}
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 4f1efb108c28..eed73204bcc9 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -19,7 +19,7 @@
* current block size.
*
* As SDIO is still new to the kernel, it is unfortunately common with
- * bugs in the host controllers related to that. One such bug is that
+ * bugs in the host controllers related to that. One such bug is that
* controllers cannot do transfers that aren't a multiple of 4 bytes.
* If you don't have time to fix the host controller driver, you can
* work around the problem by modifying if_sdio_host_to_card() and
@@ -40,11 +40,11 @@
#include "dev.h"
#include "if_sdio.h"
-static char *libertas_helper_name = NULL;
-module_param_named(helper_name, libertas_helper_name, charp, 0644);
+static char *lbs_helper_name = NULL;
+module_param_named(helper_name, lbs_helper_name, charp, 0644);
-static char *libertas_fw_name = NULL;
-module_param_named(fw_name, libertas_fw_name, charp, 0644);
+static char *lbs_fw_name = NULL;
+module_param_named(fw_name, lbs_fw_name, charp, 0644);
static const struct sdio_device_id if_sdio_ids[] = {
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
@@ -82,7 +82,7 @@ struct if_sdio_packet {
struct if_sdio_card {
struct sdio_func *func;
- wlan_private *priv;
+ struct lbs_private *priv;
int model;
unsigned long ioport;
@@ -134,32 +134,26 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
lbs_deb_enter(LBS_DEB_SDIO);
- spin_lock_irqsave(&card->priv->adapter->driver_lock, flags);
+ spin_lock_irqsave(&card->priv->driver_lock, flags);
- if (!card->priv->adapter->cur_cmd) {
- lbs_deb_sdio("discarding spurious response\n");
- ret = 0;
- goto out;
- }
-
- if (size > MRVDRV_SIZE_OF_CMD_BUFFER) {
+ if (size > LBS_CMD_BUFFER_SIZE) {
lbs_deb_sdio("response packet too large (%d bytes)\n",
(int)size);
ret = -E2BIG;
goto out;
}
- memcpy(card->priv->adapter->cur_cmd->bufvirtualaddr, buffer, size);
+ memcpy(card->priv->upld_buf, buffer, size);
card->priv->upld_len = size;
card->int_cause |= MRVDRV_CMD_UPLD_RDY;
- libertas_interrupt(card->priv->dev);
+ lbs_interrupt(card->priv);
ret = 0;
out:
- spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&card->priv->driver_lock, flags);
lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
@@ -194,7 +188,7 @@ static int if_sdio_handle_data(struct if_sdio_card *card,
memcpy(data, buffer, size);
- libertas_process_rxed_packet(card->priv, skb);
+ lbs_process_rxed_packet(card->priv, skb);
ret = 0;
@@ -231,14 +225,14 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
event <<= SBI_EVENT_CAUSE_SHIFT;
}
- spin_lock_irqsave(&card->priv->adapter->driver_lock, flags);
+ spin_lock_irqsave(&card->priv->driver_lock, flags);
card->event = event;
card->int_cause |= MRVDRV_CARDEVENT;
- libertas_interrupt(card->priv->dev);
+ lbs_interrupt(card->priv);
- spin_unlock_irqrestore(&card->priv->adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&card->priv->driver_lock, flags);
ret = 0;
@@ -454,7 +448,7 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
chunk_size = min(size, (size_t)60);
- *((u32*)chunk_buffer) = cpu_to_le32(chunk_size);
+ *((__le32*)chunk_buffer) = cpu_to_le32(chunk_size);
memcpy(chunk_buffer + 4, firmware, chunk_size);
/*
lbs_deb_sdio("sending %d bytes chunk\n", chunk_size);
@@ -694,7 +688,8 @@ out:
/* Libertas callbacks */
/*******************************************************************/
-static int if_sdio_host_to_card(wlan_private *priv, u8 type, u8 *buf, u16 nb)
+static int if_sdio_host_to_card(struct lbs_private *priv,
+ u8 type, u8 *buf, u16 nb)
{
int ret;
struct if_sdio_card *card;
@@ -775,7 +770,7 @@ out:
return ret;
}
-static int if_sdio_get_int_status(wlan_private *priv, u8 *ireg)
+static int if_sdio_get_int_status(struct lbs_private *priv, u8 *ireg)
{
struct if_sdio_card *card;
@@ -791,7 +786,7 @@ static int if_sdio_get_int_status(wlan_private *priv, u8 *ireg)
return 0;
}
-static int if_sdio_read_event_cause(wlan_private *priv)
+static int if_sdio_read_event_cause(struct lbs_private *priv)
{
struct if_sdio_card *card;
@@ -799,7 +794,7 @@ static int if_sdio_read_event_cause(wlan_private *priv)
card = priv->card;
- priv->adapter->eventcause = card->event;
+ priv->eventcause = card->event;
lbs_deb_leave(LBS_DEB_SDIO);
@@ -834,12 +829,9 @@ static void if_sdio_interrupt(struct sdio_func *func)
* Ignore the define name, this really means the card has
* successfully received the command.
*/
- if (cause & IF_SDIO_H_INT_DNLD) {
- if ((card->priv->dnld_sent == DNLD_DATA_SENT) &&
- (card->priv->adapter->connect_status == LIBERTAS_CONNECTED))
- netif_wake_queue(card->priv->dev);
- card->priv->dnld_sent = DNLD_RES_RECEIVED;
- }
+ if (cause & IF_SDIO_H_INT_DNLD)
+ lbs_host_to_card_done(card->priv);
+
if (cause & IF_SDIO_H_INT_UPLD) {
ret = if_sdio_card_to_host(card);
@@ -857,7 +849,7 @@ static int if_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
struct if_sdio_card *card;
- wlan_private *priv;
+ struct lbs_private *priv;
int ret, i;
unsigned int model;
struct if_sdio_packet *packet;
@@ -905,15 +897,15 @@ static int if_sdio_probe(struct sdio_func *func,
card->helper = if_sdio_models[i].helper;
card->firmware = if_sdio_models[i].firmware;
- if (libertas_helper_name) {
+ if (lbs_helper_name) {
lbs_deb_sdio("overriding helper firmware: %s\n",
- libertas_helper_name);
- card->helper = libertas_helper_name;
+ lbs_helper_name);
+ card->helper = lbs_helper_name;
}
- if (libertas_fw_name) {
- lbs_deb_sdio("overriding firmware: %s\n", libertas_fw_name);
- card->firmware = libertas_fw_name;
+ if (lbs_fw_name) {
+ lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name);
+ card->firmware = lbs_fw_name;
}
sdio_claim_host(func);
@@ -951,7 +943,7 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret)
goto reclaim;
- priv = libertas_add_card(card, &func->dev);
+ priv = lbs_add_card(card, &func->dev);
if (!priv) {
ret = -ENOMEM;
goto reclaim;
@@ -964,7 +956,7 @@ static int if_sdio_probe(struct sdio_func *func,
priv->hw_get_int_status = if_sdio_get_int_status;
priv->hw_read_event_cause = if_sdio_read_event_cause;
- priv->adapter->fw_ready = 1;
+ priv->fw_ready = 1;
/*
* Enable interrupts now that everything is set up
@@ -975,7 +967,7 @@ static int if_sdio_probe(struct sdio_func *func,
if (ret)
goto reclaim;
- ret = libertas_start_card(priv);
+ ret = lbs_start_card(priv);
if (ret)
goto err_activate_card;
@@ -987,7 +979,7 @@ out:
err_activate_card:
flush_scheduled_work();
free_netdev(priv->dev);
- kfree(priv->adapter);
+ kfree(priv);
reclaim:
sdio_claim_host(func);
release_int:
@@ -1017,11 +1009,11 @@ static void if_sdio_remove(struct sdio_func *func)
card = sdio_get_drvdata(func);
- card->priv->adapter->surpriseremoved = 1;
+ card->priv->surpriseremoved = 1;
lbs_deb_sdio("call remove card\n");
- libertas_stop_card(card->priv);
- libertas_remove_card(card->priv);
+ lbs_stop_card(card->priv);
+ lbs_remove_card(card->priv);
flush_scheduled_work();
@@ -1052,7 +1044,7 @@ static struct sdio_driver if_sdio_driver = {
/* Module functions */
/*******************************************************************/
-static int if_sdio_init_module(void)
+static int __init if_sdio_init_module(void)
{
int ret = 0;
@@ -1068,7 +1060,7 @@ static int if_sdio_init_module(void)
return ret;
}
-static void if_sdio_exit_module(void)
+static void __exit if_sdio_exit_module(void)
{
lbs_deb_enter(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index dfcaea7b168f..533bdfbf5d2a 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -9,8 +9,8 @@
* your option) any later version.
*/
-#ifndef LIBERTAS_IF_SDIO_H
-#define LIBERTAS_IF_SDIO_H
+#ifndef _LBS_IF_SDIO_H
+#define _LBS_IF_SDIO_H
#define IF_SDIO_IOPORT 0x00
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index cb59f46ed126..75aed9d07367 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -5,7 +5,6 @@
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
-#include <linux/list.h>
#include <linux/usb.h>
#define DRV_NAME "usb8xxx"
@@ -14,24 +13,16 @@
#include "decl.h"
#include "defs.h"
#include "dev.h"
+#include "cmd.h"
#include "if_usb.h"
-#define MESSAGE_HEADER_LEN 4
-
-static const char usbdriver_name[] = "usb8xxx";
-static u8 *default_fw_name = "usb8388.bin";
+#define INSANEDEBUG 0
+#define lbs_deb_usb2(...) do { if (INSANEDEBUG) lbs_deb_usbd(__VA_ARGS__); } while (0)
-static char *libertas_fw_name = NULL;
-module_param_named(fw_name, libertas_fw_name, charp, 0644);
+#define MESSAGE_HEADER_LEN 4
-/*
- * We need to send a RESET command to all USB devices before
- * we tear down the USB connection. Otherwise we would not
- * be able to re-init device the device if the module gets
- * loaded again. This is a list of all initialized USB devices,
- * for the reset code see if_usb_reset_device()
-*/
-static LIST_HEAD(usb_devices);
+static char *lbs_fw_name = "usb8388.bin";
+module_param_named(fw_name, lbs_fw_name, charp, 0644);
static struct usb_device_id if_usb_table[] = {
/* Enter the device signature inside */
@@ -44,14 +35,16 @@ MODULE_DEVICE_TABLE(usb, if_usb_table);
static void if_usb_receive(struct urb *urb);
static void if_usb_receive_fwload(struct urb *urb);
-static int if_usb_prog_firmware(struct usb_card_rec *cardp);
-static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
-static int if_usb_get_int_status(wlan_private * priv, u8 *);
-static int if_usb_read_event_cause(wlan_private *);
-static int usb_tx_block(struct usb_card_rec *cardp, u8 *payload, u16 nb);
-static void if_usb_free(struct usb_card_rec *cardp);
-static int if_usb_submit_rx_urb(struct usb_card_rec *cardp);
-static int if_usb_reset_device(struct usb_card_rec *cardp);
+static int if_usb_prog_firmware(struct if_usb_card *cardp);
+static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ uint8_t *payload, uint16_t nb);
+static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *);
+static int if_usb_read_event_cause(struct lbs_private *);
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
+ uint16_t nb);
+static void if_usb_free(struct if_usb_card *cardp);
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp);
+static int if_usb_reset_device(struct if_usb_card *cardp);
/**
* @brief call back function to handle the status of the URB
@@ -60,37 +53,22 @@ static int if_usb_reset_device(struct usb_card_rec *cardp);
*/
static void if_usb_write_bulk_callback(struct urb *urb)
{
- struct usb_card_rec *cardp = (struct usb_card_rec *) urb->context;
+ struct if_usb_card *cardp = (struct if_usb_card *) urb->context;
/* handle the transmission complete validations */
if (urb->status == 0) {
- wlan_private *priv = cardp->priv;
+ struct lbs_private *priv = cardp->priv;
- /*
- lbs_deb_usbd(&urb->dev->dev, "URB status is successfull\n");
- lbs_deb_usbd(&urb->dev->dev, "Actual length transmitted %d\n",
- urb->actual_length);
- */
+ lbs_deb_usb2(&urb->dev->dev, "URB status is successful\n");
+ lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
+ urb->actual_length);
/* Used for both firmware TX and regular TX. priv isn't
* valid at firmware load time.
*/
- if (priv) {
- wlan_adapter *adapter = priv->adapter;
- struct net_device *dev = priv->dev;
-
- priv->dnld_sent = DNLD_RES_RECEIVED;
-
- /* Wake main thread if commands are pending */
- if (!adapter->cur_cmd)
- wake_up_interruptible(&priv->waitq);
-
- if ((adapter->connect_status == LIBERTAS_CONNECTED)) {
- netif_wake_queue(dev);
- netif_wake_queue(priv->mesh_dev);
- }
- }
+ if (priv)
+ lbs_host_to_card_done(priv);
} else {
/* print the failure status number for debug */
lbs_pr_info("URB in failure status: %d\n", urb->status);
@@ -101,10 +79,10 @@ static void if_usb_write_bulk_callback(struct urb *urb)
/**
* @brief free tx/rx urb, skb and rx buffer
- * @param cardp pointer usb_card_rec
+ * @param cardp pointer if_usb_card
* @return N/A
*/
-static void if_usb_free(struct usb_card_rec *cardp)
+static void if_usb_free(struct if_usb_card *cardp)
{
lbs_deb_enter(LBS_DEB_USB);
@@ -118,12 +96,58 @@ static void if_usb_free(struct usb_card_rec *cardp)
usb_free_urb(cardp->rx_urb);
cardp->rx_urb = NULL;
- kfree(cardp->bulk_out_buffer);
- cardp->bulk_out_buffer = NULL;
+ kfree(cardp->ep_out_buf);
+ cardp->ep_out_buf = NULL;
lbs_deb_leave(LBS_DEB_USB);
}
+static void if_usb_setup_firmware(struct lbs_private *priv)
+{
+ struct if_usb_card *cardp = priv->card;
+ struct cmd_ds_set_boot2_ver b2_cmd;
+ struct cmd_ds_802_11_fw_wake_method wake_method;
+
+ b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
+ b2_cmd.action = 0;
+ b2_cmd.version = cardp->boot2_version;
+
+ if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
+ lbs_deb_usb("Setting boot2 version failed\n");
+
+ priv->wol_gpio = 2; /* Wake via GPIO2... */
+ priv->wol_gap = 20; /* ... after 20ms */
+ lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);
+
+ wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
+ wake_method.action = cpu_to_le16(CMD_ACT_GET);
+ if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) {
+ lbs_pr_info("Firmware does not seem to support PS mode\n");
+ } else {
+ if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) {
+ lbs_deb_usb("Firmware seems to support PS with wake-via-command\n");
+ priv->ps_supported = 1;
+ } else {
+ /* The versions which boot up this way don't seem to
+ work even if we set it to the command interrupt */
+ lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n");
+ }
+ }
+}
+
+static void if_usb_fw_timeo(unsigned long priv)
+{
+ struct if_usb_card *cardp = (void *)priv;
+
+ if (cardp->fwdnldover) {
+ lbs_deb_usb("Download complete, no event. Assuming success\n");
+ } else {
+ lbs_pr_err("Download timed out\n");
+ cardp->surprise_removed = 1;
+ }
+ wake_up(&cardp->fw_wq);
+}
+
/**
* @brief sets the configuration values
* @param ifnum interface number
@@ -136,23 +160,26 @@ static int if_usb_probe(struct usb_interface *intf,
struct usb_device *udev;
struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint;
- wlan_private *priv;
- struct usb_card_rec *cardp;
+ struct lbs_private *priv;
+ struct if_usb_card *cardp;
int i;
udev = interface_to_usbdev(intf);
- cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+ cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
if (!cardp) {
lbs_pr_err("Out of memory allocating private data.\n");
goto error;
}
+ setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
+ init_waitqueue_head(&cardp->fw_wq);
+
cardp->udev = udev;
iface_desc = intf->cur_altsetting;
lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
- " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
+ " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
le16_to_cpu(udev->descriptor.bcdUSB),
udev->descriptor.bDeviceClass,
udev->descriptor.bDeviceSubClass,
@@ -160,92 +187,62 @@ static int if_usb_probe(struct usb_interface *intf,
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc;
- if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
- && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
- /* we found a bulk in endpoint */
- lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n",
- le16_to_cpu(endpoint->wMaxPacketSize));
- if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_deb_usbd(&udev->dev,
- "Rx URB allocation failed\n");
- goto dealloc;
- }
- cardp->rx_urb_recall = 0;
-
- cardp->bulk_in_size =
- le16_to_cpu(endpoint->wMaxPacketSize);
- cardp->bulk_in_endpointAddr =
- (endpoint->
- bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
- lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n",
- endpoint->bEndpointAddress);
- }
+ if (usb_endpoint_is_bulk_in(endpoint)) {
+ cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ cardp->ep_in = usb_endpoint_num(endpoint);
- if (((endpoint->
- bEndpointAddress & USB_ENDPOINT_DIR_MASK) ==
- USB_DIR_OUT)
- && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
- USB_ENDPOINT_XFER_BULK)) {
- /* We found bulk out endpoint */
- if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
- lbs_deb_usbd(&udev->dev,
- "Tx URB allocation failed\n");
- goto dealloc;
- }
+ lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
+ lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
- cardp->bulk_out_size =
- le16_to_cpu(endpoint->wMaxPacketSize);
- lbs_deb_usbd(&udev->dev,
- "Bulk out size is %d\n",
- le16_to_cpu(endpoint->wMaxPacketSize));
- cardp->bulk_out_endpointAddr =
- endpoint->bEndpointAddress;
- lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n",
- endpoint->bEndpointAddress);
- cardp->bulk_out_buffer =
- kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
- GFP_KERNEL);
-
- if (!cardp->bulk_out_buffer) {
- lbs_deb_usbd(&udev->dev,
- "Could not allocate buffer\n");
- goto dealloc;
- }
+ } else if (usb_endpoint_is_bulk_out(endpoint)) {
+ cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize);
+ cardp->ep_out = usb_endpoint_num(endpoint);
+
+ lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
+ lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size);
}
}
+ if (!cardp->ep_out_size || !cardp->ep_in_size) {
+ lbs_deb_usbd(&udev->dev, "Endpoints not found\n");
+ goto dealloc;
+ }
+ if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
+ goto dealloc;
+ }
+ if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) {
+ lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
+ goto dealloc;
+ }
+ cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL);
+ if (!cardp->ep_out_buf) {
+ lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n");
+ goto dealloc;
+ }
/* Upload firmware */
- cardp->rinfo.cardp = cardp;
if (if_usb_prog_firmware(cardp)) {
- lbs_deb_usbd(&udev->dev, "FW upload failed");
+ lbs_deb_usbd(&udev->dev, "FW upload failed\n");
goto err_prog_firmware;
}
- if (!(priv = libertas_add_card(cardp, &udev->dev)))
+ if (!(priv = lbs_add_card(cardp, &udev->dev)))
goto err_prog_firmware;
cardp->priv = priv;
-
- if (libertas_add_mesh(priv, &udev->dev))
- goto err_add_mesh;
-
- cardp->eth_dev = priv->dev;
+ cardp->priv->fw_ready = 1;
priv->hw_host_to_card = if_usb_host_to_card;
priv->hw_get_int_status = if_usb_get_int_status;
priv->hw_read_event_cause = if_usb_read_event_cause;
- priv->boot2_version = udev->descriptor.bcdDevice;
+ cardp->boot2_version = udev->descriptor.bcdDevice;
- /* Delay 200 ms to waiting for the FW ready */
if_usb_submit_rx_urb(cardp);
- msleep_interruptible(200);
- priv->adapter->fw_ready = 1;
- if (libertas_start_card(priv))
+ if (lbs_start_card(priv))
goto err_start_card;
- list_add_tail(&cardp->list, &usb_devices);
+ if_usb_setup_firmware(priv);
usb_get_dev(udev);
usb_set_intfdata(intf, cardp);
@@ -253,9 +250,7 @@ static int if_usb_probe(struct usb_interface *intf,
return 0;
err_start_card:
- libertas_remove_mesh(priv);
-err_add_mesh:
- libertas_remove_card(priv);
+ lbs_remove_card(priv);
err_prog_firmware:
if_usb_reset_device(cardp);
dealloc:
@@ -272,23 +267,17 @@ error:
*/
static void if_usb_disconnect(struct usb_interface *intf)
{
- struct usb_card_rec *cardp = usb_get_intfdata(intf);
- wlan_private *priv = (wlan_private *) cardp->priv;
+ struct if_usb_card *cardp = usb_get_intfdata(intf);
+ struct lbs_private *priv = (struct lbs_private *) cardp->priv;
lbs_deb_enter(LBS_DEB_MAIN);
- /* Update Surprise removed to TRUE */
cardp->surprise_removed = 1;
- list_del(&cardp->list);
-
if (priv) {
- wlan_adapter *adapter = priv->adapter;
-
- adapter->surpriseremoved = 1;
- libertas_stop_card(priv);
- libertas_remove_mesh(priv);
- libertas_remove_card(priv);
+ priv->surpriseremoved = 1;
+ lbs_stop_card(priv);
+ lbs_remove_card(priv);
}
/* Unlink and free urb */
@@ -302,102 +291,82 @@ static void if_usb_disconnect(struct usb_interface *intf)
/**
* @brief This function download FW
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @return 0
*/
-static int if_prog_firmware(struct usb_card_rec *cardp)
+static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
{
- struct FWData *fwdata;
- struct fwheader *fwheader;
- u8 *firmware = cardp->fw->data;
-
- fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
-
- if (!fwdata)
- return -1;
-
- fwheader = &fwdata->fwheader;
+ struct fwdata *fwdata = cardp->ep_out_buf;
+ uint8_t *firmware = cardp->fw->data;
+ /* If we got a CRC failure on the last block, back
+ up and retry it */
if (!cardp->CRC_OK) {
cardp->totalbytes = cardp->fwlastblksent;
- cardp->fwseqnum = cardp->lastseqnum - 1;
+ cardp->fwseqnum--;
}
- /*
- lbs_deb_usbd(&cardp->udev->dev, "totalbytes = %d\n",
- cardp->totalbytes);
- */
+ lbs_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
+ cardp->totalbytes);
- memcpy(fwheader, &firmware[cardp->totalbytes],
+ /* struct fwdata (which we sent to the card) has an
+ extra __le32 field in between the header and the data,
+ which is not in the struct fwheader in the actual
+ firmware binary. Insert the seqnum in the middle... */
+ memcpy(&fwdata->hdr, &firmware[cardp->totalbytes],
sizeof(struct fwheader));
cardp->fwlastblksent = cardp->totalbytes;
cardp->totalbytes += sizeof(struct fwheader);
- /* lbs_deb_usbd(&cardp->udev->dev,"Copy Data\n"); */
memcpy(fwdata->data, &firmware[cardp->totalbytes],
- le32_to_cpu(fwdata->fwheader.datalength));
+ le32_to_cpu(fwdata->hdr.datalength));
- /*
- lbs_deb_usbd(&cardp->udev->dev,
- "Data length = %d\n", le32_to_cpu(fwdata->fwheader.datalength));
- */
+ lbs_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
+ le32_to_cpu(fwdata->hdr.datalength));
- cardp->fwseqnum = cardp->fwseqnum + 1;
+ fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
+ cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
- fwdata->seqnum = cpu_to_le32(cardp->fwseqnum);
- cardp->lastseqnum = cardp->fwseqnum;
- cardp->totalbytes += le32_to_cpu(fwdata->fwheader.datalength);
+ usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
+ le32_to_cpu(fwdata->hdr.datalength));
+
+ if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
+ lbs_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
+ lbs_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
+ cardp->fwseqnum, cardp->totalbytes);
+ } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
+ lbs_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
+ lbs_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
- if (fwheader->dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
- /*
- lbs_deb_usbd(&cardp->udev->dev, "There are data to follow\n");
- lbs_deb_usbd(&cardp->udev->dev,
- "seqnum = %d totalbytes = %d\n", cardp->fwseqnum,
- cardp->totalbytes);
- */
- memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
- usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
-
- } else if (fwdata->fwheader.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
- /*
- lbs_deb_usbd(&cardp->udev->dev,
- "Host has finished FW downloading\n");
- lbs_deb_usbd(&cardp->udev->dev,
- "Donwloading FW JUMP BLOCK\n");
- */
- memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
- usb_tx_block(cardp, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
cardp->fwfinalblk = 1;
}
- /*
- lbs_deb_usbd(&cardp->udev->dev,
- "The firmware download is done size is %d\n",
- cardp->totalbytes);
- */
-
- kfree(fwdata);
+ lbs_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
+ cardp->totalbytes);
return 0;
}
-static int if_usb_reset_device(struct usb_card_rec *cardp)
+static int if_usb_reset_device(struct if_usb_card *cardp)
{
+ struct cmd_ds_command *cmd = cardp->ep_out_buf + 4;
int ret;
- wlan_private * priv = cardp->priv;
lbs_deb_enter(LBS_DEB_USB);
- /* Try a USB port reset first, if that fails send the reset
- * command to the firmware.
- */
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
+
+ cmd->command = cpu_to_le16(CMD_802_11_RESET);
+ cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset) + S_DS_GEN);
+ cmd->result = cpu_to_le16(0);
+ cmd->seqnum = cpu_to_le16(0x5a5a);
+ cmd->params.reset.action = cpu_to_le16(CMD_ACT_HALT);
+ usb_tx_block(cardp, cardp->ep_out_buf, 4 + S_DS_GEN + sizeof(struct cmd_ds_802_11_reset));
+
+ msleep(100);
ret = usb_reset_device(cardp->udev);
- if (!ret && priv) {
- msleep(10);
- ret = libertas_reset_device(priv);
- msleep(10);
- }
+ msleep(100);
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
@@ -406,12 +375,12 @@ static int if_usb_reset_device(struct usb_card_rec *cardp)
/**
* @brief This function transfer the data to the device.
- * @param priv pointer to wlan_private
+ * @param priv pointer to struct lbs_private
* @param payload pointer to payload data
* @param nb data length
* @return 0 or -1
*/
-static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
+static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb)
{
int ret = -1;
@@ -423,17 +392,16 @@ static int usb_tx_block(struct usb_card_rec *cardp, u8 * payload, u16 nb)
usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
usb_sndbulkpipe(cardp->udev,
- cardp->bulk_out_endpointAddr),
+ cardp->ep_out),
payload, nb, if_usb_write_bulk_callback, cardp);
cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
- /* transfer failed */
- lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
ret = -1;
} else {
- /* lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb success\n"); */
+ lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
ret = 0;
}
@@ -441,11 +409,10 @@ tx_ret:
return ret;
}
-static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
+static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
void (*callbackfn)(struct urb *urb))
{
struct sk_buff *skb;
- struct read_cb_info *rinfo = &cardp->rinfo;
int ret = -1;
if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
@@ -453,25 +420,25 @@ static int __if_usb_submit_rx_urb(struct usb_card_rec *cardp,
goto rx_ret;
}
- rinfo->skb = skb;
+ cardp->rx_skb = skb;
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
- usb_rcvbulkpipe(cardp->udev,
- cardp->bulk_in_endpointAddr),
+ usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
(void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
- rinfo);
+ cardp);
cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
- /* lbs_deb_usbd(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); */
+ lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
- /* handle failure conditions */
- lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
+ kfree_skb(skb);
+ cardp->rx_skb = NULL;
ret = -1;
} else {
- /* lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB success\n"); */
+ lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
ret = 0;
}
@@ -479,58 +446,78 @@ rx_ret:
return ret;
}
-static int if_usb_submit_rx_urb_fwload(struct usb_card_rec *cardp)
+static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
{
return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload);
}
-static int if_usb_submit_rx_urb(struct usb_card_rec *cardp)
+static int if_usb_submit_rx_urb(struct if_usb_card *cardp)
{
return __if_usb_submit_rx_urb(cardp, &if_usb_receive);
}
static void if_usb_receive_fwload(struct urb *urb)
{
- struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
- struct sk_buff *skb = rinfo->skb;
- struct usb_card_rec *cardp = (struct usb_card_rec *)rinfo->cardp;
+ struct if_usb_card *cardp = urb->context;
+ struct sk_buff *skb = cardp->rx_skb;
struct fwsyncheader *syncfwheader;
- struct bootcmdrespStr bootcmdresp;
+ struct bootcmdresp bootcmdresp;
if (urb->status) {
lbs_deb_usbd(&cardp->udev->dev,
- "URB status is failed during fw load\n");
+ "URB status is failed during fw load\n");
kfree_skb(skb);
return;
}
- if (cardp->bootcmdresp == 0) {
+ if (cardp->fwdnldover) {
+ __le32 *tmp = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
+
+ if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
+ tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
+ lbs_pr_info("Firmware ready event received\n");
+ wake_up(&cardp->fw_wq);
+ } else {
+ lbs_deb_usb("Waiting for confirmation; got %x %x\n",
+ le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
+ if_usb_submit_rx_urb_fwload(cardp);
+ }
+ kfree_skb(skb);
+ return;
+ }
+ if (cardp->bootcmdresp <= 0) {
memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET,
sizeof(bootcmdresp));
+
if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) {
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(cardp);
cardp->bootcmdresp = 1;
lbs_deb_usbd(&cardp->udev->dev,
- "Received valid boot command response\n");
+ "Received valid boot command response\n");
return;
}
- if (bootcmdresp.u32magicnumber != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
- lbs_pr_info(
- "boot cmd response wrong magic number (0x%x)\n",
- le32_to_cpu(bootcmdresp.u32magicnumber));
- } else if (bootcmdresp.u8cmd_tag != BOOT_CMD_FW_BY_USB) {
- lbs_pr_info(
- "boot cmd response cmd_tag error (%d)\n",
- bootcmdresp.u8cmd_tag);
- } else if (bootcmdresp.u8result != BOOT_CMD_RESP_OK) {
- lbs_pr_info(
- "boot cmd response result error (%d)\n",
- bootcmdresp.u8result);
+ if (bootcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
+ if (bootcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
+ bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
+ bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
+ if (!cardp->bootcmdresp)
+ lbs_pr_info("Firmware already seems alive; resetting\n");
+ cardp->bootcmdresp = -1;
+ } else {
+ lbs_pr_info("boot cmd response wrong magic number (0x%x)\n",
+ le32_to_cpu(bootcmdresp.magic));
+ }
+ } else if (bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
+ lbs_pr_info("boot cmd response cmd_tag error (%d)\n",
+ bootcmdresp.cmd);
+ } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) {
+ lbs_pr_info("boot cmd response result error (%d)\n",
+ bootcmdresp.result);
} else {
cardp->bootcmdresp = 1;
lbs_deb_usbd(&cardp->udev->dev,
- "Received valid boot command response\n");
+ "Received valid boot command response\n");
}
kfree_skb(skb);
if_usb_submit_rx_urb_fwload(cardp);
@@ -545,50 +532,47 @@ static void if_usb_receive_fwload(struct urb *urb)
}
memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
- sizeof(struct fwsyncheader));
+ sizeof(struct fwsyncheader));
if (!syncfwheader->cmd) {
- /*
- lbs_deb_usbd(&cardp->udev->dev,
- "FW received Blk with correct CRC\n");
- lbs_deb_usbd(&cardp->udev->dev,
- "FW received Blk seqnum = %d\n",
- syncfwheader->seqnum);
- */
+ lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
+ lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
+ le32_to_cpu(syncfwheader->seqnum));
cardp->CRC_OK = 1;
} else {
- lbs_deb_usbd(&cardp->udev->dev,
- "FW received Blk with CRC error\n");
+ lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
cardp->CRC_OK = 0;
}
kfree_skb(skb);
+ /* reschedule timer for 200ms hence */
+ mod_timer(&cardp->fw_timeout, jiffies + (HZ/5));
+
if (cardp->fwfinalblk) {
cardp->fwdnldover = 1;
goto exit;
}
- if_prog_firmware(cardp);
+ if_usb_send_fw_pkt(cardp);
+ exit:
if_usb_submit_rx_urb_fwload(cardp);
-exit:
+
kfree(syncfwheader);
return;
-
}
#define MRVDRV_MIN_PKT_LEN 30
static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
- struct usb_card_rec *cardp,
- wlan_private *priv)
+ struct if_usb_card *cardp,
+ struct lbs_private *priv)
{
- if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
- MESSAGE_HEADER_LEN || recvlength < MRVDRV_MIN_PKT_LEN) {
- lbs_deb_usbd(&cardp->udev->dev,
- "Packet length is Invalid\n");
+ if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
+ || recvlength < MRVDRV_MIN_PKT_LEN) {
+ lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
kfree_skb(skb);
return;
}
@@ -596,19 +580,19 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
skb_put(skb, recvlength);
skb_pull(skb, MESSAGE_HEADER_LEN);
- libertas_process_rxed_packet(priv, skb);
+
+ lbs_process_rxed_packet(priv, skb);
priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
}
-static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
+static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
struct sk_buff *skb,
- struct usb_card_rec *cardp,
- wlan_private *priv)
+ struct if_usb_card *cardp,
+ struct lbs_private *priv)
{
- u8 *cmdbuf;
- if (recvlength > MRVDRV_SIZE_OF_CMD_BUFFER) {
+ if (recvlength > LBS_CMD_BUFFER_SIZE) {
lbs_deb_usbd(&cardp->udev->dev,
- "The receive buffer is too large\n");
+ "The receive buffer is too large\n");
kfree_skb(skb);
return;
}
@@ -616,28 +600,17 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
if (!in_interrupt())
BUG();
- spin_lock(&priv->adapter->driver_lock);
- /* take care of cur_cmd = NULL case by reading the
- * data to clear the interrupt */
- if (!priv->adapter->cur_cmd) {
- cmdbuf = priv->upld_buf;
- priv->adapter->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
- } else
- cmdbuf = priv->adapter->cur_cmd->bufvirtualaddr;
-
+ spin_lock(&priv->driver_lock);
cardp->usb_int_cause |= MRVDRV_CMD_UPLD_RDY;
priv->upld_len = (recvlength - MESSAGE_HEADER_LEN);
- memcpy(cmdbuf, recvbuff + MESSAGE_HEADER_LEN,
- priv->upld_len);
+ memcpy(priv->upld_buf, recvbuff + MESSAGE_HEADER_LEN, priv->upld_len);
kfree_skb(skb);
- libertas_interrupt(priv->dev);
- spin_unlock(&priv->adapter->driver_lock);
+ lbs_interrupt(priv);
+ spin_unlock(&priv->driver_lock);
lbs_deb_usbd(&cardp->udev->dev,
"Wake up main thread to handle cmd response\n");
-
- return;
}
/**
@@ -649,35 +622,33 @@ static inline void process_cmdrequest(int recvlength, u8 *recvbuff,
*/
static void if_usb_receive(struct urb *urb)
{
- struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
- struct sk_buff *skb = rinfo->skb;
- struct usb_card_rec *cardp = (struct usb_card_rec *) rinfo->cardp;
- wlan_private * priv = cardp->priv;
-
+ struct if_usb_card *cardp = urb->context;
+ struct sk_buff *skb = cardp->rx_skb;
+ struct lbs_private *priv = cardp->priv;
int recvlength = urb->actual_length;
- u8 *recvbuff = NULL;
- u32 recvtype = 0;
+ uint8_t *recvbuff = NULL;
+ uint32_t recvtype = 0;
+ __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET);
lbs_deb_enter(LBS_DEB_USB);
if (recvlength) {
- __le32 tmp;
-
if (urb->status) {
- lbs_deb_usbd(&cardp->udev->dev,
- "URB status is failed\n");
+ lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
+ urb->status);
kfree_skb(skb);
goto setup_for_next;
}
recvbuff = skb->data + IPFIELD_ALIGN_OFFSET;
- memcpy(&tmp, recvbuff, sizeof(u32));
- recvtype = le32_to_cpu(tmp);
+ recvtype = le32_to_cpu(pkt[0]);
lbs_deb_usbd(&cardp->udev->dev,
"Recv length = 0x%x, Recv type = 0x%X\n",
recvlength, recvtype);
- } else if (urb->status)
+ } else if (urb->status) {
+ kfree_skb(skb);
goto rx_exit;
+ }
switch (recvtype) {
case CMD_TYPE_DATA:
@@ -690,24 +661,28 @@ static void if_usb_receive(struct urb *urb)
case CMD_TYPE_INDICATION:
/* Event cause handling */
- spin_lock(&priv->adapter->driver_lock);
- cardp->usb_event_cause = le32_to_cpu(*(__le32 *) (recvbuff + MESSAGE_HEADER_LEN));
+ spin_lock(&priv->driver_lock);
+
+ cardp->usb_event_cause = le32_to_cpu(pkt[1]);
+
lbs_deb_usbd(&cardp->udev->dev,"**EVENT** 0x%X\n",
- cardp->usb_event_cause);
+ cardp->usb_event_cause);
+
+ /* Icky undocumented magic special case */
if (cardp->usb_event_cause & 0xffff0000) {
- libertas_send_tx_feedback(priv);
- spin_unlock(&priv->adapter->driver_lock);
+ lbs_send_tx_feedback(priv);
+ spin_unlock(&priv->driver_lock);
break;
}
cardp->usb_event_cause <<= 3;
cardp->usb_int_cause |= MRVDRV_CARDEVENT;
kfree_skb(skb);
- libertas_interrupt(priv->dev);
- spin_unlock(&priv->adapter->driver_lock);
+ lbs_interrupt(priv);
+ spin_unlock(&priv->driver_lock);
goto rx_exit;
default:
lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n",
- recvtype);
+ recvtype);
kfree_skb(skb);
break;
}
@@ -720,58 +695,54 @@ rx_exit:
/**
* @brief This function downloads data to FW
- * @param priv pointer to wlan_private structure
+ * @param priv pointer to struct lbs_private structure
* @param type type of data
* @param buf pointer to data buffer
* @param len number of bytes
* @return 0 or -1
*/
-static int if_usb_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
+static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type,
+ uint8_t *payload, uint16_t nb)
{
- struct usb_card_rec *cardp = (struct usb_card_rec *)priv->card;
+ struct if_usb_card *cardp = priv->card;
lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type);
lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb);
if (type == MVMS_CMD) {
- __le32 tmp = cpu_to_le32(CMD_TYPE_REQUEST);
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
priv->dnld_sent = DNLD_CMD_SENT;
- memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
- MESSAGE_HEADER_LEN);
-
} else {
- __le32 tmp = cpu_to_le32(CMD_TYPE_DATA);
+ *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA);
priv->dnld_sent = DNLD_DATA_SENT;
- memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
- MESSAGE_HEADER_LEN);
}
- memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
+ memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb);
- return usb_tx_block(cardp, cardp->bulk_out_buffer,
- nb + MESSAGE_HEADER_LEN);
+ return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN);
}
-/* called with adapter->driver_lock held */
-static int if_usb_get_int_status(wlan_private * priv, u8 * ireg)
+/* called with priv->driver_lock held */
+static int if_usb_get_int_status(struct lbs_private *priv, uint8_t *ireg)
{
- struct usb_card_rec *cardp = priv->card;
+ struct if_usb_card *cardp = priv->card;
*ireg = cardp->usb_int_cause;
cardp->usb_int_cause = 0;
- lbs_deb_usbd(&cardp->udev->dev,"Int cause is 0x%X\n", *ireg);
+ lbs_deb_usbd(&cardp->udev->dev, "Int cause is 0x%X\n", *ireg);
return 0;
}
-static int if_usb_read_event_cause(wlan_private * priv)
+static int if_usb_read_event_cause(struct lbs_private *priv)
{
- struct usb_card_rec *cardp = priv->card;
+ struct if_usb_card *cardp = priv->card;
- priv->adapter->eventcause = cardp->usb_event_cause;
+ priv->eventcause = cardp->usb_event_cause;
/* Re-submit rx urb here to avoid event lost issue */
if_usb_submit_rx_urb(cardp);
+
return 0;
}
@@ -781,20 +752,17 @@ static int if_usb_read_event_cause(wlan_private * priv)
* 2:Boot from FW in EEPROM
* @return 0
*/
-static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
+static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue)
{
- struct bootcmdstr sbootcmd;
- int i;
+ struct bootcmd *bootcmd = cardp->ep_out_buf;
/* Prepare command */
- sbootcmd.u32magicnumber = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
- sbootcmd.u8cmd_tag = ivalue;
- for (i=0; i<11; i++)
- sbootcmd.au8dumy[i]=0x00;
- memcpy(cardp->bulk_out_buffer, &sbootcmd, sizeof(struct bootcmdstr));
+ bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER);
+ bootcmd->cmd = ivalue;
+ memset(bootcmd->pad, 0, sizeof(bootcmd->pad));
/* Issue command */
- usb_tx_block(cardp, cardp->bulk_out_buffer, sizeof(struct bootcmdstr));
+ usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd));
return 0;
}
@@ -807,10 +775,10 @@ static int if_usb_issue_boot_command(struct usb_card_rec *cardp, int ivalue)
* len image length
* @return 0 or -1
*/
-static int check_fwfile_format(u8 *data, u32 totlen)
+static int check_fwfile_format(uint8_t *data, uint32_t totlen)
{
- u32 bincmd, exit;
- u32 blksize, offset, len;
+ uint32_t bincmd, exit;
+ uint32_t blksize, offset, len;
int ret;
ret = 1;
@@ -848,7 +816,7 @@ static int check_fwfile_format(u8 *data, u32 totlen)
}
-static int if_usb_prog_firmware(struct usb_card_rec *cardp)
+static int if_usb_prog_firmware(struct if_usb_card *cardp)
{
int i = 0;
static int reset_count = 10;
@@ -856,10 +824,10 @@ static int if_usb_prog_firmware(struct usb_card_rec *cardp)
lbs_deb_enter(LBS_DEB_USB);
- if ((ret = request_firmware(&cardp->fw, libertas_fw_name,
+ if ((ret = request_firmware(&cardp->fw, lbs_fw_name,
&cardp->udev->dev)) < 0) {
lbs_pr_err("request_firmware() failed with %#x\n", ret);
- lbs_pr_err("firmware %s not found\n", libertas_fw_name);
+ lbs_pr_err("firmware %s not found\n", lbs_fw_name);
goto done;
}
@@ -886,7 +854,7 @@ restart:
} while (cardp->bootcmdresp == 0 && j < 10);
} while (cardp->bootcmdresp == 0 && i < 5);
- if (cardp->bootcmdresp == 0) {
+ if (cardp->bootcmdresp <= 0) {
if (--reset_count >= 0) {
if_usb_reset_device(cardp);
goto restart;
@@ -904,15 +872,14 @@ restart:
cardp->totalbytes = 0;
cardp->fwfinalblk = 0;
- if_prog_firmware(cardp);
+ /* Send the first firmware packet... */
+ if_usb_send_fw_pkt(cardp);
- do {
- lbs_deb_usbd(&cardp->udev->dev,"Wlan sched timeout\n");
- i++;
- msleep_interruptible(100);
- if (cardp->surprise_removed || i >= 20)
- break;
- } while (!cardp->fwdnldover);
+ /* ... and wait for the process to complete */
+ wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover);
+
+ del_timer_sync(&cardp->fw_timeout);
+ usb_kill_urb(cardp->rx_urb);
if (!cardp->fwdnldover) {
lbs_pr_info("failed to load fw, resetting device!\n");
@@ -926,11 +893,11 @@ restart:
goto release_fw;
}
-release_fw:
+ release_fw:
release_firmware(cardp->fw);
cardp->fw = NULL;
-done:
+ done:
lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret);
return ret;
}
@@ -939,66 +906,38 @@ done:
#ifdef CONFIG_PM
static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
{
- struct usb_card_rec *cardp = usb_get_intfdata(intf);
- wlan_private *priv = cardp->priv;
+ struct if_usb_card *cardp = usb_get_intfdata(intf);
+ struct lbs_private *priv = cardp->priv;
+ int ret;
lbs_deb_enter(LBS_DEB_USB);
- if (priv->adapter->psstate != PS_STATE_FULL_POWER)
+ if (priv->psstate != PS_STATE_FULL_POWER)
return -1;
- if (priv->mesh_dev && !priv->mesh_autostart_enabled) {
- /* Mesh autostart must be activated while sleeping
- * On resume it will go back to the current state
- */
- struct cmd_ds_mesh_access mesh_access;
- memset(&mesh_access, 0, sizeof(mesh_access));
- mesh_access.data[0] = cpu_to_le32(1);
- libertas_prepare_and_send_command(priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
- }
-
- netif_device_detach(cardp->eth_dev);
- netif_device_detach(priv->mesh_dev);
+ ret = lbs_suspend(priv);
+ if (ret)
+ goto out;
/* Unlink tx & rx urb */
usb_kill_urb(cardp->tx_urb);
usb_kill_urb(cardp->rx_urb);
- cardp->rx_urb_recall = 1;
-
+ out:
lbs_deb_leave(LBS_DEB_USB);
- return 0;
+ return ret;
}
static int if_usb_resume(struct usb_interface *intf)
{
- struct usb_card_rec *cardp = usb_get_intfdata(intf);
- wlan_private *priv = cardp->priv;
+ struct if_usb_card *cardp = usb_get_intfdata(intf);
+ struct lbs_private *priv = cardp->priv;
lbs_deb_enter(LBS_DEB_USB);
- cardp->rx_urb_recall = 0;
-
- if_usb_submit_rx_urb(cardp->priv);
+ if_usb_submit_rx_urb(cardp);
- netif_device_attach(cardp->eth_dev);
- netif_device_attach(priv->mesh_dev);
-
- if (priv->mesh_dev && !priv->mesh_autostart_enabled) {
- /* Mesh autostart was activated while sleeping
- * Disable it if appropriate
- */
- struct cmd_ds_mesh_access mesh_access;
- memset(&mesh_access, 0, sizeof(mesh_access));
- mesh_access.data[0] = cpu_to_le32(0);
- libertas_prepare_and_send_command(priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
- }
+ lbs_resume(priv);
lbs_deb_leave(LBS_DEB_USB);
return 0;
@@ -1009,46 +948,30 @@ static int if_usb_resume(struct usb_interface *intf)
#endif
static struct usb_driver if_usb_driver = {
- /* driver name */
- .name = usbdriver_name,
- /* probe function name */
+ .name = DRV_NAME,
.probe = if_usb_probe,
- /* disconnect function name */
.disconnect = if_usb_disconnect,
- /* device signature table */
.id_table = if_usb_table,
.suspend = if_usb_suspend,
.resume = if_usb_resume,
};
-static int if_usb_init_module(void)
+static int __init if_usb_init_module(void)
{
int ret = 0;
lbs_deb_enter(LBS_DEB_MAIN);
- if (libertas_fw_name == NULL) {
- libertas_fw_name = default_fw_name;
- }
-
ret = usb_register(&if_usb_driver);
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
-static void if_usb_exit_module(void)
+static void __exit if_usb_exit_module(void)
{
- struct usb_card_rec *cardp, *cardp_temp;
-
lbs_deb_enter(LBS_DEB_MAIN);
- list_for_each_entry_safe(cardp, cardp_temp, &usb_devices, list) {
- libertas_prepare_and_send_command(cardp->priv, CMD_802_11_RESET,
- CMD_ACT_HALT, 0, 0, NULL);
- }
-
- /* API unregisters the driver from USB subsystem */
usb_deregister(&if_usb_driver);
lbs_deb_leave(LBS_DEB_MAIN);
@@ -1058,5 +981,5 @@ module_init(if_usb_init_module);
module_exit(if_usb_exit_module);
MODULE_DESCRIPTION("8388 USB WLAN Driver");
-MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc.");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h
index e07a10ed28b5..e4829a391eb9 100644
--- a/drivers/net/wireless/libertas/if_usb.h
+++ b/drivers/net/wireless/libertas/if_usb.h
@@ -1,79 +1,76 @@
-#ifndef _LIBERTAS_IF_USB_H
-#define _LIBERTAS_IF_USB_H
+#ifndef _LBS_IF_USB_H
+#define _LBS_IF_USB_H
-#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
+
+struct lbs_private;
/**
* This file contains definition for USB interface.
*/
-#define CMD_TYPE_REQUEST 0xF00DFACE
-#define CMD_TYPE_DATA 0xBEADC0DE
-#define CMD_TYPE_INDICATION 0xBEEFFACE
+#define CMD_TYPE_REQUEST 0xF00DFACE
+#define CMD_TYPE_DATA 0xBEADC0DE
+#define CMD_TYPE_INDICATION 0xBEEFFACE
-#define IPFIELD_ALIGN_OFFSET 2
+#define IPFIELD_ALIGN_OFFSET 2
-#define BOOT_CMD_FW_BY_USB 0x01
-#define BOOT_CMD_FW_IN_EEPROM 0x02
-#define BOOT_CMD_UPDATE_BOOT2 0x03
-#define BOOT_CMD_UPDATE_FW 0x04
-#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* M=>0x4D,R=>0x52,V=>0x56,L=>0x4C */
+#define BOOT_CMD_FW_BY_USB 0x01
+#define BOOT_CMD_FW_IN_EEPROM 0x02
+#define BOOT_CMD_UPDATE_BOOT2 0x03
+#define BOOT_CMD_UPDATE_FW 0x04
+#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */
-struct bootcmdstr
+struct bootcmd
{
- __le32 u32magicnumber;
- u8 u8cmd_tag;
- u8 au8dumy[11];
+ __le32 magic;
+ uint8_t cmd;
+ uint8_t pad[11];
};
-#define BOOT_CMD_RESP_OK 0x0001
-#define BOOT_CMD_RESP_FAIL 0x0000
+#define BOOT_CMD_RESP_OK 0x0001
+#define BOOT_CMD_RESP_FAIL 0x0000
-struct bootcmdrespStr
+struct bootcmdresp
{
- __le32 u32magicnumber;
- u8 u8cmd_tag;
- u8 u8result;
- u8 au8dumy[2];
-};
-
-/* read callback private data */
-struct read_cb_info {
- struct usb_card_rec *cardp;
- struct sk_buff *skb;
+ __le32 magic;
+ uint8_t cmd;
+ uint8_t result;
+ uint8_t pad[2];
};
/** USB card description structure*/
-struct usb_card_rec {
- struct list_head list;
- struct net_device *eth_dev;
+struct if_usb_card {
struct usb_device *udev;
struct urb *rx_urb, *tx_urb;
- void *priv;
- struct read_cb_info rinfo;
+ struct lbs_private *priv;
- int bulk_in_size;
- u8 bulk_in_endpointAddr;
+ struct sk_buff *rx_skb;
+ uint32_t usb_event_cause;
+ uint8_t usb_int_cause;
- u8 *bulk_out_buffer;
- int bulk_out_size;
- u8 bulk_out_endpointAddr;
+ uint8_t ep_in;
+ uint8_t ep_out;
- const struct firmware *fw;
- u8 CRC_OK;
- u32 fwseqnum;
- u32 lastseqnum;
- u32 totalbytes;
- u32 fwlastblksent;
- u8 fwdnldover;
- u8 fwfinalblk;
- u8 surprise_removed;
+ int8_t bootcmdresp;
- u32 usb_event_cause;
- u8 usb_int_cause;
+ int ep_in_size;
- u8 rx_urb_recall;
+ void *ep_out_buf;
+ int ep_out_size;
- u8 bootcmdresp;
+ const struct firmware *fw;
+ struct timer_list fw_timeout;
+ wait_queue_head_t fw_wq;
+ uint32_t fwseqnum;
+ uint32_t totalbytes;
+ uint32_t fwlastblksent;
+ uint8_t CRC_OK;
+ uint8_t fwdnldover;
+ uint8_t fwfinalblk;
+ uint8_t surprise_removed;
+
+ __le16 boot2_version;
};
/** fwheader */
@@ -86,10 +83,10 @@ struct fwheader {
#define FW_MAX_DATA_BLK_SIZE 600
/** FWData */
-struct FWData {
- struct fwheader fwheader;
+struct fwdata {
+ struct fwheader hdr;
__le32 seqnum;
- u8 data[FW_MAX_DATA_BLK_SIZE];
+ uint8_t data[0];
};
/** fwsyncheader */
@@ -101,7 +98,5 @@ struct fwsyncheader {
#define FW_HAS_DATA_TO_RECV 0x00000001
#define FW_HAS_LAST_BLOCK 0x00000004
-#define FW_DATA_XMIT_SIZE \
- sizeof(struct fwheader) + le32_to_cpu(fwdata->fwheader.datalength) + sizeof(u32)
#endif
diff --git a/drivers/net/wireless/libertas/join.c b/drivers/net/wireless/libertas/join.c
index dc24a05c9447..2d4508048b68 100644
--- a/drivers/net/wireless/libertas/join.c
+++ b/drivers/net/wireless/libertas/join.c
@@ -30,16 +30,18 @@
* NOTE: Setting the MSB of the basic rates need to be taken
* care, either before or after calling this function
*
- * @param adapter A pointer to wlan_adapter structure
+ * @param priv A pointer to struct lbs_private structure
* @param rate1 the buffer which keeps input and output
* @param rate1_size the size of rate1 buffer; new size of buffer on return
*
* @return 0 or -1
*/
-static int get_common_rates(wlan_adapter * adapter, u8 * rates, u16 *rates_size)
+static int get_common_rates(struct lbs_private *priv,
+ u8 *rates,
+ u16 *rates_size)
{
- u8 *card_rates = libertas_bg_rates;
- size_t num_card_rates = sizeof(libertas_bg_rates);
+ u8 *card_rates = lbs_bg_rates;
+ size_t num_card_rates = sizeof(lbs_bg_rates);
int ret = 0, i, j;
u8 tmp[30];
size_t tmp_size = 0;
@@ -55,15 +57,15 @@ static int get_common_rates(wlan_adapter * adapter, u8 * rates, u16 *rates_size)
lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
lbs_deb_hex(LBS_DEB_JOIN, "card rates ", card_rates, num_card_rates);
lbs_deb_hex(LBS_DEB_JOIN, "common rates", tmp, tmp_size);
- lbs_deb_join("Tx datarate is currently 0x%X\n", adapter->cur_rate);
+ lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
- if (!adapter->auto_rate) {
+ if (!priv->auto_rate) {
for (i = 0; i < tmp_size; i++) {
- if (tmp[i] == adapter->cur_rate)
+ if (tmp[i] == priv->cur_rate)
goto done;
}
lbs_pr_alert("Previously set fixed data rate %#x isn't "
- "compatible with the network.\n", adapter->cur_rate);
+ "compatible with the network.\n", priv->cur_rate);
ret = -1;
goto done;
}
@@ -85,7 +87,7 @@ done:
* @param rates buffer of data rates
* @param len size of buffer
*/
-static void libertas_set_basic_rate_flags(u8 * rates, size_t len)
+static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
{
int i;
@@ -104,7 +106,7 @@ static void libertas_set_basic_rate_flags(u8 * rates, size_t len)
* @param rates buffer of data rates
* @param len size of buffer
*/
-void libertas_unset_basic_rate_flags(u8 * rates, size_t len)
+void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
{
int i;
@@ -116,19 +118,18 @@ void libertas_unset_basic_rate_flags(u8 * rates, size_t len)
/**
* @brief Associate to a specific BSS discovered in a scan
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param pbssdesc Pointer to the BSS descriptor to associate with.
*
* @return 0-success, otherwise fail
*/
-int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req)
+int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret;
- lbs_deb_enter(LBS_DEB_JOIN);
+ lbs_deb_enter(LBS_DEB_ASSOC);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AUTHENTICATE,
0, CMD_OPTION_WAITFORRSP,
0, assoc_req->bss.bssid);
@@ -136,50 +137,50 @@ int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req)
goto done;
/* set preamble to firmware */
- if ( (adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+ if ( (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
&& (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE))
- adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;
+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
else
- adapter->preamble = CMD_TYPE_LONG_PREAMBLE;
+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
- libertas_set_radio_control(priv);
+ lbs_set_radio_control(priv);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_ASSOCIATE,
0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
/**
* @brief Start an Adhoc Network
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param adhocssid The ssid of the Adhoc Network
* @return 0--success, -1--fail
*/
-int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
+int lbs_start_adhoc_network(struct lbs_private *priv,
+ struct assoc_request *assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
- adapter->adhoccreate = 1;
+ priv->adhoccreate = 1;
- if (adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
+ if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
lbs_deb_join("AdhocStart: Short preamble\n");
- adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;
+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
} else {
lbs_deb_join("AdhocStart: Long preamble\n");
- adapter->preamble = CMD_TYPE_LONG_PREAMBLE;
+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
}
- libertas_set_radio_control(priv);
+ lbs_set_radio_control(priv);
lbs_deb_join("AdhocStart: channel = %d\n", assoc_req->channel);
lbs_deb_join("AdhocStart: band = %d\n", assoc_req->band);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_START,
0, CMD_OPTION_WAITFORRSP, 0, assoc_req);
return ret;
@@ -188,34 +189,34 @@ int libertas_start_adhoc_network(wlan_private * priv, struct assoc_request * ass
/**
* @brief Join an adhoc network found in a previous scan
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param pbssdesc Pointer to a BSS descriptor found in a previous scan
* to attempt to join
*
* @return 0--success, -1--fail
*/
-int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * assoc_req)
+int lbs_join_adhoc_network(struct lbs_private *priv,
+ struct assoc_request *assoc_req)
{
- wlan_adapter *adapter = priv->adapter;
struct bss_descriptor * bss = &assoc_req->bss;
int ret = 0;
lbs_deb_join("%s: Current SSID '%s', ssid length %u\n",
__func__,
- escape_essid(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len),
- adapter->curbssparams.ssid_len);
+ escape_essid(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len),
+ priv->curbssparams.ssid_len);
lbs_deb_join("%s: requested ssid '%s', ssid length %u\n",
__func__, escape_essid(bss->ssid, bss->ssid_len),
bss->ssid_len);
/* check if the requested SSID is already joined */
- if ( adapter->curbssparams.ssid_len
- && !libertas_ssid_cmp(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len,
+ if ( priv->curbssparams.ssid_len
+ && !lbs_ssid_cmp(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len,
bss->ssid, bss->ssid_len)
- && (adapter->mode == IW_MODE_ADHOC)
- && (adapter->connect_status == LIBERTAS_CONNECTED)) {
+ && (priv->mode == IW_MODE_ADHOC)
+ && (priv->connect_status == LBS_CONNECTED)) {
union iwreq_data wrqu;
lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
@@ -225,7 +226,7 @@ int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * asso
* request really was successful, even if just a null-op.
*/
memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid,
+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
@@ -235,22 +236,22 @@ int libertas_join_adhoc_network(wlan_private * priv, struct assoc_request * asso
/* Use shortpreamble only when both creator and card supports
short preamble */
if ( !(bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
- || !(adapter->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
+ || !(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) {
lbs_deb_join("AdhocJoin: Long preamble\n");
- adapter->preamble = CMD_TYPE_LONG_PREAMBLE;
+ priv->preamble = CMD_TYPE_LONG_PREAMBLE;
} else {
lbs_deb_join("AdhocJoin: Short preamble\n");
- adapter->preamble = CMD_TYPE_SHORT_PREAMBLE;
+ priv->preamble = CMD_TYPE_SHORT_PREAMBLE;
}
- libertas_set_radio_control(priv);
+ lbs_set_radio_control(priv);
lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
- adapter->adhoccreate = 0;
+ priv->adhoccreate = 0;
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_JOIN,
0, CMD_OPTION_WAITFORRSP,
OID_802_11_SSID, assoc_req);
@@ -258,38 +259,37 @@ out:
return ret;
}
-int libertas_stop_adhoc_network(wlan_private * priv)
+int lbs_stop_adhoc_network(struct lbs_private *priv)
{
- return libertas_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
+ return lbs_prepare_and_send_command(priv, CMD_802_11_AD_HOC_STOP,
0, CMD_OPTION_WAITFORRSP, 0, NULL);
}
/**
* @brief Send Deauthentication Request
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return 0--success, -1--fail
*/
-int libertas_send_deauthentication(wlan_private * priv)
+int lbs_send_deauthentication(struct lbs_private *priv)
{
- return libertas_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
+ return lbs_prepare_and_send_command(priv, CMD_802_11_DEAUTHENTICATE,
0, CMD_OPTION_WAITFORRSP, 0, NULL);
}
/**
* @brief This function prepares command of authenticate.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param cmd A pointer to cmd_ds_command structure
* @param pdata_buf Void cast of pointer to a BSSID to authenticate with
*
* @return 0 or -1
*/
-int libertas_cmd_80211_authenticate(wlan_private * priv,
+int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
int ret = -1;
u8 *bssid = pdata_buf;
@@ -302,7 +302,7 @@ int libertas_cmd_80211_authenticate(wlan_private * priv,
+ S_DS_GEN);
/* translate auth mode to 802.11 defined wire value */
- switch (adapter->secinfo.auth_mode) {
+ switch (priv->secinfo.auth_mode) {
case IW_AUTH_ALG_OPEN_SYSTEM:
pauthenticate->authtype = 0x00;
break;
@@ -314,13 +314,13 @@ int libertas_cmd_80211_authenticate(wlan_private * priv,
break;
default:
lbs_deb_join("AUTH_CMD: invalid auth alg 0x%X\n",
- adapter->secinfo.auth_mode);
+ priv->secinfo.auth_mode);
goto out;
}
memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
- lbs_deb_join("AUTH_CMD: BSSID is : %s auth=0x%X\n",
+ lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
print_mac(mac, bssid), pauthenticate->authtype);
ret = 0;
@@ -329,10 +329,9 @@ out:
return ret;
}
-int libertas_cmd_80211_deauthenticate(wlan_private * priv,
+int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_deauthenticate *dauth = &cmd->params.deauth;
lbs_deb_enter(LBS_DEB_JOIN);
@@ -342,7 +341,7 @@ int libertas_cmd_80211_deauthenticate(wlan_private * priv,
S_DS_GEN);
/* set AP MAC address */
- memmove(dauth->macaddr, adapter->curbssparams.bssid, ETH_ALEN);
+ memmove(dauth->macaddr, priv->curbssparams.bssid, ETH_ALEN);
/* Reason code 3 = Station is leaving */
#define REASON_CODE_STA_LEAVING 3
@@ -352,10 +351,9 @@ int libertas_cmd_80211_deauthenticate(wlan_private * priv,
return 0;
}
-int libertas_cmd_80211_associate(wlan_private * priv,
+int lbs_cmd_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *cmd, void *pdata_buf)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_associate *passo = &cmd->params.associate;
int ret = 0;
struct assoc_request * assoc_req = pdata_buf;
@@ -368,11 +366,11 @@ int libertas_cmd_80211_associate(wlan_private * priv,
struct mrvlietypes_ratesparamset *rates;
struct mrvlietypes_rsnparamset *rsn;
- lbs_deb_enter(LBS_DEB_JOIN);
+ lbs_deb_enter(LBS_DEB_ASSOC);
pos = (u8 *) passo;
- if (!adapter) {
+ if (!priv) {
ret = -1;
goto done;
}
@@ -416,22 +414,22 @@ int libertas_cmd_80211_associate(wlan_private * priv,
rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
memcpy(&rates->rates, &bss->rates, MAX_RATES);
tmplen = MAX_RATES;
- if (get_common_rates(adapter, rates->rates, &tmplen)) {
+ if (get_common_rates(priv, rates->rates, &tmplen)) {
ret = -1;
goto done;
}
pos += sizeof(rates->header) + tmplen;
rates->header.len = cpu_to_le16(tmplen);
- lbs_deb_join("ASSOC_CMD: num rates = %u\n", tmplen);
+ lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
/* Copy the infra. association rates into Current BSS state structure */
- memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
- memcpy(&adapter->curbssparams.rates, &rates->rates, tmplen);
+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+ memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
/* Set MSB on basic rates as the firmware requires, but _after_
* copying to current bss rates.
*/
- libertas_set_basic_rate_flags(rates->rates, tmplen);
+ lbs_set_basic_rate_flags(rates->rates, tmplen);
if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
rsn = (struct mrvlietypes_rsnparamset *) pos;
@@ -446,9 +444,9 @@ int libertas_cmd_80211_associate(wlan_private * priv,
}
/* update curbssparams */
- adapter->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
+ priv->curbssparams.channel = bss->phyparamset.dsparamset.currentchan;
- if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
+ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
ret = -1;
goto done;
}
@@ -460,18 +458,16 @@ int libertas_cmd_80211_associate(wlan_private * priv,
if (bss->mode == IW_MODE_INFRA)
tmpcap |= WLAN_CAPABILITY_ESS;
passo->capability = cpu_to_le16(tmpcap);
- lbs_deb_join("ASSOC_CMD: capability=%4X CAPINFO_MASK=%4X\n",
- tmpcap, CAPINFO_MASK);
+ lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *cmd, void *pdata_buf)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_ad_hoc_start *adhs = &cmd->params.ads;
int ret = 0;
int cmdappendsize = 0;
@@ -481,7 +477,7 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
lbs_deb_enter(LBS_DEB_JOIN);
- if (!adapter) {
+ if (!priv) {
ret = -1;
goto done;
}
@@ -491,7 +487,7 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
/*
* Fill in the parameters for 2 data structures:
* 1. cmd_ds_802_11_ad_hoc_start command
- * 2. adapter->scantable[i]
+ * 2. priv->scantable[i]
*
* Driver will fill up SSID, bsstype,IBSS param, Physical Param,
* probe delay, and cap info.
@@ -509,8 +505,10 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
/* set the BSS type */
adhs->bsstype = CMD_BSS_TYPE_IBSS;
- adapter->mode = IW_MODE_ADHOC;
- adhs->beaconperiod = cpu_to_le16(MRVDRV_BEACON_INTERVAL);
+ priv->mode = IW_MODE_ADHOC;
+ if (priv->beacon_period == 0)
+ priv->beacon_period = MRVDRV_BEACON_INTERVAL;
+ adhs->beaconperiod = cpu_to_le16(priv->beacon_period);
/* set Physical param set */
#define DS_PARA_IE_ID 3
@@ -548,24 +546,24 @@ int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
adhs->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
memset(adhs->rates, 0, sizeof(adhs->rates));
- ratesize = min(sizeof(adhs->rates), sizeof(libertas_bg_rates));
- memcpy(adhs->rates, libertas_bg_rates, ratesize);
+ ratesize = min(sizeof(adhs->rates), sizeof(lbs_bg_rates));
+ memcpy(adhs->rates, lbs_bg_rates, ratesize);
/* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
- memcpy(&adapter->curbssparams.rates, &adhs->rates, ratesize);
+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+ memcpy(&priv->curbssparams.rates, &adhs->rates, ratesize);
/* Set MSB on basic rates as the firmware requires, but _after_
* copying to current bss rates.
*/
- libertas_set_basic_rate_flags(adhs->rates, ratesize);
+ lbs_set_basic_rate_flags(adhs->rates, ratesize);
lbs_deb_join("ADHOC_S_CMD: rates=%02x %02x %02x %02x \n",
adhs->rates[0], adhs->rates[1], adhs->rates[2], adhs->rates[3]);
lbs_deb_join("ADHOC_S_CMD: AD HOC Start command is ready\n");
- if (libertas_create_dnld_countryinfo_11d(priv)) {
+ if (lbs_create_dnld_countryinfo_11d(priv)) {
lbs_deb_join("ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
ret = -1;
goto done;
@@ -580,7 +578,7 @@ done:
return ret;
}
-int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
struct cmd_ds_command *cmd)
{
cmd->command = cpu_to_le16(CMD_802_11_AD_HOC_STOP);
@@ -589,10 +587,9 @@ int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
return 0;
}
-int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
struct cmd_ds_command *cmd, void *pdata_buf)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_ad_hoc_join *join_cmd = &cmd->params.adj;
struct assoc_request * assoc_req = pdata_buf;
struct bss_descriptor *bss = &assoc_req->bss;
@@ -633,26 +630,26 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
/* probedelay */
join_cmd->probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
- adapter->curbssparams.channel = bss->channel;
+ priv->curbssparams.channel = bss->channel;
/* Copy Data rates from the rates recorded in scan response */
memset(join_cmd->bss.rates, 0, sizeof(join_cmd->bss.rates));
ratesize = min_t(u16, sizeof(join_cmd->bss.rates), MAX_RATES);
memcpy(join_cmd->bss.rates, bss->rates, ratesize);
- if (get_common_rates(adapter, join_cmd->bss.rates, &ratesize)) {
+ if (get_common_rates(priv, join_cmd->bss.rates, &ratesize)) {
lbs_deb_join("ADHOC_J_CMD: get_common_rates returns error.\n");
ret = -1;
goto done;
}
/* Copy the ad-hoc creating rates into Current BSS state structure */
- memset(&adapter->curbssparams.rates, 0, sizeof(adapter->curbssparams.rates));
- memcpy(&adapter->curbssparams.rates, join_cmd->bss.rates, ratesize);
+ memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
+ memcpy(&priv->curbssparams.rates, join_cmd->bss.rates, ratesize);
/* Set MSB on basic rates as the firmware requires, but _after_
* copying to current bss rates.
*/
- libertas_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
+ lbs_set_basic_rate_flags(join_cmd->bss.rates, ratesize);
join_cmd->bss.ssparamset.ibssparamset.atimwindow =
cpu_to_le16(bss->atimwindow);
@@ -663,12 +660,12 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
join_cmd->bss.capability = cpu_to_le16(tmp);
}
- if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
+ if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
/* wake up first */
__le32 Localpsmode;
- Localpsmode = cpu_to_le32(WLAN802_11POWERMODECAM);
- ret = libertas_prepare_and_send_command(priv,
+ Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_PS_MODE,
CMD_ACT_SET,
0, 0, &Localpsmode);
@@ -679,7 +676,7 @@ int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
}
}
- if (libertas_parse_dnld_countryinfo_11d(priv, bss)) {
+ if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
ret = -1;
goto done;
}
@@ -692,24 +689,23 @@ done:
return ret;
}
-int libertas_ret_80211_associate(wlan_private * priv,
+int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
union iwreq_data wrqu;
struct ieeetypes_assocrsp *passocrsp;
struct bss_descriptor * bss;
u16 status_code;
- lbs_deb_enter(LBS_DEB_JOIN);
+ lbs_deb_enter(LBS_DEB_ASSOC);
- if (!adapter->in_progress_assoc_req) {
- lbs_deb_join("ASSOC_RESP: no in-progress association request\n");
+ if (!priv->in_progress_assoc_req) {
+ lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
ret = -1;
goto done;
}
- bss = &adapter->in_progress_assoc_req->bss;
+ bss = &priv->in_progress_assoc_req->bss;
passocrsp = (struct ieeetypes_assocrsp *) & resp->params;
@@ -734,96 +730,83 @@ int libertas_ret_80211_associate(wlan_private * priv,
status_code = le16_to_cpu(passocrsp->statuscode);
switch (status_code) {
case 0x00:
- lbs_deb_join("ASSOC_RESP: Association succeeded\n");
break;
case 0x01:
- lbs_deb_join("ASSOC_RESP: Association failed; invalid "
- "parameters (status code %d)\n", status_code);
+ lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
break;
case 0x02:
- lbs_deb_join("ASSOC_RESP: Association failed; internal timer "
- "expired while waiting for the AP (status code %d)"
- "\n", status_code);
+ lbs_deb_assoc("ASSOC_RESP: internal timer "
+ "expired while waiting for the AP\n");
break;
case 0x03:
- lbs_deb_join("ASSOC_RESP: Association failed; association "
- "was refused by the AP (status code %d)\n",
- status_code);
+ lbs_deb_assoc("ASSOC_RESP: association "
+ "refused by AP\n");
break;
case 0x04:
- lbs_deb_join("ASSOC_RESP: Association failed; authentication "
- "was refused by the AP (status code %d)\n",
- status_code);
+ lbs_deb_assoc("ASSOC_RESP: authentication "
+ "refused by AP\n");
break;
default:
- lbs_deb_join("ASSOC_RESP: Association failed; reason unknown "
- "(status code %d)\n", status_code);
+ lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
+ " unknown\n", status_code);
break;
}
if (status_code) {
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
ret = -1;
goto done;
}
- lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_RESP", (void *)&resp->params,
+ lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
le16_to_cpu(resp->size) - S_DS_GEN);
/* Send a Media Connected event, according to the Spec */
- adapter->connect_status = LIBERTAS_CONNECTED;
-
- lbs_deb_join("ASSOC_RESP: assocated to '%s'\n",
- escape_essid(bss->ssid, bss->ssid_len));
+ priv->connect_status = LBS_CONNECTED;
/* Update current SSID and BSSID */
- memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- adapter->curbssparams.ssid_len = bss->ssid_len;
- memcpy(adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
+ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+ priv->curbssparams.ssid_len = bss->ssid_len;
+ memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
- lbs_deb_join("ASSOC_RESP: currentpacketfilter is %x\n",
- adapter->currentpacketfilter);
+ lbs_deb_assoc("ASSOC_RESP: currentpacketfilter is 0x%x\n",
+ priv->currentpacketfilter);
- adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
- adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
+ priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
+ priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
- memset(adapter->rawSNR, 0x00, sizeof(adapter->rawSNR));
- memset(adapter->rawNF, 0x00, sizeof(adapter->rawNF));
- adapter->nextSNRNF = 0;
- adapter->numSNRNF = 0;
+ memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
+ memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
+ priv->nextSNRNF = 0;
+ priv->numSNRNF = 0;
netif_carrier_on(priv->dev);
- netif_wake_queue(priv->dev);
-
- if (priv->mesh_dev) {
- netif_carrier_on(priv->mesh_dev);
- netif_wake_queue(priv->mesh_dev);
- }
+ if (!priv->tx_pending_len)
+ netif_wake_queue(priv->dev);
- memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
done:
- lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
+ lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
return ret;
}
-int libertas_ret_80211_disassociate(wlan_private * priv,
+int lbs_ret_80211_disassociate(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
lbs_deb_enter(LBS_DEB_JOIN);
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
lbs_deb_leave(LBS_DEB_JOIN);
return 0;
}
-int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
+int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
u16 command = le16_to_cpu(resp->command);
u16 result = le16_to_cpu(resp->result);
@@ -840,20 +823,20 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
lbs_deb_join("ADHOC_RESP: command = %x\n", command);
lbs_deb_join("ADHOC_RESP: result = %x\n", result);
- if (!adapter->in_progress_assoc_req) {
+ if (!priv->in_progress_assoc_req) {
lbs_deb_join("ADHOC_RESP: no in-progress association request\n");
ret = -1;
goto done;
}
- bss = &adapter->in_progress_assoc_req->bss;
+ bss = &priv->in_progress_assoc_req->bss;
/*
* Join result code 0 --> SUCCESS
*/
if (result) {
lbs_deb_join("ADHOC_RESP: failed\n");
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- libertas_mac_event_disconnected(priv);
+ if (priv->connect_status == LBS_CONNECTED) {
+ lbs_mac_event_disconnected(priv);
}
ret = -1;
goto done;
@@ -867,7 +850,7 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
escape_essid(bss->ssid, bss->ssid_len));
/* Send a Media Connected event, according to the Spec */
- adapter->connect_status = LIBERTAS_CONNECTED;
+ priv->connect_status = LBS_CONNECTED;
if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
/* Update the created network descriptor with the new BSSID */
@@ -875,27 +858,23 @@ int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
}
/* Set the BSSID from the joined/started descriptor */
- memcpy(&adapter->curbssparams.bssid, bss->bssid, ETH_ALEN);
+ memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
/* Set the new SSID to current SSID */
- memcpy(&adapter->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
- adapter->curbssparams.ssid_len = bss->ssid_len;
+ memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+ priv->curbssparams.ssid_len = bss->ssid_len;
netif_carrier_on(priv->dev);
- netif_wake_queue(priv->dev);
-
- if (priv->mesh_dev) {
- netif_carrier_on(priv->mesh_dev);
- netif_wake_queue(priv->mesh_dev);
- }
+ if (!priv->tx_pending_len)
+ netif_wake_queue(priv->dev);
memset(&wrqu, 0, sizeof(wrqu));
- memcpy(wrqu.ap_addr.sa_data, adapter->curbssparams.bssid, ETH_ALEN);
+ memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
lbs_deb_join("ADHOC_RESP: - Joined/Started Ad Hoc\n");
- lbs_deb_join("ADHOC_RESP: channel = %d\n", adapter->curbssparams.channel);
+ lbs_deb_join("ADHOC_RESP: channel = %d\n", priv->curbssparams.channel);
lbs_deb_join("ADHOC_RESP: BSSID = %s\n",
print_mac(mac, padhocresult->bssid));
@@ -904,12 +883,12 @@ done:
return ret;
}
-int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
+int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
struct cmd_ds_command *resp)
{
lbs_deb_enter(LBS_DEB_JOIN);
- libertas_mac_event_disconnected(priv);
+ lbs_mac_event_disconnected(priv);
lbs_deb_leave(LBS_DEB_JOIN);
return 0;
diff --git a/drivers/net/wireless/libertas/join.h b/drivers/net/wireless/libertas/join.h
index 894a072b9f8d..c617d071f781 100644
--- a/drivers/net/wireless/libertas/join.h
+++ b/drivers/net/wireless/libertas/join.h
@@ -2,52 +2,52 @@
* Interface for the wlan infrastructure and adhoc join routines
*
* Driver interface functions and type declarations for the join module
- * implemented in wlan_join.c. Process all start/join requests for
+ * implemented in join.c. Process all start/join requests for
* both adhoc and infrastructure networks
*/
-#ifndef _WLAN_JOIN_H
-#define _WLAN_JOIN_H
+#ifndef _LBS_JOIN_H
+#define _LBS_JOIN_H
#include "defs.h"
#include "dev.h"
struct cmd_ds_command;
-int libertas_cmd_80211_authenticate(wlan_private * priv,
+int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_join(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_stop(struct lbs_private *priv,
struct cmd_ds_command *cmd);
-int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
+int lbs_cmd_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int libertas_cmd_80211_deauthenticate(wlan_private * priv,
+int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
struct cmd_ds_command *cmd);
-int libertas_cmd_80211_associate(wlan_private * priv,
+int lbs_cmd_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
+int lbs_ret_80211_ad_hoc_start(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
+int lbs_ret_80211_ad_hoc_stop(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int libertas_ret_80211_disassociate(wlan_private * priv,
+int lbs_ret_80211_disassociate(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int libertas_ret_80211_associate(wlan_private * priv,
+int lbs_ret_80211_associate(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int libertas_start_adhoc_network(wlan_private * priv,
+int lbs_start_adhoc_network(struct lbs_private *priv,
struct assoc_request * assoc_req);
-int libertas_join_adhoc_network(wlan_private * priv,
+int lbs_join_adhoc_network(struct lbs_private *priv,
struct assoc_request * assoc_req);
-int libertas_stop_adhoc_network(wlan_private * priv);
+int lbs_stop_adhoc_network(struct lbs_private *priv);
-int libertas_send_deauthentication(wlan_private * priv);
+int lbs_send_deauthentication(struct lbs_private *priv);
-int wlan_associate(wlan_private * priv, struct assoc_request * assoc_req);
+int lbs_associate(struct lbs_private *priv, struct assoc_request *assoc_req);
-void libertas_unset_basic_rate_flags(u8 * rates, size_t len);
+void lbs_unset_basic_rate_flags(u8 *rates, size_t len);
#endif
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 1823b48a8ba7..84fb49ca0fae 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -6,7 +6,6 @@
#include <linux/moduleparam.h>
#include <linux/delay.h>
-#include <linux/freezer.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
@@ -22,9 +21,10 @@
#include "debugfs.h"
#include "assoc.h"
#include "join.h"
+#include "cmd.h"
#define DRIVER_RELEASE_VERSION "323.p0"
-const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
+const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
#ifdef DEBUG
"-dbg"
#endif
@@ -32,80 +32,80 @@ const char libertas_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
/* Module parameters */
-unsigned int libertas_debug = 0;
-module_param(libertas_debug, int, 0644);
-EXPORT_SYMBOL_GPL(libertas_debug);
+unsigned int lbs_debug;
+EXPORT_SYMBOL_GPL(lbs_debug);
+module_param_named(libertas_debug, lbs_debug, int, 0644);
-#define WLAN_TX_PWR_DEFAULT 20 /*100mW */
-#define WLAN_TX_PWR_US_DEFAULT 20 /*100mW */
-#define WLAN_TX_PWR_JP_DEFAULT 16 /*50mW */
-#define WLAN_TX_PWR_FR_DEFAULT 20 /*100mW */
-#define WLAN_TX_PWR_EMEA_DEFAULT 20 /*100mW */
+#define LBS_TX_PWR_DEFAULT 20 /*100mW */
+#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
+#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
+#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
+#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
/* Format { channel, frequency (MHz), maxtxpower } */
/* band: 'B/G', region: USA FCC/Canada IC */
static struct chan_freq_power channel_freq_power_US_BG[] = {
- {1, 2412, WLAN_TX_PWR_US_DEFAULT},
- {2, 2417, WLAN_TX_PWR_US_DEFAULT},
- {3, 2422, WLAN_TX_PWR_US_DEFAULT},
- {4, 2427, WLAN_TX_PWR_US_DEFAULT},
- {5, 2432, WLAN_TX_PWR_US_DEFAULT},
- {6, 2437, WLAN_TX_PWR_US_DEFAULT},
- {7, 2442, WLAN_TX_PWR_US_DEFAULT},
- {8, 2447, WLAN_TX_PWR_US_DEFAULT},
- {9, 2452, WLAN_TX_PWR_US_DEFAULT},
- {10, 2457, WLAN_TX_PWR_US_DEFAULT},
- {11, 2462, WLAN_TX_PWR_US_DEFAULT}
+ {1, 2412, LBS_TX_PWR_US_DEFAULT},
+ {2, 2417, LBS_TX_PWR_US_DEFAULT},
+ {3, 2422, LBS_TX_PWR_US_DEFAULT},
+ {4, 2427, LBS_TX_PWR_US_DEFAULT},
+ {5, 2432, LBS_TX_PWR_US_DEFAULT},
+ {6, 2437, LBS_TX_PWR_US_DEFAULT},
+ {7, 2442, LBS_TX_PWR_US_DEFAULT},
+ {8, 2447, LBS_TX_PWR_US_DEFAULT},
+ {9, 2452, LBS_TX_PWR_US_DEFAULT},
+ {10, 2457, LBS_TX_PWR_US_DEFAULT},
+ {11, 2462, LBS_TX_PWR_US_DEFAULT}
};
/* band: 'B/G', region: Europe ETSI */
static struct chan_freq_power channel_freq_power_EU_BG[] = {
- {1, 2412, WLAN_TX_PWR_EMEA_DEFAULT},
- {2, 2417, WLAN_TX_PWR_EMEA_DEFAULT},
- {3, 2422, WLAN_TX_PWR_EMEA_DEFAULT},
- {4, 2427, WLAN_TX_PWR_EMEA_DEFAULT},
- {5, 2432, WLAN_TX_PWR_EMEA_DEFAULT},
- {6, 2437, WLAN_TX_PWR_EMEA_DEFAULT},
- {7, 2442, WLAN_TX_PWR_EMEA_DEFAULT},
- {8, 2447, WLAN_TX_PWR_EMEA_DEFAULT},
- {9, 2452, WLAN_TX_PWR_EMEA_DEFAULT},
- {10, 2457, WLAN_TX_PWR_EMEA_DEFAULT},
- {11, 2462, WLAN_TX_PWR_EMEA_DEFAULT},
- {12, 2467, WLAN_TX_PWR_EMEA_DEFAULT},
- {13, 2472, WLAN_TX_PWR_EMEA_DEFAULT}
+ {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
+ {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
+ {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
+ {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
+ {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
+ {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
+ {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
+ {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
+ {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
+ {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
+ {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
+ {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
+ {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
};
/* band: 'B/G', region: Spain */
static struct chan_freq_power channel_freq_power_SPN_BG[] = {
- {10, 2457, WLAN_TX_PWR_DEFAULT},
- {11, 2462, WLAN_TX_PWR_DEFAULT}
+ {10, 2457, LBS_TX_PWR_DEFAULT},
+ {11, 2462, LBS_TX_PWR_DEFAULT}
};
/* band: 'B/G', region: France */
static struct chan_freq_power channel_freq_power_FR_BG[] = {
- {10, 2457, WLAN_TX_PWR_FR_DEFAULT},
- {11, 2462, WLAN_TX_PWR_FR_DEFAULT},
- {12, 2467, WLAN_TX_PWR_FR_DEFAULT},
- {13, 2472, WLAN_TX_PWR_FR_DEFAULT}
+ {10, 2457, LBS_TX_PWR_FR_DEFAULT},
+ {11, 2462, LBS_TX_PWR_FR_DEFAULT},
+ {12, 2467, LBS_TX_PWR_FR_DEFAULT},
+ {13, 2472, LBS_TX_PWR_FR_DEFAULT}
};
/* band: 'B/G', region: Japan */
static struct chan_freq_power channel_freq_power_JPN_BG[] = {
- {1, 2412, WLAN_TX_PWR_JP_DEFAULT},
- {2, 2417, WLAN_TX_PWR_JP_DEFAULT},
- {3, 2422, WLAN_TX_PWR_JP_DEFAULT},
- {4, 2427, WLAN_TX_PWR_JP_DEFAULT},
- {5, 2432, WLAN_TX_PWR_JP_DEFAULT},
- {6, 2437, WLAN_TX_PWR_JP_DEFAULT},
- {7, 2442, WLAN_TX_PWR_JP_DEFAULT},
- {8, 2447, WLAN_TX_PWR_JP_DEFAULT},
- {9, 2452, WLAN_TX_PWR_JP_DEFAULT},
- {10, 2457, WLAN_TX_PWR_JP_DEFAULT},
- {11, 2462, WLAN_TX_PWR_JP_DEFAULT},
- {12, 2467, WLAN_TX_PWR_JP_DEFAULT},
- {13, 2472, WLAN_TX_PWR_JP_DEFAULT},
- {14, 2484, WLAN_TX_PWR_JP_DEFAULT}
+ {1, 2412, LBS_TX_PWR_JP_DEFAULT},
+ {2, 2417, LBS_TX_PWR_JP_DEFAULT},
+ {3, 2422, LBS_TX_PWR_JP_DEFAULT},
+ {4, 2427, LBS_TX_PWR_JP_DEFAULT},
+ {5, 2432, LBS_TX_PWR_JP_DEFAULT},
+ {6, 2437, LBS_TX_PWR_JP_DEFAULT},
+ {7, 2442, LBS_TX_PWR_JP_DEFAULT},
+ {8, 2447, LBS_TX_PWR_JP_DEFAULT},
+ {9, 2452, LBS_TX_PWR_JP_DEFAULT},
+ {10, 2457, LBS_TX_PWR_JP_DEFAULT},
+ {11, 2462, LBS_TX_PWR_JP_DEFAULT},
+ {12, 2467, LBS_TX_PWR_JP_DEFAULT},
+ {13, 2472, LBS_TX_PWR_JP_DEFAULT},
+ {14, 2484, LBS_TX_PWR_JP_DEFAULT}
};
/**
@@ -153,13 +153,13 @@ static struct region_cfp_table region_cfp_table[] = {
/**
* the table to keep region code
*/
-u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
{ 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
/**
* 802.11b/g supported bitrates (in 500Kb/s units)
*/
-u8 libertas_bg_rates[MAX_RATES] =
+u8 lbs_bg_rates[MAX_RATES] =
{ 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
0x00, 0x00 };
@@ -179,7 +179,7 @@ static u8 fw_data_rates[MAX_RATES] =
* @param idx The index of data rate
* @return data rate or 0
*/
-u32 libertas_fw_index_to_data_rate(u8 idx)
+u32 lbs_fw_index_to_data_rate(u8 idx)
{
if (idx >= sizeof(fw_data_rates))
idx = 0;
@@ -192,7 +192,7 @@ u32 libertas_fw_index_to_data_rate(u8 idx)
* @param rate data rate
* @return index or 0
*/
-u8 libertas_data_rate_to_fw_index(u32 rate)
+u8 lbs_data_rate_to_fw_index(u32 rate)
{
u8 i;
@@ -213,16 +213,18 @@ u8 libertas_data_rate_to_fw_index(u32 rate)
/**
* @brief Get function for sysfs attribute anycast_mask
*/
-static ssize_t libertas_anycast_get(struct device * dev,
+static ssize_t lbs_anycast_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
+ struct lbs_private *priv = to_net_dev(dev)->priv;
struct cmd_ds_mesh_access mesh_access;
+ int ret;
memset(&mesh_access, 0, sizeof(mesh_access));
- libertas_prepare_and_send_command(to_net_dev(dev)->priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_GET_ANYCAST,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
+
+ ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
+ if (ret)
+ return ret;
return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
}
@@ -230,244 +232,191 @@ static ssize_t libertas_anycast_get(struct device * dev,
/**
* @brief Set function for sysfs attribute anycast_mask
*/
-static ssize_t libertas_anycast_set(struct device * dev,
+static ssize_t lbs_anycast_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
+ struct lbs_private *priv = to_net_dev(dev)->priv;
struct cmd_ds_mesh_access mesh_access;
uint32_t datum;
+ int ret;
memset(&mesh_access, 0, sizeof(mesh_access));
sscanf(buf, "%x", &datum);
mesh_access.data[0] = cpu_to_le32(datum);
- libertas_prepare_and_send_command((to_net_dev(dev))->priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_SET_ANYCAST,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
+ ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
+ if (ret)
+ return ret;
+
return strlen(buf);
}
-int libertas_add_rtap(wlan_private *priv);
-void libertas_remove_rtap(wlan_private *priv);
+static int lbs_add_rtap(struct lbs_private *priv);
+static void lbs_remove_rtap(struct lbs_private *priv);
+static int lbs_add_mesh(struct lbs_private *priv);
+static void lbs_remove_mesh(struct lbs_private *priv);
+
/**
* Get function for sysfs attribute rtap
*/
-static ssize_t libertas_rtap_get(struct device * dev,
+static ssize_t lbs_rtap_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
- wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;
- wlan_adapter *adapter = priv->adapter;
- return snprintf(buf, 5, "0x%X\n", adapter->monitormode);
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+ return snprintf(buf, 5, "0x%X\n", priv->monitormode);
}
/**
* Set function for sysfs attribute rtap
*/
-static ssize_t libertas_rtap_set(struct device * dev,
+static ssize_t lbs_rtap_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
int monitor_mode;
- wlan_private *priv = (wlan_private *) (to_net_dev(dev))->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = to_net_dev(dev)->priv;
sscanf(buf, "%x", &monitor_mode);
- if (monitor_mode != WLAN_MONITOR_OFF) {
- if(adapter->monitormode == monitor_mode)
+ if (monitor_mode != LBS_MONITOR_OFF) {
+ if(priv->monitormode == monitor_mode)
return strlen(buf);
- if (adapter->monitormode == WLAN_MONITOR_OFF) {
- if (adapter->mode == IW_MODE_INFRA)
- libertas_send_deauthentication(priv);
- else if (adapter->mode == IW_MODE_ADHOC)
- libertas_stop_adhoc_network(priv);
- libertas_add_rtap(priv);
+ if (priv->monitormode == LBS_MONITOR_OFF) {
+ if (priv->infra_open || priv->mesh_open)
+ return -EBUSY;
+ if (priv->mode == IW_MODE_INFRA)
+ lbs_send_deauthentication(priv);
+ else if (priv->mode == IW_MODE_ADHOC)
+ lbs_stop_adhoc_network(priv);
+ lbs_add_rtap(priv);
}
- adapter->monitormode = monitor_mode;
+ priv->monitormode = monitor_mode;
}
else {
- if(adapter->monitormode == WLAN_MONITOR_OFF)
+ if (priv->monitormode == LBS_MONITOR_OFF)
return strlen(buf);
- adapter->monitormode = WLAN_MONITOR_OFF;
- libertas_remove_rtap(priv);
- netif_wake_queue(priv->dev);
- netif_wake_queue(priv->mesh_dev);
+ priv->monitormode = LBS_MONITOR_OFF;
+ lbs_remove_rtap(priv);
+
+ if (priv->currenttxskb) {
+ dev_kfree_skb_any(priv->currenttxskb);
+ priv->currenttxskb = NULL;
+ }
+
+ /* Wake queues, command thread, etc. */
+ lbs_host_to_card_done(priv);
}
- libertas_prepare_and_send_command(priv,
+ lbs_prepare_and_send_command(priv,
CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
- CMD_OPTION_WAITFORRSP, 0, &adapter->monitormode);
+ CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
return strlen(buf);
}
/**
- * libertas_rtap attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/libertas-rtap)
+ * lbs_rtap attribute to be exported per ethX interface
+ * through sysfs (/sys/class/net/ethX/lbs_rtap)
*/
-static DEVICE_ATTR(libertas_rtap, 0644, libertas_rtap_get,
- libertas_rtap_set );
+static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
/**
- * anycast_mask attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/anycast_mask)
+ * Get function for sysfs attribute mesh
*/
-static DEVICE_ATTR(anycast_mask, 0644, libertas_anycast_get, libertas_anycast_set);
-
-static ssize_t libertas_autostart_enabled_get(struct device * dev,
+static ssize_t lbs_mesh_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
- struct cmd_ds_mesh_access mesh_access;
-
- memset(&mesh_access, 0, sizeof(mesh_access));
- libertas_prepare_and_send_command(to_net_dev(dev)->priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
-
- return sprintf(buf, "%d\n", le32_to_cpu(mesh_access.data[0]));
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+ return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
}
-static ssize_t libertas_autostart_enabled_set(struct device * dev,
+/**
+ * Set function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
- struct cmd_ds_mesh_access mesh_access;
- uint32_t datum;
- wlan_private * priv = (to_net_dev(dev))->priv;
+ struct lbs_private *priv = to_net_dev(dev)->priv;
+ int enable;
int ret;
- memset(&mesh_access, 0, sizeof(mesh_access));
- sscanf(buf, "%d", &datum);
- mesh_access.data[0] = cpu_to_le32(datum);
+ sscanf(buf, "%x", &enable);
+ enable = !!enable;
+ if (enable == !!priv->mesh_dev)
+ return count;
+
+ ret = lbs_mesh_config(priv, enable, priv->curbssparams.channel);
+ if (ret)
+ return ret;
- ret = libertas_prepare_and_send_command(priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
- if (ret == 0)
- priv->mesh_autostart_enabled = datum ? 1 : 0;
+ if (enable)
+ lbs_add_mesh(priv);
+ else
+ lbs_remove_mesh(priv);
- return strlen(buf);
+ return count;
}
-static DEVICE_ATTR(autostart_enabled, 0644,
- libertas_autostart_enabled_get, libertas_autostart_enabled_set);
+/**
+ * lbs_mesh attribute to be exported per ethX interface
+ * through sysfs (/sys/class/net/ethX/lbs_mesh)
+ */
+static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
-static struct attribute *libertas_mesh_sysfs_entries[] = {
+/**
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
+ */
+static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
+
+static struct attribute *lbs_mesh_sysfs_entries[] = {
&dev_attr_anycast_mask.attr,
- &dev_attr_autostart_enabled.attr,
NULL,
};
-static struct attribute_group libertas_mesh_attr_group = {
- .attrs = libertas_mesh_sysfs_entries,
+static struct attribute_group lbs_mesh_attr_group = {
+ .attrs = lbs_mesh_sysfs_entries,
};
/**
- * @brief Check if the device can be open and wait if necessary.
- *
- * @param dev A pointer to net_device structure
- * @return 0
- *
- * For USB adapter, on some systems the device open handler will be
- * called before FW ready. Use the following flag check and wait
- * function to work around the issue.
- *
- */
-static int pre_open_check(struct net_device *dev)
-{
- wlan_private *priv = (wlan_private *) dev->priv;
- wlan_adapter *adapter = priv->adapter;
- int i = 0;
-
- while (!adapter->fw_ready && i < 20) {
- i++;
- msleep_interruptible(100);
- }
- if (!adapter->fw_ready) {
- lbs_pr_err("firmware not ready\n");
- return -1;
- }
-
- return 0;
-}
-
-/**
- * @brief This function opens the device
+ * @brief This function opens the ethX or mshX interface
*
* @param dev A pointer to net_device structure
- * @return 0
+ * @return 0 or -EBUSY if monitor mode active
*/
-static int libertas_dev_open(struct net_device *dev)
+static int lbs_dev_open(struct net_device *dev)
{
- wlan_private *priv = (wlan_private *) dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv ;
+ int ret = 0;
lbs_deb_enter(LBS_DEB_NET);
- priv->open = 1;
+ spin_lock_irq(&priv->driver_lock);
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- netif_carrier_on(priv->dev);
- if (priv->mesh_dev)
- netif_carrier_on(priv->mesh_dev);
- } else {
- netif_carrier_off(priv->dev);
- if (priv->mesh_dev)
- netif_carrier_off(priv->mesh_dev);
+ if (priv->monitormode != LBS_MONITOR_OFF) {
+ ret = -EBUSY;
+ goto out;
}
- lbs_deb_leave(LBS_DEB_NET);
- return 0;
-}
-/**
- * @brief This function opens the mshX interface
- *
- * @param dev A pointer to net_device structure
- * @return 0
- */
-static int libertas_mesh_open(struct net_device *dev)
-{
- wlan_private *priv = (wlan_private *) dev->priv ;
-
- if (pre_open_check(dev) == -1)
- return -1;
- priv->mesh_open = 1 ;
- netif_wake_queue(priv->mesh_dev);
- if (priv->infra_open == 0)
- return libertas_dev_open(priv->dev) ;
- return 0;
-}
-
-/**
- * @brief This function opens the ethX interface
- *
- * @param dev A pointer to net_device structure
- * @return 0
- */
-static int libertas_open(struct net_device *dev)
-{
- wlan_private *priv = (wlan_private *) dev->priv ;
-
- if(pre_open_check(dev) == -1)
- return -1;
- priv->infra_open = 1 ;
- netif_wake_queue(priv->dev);
- if (priv->open == 0)
- return libertas_dev_open(priv->dev) ;
- return 0;
-}
-
-static int libertas_dev_close(struct net_device *dev)
-{
- wlan_private *priv = dev->priv;
+ if (dev == priv->mesh_dev) {
+ priv->mesh_open = 1;
+ priv->mesh_connect_status = LBS_CONNECTED;
+ netif_carrier_on(dev);
+ } else {
+ priv->infra_open = 1;
- lbs_deb_enter(LBS_DEB_NET);
+ if (priv->connect_status == LBS_CONNECTED)
+ netif_carrier_on(dev);
+ else
+ netif_carrier_off(dev);
+ }
- netif_carrier_off(priv->dev);
- priv->open = 0;
+ if (!priv->tx_pending_len)
+ netif_wake_queue(dev);
+ out:
- lbs_deb_leave(LBS_DEB_NET);
- return 0;
+ spin_unlock_irq(&priv->driver_lock);
+ lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+ return ret;
}
/**
@@ -476,16 +425,23 @@ static int libertas_dev_close(struct net_device *dev)
* @param dev A pointer to net_device structure
* @return 0
*/
-static int libertas_mesh_close(struct net_device *dev)
+static int lbs_mesh_stop(struct net_device *dev)
{
- wlan_private *priv = (wlan_private *) (dev->priv);
+ struct lbs_private *priv = (struct lbs_private *) (dev->priv);
+
+ lbs_deb_enter(LBS_DEB_MESH);
+ spin_lock_irq(&priv->driver_lock);
priv->mesh_open = 0;
- netif_stop_queue(priv->mesh_dev);
- if (priv->infra_open == 0)
- return libertas_dev_close(dev);
- else
- return 0;
+ priv->mesh_connect_status = LBS_DISCONNECTED;
+
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ spin_unlock_irq(&priv->driver_lock);
+
+ lbs_deb_leave(LBS_DEB_MESH);
+ return 0;
}
/**
@@ -494,134 +450,86 @@ static int libertas_mesh_close(struct net_device *dev)
* @param dev A pointer to net_device structure
* @return 0
*/
-static int libertas_close(struct net_device *dev)
-{
- wlan_private *priv = (wlan_private *) dev->priv;
-
- netif_stop_queue(dev);
- priv->infra_open = 0;
- if (priv->mesh_open == 0)
- return libertas_dev_close(dev);
- else
- return 0;
-}
-
-
-static int libertas_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int lbs_eth_stop(struct net_device *dev)
{
- int ret = 0;
- wlan_private *priv = dev->priv;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
lbs_deb_enter(LBS_DEB_NET);
- if (priv->dnld_sent || priv->adapter->TxLockFlag) {
- priv->stats.tx_dropped++;
- goto done;
- }
-
- netif_stop_queue(priv->dev);
- if (priv->mesh_dev)
- netif_stop_queue(priv->mesh_dev);
+ spin_lock_irq(&priv->driver_lock);
+ priv->infra_open = 0;
+ netif_stop_queue(dev);
+ spin_unlock_irq(&priv->driver_lock);
- if (libertas_process_tx(priv, skb) == 0)
- dev->trans_start = jiffies;
-done:
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
+ lbs_deb_leave(LBS_DEB_NET);
+ return 0;
}
-/**
- * @brief Mark mesh packets and handover them to libertas_hard_start_xmit
- *
- */
-static int libertas_mesh_pre_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
+static void lbs_tx_timeout(struct net_device *dev)
{
- wlan_private *priv = dev->priv;
- int ret;
-
- lbs_deb_enter(LBS_DEB_MESH);
- if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
- netif_stop_queue(dev);
- return -EOPNOTSUPP;
- }
-
- SET_MESH_FRAME(skb);
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
- ret = libertas_hard_start_xmit(skb, priv->dev);
- lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
- return ret;
-}
+ lbs_deb_enter(LBS_DEB_TX);
-/**
- * @brief Mark non-mesh packets and handover them to libertas_hard_start_xmit
- *
- */
-static int libertas_pre_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- wlan_private *priv = dev->priv;
- int ret;
+ lbs_pr_err("tx watch dog timeout\n");
- lbs_deb_enter(LBS_DEB_NET);
+ dev->trans_start = jiffies;
- if(priv->adapter->monitormode != WLAN_MONITOR_OFF) {
- netif_stop_queue(dev);
- return -EOPNOTSUPP;
+ if (priv->currenttxskb) {
+ priv->eventcause = 0x01000000;
+ lbs_send_tx_feedback(priv);
}
+ /* XX: Shouldn't we also call into the hw-specific driver
+ to kick it somehow? */
+ lbs_host_to_card_done(priv);
- UNSET_MESH_FRAME(skb);
+ /* More often than not, this actually happens because the
+ firmware has crapped itself -- rather than just a very
+ busy medium. So send a harmless command, and if/when
+ _that_ times out, we'll kick it in the head. */
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ 0, 0, NULL);
- ret = libertas_hard_start_xmit(skb, dev);
- lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
- return ret;
+ lbs_deb_leave(LBS_DEB_TX);
}
-static void libertas_tx_timeout(struct net_device *dev)
+void lbs_host_to_card_done(struct lbs_private *priv)
{
- wlan_private *priv = (wlan_private *) dev->priv;
+ unsigned long flags;
- lbs_deb_enter(LBS_DEB_TX);
+ lbs_deb_enter(LBS_DEB_THREAD);
- lbs_pr_err("tx watch dog timeout\n");
+ spin_lock_irqsave(&priv->driver_lock, flags);
priv->dnld_sent = DNLD_RES_RECEIVED;
- dev->trans_start = jiffies;
- if (priv->adapter->currenttxskb) {
- if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
- /* If we are here, we have not received feedback from
- the previous packet. Assume TX_FAIL and move on. */
- priv->adapter->eventcause = 0x01000000;
- libertas_send_tx_feedback(priv);
- } else
- wake_up_interruptible(&priv->waitq);
- } else if (priv->adapter->connect_status == LIBERTAS_CONNECTED) {
- netif_wake_queue(priv->dev);
- if (priv->mesh_dev)
- netif_wake_queue(priv->mesh_dev);
- }
+ /* Wake main thread if commands are pending */
+ if (!priv->cur_cmd || priv->tx_pending_len > 0)
+ wake_up_interruptible(&priv->waitq);
- lbs_deb_leave(LBS_DEB_TX);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ lbs_deb_leave(LBS_DEB_THREAD);
}
+EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
/**
* @brief This function returns the network statistics
*
- * @param dev A pointer to wlan_private structure
+ * @param dev A pointer to struct lbs_private structure
* @return A pointer to net_device_stats structure
*/
-static struct net_device_stats *libertas_get_stats(struct net_device *dev)
+static struct net_device_stats *lbs_get_stats(struct net_device *dev)
{
- wlan_private *priv = (wlan_private *) dev->priv;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ lbs_deb_enter(LBS_DEB_NET);
return &priv->stats;
}
-static int libertas_set_mac_address(struct net_device *dev, void *addr)
+static int lbs_set_mac_address(struct net_device *dev, void *addr)
{
int ret = 0;
- wlan_private *priv = (wlan_private *) dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = (struct lbs_private *) dev->priv;
struct sockaddr *phwaddr = addr;
lbs_deb_enter(LBS_DEB_NET);
@@ -629,15 +537,15 @@ static int libertas_set_mac_address(struct net_device *dev, void *addr)
/* In case it was called from the mesh device */
dev = priv->dev ;
- memset(adapter->current_addr, 0, ETH_ALEN);
+ memset(priv->current_addr, 0, ETH_ALEN);
/* dev->dev_addr is 8 bytes */
lbs_deb_hex(LBS_DEB_NET, "dev->dev_addr", dev->dev_addr, ETH_ALEN);
lbs_deb_hex(LBS_DEB_NET, "addr", phwaddr->sa_data, ETH_ALEN);
- memcpy(adapter->current_addr, phwaddr->sa_data, ETH_ALEN);
+ memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_MAC_ADDRESS,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP, 0, NULL);
@@ -647,89 +555,86 @@ static int libertas_set_mac_address(struct net_device *dev, void *addr)
goto done;
}
- lbs_deb_hex(LBS_DEB_NET, "adapter->macaddr", adapter->current_addr, ETH_ALEN);
- memcpy(dev->dev_addr, adapter->current_addr, ETH_ALEN);
+ lbs_deb_hex(LBS_DEB_NET, "priv->macaddr", priv->current_addr, ETH_ALEN);
+ memcpy(dev->dev_addr, priv->current_addr, ETH_ALEN);
if (priv->mesh_dev)
- memcpy(priv->mesh_dev->dev_addr, adapter->current_addr, ETH_ALEN);
+ memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
done:
lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
return ret;
}
-static int libertas_copy_multicast_address(wlan_adapter * adapter,
+static int lbs_copy_multicast_address(struct lbs_private *priv,
struct net_device *dev)
{
int i = 0;
struct dev_mc_list *mcptr = dev->mc_list;
for (i = 0; i < dev->mc_count; i++) {
- memcpy(&adapter->multicastlist[i], mcptr->dmi_addr, ETH_ALEN);
+ memcpy(&priv->multicastlist[i], mcptr->dmi_addr, ETH_ALEN);
mcptr = mcptr->next;
}
-
return i;
-
}
-static void libertas_set_multicast_list(struct net_device *dev)
+static void lbs_set_multicast_list(struct net_device *dev)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int oldpacketfilter;
DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_NET);
- oldpacketfilter = adapter->currentpacketfilter;
+ oldpacketfilter = priv->currentpacketfilter;
if (dev->flags & IFF_PROMISC) {
lbs_deb_net("enable promiscuous mode\n");
- adapter->currentpacketfilter |=
+ priv->currentpacketfilter |=
CMD_ACT_MAC_PROMISCUOUS_ENABLE;
- adapter->currentpacketfilter &=
+ priv->currentpacketfilter &=
~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE |
CMD_ACT_MAC_MULTICAST_ENABLE);
} else {
/* Multicast */
- adapter->currentpacketfilter &=
+ priv->currentpacketfilter &=
~CMD_ACT_MAC_PROMISCUOUS_ENABLE;
if (dev->flags & IFF_ALLMULTI || dev->mc_count >
MRVDRV_MAX_MULTICAST_LIST_SIZE) {
lbs_deb_net( "enabling all multicast\n");
- adapter->currentpacketfilter |=
+ priv->currentpacketfilter |=
CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
- adapter->currentpacketfilter &=
+ priv->currentpacketfilter &=
~CMD_ACT_MAC_MULTICAST_ENABLE;
} else {
- adapter->currentpacketfilter &=
+ priv->currentpacketfilter &=
~CMD_ACT_MAC_ALL_MULTICAST_ENABLE;
if (!dev->mc_count) {
lbs_deb_net("no multicast addresses, "
"disabling multicast\n");
- adapter->currentpacketfilter &=
+ priv->currentpacketfilter &=
~CMD_ACT_MAC_MULTICAST_ENABLE;
} else {
int i;
- adapter->currentpacketfilter |=
+ priv->currentpacketfilter |=
CMD_ACT_MAC_MULTICAST_ENABLE;
- adapter->nr_of_multicastmacaddr =
- libertas_copy_multicast_address(adapter, dev);
+ priv->nr_of_multicastmacaddr =
+ lbs_copy_multicast_address(priv, dev);
lbs_deb_net("multicast addresses: %d\n",
dev->mc_count);
for (i = 0; i < dev->mc_count; i++) {
- lbs_deb_net("Multicast address %d:%s\n",
+ lbs_deb_net("Multicast address %d: %s\n",
i, print_mac(mac,
- adapter->multicastlist[i]));
+ priv->multicastlist[i]));
}
/* send multicast addresses to firmware */
- libertas_prepare_and_send_command(priv,
+ lbs_prepare_and_send_command(priv,
CMD_MAC_MULTICAST_ADR,
CMD_ACT_SET, 0, 0,
NULL);
@@ -737,26 +642,25 @@ static void libertas_set_multicast_list(struct net_device *dev)
}
}
- if (adapter->currentpacketfilter != oldpacketfilter) {
- libertas_set_mac_packet_filter(priv);
+ if (priv->currentpacketfilter != oldpacketfilter) {
+ lbs_set_mac_packet_filter(priv);
}
lbs_deb_leave(LBS_DEB_NET);
}
/**
- * @brief This function handles the major jobs in the WLAN driver.
+ * @brief This function handles the major jobs in the LBS driver.
* It handles all events generated by firmware, RX data received
* from firmware and TX data sent from kernel.
*
- * @param data A pointer to wlan_thread structure
+ * @param data A pointer to lbs_thread structure
* @return 0
*/
-static int libertas_thread(void *data)
+static int lbs_thread(void *data)
{
struct net_device *dev = data;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
wait_queue_t wait;
u8 ireg = 0;
@@ -764,215 +668,291 @@ static int libertas_thread(void *data)
init_waitqueue_entry(&wait, current);
- set_freezable();
for (;;) {
- lbs_deb_thread( "main-thread 111: intcounter=%d "
- "currenttxskb=%p dnld_sent=%d\n",
- adapter->intcounter,
- adapter->currenttxskb, priv->dnld_sent);
+ int shouldsleep;
+
+ lbs_deb_thread( "main-thread 111: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+ priv->intcounter, priv->currenttxskb, priv->dnld_sent);
add_wait_queue(&priv->waitq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- spin_lock_irq(&adapter->driver_lock);
- if ((adapter->psstate == PS_STATE_SLEEP) ||
- (!adapter->intcounter
- && (priv->dnld_sent || adapter->cur_cmd ||
- list_empty(&adapter->cmdpendingq)))) {
- lbs_deb_thread(
- "main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
- adapter->connect_status, adapter->intcounter,
- adapter->psmode, adapter->psstate);
- spin_unlock_irq(&adapter->driver_lock);
+ spin_lock_irq(&priv->driver_lock);
+
+ if (kthread_should_stop())
+ shouldsleep = 0; /* Bye */
+ else if (priv->surpriseremoved)
+ shouldsleep = 1; /* We need to wait until we're _told_ to die */
+ else if (priv->psstate == PS_STATE_SLEEP)
+ shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */
+ else if (priv->intcounter)
+ shouldsleep = 0; /* Interrupt pending. Deal with it now */
+ else if (priv->cmd_timed_out)
+ shouldsleep = 0; /* Command timed out. Recover */
+ else if (!priv->fw_ready)
+ shouldsleep = 1; /* Firmware not ready. We're waiting for it */
+ else if (priv->dnld_sent)
+ shouldsleep = 1; /* Something is en route to the device already */
+ else if (priv->tx_pending_len > 0)
+ shouldsleep = 0; /* We've a packet to send */
+ else if (priv->cur_cmd)
+ shouldsleep = 1; /* Can't send a command; one already running */
+ else if (!list_empty(&priv->cmdpendingq))
+ shouldsleep = 0; /* We have a command to send */
+ else
+ shouldsleep = 1; /* No command */
+
+ if (shouldsleep) {
+ lbs_deb_thread("main-thread sleeping... Conn=%d IntC=%d PS_mode=%d PS_State=%d\n",
+ priv->connect_status, priv->intcounter,
+ priv->psmode, priv->psstate);
+ spin_unlock_irq(&priv->driver_lock);
schedule();
} else
- spin_unlock_irq(&adapter->driver_lock);
+ spin_unlock_irq(&priv->driver_lock);
- lbs_deb_thread(
- "main-thread 222 (waking up): intcounter=%d currenttxskb=%p "
- "dnld_sent=%d\n", adapter->intcounter,
- adapter->currenttxskb, priv->dnld_sent);
+ lbs_deb_thread("main-thread 222 (waking up): intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+ priv->intcounter, priv->currenttxskb, priv->dnld_sent);
set_current_state(TASK_RUNNING);
remove_wait_queue(&priv->waitq, &wait);
- try_to_freeze();
-
- lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p "
- "dnld_sent=%d\n",
- adapter->intcounter,
- adapter->currenttxskb, priv->dnld_sent);
-
- if (kthread_should_stop()
- || adapter->surpriseremoved) {
- lbs_deb_thread(
- "main-thread: break from main thread: surpriseremoved=0x%x\n",
- adapter->surpriseremoved);
+
+ lbs_deb_thread("main-thread 333: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+ priv->intcounter, priv->currenttxskb, priv->dnld_sent);
+
+ if (kthread_should_stop()) {
+ lbs_deb_thread("main-thread: break from main thread\n");
break;
}
+ if (priv->surpriseremoved) {
+ lbs_deb_thread("adapter removed; waiting to die...\n");
+ continue;
+ }
+
+ spin_lock_irq(&priv->driver_lock);
- spin_lock_irq(&adapter->driver_lock);
- if (adapter->intcounter) {
+ if (priv->intcounter) {
u8 int_status;
- adapter->intcounter = 0;
+
+ priv->intcounter = 0;
int_status = priv->hw_get_int_status(priv, &ireg);
if (int_status) {
- lbs_deb_thread(
- "main-thread: reading HOST_INT_STATUS_REG failed\n");
- spin_unlock_irq(&adapter->driver_lock);
+ lbs_deb_thread("main-thread: reading HOST_INT_STATUS_REG failed\n");
+ spin_unlock_irq(&priv->driver_lock);
continue;
}
- adapter->hisregcpy |= ireg;
+ priv->hisregcpy |= ireg;
}
- lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p "
- "dnld_sent=%d\n",
- adapter->intcounter,
- adapter->currenttxskb, priv->dnld_sent);
+ lbs_deb_thread("main-thread 444: intcounter=%d currenttxskb=%p dnld_sent=%d\n",
+ priv->intcounter, priv->currenttxskb, priv->dnld_sent);
/* command response? */
- if (adapter->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
+ if (priv->hisregcpy & MRVDRV_CMD_UPLD_RDY) {
lbs_deb_thread("main-thread: cmd response ready\n");
- adapter->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
- spin_unlock_irq(&adapter->driver_lock);
- libertas_process_rx_command(priv);
- spin_lock_irq(&adapter->driver_lock);
+ priv->hisregcpy &= ~MRVDRV_CMD_UPLD_RDY;
+ spin_unlock_irq(&priv->driver_lock);
+ lbs_process_rx_command(priv);
+ spin_lock_irq(&priv->driver_lock);
}
+ if (priv->cmd_timed_out && priv->cur_cmd) {
+ struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
+
+ if (++priv->nr_retries > 10) {
+ lbs_pr_info("Excessive timeouts submitting command %x\n",
+ le16_to_cpu(cmdnode->cmdbuf->command));
+ lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
+ priv->nr_retries = 0;
+ } else {
+ priv->cur_cmd = NULL;
+ lbs_pr_info("requeueing command %x due to timeout (#%d)\n",
+ le16_to_cpu(cmdnode->cmdbuf->command), priv->nr_retries);
+
+ /* Stick it back at the _top_ of the pending queue
+ for immediate resubmission */
+ list_add(&cmdnode->list, &priv->cmdpendingq);
+ }
+ }
+ priv->cmd_timed_out = 0;
+
/* Any Card Event */
- if (adapter->hisregcpy & MRVDRV_CARDEVENT) {
+ if (priv->hisregcpy & MRVDRV_CARDEVENT) {
lbs_deb_thread("main-thread: Card Event Activity\n");
- adapter->hisregcpy &= ~MRVDRV_CARDEVENT;
+ priv->hisregcpy &= ~MRVDRV_CARDEVENT;
if (priv->hw_read_event_cause(priv)) {
- lbs_pr_alert(
- "main-thread: hw_read_event_cause failed\n");
- spin_unlock_irq(&adapter->driver_lock);
+ lbs_pr_alert("main-thread: hw_read_event_cause failed\n");
+ spin_unlock_irq(&priv->driver_lock);
continue;
}
- spin_unlock_irq(&adapter->driver_lock);
- libertas_process_event(priv);
+ spin_unlock_irq(&priv->driver_lock);
+ lbs_process_event(priv);
} else
- spin_unlock_irq(&adapter->driver_lock);
+ spin_unlock_irq(&priv->driver_lock);
+
+ if (!priv->fw_ready)
+ continue;
/* Check if we need to confirm Sleep Request received previously */
- if (adapter->psstate == PS_STATE_PRE_SLEEP) {
- if (!priv->dnld_sent && !adapter->cur_cmd) {
- if (adapter->connect_status ==
- LIBERTAS_CONNECTED) {
- lbs_deb_thread(
- "main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p "
- "dnld_sent=%d cur_cmd=%p, confirm now\n",
- adapter->intcounter,
- adapter->currenttxskb,
- priv->dnld_sent,
- adapter->cur_cmd);
-
- libertas_ps_confirm_sleep(priv,
- (u16) adapter->psmode);
- } else {
- /* workaround for firmware sending
- * deauth/linkloss event immediately
- * after sleep request, remove this
- * after firmware fixes it
- */
- adapter->psstate = PS_STATE_AWAKE;
- lbs_pr_alert(
- "main-thread: ignore PS_SleepConfirm in non-connected state\n");
- }
+ if (priv->psstate == PS_STATE_PRE_SLEEP &&
+ !priv->dnld_sent && !priv->cur_cmd) {
+ if (priv->connect_status == LBS_CONNECTED) {
+ lbs_deb_thread("main_thread: PRE_SLEEP--intcounter=%d currenttxskb=%p dnld_sent=%d cur_cmd=%p, confirm now\n",
+ priv->intcounter, priv->currenttxskb, priv->dnld_sent, priv->cur_cmd);
+
+ lbs_ps_confirm_sleep(priv, (u16) priv->psmode);
+ } else {
+ /* workaround for firmware sending
+ * deauth/linkloss event immediately
+ * after sleep request; remove this
+ * after firmware fixes it
+ */
+ priv->psstate = PS_STATE_AWAKE;
+ lbs_pr_alert("main-thread: ignore PS_SleepConfirm in non-connected state\n");
}
}
/* The PS state is changed during processing of Sleep Request
* event above
*/
- if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
- (priv->adapter->psstate == PS_STATE_PRE_SLEEP))
+ if ((priv->psstate == PS_STATE_SLEEP) ||
+ (priv->psstate == PS_STATE_PRE_SLEEP))
continue;
/* Execute the next command */
- if (!priv->dnld_sent && !priv->adapter->cur_cmd)
- libertas_execute_next_command(priv);
+ if (!priv->dnld_sent && !priv->cur_cmd)
+ lbs_execute_next_command(priv);
/* Wake-up command waiters which can't sleep in
- * libertas_prepare_and_send_command
+ * lbs_prepare_and_send_command
*/
- if (!adapter->nr_cmd_pending)
- wake_up_all(&adapter->cmd_pending);
-
- libertas_tx_runqueue(priv);
+ if (!list_empty(&priv->cmdpendingq))
+ wake_up_all(&priv->cmd_pending);
+
+ spin_lock_irq(&priv->driver_lock);
+ if (!priv->dnld_sent && priv->tx_pending_len > 0) {
+ int ret = priv->hw_host_to_card(priv, MVMS_DAT,
+ priv->tx_pending_buf,
+ priv->tx_pending_len);
+ if (ret) {
+ lbs_deb_tx("host_to_card failed %d\n", ret);
+ priv->dnld_sent = DNLD_RES_RECEIVED;
+ }
+ priv->tx_pending_len = 0;
+ if (!priv->currenttxskb) {
+ /* We can wake the queues immediately if we aren't
+ waiting for TX feedback */
+ if (priv->connect_status == LBS_CONNECTED)
+ netif_wake_queue(priv->dev);
+ if (priv->mesh_dev &&
+ priv->mesh_connect_status == LBS_CONNECTED)
+ netif_wake_queue(priv->mesh_dev);
+ }
+ }
+ spin_unlock_irq(&priv->driver_lock);
}
- del_timer(&adapter->command_timer);
- adapter->nr_cmd_pending = 0;
- wake_up_all(&adapter->cmd_pending);
+ del_timer(&priv->command_timer);
+ wake_up_all(&priv->cmd_pending);
lbs_deb_leave(LBS_DEB_THREAD);
return 0;
}
+static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
+ struct cmd_header *cmd)
+{
+ lbs_deb_enter(LBS_DEB_FW);
+
+ netif_device_detach(priv->dev);
+ if (priv->mesh_dev)
+ netif_device_detach(priv->mesh_dev);
+
+ priv->fw_ready = 0;
+ lbs_deb_leave(LBS_DEB_FW);
+ return 0;
+}
+
+int lbs_suspend(struct lbs_private *priv)
+{
+ struct cmd_header cmd;
+ int ret;
+
+ lbs_deb_enter(LBS_DEB_FW);
+
+ if (priv->wol_criteria == 0xffffffff) {
+ lbs_pr_info("Suspend attempt without configuring wake params!\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd, 0, sizeof(cmd));
+
+ ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
+ sizeof(cmd), lbs_suspend_callback, 0);
+ if (ret)
+ lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
+
+ lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(lbs_suspend);
+
+int lbs_resume(struct lbs_private *priv)
+{
+ lbs_deb_enter(LBS_DEB_FW);
+
+ priv->fw_ready = 1;
+
+ /* Firmware doesn't seem to give us RX packets any more
+ until we send it some command. Might as well update */
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ 0, 0, NULL);
+
+ netif_device_attach(priv->dev);
+ if (priv->mesh_dev)
+ netif_device_attach(priv->mesh_dev);
+
+ lbs_deb_leave(LBS_DEB_FW);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(lbs_resume);
+
/**
* @brief This function downloads firmware image, gets
* HW spec from firmware and set basic parameters to
* firmware.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return 0 or -1
*/
-static int wlan_setup_firmware(wlan_private * priv)
+static int lbs_setup_firmware(struct lbs_private *priv)
{
int ret = -1;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ds_mesh_access mesh_access;
lbs_deb_enter(LBS_DEB_FW);
/*
* Read MAC address from HW
*/
- memset(adapter->current_addr, 0xff, ETH_ALEN);
-
- ret = libertas_prepare_and_send_command(priv, CMD_GET_HW_SPEC,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-
+ memset(priv->current_addr, 0xff, ETH_ALEN);
+ ret = lbs_update_hw_spec(priv);
if (ret) {
ret = -1;
goto done;
}
- libertas_set_mac_packet_filter(priv);
-
- /* Get the supported Data rates */
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
- CMD_ACT_GET_TX_RATE,
- CMD_OPTION_WAITFORRSP, 0, NULL);
+ lbs_set_mac_packet_filter(priv);
- if (ret) {
+ ret = lbs_get_data_rate(priv);
+ if (ret < 0) {
ret = -1;
goto done;
}
- /* Disable mesh autostart */
- if (priv->mesh_dev) {
- memset(&mesh_access, 0, sizeof(mesh_access));
- mesh_access.data[0] = cpu_to_le32(0);
- ret = libertas_prepare_and_send_command(priv,
- CMD_MESH_ACCESS,
- CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
- CMD_OPTION_WAITFORRSP, 0, (void *)&mesh_access);
- if (ret) {
- ret = -1;
- goto done;
- }
- priv->mesh_autostart_enabled = 0;
- }
-
- /* Set the boot2 version in firmware */
- ret = libertas_prepare_and_send_command(priv, CMD_SET_BOOT2_VER,
- 0, CMD_OPTION_WAITFORRSP, 0, NULL);
-
ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -985,164 +965,130 @@ done:
*/
static void command_timer_fn(unsigned long data)
{
- wlan_private *priv = (wlan_private *)data;
- wlan_adapter *adapter = priv->adapter;
- struct cmd_ctrl_node *ptempnode;
- struct cmd_ds_command *cmd;
+ struct lbs_private *priv = (struct lbs_private *)data;
unsigned long flags;
- ptempnode = adapter->cur_cmd;
- if (ptempnode == NULL) {
- lbs_deb_fw("ptempnode empty\n");
- return;
- }
+ lbs_deb_enter(LBS_DEB_CMD);
+ spin_lock_irqsave(&priv->driver_lock, flags);
- cmd = (struct cmd_ds_command *)ptempnode->bufvirtualaddr;
- if (!cmd) {
- lbs_deb_fw("cmd is NULL\n");
- return;
+ if (!priv->cur_cmd) {
+ lbs_pr_info("Command timer expired; no pending command\n");
+ goto out;
}
- lbs_deb_fw("command_timer_fn fired, cmd %x\n", cmd->command);
-
- if (!adapter->fw_ready)
- return;
-
- spin_lock_irqsave(&adapter->driver_lock, flags);
- adapter->cur_cmd = NULL;
- spin_unlock_irqrestore(&adapter->driver_lock, flags);
-
- lbs_deb_fw("re-sending same command because of timeout\n");
- libertas_queue_cmd(adapter, ptempnode, 0);
+ lbs_pr_info("Command %x timed out\n", le16_to_cpu(priv->cur_cmd->cmdbuf->command));
+ priv->cmd_timed_out = 1;
wake_up_interruptible(&priv->waitq);
-
- return;
+out:
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ lbs_deb_leave(LBS_DEB_CMD);
}
-static int libertas_init_adapter(wlan_private * priv)
+static int lbs_init_adapter(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
size_t bufsize;
int i, ret = 0;
+ lbs_deb_enter(LBS_DEB_MAIN);
+
/* Allocate buffer to store the BSSID list */
bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
- adapter->networks = kzalloc(bufsize, GFP_KERNEL);
- if (!adapter->networks) {
+ priv->networks = kzalloc(bufsize, GFP_KERNEL);
+ if (!priv->networks) {
lbs_pr_err("Out of memory allocating beacons\n");
ret = -1;
goto out;
}
/* Initialize scan result lists */
- INIT_LIST_HEAD(&adapter->network_free_list);
- INIT_LIST_HEAD(&adapter->network_list);
+ INIT_LIST_HEAD(&priv->network_free_list);
+ INIT_LIST_HEAD(&priv->network_list);
for (i = 0; i < MAX_NETWORK_COUNT; i++) {
- list_add_tail(&adapter->networks[i].list,
- &adapter->network_free_list);
+ list_add_tail(&priv->networks[i].list,
+ &priv->network_free_list);
}
- adapter->libertas_ps_confirm_sleep.seqnum = cpu_to_le16(++adapter->seqnum);
- adapter->libertas_ps_confirm_sleep.command =
+ priv->lbs_ps_confirm_sleep.seqnum = cpu_to_le16(++priv->seqnum);
+ priv->lbs_ps_confirm_sleep.command =
cpu_to_le16(CMD_802_11_PS_MODE);
- adapter->libertas_ps_confirm_sleep.size =
+ priv->lbs_ps_confirm_sleep.size =
cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
- adapter->libertas_ps_confirm_sleep.action =
+ priv->lbs_ps_confirm_sleep.action =
cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
- memset(adapter->current_addr, 0xff, ETH_ALEN);
-
- adapter->connect_status = LIBERTAS_DISCONNECTED;
- adapter->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
- adapter->mode = IW_MODE_INFRA;
- adapter->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
- adapter->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
- adapter->radioon = RADIO_ON;
- adapter->auto_rate = 1;
- adapter->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
- adapter->psmode = WLAN802_11POWERMODECAM;
- adapter->psstate = PS_STATE_FULL_POWER;
+ memset(priv->current_addr, 0xff, ETH_ALEN);
- mutex_init(&adapter->lock);
+ priv->connect_status = LBS_DISCONNECTED;
+ priv->mesh_connect_status = LBS_DISCONNECTED;
+ priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
+ priv->mode = IW_MODE_INFRA;
+ priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
+ priv->currentpacketfilter = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
+ priv->radioon = RADIO_ON;
+ priv->auto_rate = 1;
+ priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
+ priv->psmode = LBS802_11POWERMODECAM;
+ priv->psstate = PS_STATE_FULL_POWER;
- memset(&adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
- adapter->tx_queue_idx = 0;
- spin_lock_init(&adapter->txqueue_lock);
+ mutex_init(&priv->lock);
- setup_timer(&adapter->command_timer, command_timer_fn,
- (unsigned long)priv);
+ setup_timer(&priv->command_timer, command_timer_fn,
+ (unsigned long)priv);
- INIT_LIST_HEAD(&adapter->cmdfreeq);
- INIT_LIST_HEAD(&adapter->cmdpendingq);
+ INIT_LIST_HEAD(&priv->cmdfreeq);
+ INIT_LIST_HEAD(&priv->cmdpendingq);
- spin_lock_init(&adapter->driver_lock);
- init_waitqueue_head(&adapter->cmd_pending);
- adapter->nr_cmd_pending = 0;
+ spin_lock_init(&priv->driver_lock);
+ init_waitqueue_head(&priv->cmd_pending);
/* Allocate the command buffers */
- if (libertas_allocate_cmd_buffer(priv)) {
+ if (lbs_allocate_cmd_buffer(priv)) {
lbs_pr_err("Out of memory allocating command buffers\n");
ret = -1;
}
out:
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+
return ret;
}
-static void libertas_free_adapter(wlan_private * priv)
+static void lbs_free_adapter(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
-
- if (!adapter) {
- lbs_deb_fw("why double free adapter?\n");
- return;
- }
-
- lbs_deb_fw("free command buffer\n");
- libertas_free_cmd_buffer(priv);
-
- lbs_deb_fw("free command_timer\n");
- del_timer(&adapter->command_timer);
+ lbs_deb_enter(LBS_DEB_MAIN);
- lbs_deb_fw("free scan results table\n");
- kfree(adapter->networks);
- adapter->networks = NULL;
+ lbs_free_cmd_buffer(priv);
+ del_timer(&priv->command_timer);
+ kfree(priv->networks);
+ priv->networks = NULL;
- /* Free the adapter object itself */
- lbs_deb_fw("free adapter\n");
- kfree(adapter);
- priv->adapter = NULL;
+ lbs_deb_leave(LBS_DEB_MAIN);
}
/**
* @brief This function adds the card. it will probe the
- * card, allocate the wlan_priv and initialize the device.
+ * card, allocate the lbs_priv and initialize the device.
*
* @param card A pointer to card
- * @return A pointer to wlan_private structure
+ * @return A pointer to struct lbs_private structure
*/
-wlan_private *libertas_add_card(void *card, struct device *dmdev)
+struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
{
struct net_device *dev = NULL;
- wlan_private *priv = NULL;
+ struct lbs_private *priv = NULL;
- lbs_deb_enter(LBS_DEB_NET);
+ lbs_deb_enter(LBS_DEB_MAIN);
/* Allocate an Ethernet device and register it */
- if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
+ dev = alloc_etherdev(sizeof(struct lbs_private));
+ if (!dev) {
lbs_pr_err("init ethX device failed\n");
goto done;
}
priv = dev->priv;
- /* allocate buffer for wlan_adapter */
- if (!(priv->adapter = kzalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
- lbs_pr_err("allocate buffer for wlan_adapter failed\n");
- goto err_kzalloc;
- }
-
- if (libertas_init_adapter(priv)) {
+ if (lbs_init_adapter(priv)) {
lbs_pr_err("failed to initialize adapter structure.\n");
goto err_init_adapter;
}
@@ -1151,81 +1097,78 @@ wlan_private *libertas_add_card(void *card, struct device *dmdev)
priv->card = card;
priv->mesh_open = 0;
priv->infra_open = 0;
- priv->hotplug_device = dmdev;
/* Setup the OS Interface to our functions */
- dev->open = libertas_open;
- dev->hard_start_xmit = libertas_pre_start_xmit;
- dev->stop = libertas_close;
- dev->set_mac_address = libertas_set_mac_address;
- dev->tx_timeout = libertas_tx_timeout;
- dev->get_stats = libertas_get_stats;
+ dev->open = lbs_dev_open;
+ dev->hard_start_xmit = lbs_hard_start_xmit;
+ dev->stop = lbs_eth_stop;
+ dev->set_mac_address = lbs_set_mac_address;
+ dev->tx_timeout = lbs_tx_timeout;
+ dev->get_stats = lbs_get_stats;
dev->watchdog_timeo = 5 * HZ;
- dev->ethtool_ops = &libertas_ethtool_ops;
+ dev->ethtool_ops = &lbs_ethtool_ops;
#ifdef WIRELESS_EXT
- dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
+ dev->wireless_handlers = (struct iw_handler_def *)&lbs_handler_def;
#endif
dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
- dev->set_multicast_list = libertas_set_multicast_list;
+ dev->set_multicast_list = lbs_set_multicast_list;
SET_NETDEV_DEV(dev, dmdev);
priv->rtap_net_dev = NULL;
- if (device_create_file(dmdev, &dev_attr_libertas_rtap))
- goto err_init_adapter;
lbs_deb_thread("Starting main thread...\n");
init_waitqueue_head(&priv->waitq);
- priv->main_thread = kthread_run(libertas_thread, dev, "libertas_main");
+ priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
if (IS_ERR(priv->main_thread)) {
lbs_deb_thread("Error creating main thread.\n");
- goto err_kthread_run;
+ goto err_init_adapter;
}
- priv->work_thread = create_singlethread_workqueue("libertas_worker");
- INIT_DELAYED_WORK(&priv->assoc_work, libertas_association_worker);
- INIT_DELAYED_WORK(&priv->scan_work, libertas_scan_worker);
- INIT_WORK(&priv->sync_channel, libertas_sync_channel);
+ priv->work_thread = create_singlethread_workqueue("lbs_worker");
+ INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
+ INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
+ INIT_WORK(&priv->sync_channel, lbs_sync_channel);
- goto done;
+ sprintf(priv->mesh_ssid, "mesh");
+ priv->mesh_ssid_len = 4;
-err_kthread_run:
- device_remove_file(dmdev, &dev_attr_libertas_rtap);
+ priv->wol_criteria = 0xffffffff;
+ priv->wol_gpio = 0xff;
-err_init_adapter:
- libertas_free_adapter(priv);
+ goto done;
-err_kzalloc:
+err_init_adapter:
+ lbs_free_adapter(priv);
free_netdev(dev);
priv = NULL;
done:
- lbs_deb_leave_args(LBS_DEB_NET, "priv %p", priv);
+ lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv);
return priv;
}
-EXPORT_SYMBOL_GPL(libertas_add_card);
+EXPORT_SYMBOL_GPL(lbs_add_card);
-int libertas_remove_card(wlan_private *priv)
+int lbs_remove_card(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
struct net_device *dev = priv->dev;
union iwreq_data wrqu;
lbs_deb_enter(LBS_DEB_MAIN);
- libertas_remove_rtap(priv);
+ lbs_remove_mesh(priv);
+ lbs_remove_rtap(priv);
dev = priv->dev;
- device_remove_file(priv->hotplug_device, &dev_attr_libertas_rtap);
cancel_delayed_work(&priv->scan_work);
cancel_delayed_work(&priv->assoc_work);
destroy_workqueue(priv->work_thread);
- if (adapter->psmode == WLAN802_11POWERMODEMAX_PSP) {
- adapter->psmode = WLAN802_11POWERMODECAM;
- libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
+ if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
+ priv->psmode = LBS802_11POWERMODECAM;
+ lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
}
memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
@@ -1233,10 +1176,10 @@ int libertas_remove_card(wlan_private *priv)
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
/* Stop the thread servicing the interrupts */
- adapter->surpriseremoved = 1;
+ priv->surpriseremoved = 1;
kthread_stop(priv->main_thread);
- libertas_free_adapter(priv);
+ lbs_free_adapter(priv);
priv->dev = NULL;
free_netdev(dev);
@@ -1244,10 +1187,10 @@ int libertas_remove_card(wlan_private *priv)
lbs_deb_leave(LBS_DEB_MAIN);
return 0;
}
-EXPORT_SYMBOL_GPL(libertas_remove_card);
+EXPORT_SYMBOL_GPL(lbs_remove_card);
-int libertas_start_card(wlan_private *priv)
+int lbs_start_card(struct lbs_private *priv)
{
struct net_device *dev = priv->dev;
int ret = -1;
@@ -1255,19 +1198,52 @@ int libertas_start_card(wlan_private *priv)
lbs_deb_enter(LBS_DEB_MAIN);
/* poke the firmware */
- ret = wlan_setup_firmware(priv);
+ ret = lbs_setup_firmware(priv);
if (ret)
goto done;
/* init 802.11d */
- libertas_init_11d(priv);
+ lbs_init_11d(priv);
if (register_netdev(dev)) {
lbs_pr_err("cannot register ethX device\n");
goto done;
}
+ if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
+ lbs_pr_err("cannot register lbs_rtap attribute\n");
+
+ lbs_update_channel(priv);
+
+ /* 5.0.16p0 is known to NOT support any mesh */
+ if (priv->fwrelease > 0x05001000) {
+ /* Enable mesh, if supported, and work out which TLV it uses.
+ 0x100 + 291 is an unofficial value used in 5.110.20.pXX
+ 0x100 + 37 is the official value used in 5.110.21.pXX
+ but we check them in that order because 20.pXX doesn't
+ give an error -- it just silently fails. */
+
+ /* 5.110.20.pXX firmware will fail the command if the channel
+ doesn't match the existing channel. But only if the TLV
+ is correct. If the channel is wrong, _BOTH_ versions will
+ give an error to 0x100+291, and allow 0x100+37 to succeed.
+ It's just that 5.110.20.pXX will not have done anything
+ useful */
+
+ priv->mesh_tlv = 0x100 + 291;
+ if (lbs_mesh_config(priv, 1, priv->curbssparams.channel)) {
+ priv->mesh_tlv = 0x100 + 37;
+ if (lbs_mesh_config(priv, 1, priv->curbssparams.channel))
+ priv->mesh_tlv = 0;
+ }
+ if (priv->mesh_tlv) {
+ lbs_add_mesh(priv);
- libertas_debugfs_init_one(priv, dev);
+ if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
+ lbs_pr_err("cannot register lbs_mesh attribute\n");
+ }
+ }
+
+ lbs_debugfs_init_one(priv, dev);
lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@@ -1277,10 +1253,10 @@ done:
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_start_card);
+EXPORT_SYMBOL_GPL(lbs_start_card);
-int libertas_stop_card(wlan_private *priv)
+int lbs_stop_card(struct lbs_private *priv)
{
struct net_device *dev = priv->dev;
int ret = -1;
@@ -1292,31 +1268,35 @@ int libertas_stop_card(wlan_private *priv)
netif_stop_queue(priv->dev);
netif_carrier_off(priv->dev);
- libertas_debugfs_remove_one(priv);
+ lbs_debugfs_remove_one(priv);
+ device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
+ if (priv->mesh_tlv)
+ device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
/* Flush pending command nodes */
- spin_lock_irqsave(&priv->adapter->driver_lock, flags);
- list_for_each_entry(cmdnode, &priv->adapter->cmdpendingq, list) {
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
+ cmdnode->result = -ENOENT;
cmdnode->cmdwaitqwoken = 1;
wake_up_interruptible(&cmdnode->cmdwait_q);
}
- spin_unlock_irqrestore(&priv->adapter->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
unregister_netdev(dev);
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_stop_card);
+EXPORT_SYMBOL_GPL(lbs_stop_card);
/**
* @brief This function adds mshX interface
*
- * @param priv A pointer to the wlan_private structure
+ * @param priv A pointer to the struct lbs_private structure
* @return 0 if successful, -X otherwise
*/
-int libertas_add_mesh(wlan_private *priv, struct device *dev)
+static int lbs_add_mesh(struct lbs_private *priv)
{
struct net_device *mesh_dev = NULL;
int ret = 0;
@@ -1332,16 +1312,16 @@ int libertas_add_mesh(wlan_private *priv, struct device *dev)
mesh_dev->priv = priv;
priv->mesh_dev = mesh_dev;
- mesh_dev->open = libertas_mesh_open;
- mesh_dev->hard_start_xmit = libertas_mesh_pre_start_xmit;
- mesh_dev->stop = libertas_mesh_close;
- mesh_dev->get_stats = libertas_get_stats;
- mesh_dev->set_mac_address = libertas_set_mac_address;
- mesh_dev->ethtool_ops = &libertas_ethtool_ops;
+ mesh_dev->open = lbs_dev_open;
+ mesh_dev->hard_start_xmit = lbs_hard_start_xmit;
+ mesh_dev->stop = lbs_mesh_stop;
+ mesh_dev->get_stats = lbs_get_stats;
+ mesh_dev->set_mac_address = lbs_set_mac_address;
+ mesh_dev->ethtool_ops = &lbs_ethtool_ops;
memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
sizeof(priv->dev->dev_addr));
- SET_NETDEV_DEV(priv->mesh_dev, dev);
+ SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
#ifdef WIRELESS_EXT
mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
@@ -1353,7 +1333,7 @@ int libertas_add_mesh(wlan_private *priv, struct device *dev)
goto err_free;
}
- ret = sysfs_create_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);
+ ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
if (ret)
goto err_unregister;
@@ -1371,33 +1351,28 @@ done:
lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_add_mesh);
+EXPORT_SYMBOL_GPL(lbs_add_mesh);
-void libertas_remove_mesh(wlan_private *priv)
+static void lbs_remove_mesh(struct lbs_private *priv)
{
struct net_device *mesh_dev;
- lbs_deb_enter(LBS_DEB_MAIN);
-
- if (!priv)
- goto out;
mesh_dev = priv->mesh_dev;
+ if (!mesh_dev)
+ return;
+ lbs_deb_enter(LBS_DEB_MESH);
netif_stop_queue(mesh_dev);
netif_carrier_off(priv->mesh_dev);
-
- sysfs_remove_group(&(mesh_dev->dev.kobj), &libertas_mesh_attr_group);
+ sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
unregister_netdev(mesh_dev);
-
- priv->mesh_dev = NULL ;
+ priv->mesh_dev = NULL;
free_netdev(mesh_dev);
-
-out:
- lbs_deb_leave(LBS_DEB_MAIN);
+ lbs_deb_leave(LBS_DEB_MESH);
}
-EXPORT_SYMBOL_GPL(libertas_remove_mesh);
+EXPORT_SYMBOL_GPL(lbs_remove_mesh);
/**
* @brief This function finds the CFP in
@@ -1408,7 +1383,7 @@ EXPORT_SYMBOL_GPL(libertas_remove_mesh);
* @param cfp_no A pointer to CFP number
* @return A pointer to CFP
*/
-struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
+struct chan_freq_power *lbs_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
{
int i, end;
@@ -1430,9 +1405,8 @@ struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *c
return NULL;
}
-int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
+int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
int i = 0;
@@ -1441,24 +1415,22 @@ int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
lbs_deb_enter(LBS_DEB_MAIN);
- memset(adapter->region_channel, 0, sizeof(adapter->region_channel));
+ memset(priv->region_channel, 0, sizeof(priv->region_channel));
- {
- cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
- if (cfp != NULL) {
- adapter->region_channel[i].nrcfp = cfp_no;
- adapter->region_channel[i].CFP = cfp;
- } else {
- lbs_deb_main("wrong region code %#x in band B/G\n",
- region);
- ret = -1;
- goto out;
- }
- adapter->region_channel[i].valid = 1;
- adapter->region_channel[i].region = region;
- adapter->region_channel[i].band = band;
- i++;
+ cfp = lbs_get_region_cfp_table(region, band, &cfp_no);
+ if (cfp != NULL) {
+ priv->region_channel[i].nrcfp = cfp_no;
+ priv->region_channel[i].CFP = cfp;
+ } else {
+ lbs_deb_main("wrong region code %#x in band B/G\n",
+ region);
+ ret = -1;
+ goto out;
}
+ priv->region_channel[i].valid = 1;
+ priv->region_channel[i].region = region;
+ priv->region_channel[i].band = band;
+ i++;
out:
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
@@ -1472,58 +1444,46 @@ out:
* @param dev A pointer to net_device structure
* @return n/a
*/
-void libertas_interrupt(struct net_device *dev)
+void lbs_interrupt(struct lbs_private *priv)
{
- wlan_private *priv = dev->priv;
-
lbs_deb_enter(LBS_DEB_THREAD);
- lbs_deb_thread("libertas_interrupt: intcounter=%d\n",
- priv->adapter->intcounter);
-
- priv->adapter->intcounter++;
-
- if (priv->adapter->psstate == PS_STATE_SLEEP) {
- priv->adapter->psstate = PS_STATE_AWAKE;
- netif_wake_queue(dev);
- if (priv->mesh_dev)
- netif_wake_queue(priv->mesh_dev);
- }
-
+ lbs_deb_thread("lbs_interrupt: intcounter=%d\n", priv->intcounter);
+ priv->intcounter++;
+ if (priv->psstate == PS_STATE_SLEEP)
+ priv->psstate = PS_STATE_AWAKE;
wake_up_interruptible(&priv->waitq);
lbs_deb_leave(LBS_DEB_THREAD);
}
-EXPORT_SYMBOL_GPL(libertas_interrupt);
+EXPORT_SYMBOL_GPL(lbs_interrupt);
-int libertas_reset_device(wlan_private *priv)
+int lbs_reset_device(struct lbs_private *priv)
{
int ret;
lbs_deb_enter(LBS_DEB_MAIN);
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_RESET,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_RESET,
CMD_ACT_HALT, 0, 0, NULL);
msleep_interruptible(10);
lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_reset_device);
+EXPORT_SYMBOL_GPL(lbs_reset_device);
-static int libertas_init_module(void)
+static int __init lbs_init_module(void)
{
lbs_deb_enter(LBS_DEB_MAIN);
- libertas_debugfs_init();
+ lbs_debugfs_init();
lbs_deb_leave(LBS_DEB_MAIN);
return 0;
}
-static void libertas_exit_module(void)
+static void __exit lbs_exit_module(void)
{
lbs_deb_enter(LBS_DEB_MAIN);
-
- libertas_debugfs_remove();
-
+ lbs_debugfs_remove();
lbs_deb_leave(LBS_DEB_MAIN);
}
@@ -1531,79 +1491,89 @@ static void libertas_exit_module(void)
* rtap interface support fuctions
*/
-static int libertas_rtap_open(struct net_device *dev)
+static int lbs_rtap_open(struct net_device *dev)
{
- netif_carrier_off(dev);
- netif_stop_queue(dev);
- return 0;
+ /* Yes, _stop_ the queue. Because we don't support injection */
+ lbs_deb_enter(LBS_DEB_MAIN);
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ lbs_deb_leave(LBS_DEB_LEAVE);
+ return 0;
}
-static int libertas_rtap_stop(struct net_device *dev)
+static int lbs_rtap_stop(struct net_device *dev)
{
- return 0;
+ lbs_deb_enter(LBS_DEB_MAIN);
+ lbs_deb_leave(LBS_DEB_MAIN);
+ return 0;
}
-static int libertas_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- netif_stop_queue(dev);
- return -EOPNOTSUPP;
+ netif_stop_queue(dev);
+ return NETDEV_TX_BUSY;
}
-static struct net_device_stats *libertas_rtap_get_stats(struct net_device *dev)
+static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
{
- wlan_private *priv = dev->priv;
- return &priv->ieee->stats;
+ struct lbs_private *priv = dev->priv;
+ lbs_deb_enter(LBS_DEB_NET);
+ return &priv->stats;
}
-void libertas_remove_rtap(wlan_private *priv)
+static void lbs_remove_rtap(struct lbs_private *priv)
{
+ lbs_deb_enter(LBS_DEB_MAIN);
if (priv->rtap_net_dev == NULL)
return;
unregister_netdev(priv->rtap_net_dev);
- free_ieee80211(priv->rtap_net_dev);
+ free_netdev(priv->rtap_net_dev);
priv->rtap_net_dev = NULL;
+ lbs_deb_leave(LBS_DEB_MAIN);
}
-int libertas_add_rtap(wlan_private *priv)
+static int lbs_add_rtap(struct lbs_private *priv)
{
- int rc = 0;
-
- if (priv->rtap_net_dev)
- return -EPERM;
-
- priv->rtap_net_dev = alloc_ieee80211(0);
- if (priv->rtap_net_dev == NULL)
- return -ENOMEM;
-
-
- priv->ieee = netdev_priv(priv->rtap_net_dev);
+ int ret = 0;
+ struct net_device *rtap_dev;
- strcpy(priv->rtap_net_dev->name, "rtap%d");
+ lbs_deb_enter(LBS_DEB_MAIN);
+ if (priv->rtap_net_dev) {
+ ret = -EPERM;
+ goto out;
+ }
- priv->rtap_net_dev->type = ARPHRD_IEEE80211_RADIOTAP;
- priv->rtap_net_dev->open = libertas_rtap_open;
- priv->rtap_net_dev->stop = libertas_rtap_stop;
- priv->rtap_net_dev->get_stats = libertas_rtap_get_stats;
- priv->rtap_net_dev->hard_start_xmit = libertas_rtap_hard_start_xmit;
- priv->rtap_net_dev->set_multicast_list = libertas_set_multicast_list;
- priv->rtap_net_dev->priv = priv;
+ rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
+ if (rtap_dev == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
- priv->ieee->iw_mode = IW_MODE_MONITOR;
+ memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
+ rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
+ rtap_dev->open = lbs_rtap_open;
+ rtap_dev->stop = lbs_rtap_stop;
+ rtap_dev->get_stats = lbs_rtap_get_stats;
+ rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
+ rtap_dev->set_multicast_list = lbs_set_multicast_list;
+ rtap_dev->priv = priv;
- rc = register_netdev(priv->rtap_net_dev);
- if (rc) {
- free_ieee80211(priv->rtap_net_dev);
- priv->rtap_net_dev = NULL;
- return rc;
+ ret = register_netdev(rtap_dev);
+ if (ret) {
+ free_netdev(rtap_dev);
+ goto out;
}
+ priv->rtap_net_dev = rtap_dev;
- return 0;
+out:
+ lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+ return ret;
}
-module_init(libertas_init_module);
-module_exit(libertas_exit_module);
+module_init(lbs_init_module);
+module_exit(lbs_exit_module);
MODULE_DESCRIPTION("Libertas WLAN Driver Library");
MODULE_AUTHOR("Marvell International Ltd.");
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 0420e5b9ff9b..149557a478ac 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -35,134 +35,114 @@ struct rx80211packethdr {
void *eth80211_hdr;
} __attribute__ ((packed));
-static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb);
+static int process_rxed_802_11_packet(struct lbs_private *priv,
+ struct sk_buff *skb);
/**
* @brief This function computes the avgSNR .
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return avgSNR
*/
-static u8 wlan_getavgsnr(wlan_private * priv)
+static u8 lbs_getavgsnr(struct lbs_private *priv)
{
u8 i;
u16 temp = 0;
- wlan_adapter *adapter = priv->adapter;
- if (adapter->numSNRNF == 0)
+ if (priv->numSNRNF == 0)
return 0;
- for (i = 0; i < adapter->numSNRNF; i++)
- temp += adapter->rawSNR[i];
- return (u8) (temp / adapter->numSNRNF);
+ for (i = 0; i < priv->numSNRNF; i++)
+ temp += priv->rawSNR[i];
+ return (u8) (temp / priv->numSNRNF);
}
/**
* @brief This function computes the AvgNF
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @return AvgNF
*/
-static u8 wlan_getavgnf(wlan_private * priv)
+static u8 lbs_getavgnf(struct lbs_private *priv)
{
u8 i;
u16 temp = 0;
- wlan_adapter *adapter = priv->adapter;
- if (adapter->numSNRNF == 0)
+ if (priv->numSNRNF == 0)
return 0;
- for (i = 0; i < adapter->numSNRNF; i++)
- temp += adapter->rawNF[i];
- return (u8) (temp / adapter->numSNRNF);
+ for (i = 0; i < priv->numSNRNF; i++)
+ temp += priv->rawNF[i];
+ return (u8) (temp / priv->numSNRNF);
}
/**
* @brief This function save the raw SNR/NF to our internel buffer
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
-static void wlan_save_rawSNRNF(wlan_private * priv, struct rxpd *p_rx_pd)
+static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
{
- wlan_adapter *adapter = priv->adapter;
- if (adapter->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
- adapter->numSNRNF++;
- adapter->rawSNR[adapter->nextSNRNF] = p_rx_pd->snr;
- adapter->rawNF[adapter->nextSNRNF] = p_rx_pd->nf;
- adapter->nextSNRNF++;
- if (adapter->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
- adapter->nextSNRNF = 0;
+ if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
+ priv->numSNRNF++;
+ priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
+ priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
+ priv->nextSNRNF++;
+ if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
+ priv->nextSNRNF = 0;
return;
}
/**
* @brief This function computes the RSSI in received packet.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param prxpd A pointer to rxpd structure of received packet
* @return n/a
*/
-static void wlan_compute_rssi(wlan_private * priv, struct rxpd *p_rx_pd)
+static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
{
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_RX);
lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
- adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+ priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+ priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
- adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
- adapter->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
- wlan_save_rawSNRNF(priv, p_rx_pd);
+ priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
+ priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
+ lbs_save_rawSNRNF(priv, p_rx_pd);
- adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getavgsnr(priv) * AVG_SCALE;
- adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getavgnf(priv) * AVG_SCALE;
+ priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
+ priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
- adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+ priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+ priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
- adapter->RSSI[TYPE_RXPD][TYPE_NOAVG] =
- CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
- adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
+ priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
+ CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
+ priv->NF[TYPE_RXPD][TYPE_NOAVG]);
- adapter->RSSI[TYPE_RXPD][TYPE_AVG] =
- CAL_RSSI(adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
- adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+ priv->RSSI[TYPE_RXPD][TYPE_AVG] =
+ CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+ priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
lbs_deb_leave(LBS_DEB_RX);
}
-void libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
-{
- lbs_deb_rx("skb->data %p\n", skb->data);
-
- if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
- skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
- } else {
- if (priv->mesh_dev && IS_MESH_FRAME(skb))
- skb->protocol = eth_type_trans(skb, priv->mesh_dev);
- else
- skb->protocol = eth_type_trans(skb, priv->dev);
- }
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- netif_rx(skb);
-}
-
/**
* @brief This function processes received packet and forwards it
* to kernel/upper layer
*
- * @param priv A pointer to wlan_private
+ * @param priv A pointer to struct lbs_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
-int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
+int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
-
+ struct net_device *dev = priv->dev;
struct rxpackethdr *p_rx_pkt;
struct rxpd *p_rx_pd;
@@ -173,15 +153,15 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
lbs_deb_enter(LBS_DEB_RX);
- if (priv->adapter->monitormode != WLAN_MONITOR_OFF)
+ skb->ip_summed = CHECKSUM_NONE;
+
+ if (priv->monitormode != LBS_MONITOR_OFF)
return process_rxed_802_11_packet(priv, skb);
p_rx_pkt = (struct rxpackethdr *) skb->data;
p_rx_pd = &p_rx_pkt->rx_pd;
- if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
- SET_MESH_FRAME(skb);
- else
- UNSET_MESH_FRAME(skb);
+ if (priv->mesh_dev && (p_rx_pd->rx_control & RxPD_MESH_FRAME))
+ dev = priv->mesh_dev;
lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
min_t(unsigned int, skb->len, 100));
@@ -257,23 +237,27 @@ int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
- if (adapter->auto_rate)
- adapter->cur_rate = libertas_fw_index_to_data_rate(p_rx_pd->rx_rate);
+ if (priv->auto_rate)
+ priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
- wlan_compute_rssi(priv, p_rx_pd);
+ lbs_compute_rssi(priv, p_rx_pd);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
- libertas_upload_rx_packet(priv, skb);
+ skb->protocol = eth_type_trans(skb, dev);
+ if (in_interrupt())
+ netif_rx(skb);
+ else
+ netif_rx_ni(skb);
ret = 0;
done:
lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret);
return ret;
}
-EXPORT_SYMBOL_GPL(libertas_process_rxed_packet);
+EXPORT_SYMBOL_GPL(lbs_process_rxed_packet);
/**
* @brief This function converts Tx/Rx rates from the Marvell WLAN format
@@ -319,13 +303,13 @@ static u8 convert_mv_rate_to_radiotap(u8 rate)
* @brief This function processes a received 802.11 packet and forwards it
* to kernel/upper layer
*
- * @param priv A pointer to wlan_private
+ * @param priv A pointer to struct lbs_private
* @param skb A pointer to skb which includes the received packet
* @return 0 or -1
*/
-static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
+static int process_rxed_802_11_packet(struct lbs_private *priv,
+ struct sk_buff *skb)
{
- wlan_adapter *adapter = priv->adapter;
int ret = 0;
struct rx80211packethdr *p_rx_pkt;
@@ -341,9 +325,10 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
// lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100));
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
- lbs_deb_rx("rx err: frame received wit bad length\n");
+ lbs_deb_rx("rx err: frame received with bad length\n");
priv->stats.rx_length_errors++;
- ret = 0;
+ ret = -EINVAL;
+ kfree(skb);
goto done;
}
@@ -359,65 +344,56 @@ static int process_rxed_802_11_packet(wlan_private * priv, struct sk_buff *skb)
skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
/* create the exported radio header */
- if(priv->adapter->monitormode == WLAN_MONITOR_OFF) {
- /* no radio header */
- /* chop the rxpd */
- skb_pull(skb, sizeof(struct rxpd));
- }
- else {
- /* radiotap header */
- radiotap_hdr.hdr.it_version = 0;
- /* XXX must check this value for pad */
- radiotap_hdr.hdr.it_pad = 0;
- radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
- radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
- /* unknown values */
- radiotap_hdr.flags = 0;
- radiotap_hdr.chan_freq = 0;
- radiotap_hdr.chan_flags = 0;
- radiotap_hdr.antenna = 0;
- /* known values */
- radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
- /* XXX must check no carryout */
- radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
- radiotap_hdr.rx_flags = 0;
- if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
- radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
- //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
-
- /* chop the rxpd */
- skb_pull(skb, sizeof(struct rxpd));
-
- /* add space for the new radio header */
- if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
- pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0,
- GFP_ATOMIC)) {
- lbs_pr_alert("%s: couldn't pskb_expand_head\n",
- __func__);
- }
-
- pradiotap_hdr =
- (struct rx_radiotap_hdr *)skb_push(skb,
- sizeof(struct
- rx_radiotap_hdr));
- memcpy(pradiotap_hdr, &radiotap_hdr,
- sizeof(struct rx_radiotap_hdr));
+ /* radiotap header */
+ radiotap_hdr.hdr.it_version = 0;
+ /* XXX must check this value for pad */
+ radiotap_hdr.hdr.it_pad = 0;
+ radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
+ radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
+ /* unknown values */
+ radiotap_hdr.flags = 0;
+ radiotap_hdr.chan_freq = 0;
+ radiotap_hdr.chan_flags = 0;
+ radiotap_hdr.antenna = 0;
+ /* known values */
+ radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
+ /* XXX must check no carryout */
+ radiotap_hdr.antsignal = prxpd->snr + prxpd->nf;
+ radiotap_hdr.rx_flags = 0;
+ if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK)))
+ radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
+ //memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
+
+ /* chop the rxpd */
+ skb_pull(skb, sizeof(struct rxpd));
+
+ /* add space for the new radio header */
+ if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) &&
+ pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) {
+ lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__);
+ ret = -ENOMEM;
+ kfree_skb(skb);
+ goto done;
}
+ pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
+ memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
+
/* Take the data rate from the rxpd structure
* only if the rate is auto
*/
- if (adapter->auto_rate)
- adapter->cur_rate = libertas_fw_index_to_data_rate(prxpd->rx_rate);
+ if (priv->auto_rate)
+ priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
- wlan_compute_rssi(priv, prxpd);
+ lbs_compute_rssi(priv, prxpd);
lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
priv->stats.rx_bytes += skb->len;
priv->stats.rx_packets++;
- libertas_upload_rx_packet(priv, skb);
+ skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
+ netif_rx(skb);
ret = 0;
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index ad1e67d984ce..9a61188b62e9 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -39,9 +39,8 @@
//! Memory needed to store a max number/size SSID TLV for a firmware scan
#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvlietypes_ssidparamset))
-//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max
-#define MAX_SCAN_CFG_ALLOC (sizeof(struct wlan_scan_cmd_config) \
- + sizeof(struct mrvlietypes_numprobes) \
+//! Maximum memory needed for a lbs_scan_cmd_config with all TLVs at max
+#define MAX_SCAN_CFG_ALLOC (sizeof(struct lbs_scan_cmd_config) \
+ CHAN_TLV_MAX_SIZE \
+ SSID_TLV_MAX_SIZE)
@@ -80,7 +79,23 @@ static inline void clear_bss_descriptor (struct bss_descriptor * bss)
memset(bss, 0, offsetof(struct bss_descriptor, list));
}
-static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
+/**
+ * @brief Compare two SSIDs
+ *
+ * @param ssid1 A pointer to ssid to compare
+ * @param ssid2 A pointer to ssid to compare
+ *
+ * @return 0: ssid is same, otherwise is different
+ */
+int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
+{
+ if (ssid1_len != ssid2_len)
+ return -1;
+
+ return memcmp(ssid1, ssid2, ssid1_len);
+}
+
+static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
struct bss_descriptor * match_bss)
{
if ( !secinfo->wep_enabled
@@ -94,7 +109,7 @@ static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
return 0;
}
-static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo,
+static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
struct bss_descriptor * match_bss)
{
if ( secinfo->wep_enabled
@@ -106,7 +121,7 @@ static inline int match_bss_static_wep(struct wlan_802_11_security * secinfo,
return 0;
}
-static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
+static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
struct bss_descriptor * match_bss)
{
if ( !secinfo->wep_enabled
@@ -121,7 +136,7 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
return 0;
}
-static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
+static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
struct bss_descriptor * match_bss)
{
if ( !secinfo->wep_enabled
@@ -136,7 +151,7 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
return 0;
}
-static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
+static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
struct bss_descriptor * match_bss)
{
if ( !secinfo->wep_enabled
@@ -150,6 +165,18 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
return 0;
}
+static inline int is_same_network(struct bss_descriptor *src,
+ struct bss_descriptor *dst)
+{
+ /* A network is only a duplicate if the channel, BSSID, and ESSID
+ * all match. We treat all <hidden> with the same BSSID and channel
+ * as one network */
+ return ((src->ssid_len == dst->ssid_len) &&
+ (src->channel == dst->channel) &&
+ !compare_ether_addr(src->bssid, dst->bssid) &&
+ !memcmp(src->ssid, dst->ssid, src->ssid_len));
+}
+
/**
* @brief Check if a scanned network compatible with the driver settings
*
@@ -163,13 +190,13 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
* 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
*
*
- * @param adapter A pointer to wlan_adapter
+ * @param priv A pointer to struct lbs_private
* @param index Index in scantable to check against current driver settings
* @param mode Network mode: Infrastructure or IBSS
*
* @return Index in scantable, or error code if negative
*/
-static int is_network_compatible(wlan_adapter * adapter,
+static int is_network_compatible(struct lbs_private *priv,
struct bss_descriptor * bss, u8 mode)
{
int matched = 0;
@@ -179,34 +206,34 @@ static int is_network_compatible(wlan_adapter * adapter,
if (bss->mode != mode)
goto done;
- if ((matched = match_bss_no_security(&adapter->secinfo, bss))) {
+ if ((matched = match_bss_no_security(&priv->secinfo, bss))) {
goto done;
- } else if ((matched = match_bss_static_wep(&adapter->secinfo, bss))) {
+ } else if ((matched = match_bss_static_wep(&priv->secinfo, bss))) {
goto done;
- } else if ((matched = match_bss_wpa(&adapter->secinfo, bss))) {
+ } else if ((matched = match_bss_wpa(&priv->secinfo, bss))) {
lbs_deb_scan(
- "is_network_compatible() WPA: wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
- adapter->secinfo.wep_enabled ? "e" : "d",
- adapter->secinfo.WPAenabled ? "e" : "d",
- adapter->secinfo.WPA2enabled ? "e" : "d",
+ "is_network_compatible() WPA: wpa_ie 0x%x "
+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+ priv->secinfo.wep_enabled ? "e" : "d",
+ priv->secinfo.WPAenabled ? "e" : "d",
+ priv->secinfo.WPA2enabled ? "e" : "d",
(bss->capability & WLAN_CAPABILITY_PRIVACY));
goto done;
- } else if ((matched = match_bss_wpa2(&adapter->secinfo, bss))) {
+ } else if ((matched = match_bss_wpa2(&priv->secinfo, bss))) {
lbs_deb_scan(
- "is_network_compatible() WPA2: wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
- "privacy=%#x\n", bss->wpa_ie[0], bss->rsn_ie[0],
- adapter->secinfo.wep_enabled ? "e" : "d",
- adapter->secinfo.WPAenabled ? "e" : "d",
- adapter->secinfo.WPA2enabled ? "e" : "d",
+ "is_network_compatible() WPA2: wpa_ie 0x%x "
+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
+ "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
+ priv->secinfo.wep_enabled ? "e" : "d",
+ priv->secinfo.WPAenabled ? "e" : "d",
+ priv->secinfo.WPA2enabled ? "e" : "d",
(bss->capability & WLAN_CAPABILITY_PRIVACY));
goto done;
- } else if ((matched = match_bss_dynamic_wep(&adapter->secinfo, bss))) {
+ } else if ((matched = match_bss_dynamic_wep(&priv->secinfo, bss))) {
lbs_deb_scan(
"is_network_compatible() dynamic WEP: "
- "wpa_ie=%#x wpa2_ie=%#x privacy=%#x\n",
+ "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
bss->wpa_ie[0], bss->rsn_ie[0],
(bss->capability & WLAN_CAPABILITY_PRIVACY));
goto done;
@@ -214,12 +241,12 @@ static int is_network_compatible(wlan_adapter * adapter,
/* bss security settings don't match those configured on card */
lbs_deb_scan(
- "is_network_compatible() FAILED: wpa_ie=%#x "
- "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s privacy=%#x\n",
+ "is_network_compatible() FAILED: wpa_ie 0x%x "
+ "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
bss->wpa_ie[0], bss->rsn_ie[0],
- adapter->secinfo.wep_enabled ? "e" : "d",
- adapter->secinfo.WPAenabled ? "e" : "d",
- adapter->secinfo.WPA2enabled ? "e" : "d",
+ priv->secinfo.wep_enabled ? "e" : "d",
+ priv->secinfo.WPAenabled ? "e" : "d",
+ priv->secinfo.WPA2enabled ? "e" : "d",
(bss->capability & WLAN_CAPABILITY_PRIVACY));
done:
@@ -227,22 +254,6 @@ done:
return matched;
}
-/**
- * @brief Compare two SSIDs
- *
- * @param ssid1 A pointer to ssid to compare
- * @param ssid2 A pointer to ssid to compare
- *
- * @return 0--ssid is same, otherwise is different
- */
-int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
-{
- if (ssid1_len != ssid2_len)
- return -1;
-
- return memcmp(ssid1, ssid2, ssid1_len);
-}
-
@@ -252,17 +263,27 @@ int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
/* */
/*********************************************************************/
+void lbs_scan_worker(struct work_struct *work)
+{
+ struct lbs_private *priv =
+ container_of(work, struct lbs_private, scan_work.work);
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+ lbs_scan_networks(priv, NULL, 0);
+ lbs_deb_leave(LBS_DEB_SCAN);
+}
+
/**
* @brief Create a channel list for the driver to scan based on region info
*
- * Only used from wlan_scan_setup_scan_config()
+ * Only used from lbs_scan_setup_scan_config()
*
* Use the driver region/band information to construct a comprehensive list
* of channels to scan. This routine is used for any scan that is not
* provided a specific channel list to scan.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param scanchanlist Output parameter: resulting channel list to scan
* @param filteredscan Flag indicating whether or not a BSSID or SSID filter
* is being sent in the command to firmware. Used to
@@ -272,12 +293,11 @@ int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len)
*
* @return void
*/
-static void wlan_scan_create_channel_list(wlan_private * priv,
+static int lbs_scan_create_channel_list(struct lbs_private *priv,
struct chanscanparamset * scanchanlist,
u8 filteredscan)
{
- wlan_adapter *adapter = priv->adapter;
struct region_channel *scanregion;
struct chan_freq_power *cfp;
int rgnidx;
@@ -285,8 +305,6 @@ static void wlan_scan_create_channel_list(wlan_private * priv,
int nextchan;
u8 scantype;
- lbs_deb_enter_args(LBS_DEB_SCAN, "filteredscan %d", filteredscan);
-
chanidx = 0;
/* Set the default scan type to the user specified type, will later
@@ -295,21 +313,22 @@ static void wlan_scan_create_channel_list(wlan_private * priv,
*/
scantype = CMD_SCAN_TYPE_ACTIVE;
- for (rgnidx = 0; rgnidx < ARRAY_SIZE(adapter->region_channel); rgnidx++) {
- if (priv->adapter->enable11d &&
- adapter->connect_status != LIBERTAS_CONNECTED) {
+ for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
+ if (priv->enable11d &&
+ (priv->connect_status != LBS_CONNECTED) &&
+ (priv->mesh_connect_status != LBS_CONNECTED)) {
/* Scan all the supported chan for the first scan */
- if (!adapter->universal_channel[rgnidx].valid)
+ if (!priv->universal_channel[rgnidx].valid)
continue;
- scanregion = &adapter->universal_channel[rgnidx];
+ scanregion = &priv->universal_channel[rgnidx];
/* clear the parsed_region_chan for the first scan */
- memset(&adapter->parsed_region_chan, 0x00,
- sizeof(adapter->parsed_region_chan));
+ memset(&priv->parsed_region_chan, 0x00,
+ sizeof(priv->parsed_region_chan));
} else {
- if (!adapter->region_channel[rgnidx].valid)
+ if (!priv->region_channel[rgnidx].valid)
continue;
- scanregion = &adapter->region_channel[rgnidx];
+ scanregion = &priv->region_channel[rgnidx];
}
for (nextchan = 0;
@@ -317,10 +336,10 @@ static void wlan_scan_create_channel_list(wlan_private * priv,
cfp = scanregion->CFP + nextchan;
- if (priv->adapter->enable11d) {
+ if (priv->enable11d) {
scantype =
- libertas_get_scan_type_11d(cfp->channel,
- &adapter->
+ lbs_get_scan_type_11d(cfp->channel,
+ &priv->
parsed_region_chan);
}
@@ -353,453 +372,151 @@ static void wlan_scan_create_channel_list(wlan_private * priv,
}
}
}
+ return chanidx;
}
-/* Delayed partial scan worker */
-void libertas_scan_worker(struct work_struct *work)
+/*
+ * Add SSID TLV of the form:
+ *
+ * TLV-ID SSID 00 00
+ * length 06 00
+ * ssid 4d 4e 54 45 53 54
+ */
+static int lbs_scan_add_ssid_tlv(u8 *tlv,
+ const struct lbs_ioctl_user_scan_cfg *user_cfg)
{
- wlan_private *priv = container_of(work, wlan_private, scan_work.work);
-
- wlan_scan_networks(priv, NULL, 0);
+ struct mrvlietypes_ssidparamset *ssid_tlv =
+ (struct mrvlietypes_ssidparamset *)tlv;
+ ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
+ ssid_tlv->header.len = cpu_to_le16(user_cfg->ssid_len);
+ memcpy(ssid_tlv->ssid, user_cfg->ssid, user_cfg->ssid_len);
+ return sizeof(ssid_tlv->header) + user_cfg->ssid_len;
}
-/**
- * @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds
- *
- * Application layer or other functions can invoke wlan_scan_networks
- * with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
- * This structure is used as the basis of one or many wlan_scan_cmd_config
- * commands that are sent to the command processing module and sent to
- * firmware.
- *
- * Create a wlan_scan_cmd_config based on the following user supplied
- * parameters (if present):
- * - SSID filter
- * - BSSID filter
- * - Number of Probes to be sent
- * - channel list
- *
- * If the SSID or BSSID filter is not present, disable/clear the filter.
- * If the number of probes is not set, use the adapter default setting
- * Qualify the channel
+/*
+ * Add CHANLIST TLV of the form
*
- * @param priv A pointer to wlan_private structure
- * @param puserscanin NULL or pointer to scan configuration parameters
- * @param ppchantlvout Output parameter: Pointer to the start of the
- * channel TLV portion of the output scan config
- * @param pscanchanlist Output parameter: Pointer to the resulting channel
- * list to scan
- * @param pmaxchanperscan Output parameter: Number of channels to scan for
- * each issuance of the firmware scan command
- * @param pfilteredscan Output parameter: Flag indicating whether or not
- * a BSSID or SSID filter is being sent in the
- * command to firmware. Used to increase the number
- * of channels sent in a scan command and to
- * disable the firmware channel scan filter.
- * @param pscancurrentonly Output parameter: Flag indicating whether or not
- * we are only scanning our current active channel
+ * TLV-ID CHANLIST 01 01
+ * length 5b 00
+ * channel 1 00 01 00 00 00 64 00
+ * radio type 00
+ * channel 01
+ * scan type 00
+ * min scan time 00 00
+ * max scan time 64 00
+ * channel 2 00 02 00 00 00 64 00
+ * channel 3 00 03 00 00 00 64 00
+ * channel 4 00 04 00 00 00 64 00
+ * channel 5 00 05 00 00 00 64 00
+ * channel 6 00 06 00 00 00 64 00
+ * channel 7 00 07 00 00 00 64 00
+ * channel 8 00 08 00 00 00 64 00
+ * channel 9 00 09 00 00 00 64 00
+ * channel 10 00 0a 00 00 00 64 00
+ * channel 11 00 0b 00 00 00 64 00
+ * channel 12 00 0c 00 00 00 64 00
+ * channel 13 00 0d 00 00 00 64 00
*
- * @return resulting scan configuration
*/
-static struct wlan_scan_cmd_config *
-wlan_scan_setup_scan_config(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin,
- struct mrvlietypes_chanlistparamset ** ppchantlvout,
- struct chanscanparamset * pscanchanlist,
- int *pmaxchanperscan,
- u8 * pfilteredscan,
- u8 * pscancurrentonly)
+static int lbs_scan_add_chanlist_tlv(u8 *tlv,
+ struct chanscanparamset *chan_list,
+ int chan_count)
{
- struct mrvlietypes_numprobes *pnumprobestlv;
- struct mrvlietypes_ssidparamset *pssidtlv;
- struct wlan_scan_cmd_config * pscancfgout = NULL;
- u8 *ptlvpos;
- u16 numprobes;
- int chanidx;
- int scantype;
- int scandur;
- int channel;
- int radiotype;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- pscancfgout = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
- if (pscancfgout == NULL)
- goto out;
-
- /* The tlvbufferlen is calculated for each scan command. The TLVs added
- * in this routine will be preserved since the routine that sends
- * the command will append channelTLVs at *ppchantlvout. The difference
- * between the *ppchantlvout and the tlvbuffer start will be used
- * to calculate the size of anything we add in this routine.
- */
- pscancfgout->tlvbufferlen = 0;
-
- /* Running tlv pointer. Assigned to ppchantlvout at end of function
- * so later routines know where channels can be added to the command buf
- */
- ptlvpos = pscancfgout->tlvbuffer;
-
- /*
- * Set the initial scan paramters for progressive scanning. If a specific
- * BSSID or SSID is used, the number of channels in the scan command
- * will be increased to the absolute maximum
- */
- *pmaxchanperscan = MRVDRV_CHANNELS_PER_SCAN_CMD;
-
- /* Initialize the scan as un-filtered by firmware, set to TRUE below if
- * a SSID or BSSID filter is sent in the command
- */
- *pfilteredscan = 0;
-
- /* Initialize the scan as not being only on the current channel. If
- * the channel list is customized, only contains one channel, and
- * is the active channel, this is set true and data flow is not halted.
- */
- *pscancurrentonly = 0;
-
- if (puserscanin) {
- /* Set the bss type scan filter, use adapter setting if unset */
- pscancfgout->bsstype =
- puserscanin->bsstype ? puserscanin->bsstype : CMD_BSS_TYPE_ANY;
-
- /* Set the number of probes to send, use adapter setting if unset */
- numprobes = puserscanin->numprobes ? puserscanin->numprobes : 0;
-
- /*
- * Set the BSSID filter to the incoming configuration,
- * if non-zero. If not set, it will remain disabled (all zeros).
- */
- memcpy(pscancfgout->bssid, puserscanin->bssid,
- sizeof(pscancfgout->bssid));
-
- if (puserscanin->ssid_len) {
- pssidtlv =
- (struct mrvlietypes_ssidparamset *) pscancfgout->
- tlvbuffer;
- pssidtlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
- pssidtlv->header.len = cpu_to_le16(puserscanin->ssid_len);
- memcpy(pssidtlv->ssid, puserscanin->ssid,
- puserscanin->ssid_len);
- ptlvpos += sizeof(pssidtlv->header) + puserscanin->ssid_len;
- }
-
- /*
- * The default number of channels sent in the command is low to
- * ensure the response buffer from the firmware does not truncate
- * scan results. That is not an issue with an SSID or BSSID
- * filter applied to the scan results in the firmware.
- */
- if ( puserscanin->ssid_len
- || (compare_ether_addr(pscancfgout->bssid, &zeromac[0]) != 0)) {
- *pmaxchanperscan = MRVDRV_MAX_CHANNELS_PER_SCAN;
- *pfilteredscan = 1;
- }
- } else {
- pscancfgout->bsstype = CMD_BSS_TYPE_ANY;
- numprobes = 0;
- }
-
- /* If the input config or adapter has the number of Probes set, add tlv */
- if (numprobes) {
- pnumprobestlv = (struct mrvlietypes_numprobes *) ptlvpos;
- pnumprobestlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
- pnumprobestlv->header.len = cpu_to_le16(2);
- pnumprobestlv->numprobes = cpu_to_le16(numprobes);
-
- ptlvpos += sizeof(*pnumprobestlv);
- }
-
- /*
- * Set the output for the channel TLV to the address in the tlv buffer
- * past any TLVs that were added in this fuction (SSID, numprobes).
- * channel TLVs will be added past this for each scan command, preserving
- * the TLVs that were previously added.
- */
- *ppchantlvout = (struct mrvlietypes_chanlistparamset *) ptlvpos;
-
- if (!puserscanin || !puserscanin->chanlist[0].channumber) {
- /* Create a default channel scan list */
- lbs_deb_scan("creating full region channel list\n");
- wlan_scan_create_channel_list(priv, pscanchanlist,
- *pfilteredscan);
- goto out;
- }
-
- for (chanidx = 0;
- chanidx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
- && puserscanin->chanlist[chanidx].channumber; chanidx++) {
-
- channel = puserscanin->chanlist[chanidx].channumber;
- (pscanchanlist + chanidx)->channumber = channel;
-
- radiotype = puserscanin->chanlist[chanidx].radiotype;
- (pscanchanlist + chanidx)->radiotype = radiotype;
-
- scantype = puserscanin->chanlist[chanidx].scantype;
-
- if (scantype == CMD_SCAN_TYPE_PASSIVE) {
- (pscanchanlist +
- chanidx)->chanscanmode.passivescan = 1;
- } else {
- (pscanchanlist +
- chanidx)->chanscanmode.passivescan = 0;
- }
-
- if (puserscanin->chanlist[chanidx].scantime) {
- scandur = puserscanin->chanlist[chanidx].scantime;
- } else {
- if (scantype == CMD_SCAN_TYPE_PASSIVE) {
- scandur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
- } else {
- scandur = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
- }
- }
-
- (pscanchanlist + chanidx)->minscantime =
- cpu_to_le16(scandur);
- (pscanchanlist + chanidx)->maxscantime =
- cpu_to_le16(scandur);
- }
-
- /* Check if we are only scanning the current channel */
- if ((chanidx == 1) &&
- (puserscanin->chanlist[0].channumber ==
- priv->adapter->curbssparams.channel)) {
- *pscancurrentonly = 1;
- lbs_deb_scan("scanning current channel only");
- }
-
-out:
- return pscancfgout;
+ size_t size = sizeof(struct chanscanparamset) * chan_count;
+ struct mrvlietypes_chanlistparamset *chan_tlv =
+ (struct mrvlietypes_chanlistparamset *) tlv;
+
+ chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
+ memcpy(chan_tlv->chanscanparam, chan_list, size);
+ chan_tlv->header.len = cpu_to_le16(size);
+ return sizeof(chan_tlv->header) + size;
}
-/**
- * @brief Construct and send multiple scan config commands to the firmware
- *
- * Only used from wlan_scan_networks()
- *
- * Previous routines have created a wlan_scan_cmd_config with any requested
- * TLVs. This function splits the channel TLV into maxchanperscan lists
- * and sends the portion of the channel TLV along with the other TLVs
- * to the wlan_cmd routines for execution in the firmware.
+
+/*
+ * Add RATES TLV of the form
*
- * @param priv A pointer to wlan_private structure
- * @param maxchanperscan Maximum number channels to be included in each
- * scan command sent to firmware
- * @param filteredscan Flag indicating whether or not a BSSID or SSID
- * filter is being used for the firmware command
- * scan command sent to firmware
- * @param pscancfgout Scan configuration used for this scan.
- * @param pchantlvout Pointer in the pscancfgout where the channel TLV
- * should start. This is past any other TLVs that
- * must be sent down in each firmware command.
- * @param pscanchanlist List of channels to scan in maxchanperscan segments
+ * TLV-ID RATES 01 00
+ * length 0e 00
+ * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
*
- * @return 0 or error return otherwise
+ * The rates are in lbs_bg_rates[], but for the 802.11b
+ * rates the high bit isn't set.
*/
-static int wlan_scan_channel_list(wlan_private * priv,
- int maxchanperscan,
- u8 filteredscan,
- struct wlan_scan_cmd_config * pscancfgout,
- struct mrvlietypes_chanlistparamset * pchantlvout,
- struct chanscanparamset * pscanchanlist,
- const struct wlan_ioctl_user_scan_cfg * puserscanin,
- int full_scan)
+static int lbs_scan_add_rates_tlv(u8 *tlv)
{
- struct chanscanparamset *ptmpchan;
- struct chanscanparamset *pstartchan;
- u8 scanband;
- int doneearly;
- int tlvidx;
- int ret = 0;
- int scanned = 0;
- union iwreq_data wrqu;
-
- lbs_deb_enter_args(LBS_DEB_SCAN, "maxchanperscan %d, filteredscan %d, "
- "full_scan %d", maxchanperscan, filteredscan, full_scan);
-
- if (!pscancfgout || !pchantlvout || !pscanchanlist) {
- lbs_deb_scan("pscancfgout, pchantlvout or "
- "pscanchanlist is NULL\n");
- ret = -1;
- goto out;
- }
-
- pchantlvout->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-
- /* Set the temp channel struct pointer to the start of the desired list */
- ptmpchan = pscanchanlist;
-
- if (priv->adapter->last_scanned_channel && !puserscanin)
- ptmpchan += priv->adapter->last_scanned_channel;
-
- /* Loop through the desired channel list, sending a new firmware scan
- * commands for each maxchanperscan channels (or for 1,6,11 individually
- * if configured accordingly)
- */
- while (ptmpchan->channumber) {
-
- tlvidx = 0;
- pchantlvout->header.len = 0;
- scanband = ptmpchan->radiotype;
- pstartchan = ptmpchan;
- doneearly = 0;
-
- /* Construct the channel TLV for the scan command. Continue to
- * insert channel TLVs until:
- * - the tlvidx hits the maximum configured per scan command
- * - the next channel to insert is 0 (end of desired channel list)
- * - doneearly is set (controlling individual scanning of 1,6,11)
- */
- while (tlvidx < maxchanperscan && ptmpchan->channumber
- && !doneearly && scanned < 2) {
-
- lbs_deb_scan("channel %d, radio %d, passive %d, "
- "dischanflt %d, maxscantime %d\n",
- ptmpchan->channumber,
- ptmpchan->radiotype,
- ptmpchan->chanscanmode.passivescan,
- ptmpchan->chanscanmode.disablechanfilt,
- ptmpchan->maxscantime);
-
- /* Copy the current channel TLV to the command being prepared */
- memcpy(pchantlvout->chanscanparam + tlvidx,
- ptmpchan, sizeof(pchantlvout->chanscanparam));
-
- /* Increment the TLV header length by the size appended */
- /* Ew, it would be _so_ nice if we could just declare the
- variable little-endian and let GCC handle it for us */
- pchantlvout->header.len =
- cpu_to_le16(le16_to_cpu(pchantlvout->header.len) +
- sizeof(pchantlvout->chanscanparam));
-
- /*
- * The tlv buffer length is set to the number of bytes of the
- * between the channel tlv pointer and the start of the
- * tlv buffer. This compensates for any TLVs that were appended
- * before the channel list.
- */
- pscancfgout->tlvbufferlen = ((u8 *) pchantlvout
- - pscancfgout->tlvbuffer);
-
- /* Add the size of the channel tlv header and the data length */
- pscancfgout->tlvbufferlen +=
- (sizeof(pchantlvout->header)
- + le16_to_cpu(pchantlvout->header.len));
-
- /* Increment the index to the channel tlv we are constructing */
- tlvidx++;
-
- doneearly = 0;
-
- /* Stop the loop if the *current* channel is in the 1,6,11 set
- * and we are not filtering on a BSSID or SSID.
- */
- if (!filteredscan && (ptmpchan->channumber == 1
- || ptmpchan->channumber == 6
- || ptmpchan->channumber == 11)) {
- doneearly = 1;
- }
-
- /* Increment the tmp pointer to the next channel to be scanned */
- ptmpchan++;
- scanned++;
-
- /* Stop the loop if the *next* channel is in the 1,6,11 set.
- * This will cause it to be the only channel scanned on the next
- * interation
- */
- if (!filteredscan && (ptmpchan->channumber == 1
- || ptmpchan->channumber == 6
- || ptmpchan->channumber == 11)) {
- doneearly = 1;
- }
- }
-
- /* Send the scan command to the firmware with the specified cfg */
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
- 0, 0, pscancfgout);
- if (scanned >= 2 && !full_scan) {
- ret = 0;
- goto done;
- }
- scanned = 0;
- }
-
-done:
- priv->adapter->last_scanned_channel = ptmpchan->channumber;
-
- if (priv->adapter->last_scanned_channel) {
- /* Schedule the next part of the partial scan */
- if (!full_scan && !priv->adapter->surpriseremoved) {
- cancel_delayed_work(&priv->scan_work);
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(300));
- }
- } else {
- /* All done, tell userspace the scan table has been updated */
- memset(&wrqu, 0, sizeof(union iwreq_data));
- wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
+ int i;
+ struct mrvlietypes_ratesparamset *rate_tlv =
+ (struct mrvlietypes_ratesparamset *) tlv;
+
+ rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
+ tlv += sizeof(rate_tlv->header);
+ for (i = 0; i < MAX_RATES; i++) {
+ *tlv = lbs_bg_rates[i];
+ if (*tlv == 0)
+ break;
+ /* This code makes sure that the 802.11b rates (1 MBit/s, 2
+ MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
+ Note that the values are MBit/s * 2, to mark them as
+ basic rates so that the firmware likes it better */
+ if (*tlv == 0x02 || *tlv == 0x04 ||
+ *tlv == 0x0b || *tlv == 0x16)
+ *tlv |= 0x80;
+ tlv++;
}
-
-out:
- lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
- return ret;
+ rate_tlv->header.len = cpu_to_le16(i);
+ return sizeof(rate_tlv->header) + i;
}
+
/*
- * Only used from wlan_scan_networks()
-*/
-static void clear_selected_scan_list_entries(wlan_adapter *adapter,
- const struct wlan_ioctl_user_scan_cfg *scan_cfg)
+ * Generate the CMD_802_11_SCAN command with the proper tlv
+ * for a bunch of channels.
+ */
+static int lbs_do_scan(struct lbs_private *priv,
+ u8 bsstype,
+ struct chanscanparamset *chan_list,
+ int chan_count,
+ const struct lbs_ioctl_user_scan_cfg *user_cfg)
{
- struct bss_descriptor *bss;
- struct bss_descriptor *safe;
- u32 clear_ssid_flag = 0, clear_bssid_flag = 0;
+ int ret = -ENOMEM;
+ struct lbs_scan_cmd_config *scan_cmd;
+ u8 *tlv; /* pointer into our current, growing TLV storage area */
- lbs_deb_enter(LBS_DEB_SCAN);
+ lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, "
+ "chan_count %d",
+ bsstype, chan_list[0].channumber, chan_count);
- if (!scan_cfg)
+ /* create the fixed part for scan command */
+ scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
+ if (scan_cmd == NULL)
goto out;
-
- if (scan_cfg->clear_ssid && scan_cfg->ssid_len)
- clear_ssid_flag = 1;
-
- if (scan_cfg->clear_bssid
- && (compare_ether_addr(scan_cfg->bssid, &zeromac[0]) != 0)
- && (compare_ether_addr(scan_cfg->bssid, &bcastmac[0]) != 0)) {
- clear_bssid_flag = 1;
- }
-
- if (!clear_ssid_flag && !clear_bssid_flag)
- goto out;
-
- mutex_lock(&adapter->lock);
- list_for_each_entry_safe (bss, safe, &adapter->network_list, list) {
- u32 clear = 0;
-
- /* Check for an SSID match */
- if ( clear_ssid_flag
- && (bss->ssid_len == scan_cfg->ssid_len)
- && !memcmp(bss->ssid, scan_cfg->ssid, bss->ssid_len))
- clear = 1;
-
- /* Check for a BSSID match */
- if ( clear_bssid_flag
- && !compare_ether_addr(bss->bssid, scan_cfg->bssid))
- clear = 1;
-
- if (clear) {
- list_move_tail (&bss->list, &adapter->network_free_list);
- clear_bss_descriptor(bss);
- }
- }
- mutex_unlock(&adapter->lock);
+ tlv = scan_cmd->tlvbuffer;
+ if (user_cfg)
+ memcpy(scan_cmd->bssid, user_cfg->bssid, ETH_ALEN);
+ scan_cmd->bsstype = bsstype;
+
+ /* add TLVs */
+ if (user_cfg && user_cfg->ssid_len)
+ tlv += lbs_scan_add_ssid_tlv(tlv, user_cfg);
+ if (chan_list && chan_count)
+ tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
+ tlv += lbs_scan_add_rates_tlv(tlv);
+
+ /* This is the final data we are about to send */
+ scan_cmd->tlvbufferlen = tlv - scan_cmd->tlvbuffer;
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, 1+6);
+ lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
+ scan_cmd->tlvbufferlen);
+
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, 0,
+ CMD_OPTION_WAITFORRSP, 0, scan_cmd);
out:
- lbs_deb_leave(LBS_DEB_SCAN);
+ kfree(scan_cmd);
+ lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
+ return ret;
}
@@ -812,32 +529,32 @@ out:
* order to send the appropriate scan commands to firmware to populate or
* update the internal driver scan table
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param puserscanin Pointer to the input configuration for the requested
* scan.
- * @param full_scan ???
*
* @return 0 or < 0 if error
*/
-int wlan_scan_networks(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin,
+int lbs_scan_networks(struct lbs_private *priv,
+ const struct lbs_ioctl_user_scan_cfg *user_cfg,
int full_scan)
{
- wlan_adapter * adapter = priv->adapter;
- struct mrvlietypes_chanlistparamset *pchantlvout;
- struct chanscanparamset * scan_chan_list = NULL;
- struct wlan_scan_cmd_config * scan_cfg = NULL;
- u8 filteredscan;
- u8 scancurrentchanonly;
- int maxchanperscan;
- int ret;
+ int ret = -ENOMEM;
+ struct chanscanparamset *chan_list;
+ struct chanscanparamset *curr_chans;
+ int chan_count;
+ u8 bsstype = CMD_BSS_TYPE_ANY;
+ int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
+ int filteredscan = 0;
+ union iwreq_data wrqu;
#ifdef CONFIG_LIBERTAS_DEBUG
- struct bss_descriptor * iter_bss;
+ struct bss_descriptor *iter;
int i = 0;
DECLARE_MAC_BUF(mac);
#endif
- lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
+ lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d",
+ full_scan);
/* Cancel any partial outstanding partial scans if this scan
* is a full scan.
@@ -845,90 +562,138 @@ int wlan_scan_networks(wlan_private * priv,
if (full_scan && delayed_work_pending(&priv->scan_work))
cancel_delayed_work(&priv->scan_work);
- scan_chan_list = kzalloc(sizeof(struct chanscanparamset) *
- WLAN_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
- if (scan_chan_list == NULL) {
- ret = -ENOMEM;
+ /* Determine same scan parameters */
+ if (user_cfg) {
+ if (user_cfg->bsstype)
+ bsstype = user_cfg->bsstype;
+ if (compare_ether_addr(user_cfg->bssid, &zeromac[0]) != 0) {
+ numchannels = MRVDRV_MAX_CHANNELS_PER_SCAN;
+ filteredscan = 1;
+ }
+ }
+ lbs_deb_scan("numchannels %d, bsstype %d, "
+ "filteredscan %d\n",
+ numchannels, bsstype, filteredscan);
+
+ /* Create list of channels to scan */
+ chan_list = kzalloc(sizeof(struct chanscanparamset) *
+ LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
+ if (!chan_list) {
+ lbs_pr_alert("SCAN: chan_list empty\n");
goto out;
}
- scan_cfg = wlan_scan_setup_scan_config(priv,
- puserscanin,
- &pchantlvout,
- scan_chan_list,
- &maxchanperscan,
- &filteredscan,
- &scancurrentchanonly);
- if (scan_cfg == NULL) {
- ret = -ENOMEM;
- goto out;
+ /* We want to scan all channels */
+ chan_count = lbs_scan_create_channel_list(priv, chan_list,
+ filteredscan);
+
+ netif_stop_queue(priv->dev);
+ netif_carrier_off(priv->dev);
+ if (priv->mesh_dev) {
+ netif_stop_queue(priv->mesh_dev);
+ netif_carrier_off(priv->mesh_dev);
+ }
+
+ /* Prepare to continue an interrupted scan */
+ lbs_deb_scan("chan_count %d, last_scanned_channel %d\n",
+ chan_count, priv->last_scanned_channel);
+ curr_chans = chan_list;
+ /* advance channel list by already-scanned-channels */
+ if (priv->last_scanned_channel > 0) {
+ curr_chans += priv->last_scanned_channel;
+ chan_count -= priv->last_scanned_channel;
}
- clear_selected_scan_list_entries(adapter, puserscanin);
+ /* Send scan command(s)
+ * numchannels contains the number of channels we should maximally scan
+ * chan_count is the total number of channels to scan
+ */
- /* Keep the data path active if we are only scanning our current channel */
- if (!scancurrentchanonly) {
- netif_stop_queue(priv->dev);
- netif_carrier_off(priv->dev);
- if (priv->mesh_dev) {
- netif_stop_queue(priv->mesh_dev);
- netif_carrier_off(priv->mesh_dev);
+ while (chan_count) {
+ int to_scan = min(numchannels, chan_count);
+ lbs_deb_scan("scanning %d of %d channels\n",
+ to_scan, chan_count);
+ ret = lbs_do_scan(priv, bsstype, curr_chans,
+ to_scan, user_cfg);
+ if (ret) {
+ lbs_pr_err("SCAN_CMD failed\n");
+ goto out2;
+ }
+ curr_chans += to_scan;
+ chan_count -= to_scan;
+
+ /* somehow schedule the next part of the scan */
+ if (chan_count &&
+ !full_scan &&
+ !priv->surpriseremoved) {
+ /* -1 marks just that we're currently scanning */
+ if (priv->last_scanned_channel < 0)
+ priv->last_scanned_channel = to_scan;
+ else
+ priv->last_scanned_channel += to_scan;
+ cancel_delayed_work(&priv->scan_work);
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(300));
+ /* skip over GIWSCAN event */
+ goto out;
}
- }
- ret = wlan_scan_channel_list(priv,
- maxchanperscan,
- filteredscan,
- scan_cfg,
- pchantlvout,
- scan_chan_list,
- puserscanin,
- full_scan);
+ }
+ memset(&wrqu, 0, sizeof(union iwreq_data));
+ wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
#ifdef CONFIG_LIBERTAS_DEBUG
/* Dump the scan table */
- mutex_lock(&adapter->lock);
- lbs_deb_scan("The scan table contains:\n");
- list_for_each_entry (iter_bss, &adapter->network_list, list) {
- lbs_deb_scan("scan %02d, %s, RSSI, %d, SSID '%s'\n",
- i++, print_mac(mac, iter_bss->bssid), (s32) iter_bss->rssi,
- escape_essid(iter_bss->ssid, iter_bss->ssid_len));
- }
- mutex_unlock(&adapter->lock);
+ mutex_lock(&priv->lock);
+ lbs_deb_scan("scan table:\n");
+ list_for_each_entry(iter, &priv->network_list, list)
+ lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
+ i++, print_mac(mac, iter->bssid), (s32) iter->rssi,
+ escape_essid(iter->ssid, iter->ssid_len));
+ mutex_unlock(&priv->lock);
#endif
- if (priv->adapter->connect_status == LIBERTAS_CONNECTED) {
+out2:
+ priv->last_scanned_channel = 0;
+
+out:
+ if (priv->connect_status == LBS_CONNECTED) {
netif_carrier_on(priv->dev);
- netif_wake_queue(priv->dev);
- if (priv->mesh_dev) {
- netif_carrier_on(priv->mesh_dev);
+ if (!priv->tx_pending_len)
+ netif_wake_queue(priv->dev);
+ }
+ if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) {
+ netif_carrier_on(priv->mesh_dev);
+ if (!priv->tx_pending_len)
netif_wake_queue(priv->mesh_dev);
- }
}
-
-out:
- if (scan_cfg)
- kfree(scan_cfg);
-
- if (scan_chan_list)
- kfree(scan_chan_list);
+ kfree(chan_list);
lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
return ret;
}
+
+
+
+/*********************************************************************/
+/* */
+/* Result interpretation */
+/* */
+/*********************************************************************/
+
/**
* @brief Interpret a BSS scan response returned from the firmware
*
* Parse the various fixed fields and IEs passed back for a a BSS probe
- * response or beacon from the scan command. Record information as needed
- * in the scan table struct bss_descriptor for that entry.
+ * response or beacon from the scan command. Record information as needed
+ * in the scan table struct bss_descriptor for that entry.
*
* @param bss Output parameter: Pointer to the BSS Entry
*
* @return 0 or -1
*/
-static int libertas_process_bss(struct bss_descriptor * bss,
+static int lbs_process_bss(struct bss_descriptor *bss,
u8 ** pbeaconinfo, int *bytesleft)
{
struct ieeetypes_fhparamset *pFH;
@@ -946,7 +711,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
if (*bytesleft >= sizeof(beaconsize)) {
/* Extract & convert beacon size from the command buffer */
- beaconsize = le16_to_cpu(get_unaligned((u16 *)*pbeaconinfo));
+ beaconsize = le16_to_cpu(get_unaligned((__le16 *)*pbeaconinfo));
*bytesleft -= sizeof(beaconsize);
*pbeaconinfo += sizeof(beaconsize);
}
@@ -967,7 +732,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
*bytesleft -= beaconsize;
memcpy(bss->bssid, pos, ETH_ALEN);
- lbs_deb_scan("process_bss: AP BSSID %s\n", print_mac(mac, bss->bssid));
+ lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid));
pos += ETH_ALEN;
if ((end - pos) < 12) {
@@ -983,7 +748,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
/* RSSI is 1 byte long */
bss->rssi = *pos;
- lbs_deb_scan("process_bss: RSSI=%02X\n", *pos);
+ lbs_deb_scan("process_bss: RSSI %d\n", *pos);
pos++;
/* time stamp is 8 bytes long */
@@ -995,18 +760,18 @@ static int libertas_process_bss(struct bss_descriptor * bss,
/* capability information is 2 bytes long */
bss->capability = le16_to_cpup((void *) pos);
- lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability);
+ lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
pos += 2;
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
- lbs_deb_scan("process_bss: AP WEP enabled\n");
+ lbs_deb_scan("process_bss: WEP enabled\n");
if (bss->capability & WLAN_CAPABILITY_IBSS)
bss->mode = IW_MODE_ADHOC;
else
bss->mode = IW_MODE_INFRA;
/* rest of the current buffer are IE's */
- lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos);
+ lbs_deb_scan("process_bss: IE len %zd\n", end - pos);
lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);
/* process variable IE */
@@ -1024,7 +789,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
case MFIE_TYPE_SSID:
bss->ssid_len = elem->len;
memcpy(bss->ssid, elem->data, elem->len);
- lbs_deb_scan("ssid '%s', ssid length %u\n",
+ lbs_deb_scan("got SSID IE: '%s', len %u\n",
escape_essid(bss->ssid, bss->ssid_len),
bss->ssid_len);
break;
@@ -1033,16 +798,14 @@ static int libertas_process_bss(struct bss_descriptor * bss,
n_basic_rates = min_t(u8, MAX_RATES, elem->len);
memcpy(bss->rates, elem->data, n_basic_rates);
got_basic_rates = 1;
+ lbs_deb_scan("got RATES IE\n");
break;
case MFIE_TYPE_FH_SET:
pFH = (struct ieeetypes_fhparamset *) pos;
memmove(&bss->phyparamset.fhparamset, pFH,
sizeof(struct ieeetypes_fhparamset));
-#if 0 /* I think we can store these LE */
- bss->phyparamset.fhparamset.dwelltime
- = le16_to_cpu(bss->phyparamset.fhparamset.dwelltime);
-#endif
+ lbs_deb_scan("got FH IE\n");
break;
case MFIE_TYPE_DS_SET:
@@ -1050,31 +813,31 @@ static int libertas_process_bss(struct bss_descriptor * bss,
bss->channel = pDS->currentchan;
memcpy(&bss->phyparamset.dsparamset, pDS,
sizeof(struct ieeetypes_dsparamset));
+ lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
break;
case MFIE_TYPE_CF_SET:
pCF = (struct ieeetypes_cfparamset *) pos;
memcpy(&bss->ssparamset.cfparamset, pCF,
sizeof(struct ieeetypes_cfparamset));
+ lbs_deb_scan("got CF IE\n");
break;
case MFIE_TYPE_IBSS_SET:
pibss = (struct ieeetypes_ibssparamset *) pos;
- bss->atimwindow = le32_to_cpu(pibss->atimwindow);
+ bss->atimwindow = le16_to_cpu(pibss->atimwindow);
memmove(&bss->ssparamset.ibssparamset, pibss,
sizeof(struct ieeetypes_ibssparamset));
-#if 0
- bss->ssparamset.ibssparamset.atimwindow
- = le16_to_cpu(bss->ssparamset.ibssparamset.atimwindow);
-#endif
+ lbs_deb_scan("got IBSS IE\n");
break;
case MFIE_TYPE_COUNTRY:
pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
+ lbs_deb_scan("got COUNTRY IE\n");
if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
|| pcountryinfo->len > 254) {
lbs_deb_scan("process_bss: 11D- Err "
- "CountryInfo len =%d min=%zd max=254\n",
+ "CountryInfo len %d, min %zd, max 254\n",
pcountryinfo->len,
sizeof(pcountryinfo->countrycode));
ret = -1;
@@ -1093,8 +856,11 @@ static int libertas_process_bss(struct bss_descriptor * bss,
* already found. Data rate IE should come before
* extended supported rate IE
*/
- if (!got_basic_rates)
+ lbs_deb_scan("got RATESEX IE\n");
+ if (!got_basic_rates) {
+ lbs_deb_scan("... but ignoring it\n");
break;
+ }
n_ex_rates = elem->len;
if (n_basic_rates + n_ex_rates > MAX_RATES)
@@ -1113,24 +879,36 @@ static int libertas_process_bss(struct bss_descriptor * bss,
bss->wpa_ie_len = min(elem->len + 2,
MAX_WPA_IE_LEN);
memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: WPA IE", bss->wpa_ie,
+ lbs_deb_scan("got WPA IE\n");
+ lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
elem->len);
} else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
elem->data[0] == 0x00 &&
elem->data[1] == 0x50 &&
elem->data[2] == 0x43 &&
elem->data[3] == 0x04) {
+ lbs_deb_scan("got mesh IE\n");
bss->mesh = 1;
+ } else {
+ lbs_deb_scan("got generiec IE: "
+ "%02x:%02x:%02x:%02x, len %d\n",
+ elem->data[0], elem->data[1],
+ elem->data[2], elem->data[3],
+ elem->len);
}
break;
case MFIE_TYPE_RSN:
+ lbs_deb_scan("got RSN IE\n");
bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
- lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", bss->rsn_ie, elem->len);
+ lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
+ bss->rsn_ie, elem->len);
break;
default:
+ lbs_deb_scan("got IE 0x%04x, len %d\n",
+ elem->id, elem->len);
break;
}
@@ -1139,7 +917,7 @@ static int libertas_process_bss(struct bss_descriptor * bss,
/* Timestamp */
bss->last_scanned = jiffies;
- libertas_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
+ lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
ret = 0;
@@ -1153,13 +931,13 @@ done:
*
* Used in association code
*
- * @param adapter A pointer to wlan_adapter
+ * @param priv A pointer to struct lbs_private
* @param bssid BSSID to find in the scan list
* @param mode Network mode: Infrastructure or IBSS
*
* @return index in BSSID list, or error return code (< 0)
*/
-struct bss_descriptor *libertas_find_bssid_in_list(wlan_adapter * adapter,
+struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
u8 * bssid, u8 mode)
{
struct bss_descriptor * iter_bss;
@@ -1177,14 +955,14 @@ struct bss_descriptor *libertas_find_bssid_in_list(wlan_adapter * adapter,
* continue past a matched bssid that is not compatible in case there
* is an AP with multiple SSIDs assigned to the same BSSID
*/
- mutex_lock(&adapter->lock);
- list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ mutex_lock(&priv->lock);
+ list_for_each_entry (iter_bss, &priv->network_list, list) {
if (compare_ether_addr(iter_bss->bssid, bssid))
continue; /* bssid doesn't match */
switch (mode) {
case IW_MODE_INFRA:
case IW_MODE_ADHOC:
- if (!is_network_compatible(adapter, iter_bss, mode))
+ if (!is_network_compatible(priv, iter_bss, mode))
break;
found_bss = iter_bss;
break;
@@ -1193,7 +971,7 @@ struct bss_descriptor *libertas_find_bssid_in_list(wlan_adapter * adapter,
break;
}
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
out:
lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
@@ -1205,14 +983,14 @@ out:
*
* Used in association code
*
- * @param adapter A pointer to wlan_adapter
+ * @param priv A pointer to struct lbs_private
* @param ssid SSID to find in the list
* @param bssid BSSID to qualify the SSID selection (if provided)
* @param mode Network mode: Infrastructure or IBSS
*
* @return index in BSSID list
*/
-struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
+struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
int channel)
{
@@ -1223,14 +1001,14 @@ struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
lbs_deb_enter(LBS_DEB_SCAN);
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
- list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ list_for_each_entry (iter_bss, &priv->network_list, list) {
if ( !tmp_oldest
|| (iter_bss->last_scanned < tmp_oldest->last_scanned))
tmp_oldest = iter_bss;
- if (libertas_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
+ if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
ssid, ssid_len) != 0)
continue; /* ssid doesn't match */
if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
@@ -1241,7 +1019,7 @@ struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
switch (mode) {
case IW_MODE_INFRA:
case IW_MODE_ADHOC:
- if (!is_network_compatible(adapter, iter_bss, mode))
+ if (!is_network_compatible(priv, iter_bss, mode))
break;
if (bssid) {
@@ -1266,7 +1044,7 @@ struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
}
out:
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
return found_bss;
}
@@ -1277,12 +1055,13 @@ out:
* Search the scan table for the best SSID that also matches the current
* adapter network preference (infrastructure or adhoc)
*
- * @param adapter A pointer to wlan_adapter
+ * @param priv A pointer to struct lbs_private
*
* @return index in BSSID list
*/
-static struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * adapter,
- u8 mode)
+static struct bss_descriptor *lbs_find_best_ssid_in_list(
+ struct lbs_private *priv,
+ u8 mode)
{
u8 bestrssi = 0;
struct bss_descriptor * iter_bss;
@@ -1290,13 +1069,13 @@ static struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * ad
lbs_deb_enter(LBS_DEB_SCAN);
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
- list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ list_for_each_entry (iter_bss, &priv->network_list, list) {
switch (mode) {
case IW_MODE_INFRA:
case IW_MODE_ADHOC:
- if (!is_network_compatible(adapter, iter_bss, mode))
+ if (!is_network_compatible(priv, iter_bss, mode))
break;
if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
break;
@@ -1313,7 +1092,7 @@ static struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * ad
}
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
return best_bss;
}
@@ -1323,27 +1102,24 @@ static struct bss_descriptor * libertas_find_best_ssid_in_list(wlan_adapter * ad
*
* Used from association worker.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param pSSID A pointer to AP's ssid
*
* @return 0--success, otherwise--fail
*/
-int libertas_find_best_network_ssid(wlan_private * priv,
+int lbs_find_best_network_ssid(struct lbs_private *priv,
u8 *out_ssid, u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode)
{
- wlan_adapter *adapter = priv->adapter;
int ret = -1;
struct bss_descriptor * found;
lbs_deb_enter(LBS_DEB_SCAN);
- wlan_scan_networks(priv, NULL, 1);
- if (adapter->surpriseremoved)
+ lbs_scan_networks(priv, NULL, 1);
+ if (priv->surpriseremoved)
goto out;
- wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
-
- found = libertas_find_best_ssid_in_list(adapter, preferred_mode);
+ found = lbs_find_best_ssid_in_list(priv, preferred_mode);
if (found && (found->ssid_len > 0)) {
memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
*out_ssid_len = found->ssid_len;
@@ -1356,57 +1132,24 @@ out:
return ret;
}
-/**
- * @brief Scan Network
- *
- * @param dev A pointer to net_device structure
- * @param info A pointer to iw_request_info structure
- * @param vwrq A pointer to iw_param structure
- * @param extra A pointer to extra data buf
- *
- * @return 0 --success, otherwise fail
- */
-int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
- struct iw_param *vwrq, char *extra)
-{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
-
- lbs_deb_enter(LBS_DEB_SCAN);
-
- if (!delayed_work_pending(&priv->scan_work)) {
- queue_delayed_work(priv->work_thread, &priv->scan_work,
- msecs_to_jiffies(50));
- }
-
- if (adapter->surpriseremoved)
- return -1;
-
- lbs_deb_leave(LBS_DEB_SCAN);
- return 0;
-}
-
/**
* @brief Send a scan command for all available channels filtered on a spec
*
* Used in association code and from debugfs
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param ssid A pointer to the SSID to scan for
* @param ssid_len Length of the SSID
* @param clear_ssid Should existing scan results with this SSID
* be cleared?
- * @param prequestedssid A pointer to AP's ssid
- * @param keeppreviousscan Flag used to save/clear scan table before scan
*
* @return 0-success, otherwise fail
*/
-int libertas_send_specific_ssid_scan(wlan_private * priv,
+int lbs_send_specific_ssid_scan(struct lbs_private *priv,
u8 *ssid, u8 ssid_len, u8 clear_ssid)
{
- wlan_adapter *adapter = priv->adapter;
- struct wlan_ioctl_user_scan_cfg scancfg;
+ struct lbs_ioctl_user_scan_cfg scancfg;
int ret = 0;
lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s', clear %d",
@@ -1420,12 +1163,11 @@ int libertas_send_specific_ssid_scan(wlan_private * priv,
scancfg.ssid_len = ssid_len;
scancfg.clear_ssid = clear_ssid;
- wlan_scan_networks(priv, &scancfg, 1);
- if (adapter->surpriseremoved) {
+ lbs_scan_networks(priv, &scancfg, 1);
+ if (priv->surpriseremoved) {
ret = -1;
goto out;
}
- wait_event_interruptible(adapter->cmd_pending, !adapter->nr_cmd_pending);
out:
lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
@@ -1441,13 +1183,13 @@ out:
/* */
/*********************************************************************/
+
#define MAX_CUSTOM_LEN 64
-static inline char *libertas_translate_scan(wlan_private *priv,
+static inline char *lbs_translate_scan(struct lbs_private *priv,
char *start, char *stop,
struct bss_descriptor *bss)
{
- wlan_adapter *adapter = priv->adapter;
struct chan_freq_power *cfp;
char *current_val; /* For rates */
struct iw_event iwe; /* Temporary buffer */
@@ -1459,14 +1201,14 @@ static inline char *libertas_translate_scan(wlan_private *priv,
lbs_deb_enter(LBS_DEB_SCAN);
- cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, bss->channel);
+ cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel);
if (!cfp) {
lbs_deb_scan("Invalid channel number %d\n", bss->channel);
start = NULL;
goto out;
}
- /* First entry *MUST* be the AP BSSID */
+ /* First entry *MUST* be the BSSID */
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
@@ -1502,25 +1244,25 @@ static inline char *libertas_translate_scan(wlan_private *priv,
if (iwe.u.qual.qual > 100)
iwe.u.qual.qual = 100;
- if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+ if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
} else {
iwe.u.qual.noise =
- CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+ CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
}
/* Locally created ad-hoc BSSs won't have beacons if this is the
* only station in the adhoc network; so get signal strength
* from receive statistics.
*/
- if ((adapter->mode == IW_MODE_ADHOC)
- && adapter->adhoccreate
- && !libertas_ssid_cmp(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len,
+ if ((priv->mode == IW_MODE_ADHOC)
+ && priv->adhoccreate
+ && !lbs_ssid_cmp(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len,
bss->ssid, bss->ssid_len)) {
int snr, nf;
- snr = adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
- nf = adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+ nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
iwe.u.qual.level = CAL_RSSI(snr, nf);
}
start = iwe_stream_add_event(start, stop, &iwe, IW_EV_QUAL_LEN);
@@ -1549,10 +1291,10 @@ static inline char *libertas_translate_scan(wlan_private *priv,
stop, &iwe, IW_EV_PARAM_LEN);
}
if ((bss->mode == IW_MODE_ADHOC)
- && !libertas_ssid_cmp(adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len,
+ && !lbs_ssid_cmp(priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len,
bss->ssid, bss->ssid_len)
- && adapter->adhoccreate) {
+ && priv->adhoccreate) {
iwe.u.bitrate.value = 22 * 500000;
current_val = iwe_stream_add_value(start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
@@ -1596,6 +1338,54 @@ out:
return start;
}
+
+/**
+ * @brief Handle Scan Network ioctl
+ *
+ * @param dev A pointer to net_device structure
+ * @param info A pointer to iw_request_info structure
+ * @param vwrq A pointer to iw_param structure
+ * @param extra A pointer to extra data buf
+ *
+ * @return 0 --success, otherwise fail
+ */
+int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
+ struct iw_param *wrqu, char *extra)
+{
+ struct lbs_private *priv = dev->priv;
+
+ lbs_deb_enter(LBS_DEB_SCAN);
+
+ if (!netif_running(dev))
+ return -ENETDOWN;
+
+ /* mac80211 does this:
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ if (sdata->type != IEEE80211_IF_TYPE_xxx)
+ return -EOPNOTSUPP;
+
+ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
+ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
+ req = (struct iw_scan_req *)extra;
+ ssid = req->essid;
+ ssid_len = req->essid_len;
+ }
+ */
+
+ if (!delayed_work_pending(&priv->scan_work))
+ queue_delayed_work(priv->work_thread, &priv->scan_work,
+ msecs_to_jiffies(50));
+ /* set marker that currently a scan is taking place */
+ priv->last_scanned_channel = -1;
+
+ if (priv->surpriseremoved)
+ return -EIO;
+
+ lbs_deb_leave(LBS_DEB_SCAN);
+ return 0;
+}
+
+
/**
* @brief Handle Retrieve scan table ioctl
*
@@ -1606,12 +1396,11 @@ out:
*
* @return 0 --success, otherwise fail
*/
-int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
+int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
#define SCAN_ITEM_SIZE 128
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int err = 0;
char *ev = extra;
char *stop = ev + dwrq->length;
@@ -1620,14 +1409,18 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
lbs_deb_enter(LBS_DEB_SCAN);
+ /* iwlist should wait until the current scan is finished */
+ if (priv->last_scanned_channel)
+ return -EAGAIN;
+
/* Update RSSI if current BSS is a locally created ad-hoc BSS */
- if ((adapter->mode == IW_MODE_ADHOC) && adapter->adhoccreate) {
- libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
CMD_OPTION_WAITFORRSP, 0, NULL);
}
- mutex_lock(&adapter->lock);
- list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+ mutex_lock(&priv->lock);
+ list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
char * next_ev;
unsigned long stale_time;
@@ -1644,18 +1437,18 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
if (time_after(jiffies, stale_time)) {
list_move_tail (&iter_bss->list,
- &adapter->network_free_list);
+ &priv->network_free_list);
clear_bss_descriptor(iter_bss);
continue;
}
/* Translate to WE format this entry */
- next_ev = libertas_translate_scan(priv, ev, stop, iter_bss);
+ next_ev = lbs_translate_scan(priv, ev, stop, iter_bss);
if (next_ev == NULL)
continue;
ev = next_ev;
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
dwrq->length = (ev - extra);
dwrq->flags = 0;
@@ -1677,24 +1470,25 @@ int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
/**
* @brief Prepare a scan command to be sent to the firmware
*
- * Called from libertas_prepare_and_send_command() in cmd.c
+ * Called via lbs_prepare_and_send_command(priv, CMD_802_11_SCAN, ...)
+ * from cmd.c
*
* Sends a fixed lenght data part (specifying the BSS type and BSSID filters)
* as well as a variable number/length of TLVs to the firmware.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param cmd A pointer to cmd_ds_command structure to be sent to
* firmware with the cmd_DS_801_11_SCAN structure
- * @param pdata_buf Void pointer cast of a wlan_scan_cmd_config struct used
+ * @param pdata_buf Void pointer cast of a lbs_scan_cmd_config struct used
* to set the fields/TLVs for the command sent to firmware
*
* @return 0 or -1
*/
-int libertas_cmd_80211_scan(wlan_private * priv,
- struct cmd_ds_command *cmd, void *pdata_buf)
+int lbs_cmd_80211_scan(struct lbs_private *priv,
+ struct cmd_ds_command *cmd, void *pdata_buf)
{
struct cmd_ds_802_11_scan *pscan = &cmd->params.scan;
- struct wlan_scan_cmd_config *pscancfg = pdata_buf;
+ struct lbs_scan_cmd_config *pscancfg = pdata_buf;
lbs_deb_enter(LBS_DEB_SCAN);
@@ -1703,32 +1497,14 @@ int libertas_cmd_80211_scan(wlan_private * priv,
memcpy(pscan->bssid, pscancfg->bssid, ETH_ALEN);
memcpy(pscan->tlvbuffer, pscancfg->tlvbuffer, pscancfg->tlvbufferlen);
- cmd->command = cpu_to_le16(CMD_802_11_SCAN);
-
/* size is equal to the sizeof(fixed portions) + the TLV len + header */
cmd->size = cpu_to_le16(sizeof(pscan->bsstype) + ETH_ALEN
+ pscancfg->tlvbufferlen + S_DS_GEN);
- lbs_deb_scan("SCAN_CMD: command 0x%04x, size %d, seqnum %d\n",
- le16_to_cpu(cmd->command), le16_to_cpu(cmd->size),
- le16_to_cpu(cmd->seqnum));
-
lbs_deb_leave(LBS_DEB_SCAN);
return 0;
}
-static inline int is_same_network(struct bss_descriptor *src,
- struct bss_descriptor *dst)
-{
- /* A network is only a duplicate if the channel, BSSID, and ESSID
- * all match. We treat all <hidden> with the same BSSID and channel
- * as one network */
- return ((src->ssid_len == dst->ssid_len) &&
- (src->channel == dst->channel) &&
- !compare_ether_addr(src->bssid, dst->bssid) &&
- !memcmp(src->ssid, dst->ssid, src->ssid_len));
-}
-
/**
* @brief This function handles the command response of scan
*
@@ -1750,14 +1526,13 @@ static inline int is_same_network(struct bss_descriptor *src,
* | bufsize and sizeof the fixed fields above) |
* .-----------------------------------------------------------.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param resp A pointer to cmd_ds_command
*
* @return 0 or -1
*/
-int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
+int lbs_ret_80211_scan(struct lbs_private *priv, struct cmd_ds_command *resp)
{
- wlan_adapter *adapter = priv->adapter;
struct cmd_ds_802_11_scan_rsp *pscan;
struct bss_descriptor * iter_bss;
struct bss_descriptor * safe;
@@ -1771,11 +1546,11 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
lbs_deb_enter(LBS_DEB_SCAN);
/* Prune old entries from scan table */
- list_for_each_entry_safe (iter_bss, safe, &adapter->network_list, list) {
+ list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
if (time_before(jiffies, stale_time))
continue;
- list_move_tail (&iter_bss->list, &adapter->network_free_list);
+ list_move_tail (&iter_bss->list, &priv->network_free_list);
clear_bss_descriptor(iter_bss);
}
@@ -1789,12 +1564,11 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
goto done;
}
- bytesleft = le16_to_cpu(get_unaligned((u16*)&pscan->bssdescriptsize));
+ bytesleft = le16_to_cpu(pscan->bssdescriptsize);
lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
- scanrespsize = le16_to_cpu(get_unaligned((u16*)&resp->size));
- lbs_deb_scan("SCAN_RESP: returned %d AP before parsing\n",
- pscan->nr_sets);
+ scanrespsize = le16_to_cpu(resp->size);
+ lbs_deb_scan("SCAN_RESP: scan results %d\n", pscan->nr_sets);
pbssinfo = pscan->bssdesc_and_tlvbuffer;
@@ -1821,14 +1595,14 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
/* Process the data fields and IEs returned for this BSS */
memset(&new, 0, sizeof (struct bss_descriptor));
- if (libertas_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
+ if (lbs_process_bss(&new, &pbssinfo, &bytesleft) != 0) {
/* error parsing the scan response, skipped */
lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
continue;
}
/* Try to find this bss in the scan table */
- list_for_each_entry (iter_bss, &adapter->network_list, list) {
+ list_for_each_entry (iter_bss, &priv->network_list, list) {
if (is_same_network(iter_bss, &new)) {
found = iter_bss;
break;
@@ -1842,21 +1616,21 @@ int libertas_ret_80211_scan(wlan_private * priv, struct cmd_ds_command *resp)
if (found) {
/* found, clear it */
clear_bss_descriptor(found);
- } else if (!list_empty(&adapter->network_free_list)) {
+ } else if (!list_empty(&priv->network_free_list)) {
/* Pull one from the free list */
- found = list_entry(adapter->network_free_list.next,
+ found = list_entry(priv->network_free_list.next,
struct bss_descriptor, list);
- list_move_tail(&found->list, &adapter->network_list);
+ list_move_tail(&found->list, &priv->network_list);
} else if (oldest) {
/* If there are no more slots, expire the oldest */
found = oldest;
clear_bss_descriptor(found);
- list_move_tail(&found->list, &adapter->network_list);
+ list_move_tail(&found->list, &priv->network_list);
} else {
continue;
}
- lbs_deb_scan("SCAN_RESP: BSSID = %s\n",
+ lbs_deb_scan("SCAN_RESP: BSSID %s\n",
print_mac(mac, new.bssid));
/* Copy the locally created newbssentry to the scan table */
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index c29c031bef8c..319f70dde350 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -2,10 +2,10 @@
* Interface for the wlan network scan routines
*
* Driver interface functions and type declarations for the scan module
- * implemented in wlan_scan.c.
+ * implemented in scan.c.
*/
-#ifndef _WLAN_SCAN_H
-#define _WLAN_SCAN_H
+#ifndef _LBS_SCAN_H
+#define _LBS_SCAN_H
#include <net/ieee80211.h>
#include "hostcmd.h"
@@ -13,38 +13,38 @@
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*
- * @sa wlan_ioctl_user_scan_cfg
+ * @sa lbs_ioctl_user_scan_cfg
*/
-#define WLAN_IOCTL_USER_SCAN_CHAN_MAX 50
+#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
-//! Infrastructure BSS scan type in wlan_scan_cmd_config
-#define WLAN_SCAN_BSS_TYPE_BSS 1
+//! Infrastructure BSS scan type in lbs_scan_cmd_config
+#define LBS_SCAN_BSS_TYPE_BSS 1
-//! Adhoc BSS scan type in wlan_scan_cmd_config
-#define WLAN_SCAN_BSS_TYPE_IBSS 2
+//! Adhoc BSS scan type in lbs_scan_cmd_config
+#define LBS_SCAN_BSS_TYPE_IBSS 2
-//! Adhoc or Infrastructure BSS scan type in wlan_scan_cmd_config, no filter
-#define WLAN_SCAN_BSS_TYPE_ANY 3
+//! Adhoc or Infrastructure BSS scan type in lbs_scan_cmd_config, no filter
+#define LBS_SCAN_BSS_TYPE_ANY 3
/**
* @brief Structure used internally in the wlan driver to configure a scan.
*
* Sent to the command processing module to configure the firmware
- * scan command prepared by libertas_cmd_80211_scan.
+ * scan command prepared by lbs_cmd_80211_scan.
*
- * @sa wlan_scan_networks
+ * @sa lbs_scan_networks
*
*/
-struct wlan_scan_cmd_config {
+struct lbs_scan_cmd_config {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
- * - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
- * - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
- * - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
+ * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
+ * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+ * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
@@ -68,12 +68,12 @@ struct wlan_scan_cmd_config {
};
/**
- * @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
+ * @brief IOCTL channel sub-structure sent in lbs_ioctl_user_scan_cfg
*
* Multiple instances of this structure are included in the IOCTL command
* to configure a instance of a scan on the specific channel.
*/
-struct wlan_ioctl_user_scan_chan {
+struct lbs_ioctl_user_scan_chan {
u8 channumber; //!< channel Number to scan
u8 radiotype; //!< Radio type: 'B/G' band = 0, 'A' band = 1
u8 scantype; //!< Scan type: Active = 0, Passive = 1
@@ -83,31 +83,26 @@ struct wlan_ioctl_user_scan_chan {
/**
* @brief IOCTL input structure to configure an immediate scan cmd to firmware
*
- * Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl. Specifies
+ * Used in the setuserscan (LBS_SET_USER_SCAN) private ioctl. Specifies
* a number of parameters to be used in general for the scan as well
- * as a channel list (wlan_ioctl_user_scan_chan) for each scan period
+ * as a channel list (lbs_ioctl_user_scan_chan) for each scan period
* desired.
*
- * @sa libertas_set_user_scan_ioctl
+ * @sa lbs_set_user_scan_ioctl
*/
-struct wlan_ioctl_user_scan_cfg {
+struct lbs_ioctl_user_scan_cfg {
/**
* @brief BSS type to be sent in the firmware command
*
* Field can be used to restrict the types of networks returned in the
* scan. valid settings are:
*
- * - WLAN_SCAN_BSS_TYPE_BSS (infrastructure)
- * - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
- * - WLAN_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
+ * - LBS_SCAN_BSS_TYPE_BSS (infrastructure)
+ * - LBS_SCAN_BSS_TYPE_IBSS (adhoc)
+ * - LBS_SCAN_BSS_TYPE_ANY (unrestricted, adhoc and infrastructure)
*/
u8 bsstype;
- /**
- * @brief Configure the number of probe requests for active chan scans
- */
- u8 numprobes;
-
/**
* @brief BSSID filter sent in the firmware command to limit the results
*/
@@ -124,11 +119,6 @@ struct wlan_ioctl_user_scan_cfg {
/* Clear existing scan results matching this SSID */
u8 clear_ssid;
-
- /**
- * @brief Variable number (fixed maximum) of channels to scan up
- */
- struct wlan_ioctl_user_scan_chan chanlist[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
};
/**
@@ -174,30 +164,30 @@ struct bss_descriptor {
struct list_head list;
};
-int libertas_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
+int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
-struct bss_descriptor * libertas_find_ssid_in_list(wlan_adapter * adapter,
- u8 *ssid, u8 ssid_len, u8 * bssid, u8 mode,
- int channel);
+struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
+ u8 *ssid, u8 ssid_len, u8 *bssid, u8 mode,
+ int channel);
-struct bss_descriptor * libertas_find_bssid_in_list(wlan_adapter * adapter,
- u8 * bssid, u8 mode);
+struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
+ u8 *bssid, u8 mode);
-int libertas_find_best_network_ssid(wlan_private * priv, u8 *out_ssid,
+int lbs_find_best_network_ssid(struct lbs_private *priv, u8 *out_ssid,
u8 *out_ssid_len, u8 preferred_mode, u8 *out_mode);
-int libertas_send_specific_ssid_scan(wlan_private * priv, u8 *ssid,
+int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
u8 ssid_len, u8 clear_ssid);
-int libertas_cmd_80211_scan(wlan_private * priv,
+int lbs_cmd_80211_scan(struct lbs_private *priv,
struct cmd_ds_command *cmd,
void *pdata_buf);
-int libertas_ret_80211_scan(wlan_private * priv,
+int lbs_ret_80211_scan(struct lbs_private *priv,
struct cmd_ds_command *resp);
-int wlan_scan_networks(wlan_private * priv,
- const struct wlan_ioctl_user_scan_cfg * puserscanin,
+int lbs_scan_networks(struct lbs_private *priv,
+ const struct lbs_ioctl_user_scan_cfg *puserscanin,
int full_scan);
struct ifreq;
@@ -205,11 +195,11 @@ struct ifreq;
struct iw_point;
struct iw_param;
struct iw_request_info;
-int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
+int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra);
-int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
+int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra);
-void libertas_scan_worker(struct work_struct *work);
+void lbs_scan_worker(struct work_struct *work);
-#endif /* _WLAN_SCAN_H */
+#endif
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index fbec06c10dd7..00d95f75bd89 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -2,6 +2,7 @@
* This file contains the handling of TX in wlan driver.
*/
#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
#include "hostcmd.h"
#include "radiotap.h"
@@ -49,188 +50,122 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
}
/**
- * @brief This function processes a single packet and sends
- * to IF layer
+ * @brief This function checks the conditions and sends packet to IF
+ * layer if everything is ok.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param skb A pointer to skb which includes TX packet
* @return 0 or -1
*/
-static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
+int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- int ret = 0;
- struct txpd localtxpd;
- struct txpd *plocaltxpd = &localtxpd;
- u8 *p802x_hdr;
- struct tx_radiotap_hdr *pradiotap_hdr;
- u32 new_rate;
- u8 *ptr = priv->adapter->tmptxbuf;
+ unsigned long flags;
+ struct lbs_private *priv = dev->priv;
+ struct txpd *txpd;
+ char *p802x_hdr;
+ uint16_t pkt_len;
+ int ret;
lbs_deb_enter(LBS_DEB_TX);
- if (priv->adapter->surpriseremoved)
- return -1;
+ ret = NETDEV_TX_OK;
+
+ /* We need to protect against the queues being restarted before
+ we get round to stopping them */
+ spin_lock_irqsave(&priv->driver_lock, flags);
+
+ if (priv->surpriseremoved)
+ goto free;
if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
lbs_deb_tx("tx err: skb length %d 0 or > %zd\n",
skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
- ret = -1;
- goto done;
+ /* We'll never manage to send this one; drop it and return 'OK' */
+
+ priv->stats.tx_dropped++;
+ priv->stats.tx_errors++;
+ goto free;
}
- memset(plocaltxpd, 0, sizeof(struct txpd));
- plocaltxpd->tx_packet_length = cpu_to_le16(skb->len);
+ netif_stop_queue(priv->dev);
+ if (priv->mesh_dev)
+ netif_stop_queue(priv->mesh_dev);
- /* offset of actual data */
- plocaltxpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
+ if (priv->tx_pending_len) {
+ /* This can happen if packets come in on the mesh and eth
+ device simultaneously -- there's no mutual exclusion on
+ hard_start_xmit() calls between devices. */
+ lbs_deb_tx("Packet on %s while busy\n", dev->name);
+ ret = NETDEV_TX_BUSY;
+ goto unlock;
+ }
+
+ priv->tx_pending_len = -1;
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+ lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
+
+ txpd = (void *)priv->tx_pending_buf;
+ memset(txpd, 0, sizeof(struct txpd));
p802x_hdr = skb->data;
- if (priv->adapter->monitormode != WLAN_MONITOR_OFF) {
+ pkt_len = skb->len;
- /* locate radiotap header */
- pradiotap_hdr = (struct tx_radiotap_hdr *)skb->data;
+ if (dev == priv->rtap_net_dev) {
+ struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
/* set txpd fields from the radiotap header */
- new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
- if (new_rate != 0) {
- /* use new tx_control[4:0] */
- plocaltxpd->tx_control = cpu_to_le32(new_rate);
- }
+ txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate));
/* skip the radiotap header */
- p802x_hdr += sizeof(struct tx_radiotap_hdr);
- plocaltxpd->tx_packet_length =
- cpu_to_le16(le16_to_cpu(plocaltxpd->tx_packet_length)
- - sizeof(struct tx_radiotap_hdr));
+ p802x_hdr += sizeof(*rtap_hdr);
+ pkt_len -= sizeof(*rtap_hdr);
+ /* copy destination address from 802.11 header */
+ memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
+ } else {
+ /* copy destination address from 802.3 header */
+ memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
}
- /* copy destination address from 802.3 or 802.11 header */
- if (priv->adapter->monitormode != WLAN_MONITOR_OFF)
- memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN);
- else
- memcpy(plocaltxpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN);
- lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) plocaltxpd, sizeof(struct txpd));
+ txpd->tx_packet_length = cpu_to_le16(pkt_len);
+ txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
- if (IS_MESH_FRAME(skb)) {
- plocaltxpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
- }
+ if (dev == priv->mesh_dev)
+ txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
- memcpy(ptr, plocaltxpd, sizeof(struct txpd));
+ lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
- ptr += sizeof(struct txpd);
+ lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
- lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
- memcpy(ptr, p802x_hdr, le16_to_cpu(plocaltxpd->tx_packet_length));
- ret = priv->hw_host_to_card(priv, MVMS_DAT,
- priv->adapter->tmptxbuf,
- le16_to_cpu(plocaltxpd->tx_packet_length) +
- sizeof(struct txpd));
+ memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
- if (ret) {
- lbs_deb_tx("tx err: hw_host_to_card returned 0x%X\n", ret);
- goto done;
- }
+ spin_lock_irqsave(&priv->driver_lock, flags);
+ priv->tx_pending_len = pkt_len + sizeof(struct txpd);
- lbs_deb_tx("SendSinglePacket succeeds\n");
+ lbs_deb_tx("%s lined up packet\n", __func__);
-done:
- if (!ret) {
- priv->stats.tx_packets++;
- priv->stats.tx_bytes += skb->len;
- } else {
- priv->stats.tx_dropped++;
- priv->stats.tx_errors++;
- }
+ priv->stats.tx_packets++;
+ priv->stats.tx_bytes += skb->len;
- if (!ret && priv->adapter->monitormode != WLAN_MONITOR_OFF) {
+ dev->trans_start = jiffies;
+
+ if (priv->monitormode != LBS_MONITOR_OFF) {
/* Keep the skb to echo it back once Tx feedback is
received from FW */
skb_orphan(skb);
- /* stop processing outgoing pkts */
- netif_stop_queue(priv->dev);
- if (priv->mesh_dev)
- netif_stop_queue(priv->mesh_dev);
- /* freeze any packets already in our queues */
- priv->adapter->TxLockFlag = 1;
- } else {
- dev_kfree_skb_any(skb);
- priv->adapter->currenttxskb = NULL;
- }
- lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
- return ret;
-}
-
-
-void libertas_tx_runqueue(wlan_private *priv)
-{
- wlan_adapter *adapter = priv->adapter;
- int i;
-
- spin_lock(&adapter->txqueue_lock);
- for (i = 0; i < adapter->tx_queue_idx; i++) {
- struct sk_buff *skb = adapter->tx_queue_ps[i];
- spin_unlock(&adapter->txqueue_lock);
- SendSinglePacket(priv, skb);
- spin_lock(&adapter->txqueue_lock);
- }
- adapter->tx_queue_idx = 0;
- spin_unlock(&adapter->txqueue_lock);
-}
-
-static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
-{
- wlan_adapter *adapter = priv->adapter;
-
- spin_lock(&adapter->txqueue_lock);
-
- WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
- adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
- if (adapter->tx_queue_idx == NR_TX_QUEUE) {
- netif_stop_queue(priv->dev);
- if (priv->mesh_dev)
- netif_stop_queue(priv->mesh_dev);
+ /* Keep the skb around for when we get feedback */
+ priv->currenttxskb = skb;
} else {
- netif_start_queue(priv->dev);
- if (priv->mesh_dev)
- netif_start_queue(priv->mesh_dev);
- }
-
- spin_unlock(&adapter->txqueue_lock);
-}
-
-/**
- * @brief This function checks the conditions and sends packet to IF
- * layer if everything is ok.
- *
- * @param priv A pointer to wlan_private structure
- * @return n/a
- */
-int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
-{
- int ret = -1;
-
- lbs_deb_enter(LBS_DEB_TX);
- lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
-
- if (priv->dnld_sent) {
- lbs_pr_alert( "TX error: dnld_sent = %d, not sending\n",
- priv->dnld_sent);
- goto done;
- }
-
- if ((priv->adapter->psstate == PS_STATE_SLEEP) ||
- (priv->adapter->psstate == PS_STATE_PRE_SLEEP)) {
- wlan_tx_queue(priv, skb);
- return ret;
+ free:
+ dev_kfree_skb_any(skb);
}
+ unlock:
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
+ wake_up(&priv->waitq);
- priv->adapter->currenttxskb = skb;
-
- ret = SendSinglePacket(priv, skb);
-done:
lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret);
return ret;
}
@@ -239,24 +174,23 @@ done:
* @brief This function sends to the host the last transmitted packet,
* filling the radiotap headers with transmission information.
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @param status A 32 bit value containing transmission status.
*
* @returns void
*/
-void libertas_send_tx_feedback(wlan_private * priv)
+void lbs_send_tx_feedback(struct lbs_private *priv)
{
- wlan_adapter *adapter = priv->adapter;
struct tx_radiotap_hdr *radiotap_hdr;
- u32 status = adapter->eventcause;
+ u32 status = priv->eventcause;
int txfail;
int try_count;
- if (adapter->monitormode == WLAN_MONITOR_OFF ||
- adapter->currenttxskb == NULL)
+ if (priv->monitormode == LBS_MONITOR_OFF ||
+ priv->currenttxskb == NULL)
return;
- radiotap_hdr = (struct tx_radiotap_hdr *)adapter->currenttxskb->data;
+ radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
txfail = (status >> 24);
@@ -269,14 +203,19 @@ void libertas_send_tx_feedback(wlan_private * priv)
#endif
try_count = (status >> 16) & 0xff;
radiotap_hdr->data_retries = (try_count) ?
- (1 + adapter->txretrycount - try_count) : 0;
- libertas_upload_rx_packet(priv, adapter->currenttxskb);
- adapter->currenttxskb = NULL;
- priv->adapter->TxLockFlag = 0;
- if (priv->adapter->connect_status == LIBERTAS_CONNECTED) {
+ (1 + priv->txretrycount - try_count) : 0;
+
+
+ priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
+ priv->rtap_net_dev);
+ netif_rx(priv->currenttxskb);
+
+ priv->currenttxskb = NULL;
+
+ if (priv->connect_status == LBS_CONNECTED)
netif_wake_queue(priv->dev);
- if (priv->mesh_dev)
- netif_wake_queue(priv->mesh_dev);
- }
+
+ if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED))
+ netif_wake_queue(priv->mesh_dev);
}
-EXPORT_SYMBOL_GPL(libertas_send_tx_feedback);
+EXPORT_SYMBOL_GPL(lbs_send_tx_feedback);
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index a43a5f63c879..f0d57958b34b 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -1,8 +1,8 @@
/**
* This header file contains definition for global types
*/
-#ifndef _WLAN_TYPES_
-#define _WLAN_TYPES_
+#ifndef _LBS_TYPES_H_
+#define _LBS_TYPES_H_
#include <linux/if_ether.h>
#include <asm/byteorder.h>
@@ -201,22 +201,11 @@ struct mrvlietypes_powercapability {
s8 maxpower;
} __attribute__ ((packed));
-struct mrvlietypes_rssithreshold {
+/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
+struct mrvlietypes_thresholds {
struct mrvlietypesheader header;
- u8 rssivalue;
- u8 rssifreq;
-} __attribute__ ((packed));
-
-struct mrvlietypes_snrthreshold {
- struct mrvlietypesheader header;
- u8 snrvalue;
- u8 snrfreq;
-} __attribute__ ((packed));
-
-struct mrvlietypes_failurecount {
- struct mrvlietypesheader header;
- u8 failvalue;
- u8 Failfreq;
+ u8 value;
+ u8 freq;
} __attribute__ ((packed));
struct mrvlietypes_beaconsmissed {
@@ -250,4 +239,4 @@ struct mrvlietypes_ledgpio {
struct led_pin ledpin[1];
} __attribute__ ((packed));
-#endif /* _WLAN_TYPES_ */
+#endif
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 395b7882d4d6..e8bfc26b10a4 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -19,30 +19,47 @@
#include "join.h"
#include "wext.h"
#include "assoc.h"
+#include "cmd.h"
+
+
+static inline void lbs_postpone_association_work(struct lbs_private *priv)
+{
+ if (priv->surpriseremoved)
+ return;
+ cancel_delayed_work(&priv->assoc_work);
+ queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
+}
+
+static inline void lbs_cancel_association_work(struct lbs_private *priv)
+{
+ cancel_delayed_work(&priv->assoc_work);
+ kfree(priv->pending_assoc_req);
+ priv->pending_assoc_req = NULL;
+}
/**
* @brief Find the channel frequency power info with specific channel
*
- * @param adapter A pointer to wlan_adapter structure
+ * @param priv A pointer to struct lbs_private structure
* @param band it can be BAND_A, BAND_G or BAND_B
* @param channel the channel for looking
* @return A pointer to struct chan_freq_power structure or NULL if not find.
*/
-struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter,
- u8 band, u16 channel)
+struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
+ struct lbs_private *priv,
+ u8 band,
+ u16 channel)
{
struct chan_freq_power *cfp = NULL;
struct region_channel *rc;
- int count = sizeof(adapter->region_channel) /
- sizeof(adapter->region_channel[0]);
int i, j;
- for (j = 0; !cfp && (j < count); j++) {
- rc = &adapter->region_channel[j];
+ for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
+ rc = &priv->region_channel[j];
- if (adapter->enable11d)
- rc = &adapter->universal_channel[j];
+ if (priv->enable11d)
+ rc = &priv->universal_channel[j];
if (!rc->valid || !rc->CFP)
continue;
if (rc->band != band)
@@ -56,7 +73,7 @@ struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * ada
}
if (!cfp && channel)
- lbs_deb_wext("libertas_find_cfp_by_band_and_channel: can't find "
+ lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find "
"cfp by band %d / channel %d\n", band, channel);
return cfp;
@@ -65,25 +82,25 @@ struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * ada
/**
* @brief Find the channel frequency power info with specific frequency
*
- * @param adapter A pointer to wlan_adapter structure
+ * @param priv A pointer to struct lbs_private structure
* @param band it can be BAND_A, BAND_G or BAND_B
* @param freq the frequency for looking
* @return A pointer to struct chan_freq_power structure or NULL if not find.
*/
-static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
- u8 band, u32 freq)
+static struct chan_freq_power *find_cfp_by_band_and_freq(
+ struct lbs_private *priv,
+ u8 band,
+ u32 freq)
{
struct chan_freq_power *cfp = NULL;
struct region_channel *rc;
- int count = sizeof(adapter->region_channel) /
- sizeof(adapter->region_channel[0]);
int i, j;
- for (j = 0; !cfp && (j < count); j++) {
- rc = &adapter->region_channel[j];
+ for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
+ rc = &priv->region_channel[j];
- if (adapter->enable11d)
- rc = &adapter->universal_channel[j];
+ if (priv->enable11d)
+ rc = &priv->universal_channel[j];
if (!rc->valid || !rc->CFP)
continue;
if (rc->band != band)
@@ -107,22 +124,21 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
/**
* @brief Set Radio On/OFF
*
- * @param priv A pointer to wlan_private structure
+ * @param priv A pointer to struct lbs_private structure
* @option Radio Option
* @return 0 --success, otherwise fail
*/
-static int wlan_radio_ioctl(wlan_private * priv, u8 option)
+static int lbs_radio_ioctl(struct lbs_private *priv, u8 option)
{
int ret = 0;
- wlan_adapter *adapter = priv->adapter;
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->radioon != option) {
+ if (priv->radioon != option) {
lbs_deb_wext("switching radio %s\n", option ? "on" : "off");
- adapter->radioon = option;
+ priv->radioon = option;
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_RADIO_CONTROL,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP, 0, NULL);
@@ -135,22 +151,23 @@ static int wlan_radio_ioctl(wlan_private * priv, u8 option)
/**
* @brief Copy active data rates based on adapter mode and status
*
- * @param adapter A pointer to wlan_adapter structure
+ * @param priv A pointer to struct lbs_private structure
* @param rate The buf to return the active rates
*/
-static void copy_active_data_rates(wlan_adapter * adapter, u8 * rates)
+static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
{
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->connect_status != LIBERTAS_CONNECTED)
- memcpy(rates, libertas_bg_rates, MAX_RATES);
+ if ((priv->connect_status != LBS_CONNECTED) &&
+ (priv->mesh_connect_status != LBS_CONNECTED))
+ memcpy(rates, lbs_bg_rates, MAX_RATES);
else
- memcpy(rates, adapter->curbssparams.rates, MAX_RATES);
+ memcpy(rates, priv->curbssparams.rates, MAX_RATES);
lbs_deb_leave(LBS_DEB_WEXT);
}
-static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
char *cwrq, char *extra)
{
@@ -163,22 +180,21 @@ static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct chan_freq_power *cfp;
lbs_deb_enter(LBS_DEB_WEXT);
- cfp = libertas_find_cfp_by_band_and_channel(adapter, 0,
- adapter->curbssparams.channel);
+ cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
+ priv->curbssparams.channel);
if (!cfp) {
- if (adapter->curbssparams.channel)
+ if (priv->curbssparams.channel)
lbs_deb_wext("invalid channel %d\n",
- adapter->curbssparams.channel);
+ priv->curbssparams.channel);
return -EINVAL;
}
@@ -190,16 +206,15 @@ static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
struct sockaddr *awrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- memcpy(awrq->sa_data, adapter->curbssparams.bssid, ETH_ALEN);
+ if (priv->connect_status == LBS_CONNECTED) {
+ memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
} else {
memset(awrq->sa_data, 0, ETH_ALEN);
}
@@ -209,11 +224,10 @@ static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -225,25 +239,24 @@ static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
return -E2BIG;
}
- mutex_lock(&adapter->lock);
- memset(adapter->nodename, 0, sizeof(adapter->nodename));
- memcpy(adapter->nodename, extra, dwrq->length);
- mutex_unlock(&adapter->lock);
+ mutex_lock(&priv->lock);
+ memset(priv->nodename, 0, sizeof(priv->nodename));
+ memcpy(priv->nodename, extra, dwrq->length);
+ mutex_unlock(&priv->lock);
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
-static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- dwrq->length = strlen(adapter->nodename);
- memcpy(extra, adapter->nodename, dwrq->length);
+ dwrq->length = strlen(priv->nodename);
+ memcpy(extra, priv->nodename, dwrq->length);
extra[dwrq->length] = '\0';
dwrq->flags = 1; /* active */
@@ -255,14 +268,13 @@ static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
/* Use nickname to indicate that mesh is on */
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
+ if (priv->mesh_connect_status == LBS_CONNECTED) {
strncpy(extra, "Mesh", 12);
extra[12] = '\0';
dwrq->length = strlen(extra);
@@ -277,25 +289,24 @@ static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
u32 rthr = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
- adapter->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
+ priv->rtsthsd = rthr = MRVDRV_RTS_MAX_VALUE;
} else {
if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
return -EINVAL;
- adapter->rtsthsd = rthr;
+ priv->rtsthsd = rthr;
}
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
OID_802_11_RTS_THRESHOLD, &rthr);
@@ -303,23 +314,22 @@ static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
return ret;
}
-static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- adapter->rtsthsd = 0;
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
+ priv->rtsthsd = 0;
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_RTS_THRESHOLD, NULL);
if (ret)
goto out;
- vwrq->value = adapter->rtsthsd;
+ vwrq->value = priv->rtsthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
|| (vwrq->value > MRVDRV_RTS_MAX_VALUE));
vwrq->fixed = 1;
@@ -329,26 +339,25 @@ out:
return ret;
}
-static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
u32 fthr = vwrq->value;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
- adapter->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
+ priv->fragthsd = fthr = MRVDRV_FRAG_MAX_VALUE;
} else {
if (fthr < MRVDRV_FRAG_MIN_VALUE
|| fthr > MRVDRV_FRAG_MAX_VALUE)
return -EINVAL;
- adapter->fragthsd = fthr;
+ priv->fragthsd = fthr;
}
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET, CMD_OPTION_WAITFORRSP,
OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
@@ -356,24 +365,23 @@ static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
return ret;
}
-static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- adapter->fragthsd = 0;
- ret = libertas_prepare_and_send_command(priv,
+ priv->fragthsd = 0;
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
if (ret)
goto out;
- vwrq->value = adapter->fragthsd;
+ vwrq->value = priv->fragthsd;
vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
|| (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
vwrq->fixed = 1;
@@ -383,15 +391,14 @@ out:
return ret;
}
-static int wlan_get_mode(struct net_device *dev,
+static int lbs_get_mode(struct net_device *dev,
struct iw_request_info *info, u32 * uwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- *uwrq = adapter->mode;
+ *uwrq = priv->mode;
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
@@ -409,17 +416,16 @@ static int mesh_wlan_get_mode(struct net_device *dev,
return 0;
}
-static int wlan_get_txpow(struct net_device *dev,
+static int lbs_get_txpow(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_RF_TX_POWER,
CMD_ACT_TX_POWER_OPT_GET,
CMD_OPTION_WAITFORRSP, 0, NULL);
@@ -427,10 +433,10 @@ static int wlan_get_txpow(struct net_device *dev,
if (ret)
goto out;
- lbs_deb_wext("tx power level %d dbm\n", adapter->txpowerlevel);
- vwrq->value = adapter->txpowerlevel;
+ lbs_deb_wext("tx power level %d dbm\n", priv->txpowerlevel);
+ vwrq->value = priv->txpowerlevel;
vwrq->fixed = 1;
- if (adapter->radioon) {
+ if (priv->radioon) {
vwrq->disabled = 0;
vwrq->flags = IW_TXPOW_DBM;
} else {
@@ -442,12 +448,11 @@ out:
return ret;
}
-static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -460,9 +465,9 @@ static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
return -EINVAL;
/* Adding 1 to convert retry count to try count */
- adapter->txretrycount = vwrq->value + 1;
+ priv->txretrycount = vwrq->value + 1;
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
+ ret = lbs_prepare_and_send_command(priv, CMD_802_11_SNMP_MIB,
CMD_ACT_SET,
CMD_OPTION_WAITFORRSP,
OID_802_11_TX_RETRYCOUNT, NULL);
@@ -478,17 +483,16 @@ out:
return ret;
}
-static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int ret = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- adapter->txretrycount = 0;
- ret = libertas_prepare_and_send_command(priv,
+ priv->txretrycount = 0;
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_SNMP_MIB,
CMD_ACT_GET, CMD_OPTION_WAITFORRSP,
OID_802_11_TX_RETRYCOUNT, NULL);
@@ -499,7 +503,7 @@ static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
if (!vwrq->flags) {
vwrq->flags = IW_RETRY_LIMIT;
/* Subtract 1 to convert try count to retry count */
- vwrq->value = adapter->txretrycount - 1;
+ vwrq->value = priv->txretrycount - 1;
}
out:
@@ -546,12 +550,11 @@ static inline void sort_channels(struct iw_freq *freq, int num)
* @param extra A pointer to extra data buf
* @return 0 --success, otherwise fail
*/
-static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
int i, j;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct iw_range *range = (struct iw_range *)extra;
struct chan_freq_power *cfp;
u8 rates[MAX_RATES + 1];
@@ -567,7 +570,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
range->max_nwid = 0;
memset(rates, 0, sizeof(rates));
- copy_active_data_rates(adapter, rates);
+ copy_active_data_rates(priv, rates);
range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
for (i = 0; i < range->num_bitrates; i++)
range->bitrate[i] = rates[i] * 500000;
@@ -576,13 +579,14 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
range->num_bitrates);
range->num_frequency = 0;
- if (priv->adapter->enable11d &&
- adapter->connect_status == LIBERTAS_CONNECTED) {
+ if (priv->enable11d &&
+ (priv->connect_status == LBS_CONNECTED ||
+ priv->mesh_connect_status == LBS_CONNECTED)) {
u8 chan_no;
u8 band;
struct parsed_region_chan_11d *parsed_region_chan =
- &adapter->parsed_region_chan;
+ &priv->parsed_region_chan;
if (parsed_region_chan == NULL) {
lbs_deb_wext("11d: parsed_region_chan is NULL\n");
@@ -598,7 +602,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
lbs_deb_wext("chan_no %d\n", chan_no);
range->freq[range->num_frequency].i = (long)chan_no;
range->freq[range->num_frequency].m =
- (long)libertas_chan_2_freq(chan_no, band) * 100000;
+ (long)lbs_chan_2_freq(chan_no, band) * 100000;
range->freq[range->num_frequency].e = 1;
range->num_frequency++;
}
@@ -606,13 +610,12 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
}
if (!flag) {
for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
- && (j < sizeof(adapter->region_channel)
- / sizeof(adapter->region_channel[0])); j++) {
- cfp = adapter->region_channel[j].CFP;
+ && (j < ARRAY_SIZE(priv->region_channel)); j++) {
+ cfp = priv->region_channel[j].CFP;
for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
- && adapter->region_channel[j].valid
+ && priv->region_channel[j].valid
&& cfp
- && (i < adapter->region_channel[j].nrcfp); i++) {
+ && (i < priv->region_channel[j].nrcfp); i++) {
range->freq[range->num_frequency].i =
(long)cfp->channel;
range->freq[range->num_frequency].m =
@@ -712,7 +715,7 @@ static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
range->event_capa[1] = IW_EVENT_CAPA_K_1;
- if (adapter->fwcapinfo & FW_CAPINFO_WPA) {
+ if (priv->fwcapinfo & FW_CAPINFO_WPA) {
range->enc_capa = IW_ENC_CAPA_WPA
| IW_ENC_CAPA_WPA2
| IW_ENC_CAPA_CIPHER_TKIP
@@ -724,22 +727,28 @@ out:
return 0;
}
-static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
+ if (!priv->ps_supported) {
+ if (vwrq->disabled)
+ return 0;
+ else
+ return -EINVAL;
+ }
+
/* PS is currently supported only in Infrastructure mode
* Remove this check if it is to be supported in IBSS mode also
*/
if (vwrq->disabled) {
- adapter->psmode = WLAN802_11POWERMODECAM;
- if (adapter->psstate != PS_STATE_FULL_POWER) {
- libertas_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
+ priv->psmode = LBS802_11POWERMODECAM;
+ if (priv->psstate != PS_STATE_FULL_POWER) {
+ lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
}
return 0;
@@ -754,33 +763,32 @@ static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
return -EINVAL;
}
- if (adapter->psmode != WLAN802_11POWERMODECAM) {
+ if (priv->psmode != LBS802_11POWERMODECAM) {
return 0;
}
- adapter->psmode = WLAN802_11POWERMODEMAX_PSP;
+ priv->psmode = LBS802_11POWERMODEMAX_PSP;
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- libertas_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
+ if (priv->connect_status == LBS_CONNECTED) {
+ lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
}
lbs_deb_leave(LBS_DEB_WEXT);
return 0;
}
-static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int mode;
lbs_deb_enter(LBS_DEB_WEXT);
- mode = adapter->psmode;
+ mode = priv->psmode;
- if ((vwrq->disabled = (mode == WLAN802_11POWERMODECAM))
- || adapter->connect_status == LIBERTAS_DISCONNECTED)
+ if ((vwrq->disabled = (mode == LBS802_11POWERMODECAM))
+ || priv->connect_status == LBS_DISCONNECTED)
{
goto out;
}
@@ -792,7 +800,7 @@ out:
return 0;
}
-static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
{
enum {
POOR = 30,
@@ -802,8 +810,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
EXCELLENT = 95,
PERFECT = 100
};
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
u32 rssi_qual;
u32 tx_qual;
u32 quality = 0;
@@ -813,22 +820,23 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
lbs_deb_enter(LBS_DEB_WEXT);
- priv->wstats.status = adapter->mode;
+ priv->wstats.status = priv->mode;
/* If we're not associated, all quality values are meaningless */
- if (adapter->connect_status != LIBERTAS_CONNECTED)
+ if ((priv->connect_status != LBS_CONNECTED) &&
+ (priv->mesh_connect_status != LBS_CONNECTED))
goto out;
/* Quality by RSSI */
priv->wstats.qual.level =
- CAL_RSSI(adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
- adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+ CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
+ priv->NF[TYPE_BEACON][TYPE_NOAVG]);
- if (adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+ if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
} else {
priv->wstats.qual.noise =
- CAL_NF(adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+ CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
}
lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
@@ -852,7 +860,7 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
/* Quality by TX errors */
priv->wstats.discard.retries = priv->stats.tx_errors;
- tx_retries = le32_to_cpu(adapter->logmsg.retry);
+ tx_retries = le32_to_cpu(priv->logmsg.retry);
if (tx_retries > 75)
tx_qual = (90 - tx_retries) * POOR / 15;
@@ -868,10 +876,10 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
(PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
quality = min(quality, tx_qual);
- priv->wstats.discard.code = le32_to_cpu(adapter->logmsg.wepundecryptable);
- priv->wstats.discard.fragment = le32_to_cpu(adapter->logmsg.rxfrag);
+ priv->wstats.discard.code = le32_to_cpu(priv->logmsg.wepundecryptable);
+ priv->wstats.discard.fragment = le32_to_cpu(priv->logmsg.rxfrag);
priv->wstats.discard.retries = tx_retries;
- priv->wstats.discard.misc = le32_to_cpu(adapter->logmsg.ackfailure);
+ priv->wstats.discard.misc = le32_to_cpu(priv->logmsg.ackfailure);
/* Calculate quality */
priv->wstats.qual.qual = min_t(u8, quality, 100);
@@ -879,9 +887,9 @@ static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
stats_valid = 1;
/* update stats asynchronously for future calls */
- libertas_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+ lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
0, 0, NULL);
- libertas_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
+ lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
0, 0, NULL);
out:
if (!stats_valid) {
@@ -901,19 +909,18 @@ out:
}
-static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
int ret = -EINVAL;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct chan_freq_power *cfp;
struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
goto out;
@@ -923,7 +930,7 @@ static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
if (fwrq->e == 1) {
long f = fwrq->m / 100000;
- cfp = find_cfp_by_band_and_freq(adapter, 0, f);
+ cfp = find_cfp_by_band_and_freq(priv, 0, f);
if (!cfp) {
lbs_deb_wext("invalid freq %ld\n", f);
goto out;
@@ -938,7 +945,7 @@ static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
goto out;
}
- cfp = libertas_find_cfp_by_band_and_channel(adapter, 0, fwrq->m);
+ cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
if (!cfp) {
goto out;
}
@@ -949,23 +956,71 @@ static int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
out:
if (ret == 0) {
set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
} else {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
+ }
+ mutex_unlock(&priv->lock);
+
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
+}
+
+static int lbs_mesh_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_freq *fwrq, char *extra)
+{
+ struct lbs_private *priv = dev->priv;
+ struct chan_freq_power *cfp;
+ int ret = -EINVAL;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ /* If setting by frequency, convert to a channel */
+ if (fwrq->e == 1) {
+ long f = fwrq->m / 100000;
+
+ cfp = find_cfp_by_band_and_freq(priv, 0, f);
+ if (!cfp) {
+ lbs_deb_wext("invalid freq %ld\n", f);
+ goto out;
+ }
+
+ fwrq->e = 0;
+ fwrq->m = (int) cfp->channel;
+ }
+
+ /* Setting by channel number */
+ if (fwrq->m > 1000 || fwrq->e > 0) {
+ goto out;
+ }
+
+ cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
+ if (!cfp) {
+ goto out;
+ }
+
+ if (fwrq->m != priv->curbssparams.channel) {
+ lbs_deb_wext("mesh channel change forces eth disconnect\n");
+ if (priv->mode == IW_MODE_INFRA)
+ lbs_send_deauthentication(priv);
+ else if (priv->mode == IW_MODE_ADHOC)
+ lbs_stop_adhoc_network(priv);
}
- mutex_unlock(&adapter->lock);
+ lbs_mesh_config(priv, 1, fwrq->m);
+ lbs_update_channel(priv);
+ ret = 0;
+out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
- u32 new_rate;
- u16 action;
+ struct lbs_private *priv = dev->priv;
+ u8 new_rate = 0;
int ret = -EINVAL;
u8 rates[MAX_RATES + 1];
@@ -974,15 +1029,14 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
/* Auto rate? */
if (vwrq->value == -1) {
- action = CMD_ACT_SET_TX_AUTO;
- adapter->auto_rate = 1;
- adapter->cur_rate = 0;
+ priv->auto_rate = 1;
+ priv->cur_rate = 0;
} else {
if (vwrq->value % 100000)
goto out;
memset(rates, 0, sizeof(rates));
- copy_active_data_rates(adapter, rates);
+ copy_active_data_rates(priv, rates);
new_rate = vwrq->value / 500000;
if (!memchr(rates, new_rate, sizeof(rates))) {
lbs_pr_alert("fixed data rate 0x%X out of range\n",
@@ -990,31 +1044,28 @@ static int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
goto out;
}
- adapter->cur_rate = new_rate;
- action = CMD_ACT_SET_TX_FIX_RATE;
- adapter->auto_rate = 0;
+ priv->cur_rate = new_rate;
+ priv->auto_rate = 0;
}
- ret = libertas_prepare_and_send_command(priv, CMD_802_11_DATA_RATE,
- action, CMD_OPTION_WAITFORRSP, 0, NULL);
+ ret = lbs_set_data_rate(priv, new_rate);
out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- vwrq->value = adapter->cur_rate * 500000;
+ if (priv->connect_status == LBS_CONNECTED) {
+ vwrq->value = priv->cur_rate * 500000;
- if (adapter->auto_rate)
+ if (priv->auto_rate)
vwrq->fixed = 0;
else
vwrq->fixed = 1;
@@ -1028,12 +1079,11 @@ static int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_set_mode(struct net_device *dev,
+static int lbs_set_mode(struct net_device *dev,
struct iw_request_info *info, u32 * uwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1046,18 +1096,18 @@ static int wlan_set_mode(struct net_device *dev,
goto out;
}
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
} else {
assoc_req->mode = *uwrq;
set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
@@ -1074,23 +1124,22 @@ out:
* @param extra A pointer to extra data buf
* @return 0 --success, otherwise fail
*/
-static int wlan_get_encode(struct net_device *dev,
+static int lbs_get_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, u8 * extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
lbs_deb_enter(LBS_DEB_WEXT);
lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
- dwrq->flags, index, dwrq->length, adapter->wep_tx_keyidx);
+ dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx);
dwrq->flags = 0;
/* Authentication method */
- switch (adapter->secinfo.auth_mode) {
+ switch (priv->secinfo.auth_mode) {
case IW_AUTH_ALG_OPEN_SYSTEM:
dwrq->flags = IW_ENCODE_OPEN;
break;
@@ -1104,41 +1153,32 @@ static int wlan_get_encode(struct net_device *dev,
break;
}
- if ( adapter->secinfo.wep_enabled
- || adapter->secinfo.WPAenabled
- || adapter->secinfo.WPA2enabled) {
- dwrq->flags &= ~IW_ENCODE_DISABLED;
- } else {
- dwrq->flags |= IW_ENCODE_DISABLED;
- }
-
memset(extra, 0, 16);
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
/* Default to returning current transmit key */
if (index < 0)
- index = adapter->wep_tx_keyidx;
+ index = priv->wep_tx_keyidx;
- if ((adapter->wep_keys[index].len) && adapter->secinfo.wep_enabled) {
- memcpy(extra, adapter->wep_keys[index].key,
- adapter->wep_keys[index].len);
- dwrq->length = adapter->wep_keys[index].len;
+ if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) {
+ memcpy(extra, priv->wep_keys[index].key,
+ priv->wep_keys[index].len);
+ dwrq->length = priv->wep_keys[index].len;
dwrq->flags |= (index + 1);
/* Return WEP enabled */
dwrq->flags &= ~IW_ENCODE_DISABLED;
- } else if ((adapter->secinfo.WPAenabled)
- || (adapter->secinfo.WPA2enabled)) {
+ } else if ((priv->secinfo.WPAenabled)
+ || (priv->secinfo.WPA2enabled)) {
/* return WPA enabled */
dwrq->flags &= ~IW_ENCODE_DISABLED;
+ dwrq->flags |= IW_ENCODE_NOKEY;
} else {
dwrq->flags |= IW_ENCODE_DISABLED;
}
- mutex_unlock(&adapter->lock);
-
- dwrq->flags |= IW_ENCODE_NOKEY;
+ mutex_unlock(&priv->lock);
lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
extra[0], extra[1], extra[2],
@@ -1160,7 +1200,7 @@ static int wlan_get_encode(struct net_device *dev,
* @param set_tx_key Force set TX key (1 = yes, 0 = no)
* @return 0 --success, otherwise fail
*/
-static int wlan_set_wep_key(struct assoc_request *assoc_req,
+static int lbs_set_wep_key(struct assoc_request *assoc_req,
const char *key_material,
u16 key_length,
u16 index,
@@ -1278,20 +1318,19 @@ static void disable_wpa(struct assoc_request *assoc_req)
* @param extra A pointer to extra data buf
* @return 0 --success, otherwise fail
*/
-static int wlan_set_encode(struct net_device *dev,
+static int lbs_set_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct assoc_request * assoc_req;
u16 is_default = 0, index = 0, set_tx_key = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
goto out;
@@ -1317,7 +1356,7 @@ static int wlan_set_encode(struct net_device *dev,
if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
set_tx_key = 1;
- ret = wlan_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
+ ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
if (ret)
goto out;
@@ -1335,11 +1374,11 @@ static int wlan_set_encode(struct net_device *dev,
out:
if (ret == 0) {
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
} else {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
@@ -1354,14 +1393,13 @@ out:
* @param extra A pointer to extra data buf
* @return 0 on success, otherwise failure
*/
-static int wlan_get_encodeext(struct net_device *dev,
+static int lbs_get_encodeext(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
int ret = -EINVAL;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int index, max_key_len;
@@ -1377,46 +1415,46 @@ static int wlan_get_encodeext(struct net_device *dev,
goto out;
index--;
} else {
- index = adapter->wep_tx_keyidx;
+ index = priv->wep_tx_keyidx;
}
- if (!ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY &&
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
ext->alg != IW_ENCODE_ALG_WEP) {
- if (index != 0 || adapter->mode != IW_MODE_INFRA)
+ if (index != 0 || priv->mode != IW_MODE_INFRA)
goto out;
}
dwrq->flags = index + 1;
memset(ext, 0, sizeof(*ext));
- if ( !adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled) {
+ if ( !priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled
+ && !priv->secinfo.WPA2enabled) {
ext->alg = IW_ENCODE_ALG_NONE;
ext->key_len = 0;
dwrq->flags |= IW_ENCODE_DISABLED;
} else {
u8 *key = NULL;
- if ( adapter->secinfo.wep_enabled
- && !adapter->secinfo.WPAenabled
- && !adapter->secinfo.WPA2enabled) {
+ if ( priv->secinfo.wep_enabled
+ && !priv->secinfo.WPAenabled
+ && !priv->secinfo.WPA2enabled) {
/* WEP */
ext->alg = IW_ENCODE_ALG_WEP;
- ext->key_len = adapter->wep_keys[index].len;
- key = &adapter->wep_keys[index].key[0];
- } else if ( !adapter->secinfo.wep_enabled
- && (adapter->secinfo.WPAenabled ||
- adapter->secinfo.WPA2enabled)) {
+ ext->key_len = priv->wep_keys[index].len;
+ key = &priv->wep_keys[index].key[0];
+ } else if ( !priv->secinfo.wep_enabled
+ && (priv->secinfo.WPAenabled ||
+ priv->secinfo.WPA2enabled)) {
/* WPA */
struct enc_key * pkey = NULL;
- if ( adapter->wpa_mcast_key.len
- && (adapter->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
- pkey = &adapter->wpa_mcast_key;
- else if ( adapter->wpa_unicast_key.len
- && (adapter->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
- pkey = &adapter->wpa_unicast_key;
+ if ( priv->wpa_mcast_key.len
+ && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_mcast_key;
+ else if ( priv->wpa_unicast_key.len
+ && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
+ pkey = &priv->wpa_unicast_key;
if (pkey) {
if (pkey->type == KEY_TYPE_ID_AES) {
@@ -1461,22 +1499,21 @@ out:
* @param extra A pointer to extra data buf
* @return 0 --success, otherwise fail
*/
-static int wlan_set_encodeext(struct net_device *dev,
+static int lbs_set_encodeext(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int alg = ext->alg;
struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
goto out;
@@ -1503,7 +1540,7 @@ static int wlan_set_encodeext(struct net_device *dev,
set_tx_key = 1;
/* Copy key to driver */
- ret = wlan_set_wep_key (assoc_req, ext->key, ext->key_len, index,
+ ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index,
set_tx_key);
if (ret)
goto out;
@@ -1576,31 +1613,30 @@ static int wlan_set_encodeext(struct net_device *dev,
out:
if (ret == 0) {
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
} else {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-static int wlan_set_genie(struct net_device *dev,
+static int lbs_set_genie(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int ret = 0;
struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
goto out;
@@ -1616,46 +1652,45 @@ static int wlan_set_genie(struct net_device *dev,
memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
assoc_req->wpa_ie_len = dwrq->length;
} else {
- memset(&assoc_req->wpa_ie[0], 0, sizeof(adapter->wpa_ie));
+ memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie));
assoc_req->wpa_ie_len = 0;
}
out:
if (ret == 0) {
set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
} else {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-static int wlan_get_genie(struct net_device *dev,
+static int lbs_get_genie(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq,
char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
- if (adapter->wpa_ie_len == 0) {
+ if (priv->wpa_ie_len == 0) {
dwrq->length = 0;
goto out;
}
- if (dwrq->length < adapter->wpa_ie_len) {
+ if (dwrq->length < priv->wpa_ie_len) {
ret = -E2BIG;
goto out;
}
- dwrq->length = adapter->wpa_ie_len;
- memcpy(extra, &adapter->wpa_ie[0], adapter->wpa_ie_len);
+ dwrq->length = priv->wpa_ie_len;
+ memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
@@ -1663,21 +1698,20 @@ out:
}
-static int wlan_set_auth(struct net_device *dev,
+static int lbs_set_auth(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *dwrq,
char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct assoc_request * assoc_req;
int ret = 0;
int updated = 0;
lbs_deb_enter(LBS_DEB_WEXT);
- mutex_lock(&adapter->lock);
- assoc_req = wlan_get_association_request(adapter);
+ mutex_lock(&priv->lock);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
goto out;
@@ -1752,44 +1786,43 @@ out:
if (ret == 0) {
if (updated)
set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
} else if (ret != -EOPNOTSUPP) {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
-static int wlan_get_auth(struct net_device *dev,
+static int lbs_get_auth(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *dwrq,
char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
switch (dwrq->flags & IW_AUTH_INDEX) {
case IW_AUTH_WPA_VERSION:
dwrq->value = 0;
- if (adapter->secinfo.WPAenabled)
+ if (priv->secinfo.WPAenabled)
dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
- if (adapter->secinfo.WPA2enabled)
+ if (priv->secinfo.WPA2enabled)
dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
if (!dwrq->value)
dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
break;
case IW_AUTH_80211_AUTH_ALG:
- dwrq->value = adapter->secinfo.auth_mode;
+ dwrq->value = priv->secinfo.auth_mode;
break;
case IW_AUTH_WPA_ENABLED:
- if (adapter->secinfo.WPAenabled && adapter->secinfo.WPA2enabled)
+ if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
dwrq->value = 1;
break;
@@ -1802,25 +1835,24 @@ static int wlan_get_auth(struct net_device *dev,
}
-static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
u16 dbm;
lbs_deb_enter(LBS_DEB_WEXT);
if (vwrq->disabled) {
- wlan_radio_ioctl(priv, RADIO_OFF);
+ lbs_radio_ioctl(priv, RADIO_OFF);
return 0;
}
- adapter->preamble = CMD_TYPE_AUTO_PREAMBLE;
+ priv->preamble = CMD_TYPE_AUTO_PREAMBLE;
- wlan_radio_ioctl(priv, RADIO_ON);
+ lbs_radio_ioctl(priv, RADIO_ON);
/* Userspace check in iwrange if it should use dBm or mW,
* therefore this should never happen... Jean II */
@@ -1836,7 +1868,7 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
lbs_deb_wext("txpower set %d dbm\n", dbm);
- ret = libertas_prepare_and_send_command(priv,
+ ret = lbs_prepare_and_send_command(priv,
CMD_802_11_RF_TX_POWER,
CMD_ACT_TX_POWER_OPT_SET_LOW,
CMD_OPTION_WAITFORRSP, 0, (void *)&dbm);
@@ -1845,11 +1877,10 @@ static int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
return ret;
}
-static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
+static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1861,19 +1892,19 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
/*
* Get the current SSID
*/
- if (adapter->connect_status == LIBERTAS_CONNECTED) {
- memcpy(extra, adapter->curbssparams.ssid,
- adapter->curbssparams.ssid_len);
- extra[adapter->curbssparams.ssid_len] = '\0';
+ if (priv->connect_status == LBS_CONNECTED) {
+ memcpy(extra, priv->curbssparams.ssid,
+ priv->curbssparams.ssid_len);
+ extra[priv->curbssparams.ssid_len] = '\0';
} else {
memset(extra, 0, 32);
- extra[adapter->curbssparams.ssid_len] = '\0';
+ extra[priv->curbssparams.ssid_len] = '\0';
}
/*
* If none, we may want to get the one that was set
*/
- dwrq->length = adapter->curbssparams.ssid_len;
+ dwrq->length = priv->curbssparams.ssid_len;
dwrq->flags = 1; /* active */
@@ -1881,11 +1912,10 @@ static int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
return 0;
}
-static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
int ret = 0;
u8 ssid[IW_ESSID_MAX_SIZE];
u8 ssid_len = 0;
@@ -1918,10 +1948,10 @@ static int wlan_set_essid(struct net_device *dev, struct iw_request_info *info,
}
out:
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
if (ret == 0) {
/* Get or create the current association request */
- assoc_req = wlan_get_association_request(adapter);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
ret = -ENOMEM;
} else {
@@ -1929,17 +1959,65 @@ out:
memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
assoc_req->ssid_len = ssid_len;
set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
}
}
/* Cancel the association request if there was an error */
if (ret != 0) {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
+ }
+
+ mutex_unlock(&priv->lock);
+
+ lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
+ return ret;
+}
+
+static int lbs_mesh_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ struct lbs_private *priv = dev->priv;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len);
+
+ dwrq->length = priv->mesh_ssid_len;
+
+ dwrq->flags = 1; /* active */
+
+ lbs_deb_leave(LBS_DEB_WEXT);
+ return 0;
+}
+
+static int lbs_mesh_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *dwrq, char *extra)
+{
+ struct lbs_private *priv = dev->priv;
+ int ret = 0;
+
+ lbs_deb_enter(LBS_DEB_WEXT);
+
+ /* Check the size of the string */
+ if (dwrq->length > IW_ESSID_MAX_SIZE) {
+ ret = -E2BIG;
+ goto out;
}
- mutex_unlock(&adapter->lock);
+ if (!dwrq->flags || !dwrq->length) {
+ ret = -EINVAL;
+ goto out;
+ } else {
+ /* Specific SSID requested */
+ memcpy(priv->mesh_ssid, extra, dwrq->length);
+ priv->mesh_ssid_len = dwrq->length;
+ }
+ lbs_mesh_config(priv, 1, priv->curbssparams.channel);
+ out:
lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
return ret;
}
@@ -1953,11 +2031,10 @@ out:
* @param extra A pointer to extra data buf
* @return 0 --success, otherwise fail
*/
-static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
+static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
struct sockaddr *awrq, char *extra)
{
- wlan_private *priv = dev->priv;
- wlan_adapter *adapter = priv->adapter;
+ struct lbs_private *priv = dev->priv;
struct assoc_request * assoc_req;
int ret = 0;
DECLARE_MAC_BUF(mac);
@@ -1969,44 +2046,38 @@ static int wlan_set_wap(struct net_device *dev, struct iw_request_info *info,
lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
/* Get or create the current association request */
- assoc_req = wlan_get_association_request(adapter);
+ assoc_req = lbs_get_association_request(priv);
if (!assoc_req) {
- wlan_cancel_association_work(priv);
+ lbs_cancel_association_work(priv);
ret = -ENOMEM;
} else {
/* Copy the BSSID to the association request */
memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
- wlan_postpone_association_work(priv);
+ lbs_postpone_association_work(priv);
}
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
return ret;
}
-void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
+void lbs_get_fwversion(struct lbs_private *priv, char *fwversion, int maxlen)
{
char fwver[32];
- mutex_lock(&adapter->lock);
+ mutex_lock(&priv->lock);
- if (adapter->fwreleasenumber[3] == 0)
- sprintf(fwver, "%u.%u.%u",
- adapter->fwreleasenumber[2],
- adapter->fwreleasenumber[1],
- adapter->fwreleasenumber[0]);
- else
- sprintf(fwver, "%u.%u.%u.p%u",
- adapter->fwreleasenumber[2],
- adapter->fwreleasenumber[1],
- adapter->fwreleasenumber[0],
- adapter->fwreleasenumber[3]);
+ sprintf(fwver, "%u.%u.%u.p%u",
+ priv->fwrelease >> 24 & 0xff,
+ priv->fwrelease >> 16 & 0xff,
+ priv->fwrelease >> 8 & 0xff,
+ priv->fwrelease & 0xff);
- mutex_unlock(&adapter->lock);
+ mutex_unlock(&priv->lock);
snprintf(fwversion, maxlen, fwver);
}
@@ -2014,19 +2085,19 @@ void libertas_get_fwversion(wlan_adapter * adapter, char *fwversion, int maxlen)
/*
* iwconfig settable callbacks
*/
-static const iw_handler wlan_handler[] = {
+static const iw_handler lbs_handler[] = {
(iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) wlan_get_name, /* SIOCGIWNAME */
+ (iw_handler) lbs_get_name, /* SIOCGIWNAME */
(iw_handler) NULL, /* SIOCSIWNWID */
(iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
- (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
- (iw_handler) wlan_set_mode, /* SIOCSIWMODE */
- (iw_handler) wlan_get_mode, /* SIOCGIWMODE */
+ (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) lbs_set_mode, /* SIOCSIWMODE */
+ (iw_handler) lbs_get_mode, /* SIOCGIWMODE */
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWRANGE */
- (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
+ (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
(iw_handler) NULL, /* SIOCSIWPRIV */
(iw_handler) NULL, /* SIOCGIWPRIV */
(iw_handler) NULL, /* SIOCSIWSTATS */
@@ -2035,56 +2106,56 @@ static const iw_handler wlan_handler[] = {
iw_handler_get_spy, /* SIOCGIWSPY */
iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
- (iw_handler) wlan_set_wap, /* SIOCSIWAP */
- (iw_handler) wlan_get_wap, /* SIOCGIWAP */
+ (iw_handler) lbs_set_wap, /* SIOCSIWAP */
+ (iw_handler) lbs_get_wap, /* SIOCGIWAP */
(iw_handler) NULL, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
- (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
- (iw_handler) wlan_set_essid, /* SIOCSIWESSID */
- (iw_handler) wlan_get_essid, /* SIOCGIWESSID */
- (iw_handler) wlan_set_nick, /* SIOCSIWNICKN */
- (iw_handler) wlan_get_nick, /* SIOCGIWNICKN */
+ (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) lbs_set_essid, /* SIOCSIWESSID */
+ (iw_handler) lbs_get_essid, /* SIOCGIWESSID */
+ (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */
+ (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
- (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
- (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
- (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
- (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
- (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
- (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
- (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
- (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
- (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
- (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
- (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
- (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
- (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
+ (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
+ (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
+ (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
+ (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
+ (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
+ (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
+ (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
+ (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
- (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
- (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
- (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
- (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
- (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
+ (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
+ (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
+ (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
+ (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
static const iw_handler mesh_wlan_handler[] = {
(iw_handler) NULL, /* SIOCSIWCOMMIT */
- (iw_handler) wlan_get_name, /* SIOCGIWNAME */
+ (iw_handler) lbs_get_name, /* SIOCGIWNAME */
(iw_handler) NULL, /* SIOCSIWNWID */
(iw_handler) NULL, /* SIOCGIWNWID */
- (iw_handler) wlan_set_freq, /* SIOCSIWFREQ */
- (iw_handler) wlan_get_freq, /* SIOCGIWFREQ */
+ (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */
+ (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
(iw_handler) NULL, /* SIOCSIWMODE */
(iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
(iw_handler) NULL, /* SIOCSIWSENS */
(iw_handler) NULL, /* SIOCGIWSENS */
(iw_handler) NULL, /* SIOCSIWRANGE */
- (iw_handler) wlan_get_range, /* SIOCGIWRANGE */
+ (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
(iw_handler) NULL, /* SIOCSIWPRIV */
(iw_handler) NULL, /* SIOCGIWPRIV */
(iw_handler) NULL, /* SIOCSIWSTATS */
@@ -2097,46 +2168,46 @@ static const iw_handler mesh_wlan_handler[] = {
(iw_handler) NULL, /* SIOCGIWAP */
(iw_handler) NULL, /* SIOCSIWMLME */
(iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
- (iw_handler) libertas_set_scan, /* SIOCSIWSCAN */
- (iw_handler) libertas_get_scan, /* SIOCGIWSCAN */
- (iw_handler) NULL, /* SIOCSIWESSID */
- (iw_handler) NULL, /* SIOCGIWESSID */
+ (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
+ (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
+ (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
+ (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
(iw_handler) NULL, /* SIOCSIWNICKN */
(iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) wlan_set_rate, /* SIOCSIWRATE */
- (iw_handler) wlan_get_rate, /* SIOCGIWRATE */
- (iw_handler) wlan_set_rts, /* SIOCSIWRTS */
- (iw_handler) wlan_get_rts, /* SIOCGIWRTS */
- (iw_handler) wlan_set_frag, /* SIOCSIWFRAG */
- (iw_handler) wlan_get_frag, /* SIOCGIWFRAG */
- (iw_handler) wlan_set_txpow, /* SIOCSIWTXPOW */
- (iw_handler) wlan_get_txpow, /* SIOCGIWTXPOW */
- (iw_handler) wlan_set_retry, /* SIOCSIWRETRY */
- (iw_handler) wlan_get_retry, /* SIOCGIWRETRY */
- (iw_handler) wlan_set_encode, /* SIOCSIWENCODE */
- (iw_handler) wlan_get_encode, /* SIOCGIWENCODE */
- (iw_handler) wlan_set_power, /* SIOCSIWPOWER */
- (iw_handler) wlan_get_power, /* SIOCGIWPOWER */
+ (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
+ (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
+ (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
+ (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
+ (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
+ (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
+ (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
+ (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
+ (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
+ (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
+ (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
+ (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
+ (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
+ (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
(iw_handler) NULL, /* -- hole -- */
(iw_handler) NULL, /* -- hole -- */
- (iw_handler) wlan_set_genie, /* SIOCSIWGENIE */
- (iw_handler) wlan_get_genie, /* SIOCGIWGENIE */
- (iw_handler) wlan_set_auth, /* SIOCSIWAUTH */
- (iw_handler) wlan_get_auth, /* SIOCGIWAUTH */
- (iw_handler) wlan_set_encodeext,/* SIOCSIWENCODEEXT */
- (iw_handler) wlan_get_encodeext,/* SIOCGIWENCODEEXT */
+ (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
+ (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
+ (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
+ (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
+ (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
+ (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
(iw_handler) NULL, /* SIOCSIWPMKSA */
};
-struct iw_handler_def libertas_handler_def = {
- .num_standard = ARRAY_SIZE(wlan_handler),
- .standard = (iw_handler *) wlan_handler,
- .get_wireless_stats = wlan_get_wireless_stats,
+struct iw_handler_def lbs_handler_def = {
+ .num_standard = ARRAY_SIZE(lbs_handler),
+ .standard = (iw_handler *) lbs_handler,
+ .get_wireless_stats = lbs_get_wireless_stats,
};
struct iw_handler_def mesh_handler_def = {
.num_standard = ARRAY_SIZE(mesh_wlan_handler),
.standard = (iw_handler *) mesh_wlan_handler,
- .get_wireless_stats = wlan_get_wireless_stats,
+ .get_wireless_stats = lbs_get_wireless_stats,
};
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 6aa444c7de8d..a563d9a231b6 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -1,11 +1,11 @@
/**
* This file contains definition for IOCTL call.
*/
-#ifndef _WLAN_WEXT_H_
-#define _WLAN_WEXT_H_
+#ifndef _LBS_WEXT_H_
+#define _LBS_WEXT_H_
-/** wlan_ioctl_regrdwr */
-struct wlan_ioctl_regrdwr {
+/** lbs_ioctl_regrdwr */
+struct lbs_ioctl_regrdwr {
/** Which register to access */
u16 whichreg;
/** Read or Write */
@@ -15,9 +15,9 @@ struct wlan_ioctl_regrdwr {
u32 value;
};
-#define WLAN_MONITOR_OFF 0
+#define LBS_MONITOR_OFF 0
-extern struct iw_handler_def libertas_handler_def;
+extern struct iw_handler_def lbs_handler_def;
extern struct iw_handler_def mesh_handler_def;
-#endif /* _WLAN_WEXT_H_ */
+#endif
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index ca6c2da7bc5d..6d13a0d15a0c 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -270,6 +270,37 @@ static inline void set_port_type(struct orinoco_private *priv)
}
}
+#define ORINOCO_MAX_BSS_COUNT 64
+static int orinoco_bss_data_allocate(struct orinoco_private *priv)
+{
+ if (priv->bss_data)
+ return 0;
+
+ priv->bss_data =
+ kzalloc(ORINOCO_MAX_BSS_COUNT * sizeof(bss_element), GFP_KERNEL);
+ if (!priv->bss_data) {
+ printk(KERN_WARNING "Out of memory allocating beacons");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void orinoco_bss_data_free(struct orinoco_private *priv)
+{
+ kfree(priv->bss_data);
+ priv->bss_data = NULL;
+}
+
+static void orinoco_bss_data_init(struct orinoco_private *priv)
+{
+ int i;
+
+ INIT_LIST_HEAD(&priv->bss_free_list);
+ INIT_LIST_HEAD(&priv->bss_list);
+ for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
+ list_add_tail(&priv->bss_data[i].list, &priv->bss_free_list);
+}
+
/********************************************************************/
/* Device methods */
/********************************************************************/
@@ -1083,6 +1114,124 @@ static void orinoco_send_wevents(struct work_struct *work)
orinoco_unlock(priv, &flags);
}
+
+static inline void orinoco_clear_scan_results(struct orinoco_private *priv,
+ unsigned long scan_age)
+{
+ bss_element *bss;
+ bss_element *tmp_bss;
+
+ /* Blow away current list of scan results */
+ list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
+ if (!scan_age ||
+ time_after(jiffies, bss->last_scanned + scan_age)) {
+ list_move_tail(&bss->list, &priv->bss_free_list);
+ /* Don't blow away ->list, just BSS data */
+ memset(bss, 0, sizeof(bss->bss));
+ bss->last_scanned = 0;
+ }
+ }
+}
+
+static int orinoco_process_scan_results(struct net_device *dev,
+ unsigned char *buf,
+ int len)
+{
+ struct orinoco_private *priv = netdev_priv(dev);
+ int offset; /* In the scan data */
+ union hermes_scan_info *atom;
+ int atom_len;
+
+ switch (priv->firmware_type) {
+ case FIRMWARE_TYPE_AGERE:
+ atom_len = sizeof(struct agere_scan_apinfo);
+ offset = 0;
+ break;
+ case FIRMWARE_TYPE_SYMBOL:
+ /* Lack of documentation necessitates this hack.
+ * Different firmwares have 68 or 76 byte long atoms.
+ * We try modulo first. If the length divides by both,
+ * we check what would be the channel in the second
+ * frame for a 68-byte atom. 76-byte atoms have 0 there.
+ * Valid channel cannot be 0. */
+ if (len % 76)
+ atom_len = 68;
+ else if (len % 68)
+ atom_len = 76;
+ else if (len >= 1292 && buf[68] == 0)
+ atom_len = 76;
+ else
+ atom_len = 68;
+ offset = 0;
+ break;
+ case FIRMWARE_TYPE_INTERSIL:
+ offset = 4;
+ if (priv->has_hostscan) {
+ atom_len = le16_to_cpup((__le16 *)buf);
+ /* Sanity check for atom_len */
+ if (atom_len < sizeof(struct prism2_scan_apinfo)) {
+ printk(KERN_ERR "%s: Invalid atom_len in scan "
+ "data: %d\n", dev->name, atom_len);
+ return -EIO;
+ }
+ } else
+ atom_len = offsetof(struct prism2_scan_apinfo, atim);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ /* Check that we got an whole number of atoms */
+ if ((len - offset) % atom_len) {
+ printk(KERN_ERR "%s: Unexpected scan data length %d, "
+ "atom_len %d, offset %d\n", dev->name, len,
+ atom_len, offset);
+ return -EIO;
+ }
+
+ orinoco_clear_scan_results(priv, msecs_to_jiffies(15000));
+
+ /* Read the entries one by one */
+ for (; offset + atom_len <= len; offset += atom_len) {
+ int found = 0;
+ bss_element *bss = NULL;
+
+ /* Get next atom */
+ atom = (union hermes_scan_info *) (buf + offset);
+
+ /* Try to update an existing bss first */
+ list_for_each_entry(bss, &priv->bss_list, list) {
+ if (compare_ether_addr(bss->bss.a.bssid, atom->a.bssid))
+ continue;
+ if (le16_to_cpu(bss->bss.a.essid_len) !=
+ le16_to_cpu(atom->a.essid_len))
+ continue;
+ if (memcmp(bss->bss.a.essid, atom->a.essid,
+ le16_to_cpu(atom->a.essid_len)))
+ continue;
+ found = 1;
+ break;
+ }
+
+ /* Grab a bss off the free list */
+ if (!found && !list_empty(&priv->bss_free_list)) {
+ bss = list_entry(priv->bss_free_list.next,
+ bss_element, list);
+ list_del(priv->bss_free_list.next);
+
+ list_add_tail(&bss->list, &priv->bss_list);
+ }
+
+ if (bss) {
+ /* Always update the BSS to get latest beacon info */
+ memcpy(&bss->bss, atom, sizeof(bss->bss));
+ bss->last_scanned = jiffies;
+ }
+ }
+
+ return 0;
+}
+
static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
{
struct orinoco_private *priv = netdev_priv(dev);
@@ -1208,6 +1357,9 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
union iwreq_data wrqu;
unsigned char *buf;
+ /* Scan is no longer in progress */
+ priv->scan_inprogress = 0;
+
/* Sanity check */
if (len > 4096) {
printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
@@ -1215,15 +1367,6 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
break;
}
- /* We are a strict producer. If the previous scan results
- * have not been consumed, we just have to drop this
- * frame. We can't remove the previous results ourselves,
- * that would be *very* racy... Jean II */
- if (priv->scan_result != NULL) {
- printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name);
- break;
- }
-
/* Allocate buffer for results */
buf = kmalloc(len, GFP_ATOMIC);
if (buf == NULL)
@@ -1248,18 +1391,17 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
}
#endif /* ORINOCO_DEBUG */
- /* Allow the clients to access the results */
- priv->scan_len = len;
- priv->scan_result = buf;
-
- /* Send an empty event to user space.
- * We don't send the received data on the event because
- * it would require us to do complex transcoding, and
- * we want to minimise the work done in the irq handler
- * Use a request to extract the data - Jean II */
- wrqu.data.length = 0;
- wrqu.data.flags = 0;
- wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ if (orinoco_process_scan_results(dev, buf, len) == 0) {
+ /* Send an empty event to user space.
+ * We don't send the received data on the event because
+ * it would require us to do complex transcoding, and
+ * we want to minimise the work done in the irq handler
+ * Use a request to extract the data - Jean II */
+ wrqu.data.length = 0;
+ wrqu.data.flags = 0;
+ wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+ }
+ kfree(buf);
}
break;
case HERMES_INQ_SEC_STAT_AGERE:
@@ -1896,8 +2038,7 @@ static void orinoco_reset(struct work_struct *work)
orinoco_unlock(priv, &flags);
/* Scanning support: Cleanup of driver struct */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
+ orinoco_clear_scan_results(priv, 0);
priv->scan_inprogress = 0;
if (priv->hard_reset) {
@@ -2412,6 +2553,10 @@ struct net_device *alloc_orinocodev(int sizeof_card,
else
priv->card = NULL;
+ if (orinoco_bss_data_allocate(priv))
+ goto err_out_free;
+ orinoco_bss_data_init(priv);
+
/* Setup / override net_device fields */
dev->init = orinoco_init;
dev->hard_start_xmit = orinoco_xmit;
@@ -2447,13 +2592,16 @@ struct net_device *alloc_orinocodev(int sizeof_card,
return dev;
+err_out_free:
+ free_netdev(dev);
+ return NULL;
}
void free_orinocodev(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
- kfree(priv->scan_result);
+ orinoco_bss_data_free(priv);
free_netdev(dev);
}
@@ -3841,23 +3989,10 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
* we access scan variables in priv is critical.
* o scan_inprogress : not touched by irq handler
* o scan_mode : not touched by irq handler
- * o scan_result : irq is strict producer, non-irq is strict
- * consumer.
* o scan_len : synchronised with scan_result
* Before modifying anything on those variables, please think hard !
* Jean II */
- /* If there is still some left-over scan results, get rid of it */
- if (priv->scan_result != NULL) {
- /* What's likely is that a client did crash or was killed
- * between triggering the scan request and reading the
- * results, so we need to reset everything.
- * Some clients that are too slow may suffer from that...
- * Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
- }
-
/* Save flags */
priv->scan_mode = srq->flags;
@@ -3905,169 +4040,125 @@ static int orinoco_ioctl_setscan(struct net_device *dev,
return err;
}
+#define MAX_CUSTOM_LEN 64
+
/* Translate scan data returned from the card to a card independant
* format that the Wireless Tools will understand - Jean II
* Return message length or -errno for fatal errors */
-static inline int orinoco_translate_scan(struct net_device *dev,
- char *buffer,
- char *scan,
- int scan_len)
+static inline char *orinoco_translate_scan(struct net_device *dev,
+ char *current_ev,
+ char *end_buf,
+ union hermes_scan_info *bss,
+ unsigned int last_scanned)
{
struct orinoco_private *priv = netdev_priv(dev);
- int offset; /* In the scan data */
- union hermes_scan_info *atom;
- int atom_len;
u16 capabilities;
u16 channel;
struct iw_event iwe; /* Temporary buffer */
- char * current_ev = buffer;
- char * end_buf = buffer + IW_SCAN_MAX_DATA;
-
- switch (priv->firmware_type) {
- case FIRMWARE_TYPE_AGERE:
- atom_len = sizeof(struct agere_scan_apinfo);
- offset = 0;
- break;
- case FIRMWARE_TYPE_SYMBOL:
- /* Lack of documentation necessitates this hack.
- * Different firmwares have 68 or 76 byte long atoms.
- * We try modulo first. If the length divides by both,
- * we check what would be the channel in the second
- * frame for a 68-byte atom. 76-byte atoms have 0 there.
- * Valid channel cannot be 0. */
- if (scan_len % 76)
- atom_len = 68;
- else if (scan_len % 68)
- atom_len = 76;
- else if (scan_len >= 1292 && scan[68] == 0)
- atom_len = 76;
+ char *p;
+ char custom[MAX_CUSTOM_LEN];
+
+ /* First entry *MUST* be the AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+ /* Other entries will be displayed in the order we give them */
+
+ /* Add the ESSID */
+ iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
+ if (iwe.u.data.length > 32)
+ iwe.u.data.length = 32;
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid);
+
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ capabilities = le16_to_cpu(bss->a.capabilities);
+ if (capabilities & 0x3) {
+ if (capabilities & 0x1)
+ iwe.u.mode = IW_MODE_MASTER;
else
- atom_len = 68;
- offset = 0;
- break;
- case FIRMWARE_TYPE_INTERSIL:
- offset = 4;
- if (priv->has_hostscan) {
- atom_len = le16_to_cpup((__le16 *)scan);
- /* Sanity check for atom_len */
- if (atom_len < sizeof(struct prism2_scan_apinfo)) {
- printk(KERN_ERR "%s: Invalid atom_len in scan data: %d\n",
- dev->name, atom_len);
- return -EIO;
- }
- } else
- atom_len = offsetof(struct prism2_scan_apinfo, atim);
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- /* Check that we got an whole number of atoms */
- if ((scan_len - offset) % atom_len) {
- printk(KERN_ERR "%s: Unexpected scan data length %d, "
- "atom_len %d, offset %d\n", dev->name, scan_len,
- atom_len, offset);
- return -EIO;
- }
-
- /* Read the entries one by one */
- for (; offset + atom_len <= scan_len; offset += atom_len) {
- /* Get next atom */
- atom = (union hermes_scan_info *) (scan + offset);
-
- /* First entry *MUST* be the AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
-
- /* Other entries will be displayed in the order we give them */
-
- /* Add the ESSID */
- iwe.u.data.length = le16_to_cpu(atom->a.essid_len);
- if (iwe.u.data.length > 32)
- iwe.u.data.length = 32;
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
-
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- capabilities = le16_to_cpu(atom->a.capabilities);
- if (capabilities & 0x3) {
- if (capabilities & 0x1)
- iwe.u.mode = IW_MODE_MASTER;
- else
- iwe.u.mode = IW_MODE_ADHOC;
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
- }
-
- channel = atom->s.channel;
- if ( (channel >= 1) && (channel <= NUM_CHANNELS) ) {
- /* Add frequency */
- iwe.cmd = SIOCGIWFREQ;
- iwe.u.freq.m = channel_frequency[channel-1] * 100000;
- iwe.u.freq.e = 1;
- current_ev = iwe_stream_add_event(current_ev, end_buf,
- &iwe, IW_EV_FREQ_LEN);
- }
+ iwe.u.mode = IW_MODE_ADHOC;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+ }
+
+ channel = bss->s.channel;
+ if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
+ /* Add frequency */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = channel_frequency[channel-1] * 100000;
+ iwe.u.freq.e = 1;
+ current_ev = iwe_stream_add_event(current_ev, end_buf,
+ &iwe, IW_EV_FREQ_LEN);
+ }
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = 0x10; /* no link quality */
+ iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
+ iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
+ /* Wireless tools prior to 27.pre22 will show link quality
+ * anyway, so we provide a reasonable value. */
+ if (iwe.u.qual.level > iwe.u.qual.noise)
+ iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
+ else
+ iwe.u.qual.qual = 0;
+ current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- iwe.u.qual.updated = 0x10; /* no link quality */
- iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95;
- iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95;
- /* Wireless tools prior to 27.pre22 will show link quality
- * anyway, so we provide a reasonable value. */
- if (iwe.u.qual.level > iwe.u.qual.noise)
- iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
- else
- iwe.u.qual.qual = 0;
- current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (capabilities & 0x10)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss->a.essid);
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network. */
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ " Last beacon: %dms ago",
+ jiffies_to_msecs(jiffies - last_scanned));
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, custom);
+
+ /* Bit rate is not available in Lucent/Agere firmwares */
+ if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
+ char *current_val = current_ev + IW_EV_LCP_LEN;
+ int i;
+ int step;
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (capabilities & 0x10)
- iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
+ step = 2;
else
- iwe.u.data.flags = IW_ENCODE_DISABLED;
- iwe.u.data.length = 0;
- current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
-
- /* Bit rate is not available in Lucent/Agere firmwares */
- if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
- char * current_val = current_ev + IW_EV_LCP_LEN;
- int i;
- int step;
-
- if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
- step = 2;
- else
- step = 1;
-
- iwe.cmd = SIOCGIWRATE;
- /* Those two flags are ignored... */
- iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
- /* Max 10 values */
- for (i = 0; i < 10; i += step) {
- /* NULL terminated */
- if (atom->p.rates[i] == 0x0)
- break;
- /* Bit rate given in 500 kb/s units (+ 0x80) */
- iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
- current_val = iwe_stream_add_value(current_ev, current_val,
- end_buf, &iwe,
- IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - current_ev) > IW_EV_LCP_LEN)
- current_ev = current_val;
+ step = 1;
+
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+ /* Max 10 values */
+ for (i = 0; i < 10; i += step) {
+ /* NULL terminated */
+ if (bss->p.rates[i] == 0x0)
+ break;
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((bss->p.rates[i] & 0x7f) * 500000);
+ current_val = iwe_stream_add_value(current_ev, current_val,
+ end_buf, &iwe,
+ IW_EV_PARAM_LEN);
}
-
- /* The other data in the scan result are not really
- * interesting, so for now drop it - Jean II */
+ /* Check if we added any event */
+ if ((current_val - current_ev) > IW_EV_LCP_LEN)
+ current_ev = current_val;
}
- return current_ev - buffer;
+
+ return current_ev;
}
/* Return results of a scan */
@@ -4077,68 +4168,45 @@ static int orinoco_ioctl_getscan(struct net_device *dev,
char *extra)
{
struct orinoco_private *priv = netdev_priv(dev);
+ bss_element *bss;
int err = 0;
unsigned long flags;
+ char *current_ev = extra;
if (orinoco_lock(priv, &flags) != 0)
return -EBUSY;
- /* If no results yet, ask to try again later */
- if (priv->scan_result == NULL) {
- if (priv->scan_inprogress)
- /* Important note : we don't want to block the caller
- * until results are ready for various reasons.
- * First, managing wait queues is complex and racy.
- * Second, we grab some rtnetlink lock before comming
- * here (in dev_ioctl()).
- * Third, we generate an Wireless Event, so the
- * caller can wait itself on that - Jean II */
- err = -EAGAIN;
- else
- /* Client error, no scan results...
- * The caller need to restart the scan. */
- err = -ENODATA;
- } else {
- /* We have some results to push back to user space */
-
- /* Translate to WE format */
- int ret = orinoco_translate_scan(dev, extra,
- priv->scan_result,
- priv->scan_len);
-
- if (ret < 0) {
- err = ret;
- kfree(priv->scan_result);
- priv->scan_result = NULL;
- } else {
- srq->length = ret;
+ if (priv->scan_inprogress) {
+ /* Important note : we don't want to block the caller
+ * until results are ready for various reasons.
+ * First, managing wait queues is complex and racy.
+ * Second, we grab some rtnetlink lock before comming
+ * here (in dev_ioctl()).
+ * Third, we generate an Wireless Event, so the
+ * caller can wait itself on that - Jean II */
+ err = -EAGAIN;
+ goto out;
+ }
- /* Return flags */
- srq->flags = (__u16) priv->scan_mode;
+ list_for_each_entry(bss, &priv->bss_list, list) {
+ /* Translate to WE format this entry */
+ current_ev = orinoco_translate_scan(dev, current_ev,
+ extra + srq->length,
+ &bss->bss,
+ bss->last_scanned);
- /* In any case, Scan results will be cleaned up in the
- * reset function and when exiting the driver.
- * The person triggering the scanning may never come to
- * pick the results, so we need to do it in those places.
- * Jean II */
-
-#ifdef SCAN_SINGLE_READ
- /* If you enable this option, only one client (the first
- * one) will be able to read the result (and only one
- * time). If there is multiple concurent clients that
- * want to read scan results, this behavior is not
- * advisable - Jean II */
- kfree(priv->scan_result);
- priv->scan_result = NULL;
-#endif /* SCAN_SINGLE_READ */
- /* Here, if too much time has elapsed since last scan,
- * we may want to clean up scan results... - Jean II */
+ /* Check if there is space for one more entry */
+ if ((extra + srq->length - current_ev) <= IW_EV_ADDR_LEN) {
+ /* Ask user space to try again with a bigger buffer */
+ err = -E2BIG;
+ goto out;
}
-
- /* Scan is no longer in progress */
- priv->scan_inprogress = 0;
}
-
+
+ srq->length = (current_ev - extra);
+ srq->flags = (__u16) priv->scan_mode;
+
+out:
orinoco_unlock(priv, &flags);
return err;
}
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
index 4720fb20d66d..c6b1858abde8 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco.h
@@ -36,6 +36,12 @@ typedef enum {
FIRMWARE_TYPE_SYMBOL
} fwtype_t;
+typedef struct {
+ union hermes_scan_info bss;
+ unsigned long last_scanned;
+ struct list_head list;
+} bss_element;
+
struct orinoco_private {
void *card; /* Pointer to card dependent structure */
int (*hard_reset)(struct orinoco_private *);
@@ -105,10 +111,12 @@ struct orinoco_private {
int promiscuous, mc_count;
/* Scanning support */
+ struct list_head bss_list;
+ struct list_head bss_free_list;
+ bss_element *bss_data;
+
int scan_inprogress; /* Scan pending... */
u32 scan_mode; /* Type of scan done */
- char * scan_result; /* Result of previous scan */
- int scan_len; /* Lenght of result */
};
#ifdef ORINOCO_DEBUG
diff --git a/drivers/net/wireless/p54common.c b/drivers/net/wireless/p54common.c
index 1437db0cf4b2..5cda49aff3a8 100644
--- a/drivers/net/wireless/p54common.c
+++ b/drivers/net/wireless/p54common.c
@@ -54,7 +54,7 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
u32 code = le32_to_cpu(bootrec->code);
switch (code) {
case BR_CODE_COMPONENT_ID:
- switch (be32_to_cpu(*bootrec->data)) {
+ switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
case FW_FMAC:
printk(KERN_INFO "p54: FreeMAC firmware\n");
break;
@@ -78,14 +78,14 @@ void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
fw_version = (unsigned char*)bootrec->data;
break;
case BR_CODE_DESCR:
- priv->rx_start = le32_to_cpu(bootrec->data[1]);
+ priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
/* FIXME add sanity checking */
- priv->rx_end = le32_to_cpu(bootrec->data[2]) - 0x3500;
+ priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
break;
case BR_CODE_EXPOSED_IF:
exp_if = (struct bootrec_exp_if *) bootrec->data;
for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
- if (exp_if[i].if_id == 0x1a)
+ if (exp_if[i].if_id == cpu_to_le16(0x1a))
priv->fw_var = le16_to_cpu(exp_if[i].variant);
break;
case BR_CODE_DEPENDENT_IF:
@@ -314,6 +314,7 @@ static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
rx_status.phymode = MODE_IEEE80211G;
rx_status.antenna = hdr->antenna;
rx_status.mactime = le64_to_cpu(hdr->timestamp);
+ rx_status.flag |= RX_FLAG_TSFT;
skb_pull(skb, sizeof(*hdr));
skb_trim(skb, le16_to_cpu(hdr->len));
@@ -374,7 +375,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
pad = entry_data->align[0];
- if (!status.control.flags & IEEE80211_TXCTL_NO_ACK) {
+ if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
if (!(payload->status & 0x01))
status.flags |= IEEE80211_TX_STATUS_ACK;
else
@@ -853,7 +854,8 @@ static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
return ret;
}
-static int p54_config_interface(struct ieee80211_hw *dev, int if_id,
+static int p54_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct p54_common *priv = dev->priv;
diff --git a/drivers/net/wireless/p54pci.c b/drivers/net/wireless/p54pci.c
index 410b54387f23..fa527723fbe0 100644
--- a/drivers/net/wireless/p54pci.c
+++ b/drivers/net/wireless/p54pci.c
@@ -48,10 +48,10 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
const struct firmware *fw_entry = NULL;
__le32 reg;
int err;
- u32 *data;
+ __le32 *data;
u32 remains, left, device_addr;
- P54P_WRITE(int_enable, 0);
+ P54P_WRITE(int_enable, cpu_to_le32(0));
P54P_READ(int_enable);
udelay(10);
@@ -82,7 +82,7 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
p54_parse_firmware(dev, fw_entry);
- data = (u32 *) fw_entry->data;
+ data = (__le32 *) fw_entry->data;
remains = fw_entry->size;
device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
while (remains) {
@@ -141,6 +141,7 @@ static irqreturn_t p54p_simple_interrupt(int irq, void *dev_id)
static int p54p_read_eeprom(struct ieee80211_hw *dev)
{
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
int err;
struct p54_control_hdr *hdr;
void *eeprom;
@@ -164,8 +165,8 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
goto out;
}
- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
- P54P_WRITE(ring_control_base, priv->ring_control_dma);
+ memset(ring_control, 0, sizeof(*ring_control));
+ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
P54P_READ(ring_control_base);
udelay(10);
@@ -194,14 +195,14 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
tx_mapping = pci_map_single(priv->pdev, (void *)hdr,
EEPROM_READBACK_LEN, PCI_DMA_TODEVICE);
- priv->ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
- priv->ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
- priv->ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
- priv->ring_control->tx_data[0].device_addr = hdr->req_id;
- priv->ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
+ ring_control->rx_mgmt[0].host_addr = cpu_to_le32(rx_mapping);
+ ring_control->rx_mgmt[0].len = cpu_to_le16(0x2010);
+ ring_control->tx_data[0].host_addr = cpu_to_le32(tx_mapping);
+ ring_control->tx_data[0].device_addr = hdr->req_id;
+ ring_control->tx_data[0].len = cpu_to_le16(EEPROM_READBACK_LEN);
- priv->ring_control->host_idx[2] = cpu_to_le32(1);
- priv->ring_control->host_idx[1] = cpu_to_le32(1);
+ ring_control->host_idx[2] = cpu_to_le32(1);
+ ring_control->host_idx[1] = cpu_to_le32(1);
wmb();
mdelay(100);
@@ -215,8 +216,8 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
pci_unmap_single(priv->pdev, rx_mapping,
0x2010, PCI_DMA_FROMDEVICE);
- alen = le16_to_cpu(priv->ring_control->rx_mgmt[0].len);
- if (le32_to_cpu(priv->ring_control->device_idx[2]) != 1 ||
+ alen = le16_to_cpu(ring_control->rx_mgmt[0].len);
+ if (le32_to_cpu(ring_control->device_idx[2]) != 1 ||
alen < 0x10) {
printk(KERN_ERR "%s (prism54pci): Cannot read eeprom!\n",
pci_name(priv->pdev));
@@ -228,7 +229,7 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
out:
kfree(eeprom);
- P54P_WRITE(int_enable, 0);
+ P54P_WRITE(int_enable, cpu_to_le32(0));
P54P_READ(int_enable);
udelay(10);
free_irq(priv->pdev->irq, priv);
@@ -239,16 +240,17 @@ static int p54p_read_eeprom(struct ieee80211_hw *dev)
static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
{
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
u32 limit, host_idx, idx;
- host_idx = le32_to_cpu(priv->ring_control->host_idx[0]);
+ host_idx = le32_to_cpu(ring_control->host_idx[0]);
limit = host_idx;
- limit -= le32_to_cpu(priv->ring_control->device_idx[0]);
- limit = ARRAY_SIZE(priv->ring_control->rx_data) - limit;
+ limit -= le32_to_cpu(ring_control->device_idx[0]);
+ limit = ARRAY_SIZE(ring_control->rx_data) - limit;
- idx = host_idx % ARRAY_SIZE(priv->ring_control->rx_data);
+ idx = host_idx % ARRAY_SIZE(ring_control->rx_data);
while (limit-- > 1) {
- struct p54p_desc *desc = &priv->ring_control->rx_data[idx];
+ struct p54p_desc *desc = &ring_control->rx_data[idx];
if (!desc->host_addr) {
struct sk_buff *skb;
@@ -270,22 +272,23 @@ static void p54p_refill_rx_ring(struct ieee80211_hw *dev)
idx++;
host_idx++;
- idx %= ARRAY_SIZE(priv->ring_control->rx_data);
+ idx %= ARRAY_SIZE(ring_control->rx_data);
}
wmb();
- priv->ring_control->host_idx[0] = cpu_to_le32(host_idx);
+ ring_control->host_idx[0] = cpu_to_le32(host_idx);
}
static irqreturn_t p54p_interrupt(int irq, void *dev_id)
{
struct ieee80211_hw *dev = dev_id;
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
__le32 reg;
spin_lock(&priv->lock);
reg = P54P_READ(int_ident);
- if (unlikely(reg == 0xFFFFFFFF)) {
+ if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) {
spin_unlock(&priv->lock);
return IRQ_HANDLED;
}
@@ -298,12 +301,12 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
struct p54p_desc *desc;
u32 idx, i;
i = priv->tx_idx;
- i %= ARRAY_SIZE(priv->ring_control->tx_data);
- priv->tx_idx = idx = le32_to_cpu(priv->ring_control->device_idx[1]);
- idx %= ARRAY_SIZE(priv->ring_control->tx_data);
+ i %= ARRAY_SIZE(ring_control->tx_data);
+ priv->tx_idx = idx = le32_to_cpu(ring_control->device_idx[1]);
+ idx %= ARRAY_SIZE(ring_control->tx_data);
while (i != idx) {
- desc = &priv->ring_control->tx_data[i];
+ desc = &ring_control->tx_data[i];
if (priv->tx_buf[i]) {
kfree(priv->tx_buf[i]);
priv->tx_buf[i] = NULL;
@@ -318,17 +321,17 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
desc->flags = 0;
i++;
- i %= ARRAY_SIZE(priv->ring_control->tx_data);
+ i %= ARRAY_SIZE(ring_control->tx_data);
}
i = priv->rx_idx;
- i %= ARRAY_SIZE(priv->ring_control->rx_data);
- priv->rx_idx = idx = le32_to_cpu(priv->ring_control->device_idx[0]);
- idx %= ARRAY_SIZE(priv->ring_control->rx_data);
+ i %= ARRAY_SIZE(ring_control->rx_data);
+ priv->rx_idx = idx = le32_to_cpu(ring_control->device_idx[0]);
+ idx %= ARRAY_SIZE(ring_control->rx_data);
while (i != idx) {
u16 len;
struct sk_buff *skb;
- desc = &priv->ring_control->rx_data[i];
+ desc = &ring_control->rx_data[i];
len = le16_to_cpu(desc->len);
skb = priv->rx_buf[i];
@@ -347,7 +350,7 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
}
i++;
- i %= ARRAY_SIZE(priv->ring_control->rx_data);
+ i %= ARRAY_SIZE(ring_control->rx_data);
}
p54p_refill_rx_ring(dev);
@@ -366,6 +369,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
size_t len, int free_on_tx)
{
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
unsigned long flags;
struct p54p_desc *desc;
dma_addr_t mapping;
@@ -373,19 +377,19 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
spin_lock_irqsave(&priv->lock, flags);
- device_idx = le32_to_cpu(priv->ring_control->device_idx[1]);
- idx = le32_to_cpu(priv->ring_control->host_idx[1]);
- i = idx % ARRAY_SIZE(priv->ring_control->tx_data);
+ device_idx = le32_to_cpu(ring_control->device_idx[1]);
+ idx = le32_to_cpu(ring_control->host_idx[1]);
+ i = idx % ARRAY_SIZE(ring_control->tx_data);
mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
- desc = &priv->ring_control->tx_data[i];
+ desc = &ring_control->tx_data[i];
desc->host_addr = cpu_to_le32(mapping);
desc->device_addr = data->req_id;
desc->len = cpu_to_le16(len);
desc->flags = 0;
wmb();
- priv->ring_control->host_idx[1] = cpu_to_le32(idx + 1);
+ ring_control->host_idx[1] = cpu_to_le32(idx + 1);
if (free_on_tx)
priv->tx_buf[i] = data;
@@ -397,7 +401,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
/* FIXME: unlikely to happen because the device usually runs out of
memory before we fill the ring up, but we can make it impossible */
- if (idx - device_idx > ARRAY_SIZE(priv->ring_control->tx_data) - 2)
+ if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
}
@@ -421,7 +425,7 @@ static int p54p_open(struct ieee80211_hw *dev)
p54p_upload_firmware(dev);
- P54P_WRITE(ring_control_base, priv->ring_control_dma);
+ P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma));
P54P_READ(ring_control_base);
wmb();
udelay(10);
@@ -457,10 +461,11 @@ static int p54p_open(struct ieee80211_hw *dev)
static void p54p_stop(struct ieee80211_hw *dev)
{
struct p54p_priv *priv = dev->priv;
+ struct p54p_ring_control *ring_control = priv->ring_control;
unsigned int i;
struct p54p_desc *desc;
- P54P_WRITE(int_enable, 0);
+ P54P_WRITE(int_enable, cpu_to_le32(0));
P54P_READ(int_enable);
udelay(10);
@@ -469,7 +474,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET));
for (i = 0; i < ARRAY_SIZE(priv->rx_buf); i++) {
- desc = &priv->ring_control->rx_data[i];
+ desc = &ring_control->rx_data[i];
if (desc->host_addr)
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
@@ -478,7 +483,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
}
for (i = 0; i < ARRAY_SIZE(priv->tx_buf); i++) {
- desc = &priv->ring_control->tx_data[i];
+ desc = &ring_control->tx_data[i];
if (desc->host_addr)
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
le16_to_cpu(desc->len), PCI_DMA_TODEVICE);
@@ -487,7 +492,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
priv->tx_buf[i] = NULL;
}
- memset(priv->ring_control, 0, sizeof(*priv->ring_control));
+ memset(ring_control, 0, sizeof(ring_control));
}
static int __devinit p54p_probe(struct pci_dev *pdev,
diff --git a/drivers/net/wireless/p54pci.h b/drivers/net/wireless/p54pci.h
index 52feb597dc4a..5bedd7af385d 100644
--- a/drivers/net/wireless/p54pci.h
+++ b/drivers/net/wireless/p54pci.h
@@ -85,8 +85,8 @@ struct p54p_ring_control {
struct p54p_desc tx_mgmt[4];
} __attribute__ ((packed));
-#define P54P_READ(r) __raw_readl(&priv->map->r)
-#define P54P_WRITE(r, val) __raw_writel((__force u32)(val), &priv->map->r)
+#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r)
+#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r)
struct p54p_priv {
struct p54_common common;
diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h
index 3fadcb6f5297..19c33d313734 100644
--- a/drivers/net/wireless/prism54/isl_38xx.h
+++ b/drivers/net/wireless/prism54/isl_38xx.h
@@ -138,14 +138,14 @@ isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset)
#define MAX_FRAGMENT_SIZE_RX 1600
typedef struct {
- u32 address; /* physical address on host */
- u16 size; /* packet size */
- u16 flags; /* set of bit-wise flags */
+ __le32 address; /* physical address on host */
+ __le16 size; /* packet size */
+ __le16 flags; /* set of bit-wise flags */
} isl38xx_fragment;
struct isl38xx_cb {
- u32 driver_curr_frag[ISL38XX_CB_QCOUNT];
- u32 device_curr_frag[ISL38XX_CB_QCOUNT];
+ __le32 driver_curr_frag[ISL38XX_CB_QCOUNT];
+ __le32 device_curr_frag[ISL38XX_CB_QCOUNT];
isl38xx_fragment rx_data_low[ISL38XX_CB_RX_QSIZE];
isl38xx_fragment tx_data_low[ISL38XX_CB_TX_QSIZE];
isl38xx_fragment rx_data_high[ISL38XX_CB_RX_QSIZE];
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 6d80ca421cf0..1b595a6525f4 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -165,8 +165,7 @@ prism54_update_stats(struct work_struct *work)
struct obj_bss bss, *bss2;
union oid_res_t r;
- if (down_interruptible(&priv->stats_sem))
- return;
+ down(&priv->stats_sem);
/* Noise floor.
* I'm not sure if the unit is dBm.
@@ -1118,7 +1117,7 @@ prism54_set_encode(struct net_device *ndev, struct iw_request_info *info,
mgt_set_request(priv, DOT11_OID_DEFKEYID, 0,
&index);
} else {
- if (!dwrq->flags & IW_ENCODE_MODE) {
+ if (!(dwrq->flags & IW_ENCODE_MODE)) {
/* we cannot do anything. Complain. */
return -EINVAL;
}
@@ -1793,8 +1792,7 @@ prism54_clear_mac(struct islpci_acl *acl)
struct list_head *ptr, *next;
struct mac_entry *entry;
- if (down_interruptible(&acl->sem))
- return;
+ down(&acl->sem);
if (acl->size == 0) {
up(&acl->sem);
@@ -2116,8 +2114,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
if (wpa_ie_len > MAX_WPA_IE_LEN)
wpa_ie_len = MAX_WPA_IE_LEN;
- if (down_interruptible(&priv->wpa_sem))
- return;
+ down(&priv->wpa_sem);
/* try to use existing entry */
list_for_each(ptr, &priv->bss_wpa_list) {
@@ -2178,8 +2175,7 @@ prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie)
struct islpci_bss_wpa_ie *bss = NULL;
size_t len = 0;
- if (down_interruptible(&priv->wpa_sem))
- return 0;
+ down(&priv->wpa_sem);
list_for_each(ptr, &priv->bss_wpa_list) {
bss = list_entry(ptr, struct islpci_bss_wpa_ie, list);
@@ -2610,7 +2606,7 @@ prism2_ioctl_set_encryption(struct net_device *dev,
mgt_set_request(priv, DOT11_OID_DEFKEYID, 0,
&index);
} else {
- if (!param->u.crypt.flags & IW_ENCODE_MODE) {
+ if (!(param->u.crypt.flags & IW_ENCODE_MODE)) {
/* we cannot do anything. Complain. */
return -EINVAL;
}
diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c
index 219dd651dc41..dbb538ccb4ec 100644
--- a/drivers/net/wireless/prism54/islpci_dev.c
+++ b/drivers/net/wireless/prism54/islpci_dev.c
@@ -861,7 +861,7 @@ islpci_setup(struct pci_dev *pdev)
init_waitqueue_head(&priv->reset_done);
/* init the queue read locks, process wait counter */
- sema_init(&priv->mgmt_sem, 1);
+ mutex_init(&priv->mgmt_lock);
priv->mgmt_received = NULL;
init_waitqueue_head(&priv->mgmt_wqueue);
sema_init(&priv->stats_sem, 1);
diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h
index 736666da6c24..4e0182ce835b 100644
--- a/drivers/net/wireless/prism54/islpci_dev.h
+++ b/drivers/net/wireless/prism54/islpci_dev.h
@@ -26,6 +26,7 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <linux/list.h>
+#include <linux/mutex.h>
#include "isl_38xx.h"
#include "isl_oid.h"
@@ -164,7 +165,7 @@ typedef struct {
wait_queue_head_t reset_done;
/* used by islpci_mgt_transaction */
- struct semaphore mgmt_sem; /* serialize access to mailbox and wqueue */
+ struct mutex mgmt_lock; /* serialize access to mailbox and wqueue */
struct islpci_mgmtframe *mgmt_received; /* mbox for incoming frame */
wait_queue_head_t mgmt_wqueue; /* waitqueue for mbox */
diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c
index f49eb068c7d0..762e85bef55d 100644
--- a/drivers/net/wireless/prism54/islpci_eth.c
+++ b/drivers/net/wireless/prism54/islpci_eth.c
@@ -471,7 +471,7 @@ islpci_eth_receive(islpci_private *priv)
wmb();
/* increment the driver read pointer */
- add_le32p((u32 *) &control_block->
+ add_le32p(&control_block->
driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1);
}
diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h
index 5bf820defbd0..61454d32d74d 100644
--- a/drivers/net/wireless/prism54/islpci_eth.h
+++ b/drivers/net/wireless/prism54/islpci_eth.h
@@ -23,15 +23,15 @@
#include "islpci_dev.h"
struct rfmon_header {
- u16 unk0; /* = 0x0000 */
- u16 length; /* = 0x1400 */
- u32 clock; /* 1MHz clock */
+ __le16 unk0; /* = 0x0000 */
+ __le16 length; /* = 0x1400 */
+ __le32 clock; /* 1MHz clock */
u8 flags;
u8 unk1;
u8 rate;
u8 unk2;
- u16 freq;
- u16 unk3;
+ __le16 freq;
+ __le16 unk3;
u8 rssi;
u8 padding[3];
} __attribute__ ((packed));
@@ -47,20 +47,20 @@ struct rx_annex_header {
#define P80211CAPTURE_VERSION 0x80211001
struct avs_80211_1_header {
- uint32_t version;
- uint32_t length;
- uint64_t mactime;
- uint64_t hosttime;
- uint32_t phytype;
- uint32_t channel;
- uint32_t datarate;
- uint32_t antenna;
- uint32_t priority;
- uint32_t ssi_type;
- int32_t ssi_signal;
- int32_t ssi_noise;
- uint32_t preamble;
- uint32_t encoding;
+ __be32 version;
+ __be32 length;
+ __be64 mactime;
+ __be64 hosttime;
+ __be32 phytype;
+ __be32 channel;
+ __be32 datarate;
+ __be32 antenna;
+ __be32 priority;
+ __be32 ssi_type;
+ __be32 ssi_signal;
+ __be32 ssi_noise;
+ __be32 preamble;
+ __be32 encoding;
};
void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *);
diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c
index 2246f7930b4e..f7c677e2094d 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/prism54/islpci_mgt.c
@@ -460,7 +460,7 @@ islpci_mgt_transaction(struct net_device *ndev,
*recvframe = NULL;
- if (down_interruptible(&priv->mgmt_sem))
+ if (mutex_lock_interruptible(&priv->mgmt_lock))
return -ERESTARTSYS;
prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE);
@@ -504,7 +504,7 @@ islpci_mgt_transaction(struct net_device *ndev,
/* TODO: we should reset the device here */
out:
finish_wait(&priv->mgmt_wqueue, &wait);
- up(&priv->mgmt_sem);
+ mutex_unlock(&priv->mgmt_lock);
return err;
}
diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h
index fc53b587b722..f91a88fc1e35 100644
--- a/drivers/net/wireless/prism54/islpci_mgt.h
+++ b/drivers/net/wireless/prism54/islpci_mgt.h
@@ -86,7 +86,7 @@ extern int pc_debug;
#define PIMFOR_FLAG_LITTLE_ENDIAN 0x02
static inline void
-add_le32p(u32 * le_number, u32 add)
+add_le32p(__le32 * le_number, u32 add)
{
*le_number = cpu_to_le32(le32_to_cpup(le_number) + add);
}
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index f87fe10059ae..f3858ee36f32 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -44,6 +44,7 @@
#include <linux/ioport.h>
#include <linux/skbuff.h>
#include <linux/ethtool.h>
+#include <linux/ieee80211.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
@@ -997,13 +998,13 @@ static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data,
int len)
{
- unsigned short int proto = ((struct ethhdr *)data)->h_proto;
+ __be16 proto = ((struct ethhdr *)data)->h_proto;
if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
DEBUG(3,"ray_cs translate_frame DIX II\n");
/* Copy LLC header to card buffer */
memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
- if ((proto == 0xf380) || (proto == 0x3781)) {
+ if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) {
/* This is the selective translation table, only 2 entries */
writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]);
}
@@ -1014,7 +1015,7 @@ static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigne
}
else { /* already 802 type, and proto is length */
DEBUG(3,"ray_cs translate_frame 802\n");
- if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */
+ if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */
DEBUG(3,"ray_cs translate_frame evil IPX\n");
memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN);
return 0 - ETH_HLEN;
@@ -1780,19 +1781,19 @@ static struct net_device_stats *ray_get_stats(struct net_device *dev)
}
if (readb(&p->mrx_overflow_for_host))
{
- local->stats.rx_over_errors += ntohs(readb(&p->mrx_overflow));
+ local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow));
writeb(0,&p->mrx_overflow);
writeb(0,&p->mrx_overflow_for_host);
}
if (readb(&p->mrx_checksum_error_for_host))
{
- local->stats.rx_crc_errors += ntohs(readb(&p->mrx_checksum_error));
+ local->stats.rx_crc_errors += swab16(readw(&p->mrx_checksum_error));
writeb(0,&p->mrx_checksum_error);
writeb(0,&p->mrx_checksum_error_for_host);
}
if (readb(&p->rx_hec_error_for_host))
{
- local->stats.rx_frame_errors += ntohs(readb(&p->rx_hec_error));
+ local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error));
writeb(0,&p->rx_hec_error);
writeb(0,&p->rx_hec_error_for_host);
}
@@ -2316,32 +2317,17 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned i
static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
{
snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH);
- struct mac_header *pmac = (struct mac_header *)skb->data;
- unsigned short type = *(unsigned short *)psnap->ethertype;
- unsigned int xsap = *(unsigned int *)psnap & 0x00ffffff;
- unsigned int org = (*(unsigned int *)psnap->org) & 0x00ffffff;
+ struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data;
+ __be16 type = *(__be16 *)psnap->ethertype;
int delta;
struct ethhdr *peth;
UCHAR srcaddr[ADDRLEN];
UCHAR destaddr[ADDRLEN];
+ static UCHAR org_bridge[3] = {0, 0, 0xf8};
+ static UCHAR org_1042[3] = {0, 0, 0};
- if (pmac->frame_ctl_2 & FC2_FROM_DS) {
- if (pmac->frame_ctl_2 & FC2_TO_DS) { /* AP to AP */
- memcpy(destaddr, pmac->addr_3, ADDRLEN);
- memcpy(srcaddr, ((unsigned char *)pmac->addr_3) + ADDRLEN, ADDRLEN);
- } else { /* AP to terminal */
- memcpy(destaddr, pmac->addr_1, ADDRLEN);
- memcpy(srcaddr, pmac->addr_3, ADDRLEN);
- }
- } else { /* Terminal to AP */
- if (pmac->frame_ctl_2 & FC2_TO_DS) {
- memcpy(destaddr, pmac->addr_3, ADDRLEN);
- memcpy(srcaddr, pmac->addr_2, ADDRLEN);
- } else { /* Adhoc */
- memcpy(destaddr, pmac->addr_1, ADDRLEN);
- memcpy(srcaddr, pmac->addr_2, ADDRLEN);
- }
- }
+ memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN);
+ memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN);
#ifdef PCMCIA_DEBUG
if (pc_debug > 3) {
@@ -2349,33 +2335,34 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
printk(KERN_DEBUG "skb->data before untranslate");
for (i=0;i<64;i++)
printk("%02x ",skb->data[i]);
- printk("\n" KERN_DEBUG "type = %08x, xsap = %08x, org = %08x\n",
- type,xsap,org);
+ printk("\n" KERN_DEBUG "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n",
+ ntohs(type),
+ psnap->dsap, psnap->ssap, psnap->ctrl,
+ psnap->org[0], psnap->org[1], psnap->org[2]);
printk(KERN_DEBUG "untranslate skb->data = %p\n",skb->data);
}
#endif
- if ( xsap != SNAP_ID) {
+ if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) {
/* not a snap type so leave it alone */
- DEBUG(3,"ray_cs untranslate NOT SNAP %x\n", *(unsigned int *)psnap & 0x00ffffff);
+ DEBUG(3,"ray_cs untranslate NOT SNAP %02x %02x %02x\n",
+ psnap->dsap, psnap->ssap, psnap->ctrl);
delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
peth = (struct ethhdr *)(skb->data + delta);
peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH);
}
else { /* Its a SNAP */
- if (org == BRIDGE_ENCAP) { /* EtherII and nuke the LLC */
+ if (memcmp(psnap->org, org_bridge, 3) == 0) { /* EtherII and nuke the LLC */
DEBUG(3,"ray_cs untranslate Bridge encap\n");
delta = RX_MAC_HEADER_LENGTH
+ sizeof(struct snaphdr_t) - ETH_HLEN;
peth = (struct ethhdr *)(skb->data + delta);
peth->h_proto = type;
- }
- else {
- if (org == RFC1042_ENCAP) {
- switch (type) {
- case RAY_IPX_TYPE:
- case APPLEARP_TYPE:
+ } else if (memcmp(psnap->org, org_1042, 3) == 0) {
+ switch (ntohs(type)) {
+ case ETH_P_IPX:
+ case ETH_P_AARP:
DEBUG(3,"ray_cs untranslate RFC IPX/AARP\n");
delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
peth = (struct ethhdr *)(skb->data + delta);
@@ -2389,14 +2376,12 @@ static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
peth->h_proto = type;
break;
}
- }
- else {
+ } else {
printk("ray_cs untranslate very confused by packet\n");
delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
peth = (struct ethhdr *)(skb->data + delta);
peth->h_proto = type;
- }
- }
+ }
}
/* TBD reserve skb_reserve(skb, delta); */
skb_pull(skb, delta);
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 31c1dd271627..d6cba138c7ab 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -24,11 +24,6 @@
Supported chipsets: RT2460.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2400pci"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -54,7 +49,7 @@
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2400pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -69,7 +64,7 @@ static u32 rt2400pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
return reg;
}
-static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
@@ -95,7 +90,7 @@ static void rt2400pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
}
-static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
@@ -132,7 +127,7 @@ static void rt2400pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
}
-static void rt2400pci_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
@@ -195,13 +190,13 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-static void rt2400pci_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2400pci_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
}
-static void rt2400pci_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2400pci_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -285,7 +280,7 @@ static void rt2400pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
@@ -397,7 +392,7 @@ static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
}
static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- int antenna_tx, int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r1;
u8 r4;
@@ -408,14 +403,20 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the TX antenna.
*/
- switch (antenna_tx) {
- case ANTENNA_SW_DIVERSITY:
+ switch (ant->tx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
break;
case ANTENNA_A:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
break;
@@ -424,14 +425,20 @@ static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the RX antenna.
*/
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
break;
case ANTENNA_A:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
break;
@@ -485,9 +492,7 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
rt2400pci_config_txpower(rt2x00dev,
libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2400pci_config_antenna(rt2x00dev,
- libconf->conf->antenna_sel_tx,
- libconf->conf->antenna_sel_rx);
+ rt2400pci_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
rt2400pci_config_duration(rt2x00dev, libconf);
}
@@ -514,18 +519,10 @@ static void rt2400pci_enable_led(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
-
- if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
- } else if (rt2x00dev->led_mode == LED_MODE_ASUS) {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
- } else {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
- }
-
+ rt2x00_set_field32(&reg, LEDCSR_LINK,
+ (rt2x00dev->led_mode != LED_MODE_ASUS));
+ rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
+ (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
@@ -542,7 +539,8 @@ static void rt2400pci_disable_led(struct rt2x00_dev *rt2x00dev)
/*
* Link tuning
*/
-static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u32 reg;
u8 bbp;
@@ -551,13 +549,13 @@ static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev)
* Update FCS error count from register.
*/
rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2400pci_bbp_read(rt2x00dev, 39, &bbp);
- rt2x00dev->link.false_cca = bbp;
+ qual->false_cca = bbp;
}
static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -582,10 +580,10 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
*/
rt2400pci_bbp_read(rt2x00dev, 13, &reg);
- if (rt2x00dev->link.false_cca > 512 && reg < 0x20) {
+ if (rt2x00dev->link.qual.false_cca > 512 && reg < 0x20) {
rt2400pci_bbp_write(rt2x00dev, 13, ++reg);
rt2x00dev->link.vgc_level = reg;
- } else if (rt2x00dev->link.false_cca < 100 && reg > 0x08) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && reg > 0x08) {
rt2400pci_bbp_write(rt2x00dev, 13, --reg);
rt2x00dev->link.vgc_level = reg;
}
@@ -594,65 +592,43 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
/*
* Initialization functions.
*/
-static void rt2400pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- struct data_desc *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 2, &word);
- rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH,
- ring->data_size);
- rt2x00_desc_write(rxd, 2, word);
-
- rt2x00_desc_read(rxd, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 1, word);
+ rt2x00_desc_read(rxd, 2, &word);
+ rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+ rt2x00_desc_write(rxd, 2, word);
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(rxd, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(rxd, 1, word);
- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}
-static void rt2400pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- struct data_desc *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH,
- ring->data_size);
- rt2x00_desc_write(txd, 2, word);
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
+ rt2x00_desc_read(txd, 2, &word);
+ rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, entry->ring->data_size);
+ rt2x00_desc_write(txd, 2, word);
- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}
static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -660,15 +636,6 @@ static int rt2400pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;
/*
- * Initialize rings.
- */
- rt2400pci_init_rxring(rt2x00dev);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
- rt2400pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
@@ -1014,53 +981,37 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
- u32 signal = 0;
- u32 service = 0;
- u32 length_high = 0;
- u32 length_low = 0;
-
- /*
- * The PLCP values should be treated as if they
- * were BBP values.
- */
- rt2x00_set_field32(&signal, BBPCSR_VALUE, desc->signal);
- rt2x00_set_field32(&signal, BBPCSR_REGNUM, 5);
- rt2x00_set_field32(&signal, BBPCSR_BUSY, 1);
-
- rt2x00_set_field32(&service, BBPCSR_VALUE, desc->service);
- rt2x00_set_field32(&service, BBPCSR_REGNUM, 6);
- rt2x00_set_field32(&service, BBPCSR_BUSY, 1);
-
- rt2x00_set_field32(&length_high, BBPCSR_VALUE, desc->length_high);
- rt2x00_set_field32(&length_high, BBPCSR_REGNUM, 7);
- rt2x00_set_field32(&length_high, BBPCSR_BUSY, 1);
-
- rt2x00_set_field32(&length_low, BBPCSR_VALUE, desc->length_low);
- rt2x00_set_field32(&length_low, BBPCSR_REGNUM, 8);
- rt2x00_set_field32(&length_low, BBPCSR_BUSY, 1);
/*
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 2, &word);
- rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_desc_write(txd, 2, word);
rt2x00_desc_read(txd, 3, &word);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, signal);
- rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, service);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, desc->signal);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, desc->service);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
rt2x00_desc_write(txd, 3, word);
rt2x00_desc_read(txd, 4, &word);
- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, length_low);
- rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, length_high);
+ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, desc->length_low);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
+ rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, desc->length_high);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
+ rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
rt2x00_desc_write(txd, 4, word);
rt2x00_desc_read(txd, 0, &word);
@@ -1069,7 +1020,7 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ test_bit(ENTRY_TXD_ACK, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_RTS,
@@ -1099,12 +1050,12 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
}
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
- if (queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+ rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO,
+ (queue == IEEE80211_TX_QUEUE_DATA0));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
+ (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
@@ -1114,7 +1065,7 @@ static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2400pci_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
- struct data_desc *rxd = entry->priv;
+ __le32 *rxd = entry->priv;
u32 word0;
u32 word2;
@@ -1135,6 +1086,7 @@ static void rt2400pci_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = 0;
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
@@ -1144,7 +1096,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
{
struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
struct data_entry *entry;
- struct data_desc *txd;
+ __le32 *txd;
u32 word;
int tx_status;
int retry;
@@ -1164,26 +1116,8 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
- rt2x00lib_txdone(entry, tx_status, retry);
-
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_desc_write(txd, 0, word);
- rt2x00_ring_index_done_inc(ring);
+ rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
}
-
- /*
- * If the data ring was full before the txdone handler
- * we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
- */
- entry = ring->entry;
- if (!rt2x00_ring_full(ring))
- ieee80211_wake_queue(rt2x00dev->hw,
- entry->tx_status.control.queue);
}
static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
@@ -1315,12 +1249,23 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
+ * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
+ * I am not 100% sure about this, but the legacy drivers do not
+ * indicate antenna swapping in software is required when
+ * diversity is enabled.
+ */
+ if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+ rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
+ if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+ rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
+
+ /*
* Store led mode, for correct led behaviour.
*/
rt2x00dev->led_mode =
@@ -1447,7 +1392,6 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;
/*
@@ -1466,21 +1410,18 @@ static void rt2400pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* Start configuration steps.
@@ -1583,7 +1524,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.configure_filter = rt2400pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt2400pci_set_retry_limit,
- .erp_ie_changed = rt2x00mac_erp_ie_changed,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2400pci_get_tsf,
@@ -1597,6 +1538,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.probe_hw = rt2400pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt2400pci_init_rxentry,
+ .init_txentry = rt2400pci_init_txentry,
.set_device_state = rt2400pci_set_device_state,
.rfkill_poll = rt2400pci_rfkill_poll,
.link_stats = rt2400pci_link_stats,
@@ -1614,7 +1557,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
};
static const struct rt2x00_ops rt2400pci_ops = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.eeprom_size = EEPROM_SIZE,
@@ -1642,7 +1585,7 @@ MODULE_DEVICE_TABLE(pci, rt2400pci_device_table);
MODULE_LICENSE("GPL");
static struct pci_driver rt2400pci_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt2400pci_device_table,
.probe = rt2x00pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index ae22501f085d..369aac6d0336 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -803,8 +803,8 @@
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 8 * sizeof(struct data_desc) )
-#define RXD_DESC_SIZE ( 8 * sizeof(struct data_desc) )
+#define TXD_DESC_SIZE ( 8 * sizeof(__le32) )
+#define RXD_DESC_SIZE ( 8 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
@@ -839,11 +839,21 @@
/*
* Word3 & 4: PLCP information
- */
-#define TXD_W3_PLCP_SIGNAL FIELD32(0x0000ffff)
-#define TXD_W3_PLCP_SERVICE FIELD32(0xffff0000)
-#define TXD_W4_PLCP_LENGTH_LOW FIELD32(0x0000ffff)
-#define TXD_W4_PLCP_LENGTH_HIGH FIELD32(0xffff0000)
+ * The PLCP values should be treated as if they were BBP values.
+ */
+#define TXD_W3_PLCP_SIGNAL FIELD32(0x000000ff)
+#define TXD_W3_PLCP_SIGNAL_REGNUM FIELD32(0x00007f00)
+#define TXD_W3_PLCP_SIGNAL_BUSY FIELD32(0x00008000)
+#define TXD_W3_PLCP_SERVICE FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_SERVICE_REGNUM FIELD32(0x7f000000)
+#define TXD_W3_PLCP_SERVICE_BUSY FIELD32(0x80000000)
+
+#define TXD_W4_PLCP_LENGTH_LOW FIELD32(0x000000ff)
+#define TXD_W3_PLCP_LENGTH_LOW_REGNUM FIELD32(0x00007f00)
+#define TXD_W3_PLCP_LENGTH_LOW_BUSY FIELD32(0x00008000)
+#define TXD_W4_PLCP_LENGTH_HIGH FIELD32(0x00ff0000)
+#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM FIELD32(0x7f000000)
+#define TXD_W3_PLCP_LENGTH_HIGH_BUSY FIELD32(0x80000000)
/*
* Word5
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 702321c30164..e874fdcae204 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -24,11 +24,6 @@
Supported chipsets: RT2560.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2500pci"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -54,7 +49,7 @@
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2500pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -69,7 +64,7 @@ static u32 rt2500pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
return reg;
}
-static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
@@ -95,7 +90,7 @@ static void rt2500pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
}
-static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
@@ -132,7 +127,7 @@ static void rt2500pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
}
-static void rt2500pci_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
@@ -195,13 +190,13 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-static void rt2500pci_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500pci_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
}
-static void rt2500pci_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500pci_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -289,7 +284,7 @@ static void rt2500pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
- rt2x00_set_field32(&reg, CSR14_TBCN, 1);
+ rt2x00_set_field32(&reg, CSR14_TBCN, (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
rt2x00_set_field32(&reg, CSR14_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, CSR14, reg);
@@ -424,7 +419,7 @@ static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
}
static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx, const int antenna_rx)
+ struct antenna_setup *ant)
{
u32 reg;
u8 r14;
@@ -437,18 +432,20 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the TX antenna.
*/
- switch (antenna_tx) {
- case ANTENNA_SW_DIVERSITY:
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
- rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
- break;
+ switch (ant->tx) {
case ANTENNA_A:
rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
break;
+ case ANTENNA_HW_DIVERSITY:
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
@@ -459,14 +456,18 @@ static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the RX antenna.
*/
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
- break;
+ switch (ant->rx) {
case ANTENNA_A:
rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
break;
+ case ANTENNA_HW_DIVERSITY:
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
break;
@@ -541,9 +542,7 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
rt2500pci_config_txpower(rt2x00dev,
libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500pci_config_antenna(rt2x00dev,
- libconf->conf->antenna_sel_tx,
- libconf->conf->antenna_sel_rx);
+ rt2500pci_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
rt2500pci_config_duration(rt2x00dev, libconf);
}
@@ -559,18 +558,10 @@ static void rt2500pci_enable_led(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, LEDCSR_ON_PERIOD, 70);
rt2x00_set_field32(&reg, LEDCSR_OFF_PERIOD, 30);
-
- if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 0);
- } else if (rt2x00dev->led_mode == LED_MODE_ASUS) {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 0);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
- } else {
- rt2x00_set_field32(&reg, LEDCSR_LINK, 1);
- rt2x00_set_field32(&reg, LEDCSR_ACTIVITY, 1);
- }
-
+ rt2x00_set_field32(&reg, LEDCSR_LINK,
+ (rt2x00dev->led_mode != LED_MODE_ASUS));
+ rt2x00_set_field32(&reg, LEDCSR_ACTIVITY,
+ (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2x00pci_register_write(rt2x00dev, LEDCSR, reg);
}
@@ -587,7 +578,8 @@ static void rt2500pci_disable_led(struct rt2x00_dev *rt2x00dev)
/*
* Link tuning
*/
-static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u32 reg;
@@ -595,13 +587,13 @@ static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev)
* Update FCS error count from register.
*/
rt2x00pci_register_read(rt2x00dev, CNT0, &reg);
- rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2x00pci_register_read(rt2x00dev, CNT3, &reg);
- rt2x00dev->link.false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
+ qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA);
}
static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -679,10 +671,10 @@ dynamic_cca_tune:
* R17 is inside the dynamic tuning range,
* start tuning the link based on the false cca counter.
*/
- if (rt2x00dev->link.false_cca > 512 && r17 < 0x40) {
+ if (rt2x00dev->link.qual.false_cca > 512 && r17 < 0x40) {
rt2500pci_bbp_write(rt2x00dev, 17, ++r17);
rt2x00dev->link.vgc_level = r17;
- } else if (rt2x00dev->link.false_cca < 100 && r17 > 0x32) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > 0x32) {
rt2500pci_bbp_write(rt2x00dev, 17, --r17);
rt2x00dev->link.vgc_level = r17;
}
@@ -691,55 +683,35 @@ dynamic_cca_tune:
/*
* Initialization functions.
*/
-static void rt2500pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- struct data_desc *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 1, word);
-
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
+ rt2x00_desc_read(rxd, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(rxd, 1, word);
- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}
-static void rt2500pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- struct data_desc *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, entry->data_dma);
+ rt2x00_desc_write(txd, 1, word);
- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}
static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -747,15 +719,6 @@ static int rt2500pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;
/*
- * Initialize rings.
- */
- rt2500pci_init_rxring(rt2x00dev);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_AFTER_BEACON);
- rt2500pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
@@ -1170,12 +1133,12 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
/*
@@ -1206,7 +1169,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ test_bit(ENTRY_TXD_ACK, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
@@ -1216,7 +1179,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
@@ -1239,12 +1202,12 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
}
rt2x00pci_register_read(rt2x00dev, TXCSR0, &reg);
- if (queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(&reg, TXCSR0_KICK_TX, 1);
- else if (queue == IEEE80211_TX_QUEUE_AFTER_BEACON)
- rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM, 1);
+ rt2x00_set_field32(&reg, TXCSR0_KICK_PRIO,
+ (queue == IEEE80211_TX_QUEUE_DATA0));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_TX,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(&reg, TXCSR0_KICK_ATIM,
+ (queue == IEEE80211_TX_QUEUE_AFTER_BEACON));
rt2x00pci_register_write(rt2x00dev, TXCSR0, reg);
}
@@ -1254,7 +1217,7 @@ static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2500pci_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
- struct data_desc *rxd = entry->priv;
+ __le32 *rxd = entry->priv;
u32 word0;
u32 word2;
@@ -1272,6 +1235,7 @@ static void rt2500pci_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
@@ -1281,7 +1245,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
{
struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
struct data_entry *entry;
- struct data_desc *txd;
+ __le32 *txd;
u32 word;
int tx_status;
int retry;
@@ -1301,26 +1265,8 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, const int queue)
tx_status = rt2x00_get_field32(word, TXD_W0_RESULT);
retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
- rt2x00lib_txdone(entry, tx_status, retry);
-
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_desc_write(txd, 0, word);
- rt2x00_ring_index_done_inc(ring);
+ rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
}
-
- /*
- * If the data ring was full before the txdone handler
- * we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
- */
- entry = ring->entry;
- if (!rt2x00_ring_full(ring))
- ieee80211_wake_queue(rt2x00dev->hw,
- entry->tx_status.control.queue);
}
static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
@@ -1420,9 +1366,12 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 0);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+ ANTENNA_SW_DIVERSITY);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+ ANTENNA_SW_DIVERSITY);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
+ LED_MODE_DEFAULT);
rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
@@ -1481,9 +1430,9 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
@@ -1774,7 +1723,6 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;
/*
@@ -1793,22 +1741,19 @@ static void rt2500pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* Start configuration steps.
@@ -1890,7 +1835,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.configure_filter = rt2500pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt2500pci_set_retry_limit,
- .erp_ie_changed = rt2x00mac_erp_ie_changed,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt2500pci_get_tsf,
@@ -1904,6 +1849,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.probe_hw = rt2500pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt2500pci_init_rxentry,
+ .init_txentry = rt2500pci_init_txentry,
.set_device_state = rt2500pci_set_device_state,
.rfkill_poll = rt2500pci_rfkill_poll,
.link_stats = rt2500pci_link_stats,
@@ -1921,7 +1868,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
};
static const struct rt2x00_ops rt2500pci_ops = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.eeprom_size = EEPROM_SIZE,
@@ -1949,7 +1896,7 @@ MODULE_DEVICE_TABLE(pci, rt2500pci_device_table);
MODULE_LICENSE("GPL");
static struct pci_driver rt2500pci_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt2500pci_device_table,
.probe = rt2x00pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
index d92aa56b2f4b..92ba0902d107 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -1082,8 +1082,8 @@
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 11 * sizeof(struct data_desc) )
-#define RXD_DESC_SIZE ( 11 * sizeof(struct data_desc) )
+#define TXD_DESC_SIZE ( 11 * sizeof(__le32) )
+#define RXD_DESC_SIZE ( 11 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 18b1f9145389..86ded4066f5b 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -24,11 +24,6 @@
Supported chipsets: RT2570.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2500usb"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -52,8 +47,10 @@
* 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.
+ * If the usb_cache_mutex is already held then the _lock variants must
+ * be used instead.
*/
-static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u16 *value)
{
@@ -64,8 +61,18 @@ static inline void rt2500usb_register_read(const struct rt2x00_dev *rt2x00dev,
*value = le16_to_cpu(reg);
}
-static inline void rt2500usb_register_multiread(const struct rt2x00_dev
- *rt2x00dev,
+static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u16 *value)
+{
+ __le16 reg;
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+ USB_VENDOR_REQUEST_IN, offset,
+ &reg, sizeof(u16), REGISTER_TIMEOUT);
+ *value = le16_to_cpu(reg);
+}
+
+static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u16 length)
{
@@ -75,7 +82,7 @@ static inline void rt2500usb_register_multiread(const struct rt2x00_dev
value, length, timeout);
}
-static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u16 value)
{
@@ -85,8 +92,17 @@ static inline void rt2500usb_register_write(const struct rt2x00_dev *rt2x00dev,
&reg, sizeof(u16), REGISTER_TIMEOUT);
}
-static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev
- *rt2x00dev,
+static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u16 value)
+{
+ __le16 reg = cpu_to_le16(value);
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, offset,
+ &reg, sizeof(u16), REGISTER_TIMEOUT);
+}
+
+static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u16 length)
{
@@ -96,13 +112,13 @@ static inline void rt2500usb_register_multiwrite(const struct rt2x00_dev
value, length, timeout);
}
-static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u16 reg;
unsigned int i;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read(rt2x00dev, PHY_CSR8, &reg);
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, &reg);
if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
break;
udelay(REGISTER_BUSY_DELAY);
@@ -111,17 +127,20 @@ static u16 rt2500usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
return reg;
}
-static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u16 reg;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
/*
* Wait until the BBP becomes ready.
*/
reg = rt2500usb_bbp_check(rt2x00dev);
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
@@ -133,14 +152,18 @@ static void rt2500usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
- rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
-static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u16 reg;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
/*
* Wait until the BBP becomes ready.
*/
@@ -157,7 +180,7 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
- rt2500usb_register_write(rt2x00dev, PHY_CSR7, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
/*
* Wait until the BBP becomes ready.
@@ -166,14 +189,17 @@ static void rt2500usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
if (rt2x00_get_field16(reg, PHY_CSR8_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
*value = 0xff;
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
- rt2500usb_register_read(rt2x00dev, PHY_CSR7, &reg);
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
+
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
-static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u16 reg;
@@ -182,20 +208,23 @@ static void rt2500usb_rf_write(const struct rt2x00_dev *rt2x00dev,
if (!word)
return;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read(rt2x00dev, PHY_CSR10, &reg);
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, &reg);
if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
goto rf_write;
udelay(REGISTER_BUSY_DELAY);
}
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
return;
rf_write:
reg = 0;
rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
- rt2500usb_register_write(rt2x00dev, PHY_CSR9, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
reg = 0;
rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
@@ -203,20 +232,22 @@ rf_write:
rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
- rt2500usb_register_write(rt2x00dev, PHY_CSR10, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
rt2x00_rf_write(rt2x00dev, word, value);
+
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u16)) )
-static void rt2500usb_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data);
}
-static void rt2500usb_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -296,7 +327,8 @@ static void rt2500usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
- rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
+ rt2x00_set_field16(&reg, TXRX_CSR19_TBCN,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, tsf_sync);
rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
@@ -385,7 +417,7 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
}
static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx, const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r2;
u8 r14;
@@ -400,8 +432,7 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the TX antenna.
*/
- switch (antenna_tx) {
- case ANTENNA_SW_DIVERSITY:
+ switch (ant->tx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1);
rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1);
@@ -412,6 +443,13 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0);
rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2);
@@ -422,14 +460,20 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
/*
* Configure the RX antenna.
*/
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1);
break;
case ANTENNA_A:
rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
break;
@@ -487,9 +531,7 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
rt2500usb_config_txpower(rt2x00dev,
libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500usb_config_antenna(rt2x00dev,
- libconf->conf->antenna_sel_tx,
- libconf->conf->antenna_sel_rx);
+ rt2500usb_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
rt2500usb_config_duration(rt2x00dev, libconf);
}
@@ -507,18 +549,10 @@ static void rt2500usb_enable_led(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_write(rt2x00dev, MAC_CSR21, reg);
rt2500usb_register_read(rt2x00dev, MAC_CSR20, &reg);
-
- if (rt2x00dev->led_mode == LED_MODE_TXRX_ACTIVITY) {
- rt2x00_set_field16(&reg, MAC_CSR20_LINK, 1);
- rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 0);
- } else if (rt2x00dev->led_mode == LED_MODE_ASUS) {
- rt2x00_set_field16(&reg, MAC_CSR20_LINK, 0);
- rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 1);
- } else {
- rt2x00_set_field16(&reg, MAC_CSR20_LINK, 1);
- rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY, 1);
- }
-
+ rt2x00_set_field16(&reg, MAC_CSR20_LINK,
+ (rt2x00dev->led_mode != LED_MODE_ASUS));
+ rt2x00_set_field16(&reg, MAC_CSR20_ACTIVITY,
+ (rt2x00dev->led_mode != LED_MODE_TXRX_ACTIVITY));
rt2500usb_register_write(rt2x00dev, MAC_CSR20, reg);
}
@@ -535,7 +569,8 @@ static void rt2500usb_disable_led(struct rt2x00_dev *rt2x00dev)
/*
* Link tuning
*/
-static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u16 reg;
@@ -543,14 +578,13 @@ static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev)
* Update FCS error count from register.
*/
rt2500usb_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00dev->link.rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2500usb_register_read(rt2x00dev, STA_CSR3, &reg);
- rt2x00dev->link.false_cca =
- rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
+ qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR);
}
static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -673,10 +707,10 @@ static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
if (r17 > up_bound) {
rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
rt2x00dev->link.vgc_level = up_bound;
- } else if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) {
+ } else if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
rt2x00dev->link.vgc_level = r17;
- } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
rt2500usb_bbp_write(rt2x00dev, 17, --r17);
rt2x00dev->link.vgc_level = r17;
}
@@ -755,9 +789,11 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) {
rt2500usb_register_read(rt2x00dev, PHY_CSR2, &reg);
- reg &= ~0x0002;
+ rt2x00_set_field16(&reg, PHY_CSR2_LNA, 0);
} else {
- reg = 0x3002;
+ reg = 0;
+ rt2x00_set_field16(&reg, PHY_CSR2_LNA, 1);
+ rt2x00_set_field16(&reg, PHY_CSR2_LNA_MODE, 3);
}
rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg);
@@ -884,8 +920,6 @@ static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}
- rt2x00usb_enable_radio(rt2x00dev);
-
/*
* Enable LED
*/
@@ -988,12 +1022,12 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
/*
@@ -1018,7 +1052,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ test_bit(ENTRY_TXD_ACK, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
@@ -1026,7 +1060,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
!!(control->flags & IEEE80211_TXCTL_FIRST_FRAGMENT));
rt2x00_set_field32(&word, TXD_W0_IFS, desc->ifs);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
rt2x00_desc_write(txd, 0, word);
}
@@ -1079,10 +1113,10 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2500usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
+ struct skb_desc *skbdesc = get_skb_desc(entry->skb);
struct urb *urb = entry->priv;
- struct data_desc *rxd = (struct data_desc *)(entry->skb->data +
- (urb->actual_length -
- entry->ring->desc_size));
+ __le32 *rxd = (__le32 *)(entry->skb->data +
+ (urb->actual_length - entry->ring->desc_size));
u32 word0;
u32 word1;
@@ -1103,8 +1137,15 @@ static void rt2500usb_fill_rxdone(struct data_entry *entry,
entry->ring->rt2x00dev->rssi_offset;
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
- return;
+ /*
+ * Set descriptor and data pointer.
+ */
+ skbdesc->desc = entry->skb->data + desc->size;
+ skbdesc->desc_len = entry->ring->desc_size;
+ skbdesc->data = entry->skb->data;
+ skbdesc->data_len = desc->size;
}
/*
@@ -1163,9 +1204,12 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 0);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 0);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, 0);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+ ANTENNA_SW_DIVERSITY);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+ ANTENNA_SW_DIVERSITY);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE,
+ LED_MODE_DEFAULT);
rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522);
@@ -1275,12 +1319,23 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
+ * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead.
+ * I am not 100% sure about this, but the legacy drivers do not
+ * indicate antenna swapping in software is required when
+ * diversity is enabled.
+ */
+ if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+ rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY;
+ if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+ rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY;
+
+ /*
* Store led mode, for correct led behaviour.
*/
rt2x00dev->led_mode =
@@ -1562,7 +1617,6 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u16 reg;
/*
@@ -1581,22 +1635,19 @@ static void rt2500usb_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* When in atomic context, reschedule and let rt2x00lib
@@ -1638,8 +1689,8 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
struct rt2x00_dev *rt2x00dev = hw->priv;
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
- struct data_ring *ring =
- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
+ struct skb_desc *desc;
+ struct data_ring *ring;
struct data_entry *beacon;
struct data_entry *guardian;
int pipe = usb_sndbulkpipe(usb_dev, 1);
@@ -1651,6 +1702,7 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
+ ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
/*
* Obtain 2 entries, one for the guardian byte,
@@ -1661,23 +1713,34 @@ static int rt2500usb_beacon_update(struct ieee80211_hw *hw,
beacon = rt2x00_get_data_entry(ring);
/*
- * First we create the beacon.
+ * Add the descriptor in front of the skb.
*/
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
- rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
- (struct ieee80211_hdr *)(skb->data +
- ring->desc_size),
- skb->len - ring->desc_size, control);
+ /*
+ * Fill in skb descriptor
+ */
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len - ring->desc_size;
+ desc->desc = skb->data;
+ desc->data = skb->data + ring->desc_size;
+ desc->ring = ring;
+ desc->entry = beacon;
+
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
+ /*
+ * USB devices cannot blindly pass the skb->len as the
+ * length of the data to usb_fill_bulk_urb. Pass the skb
+ * to the driver to determine what the length should be.
+ */
length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
usb_fill_bulk_urb(beacon->priv, usb_dev, pipe,
skb->data, length, rt2500usb_beacondone, beacon);
- beacon->skb = skb;
-
/*
* Second we need to create the guardian byte.
* We only need a single byte, so lets recycle
@@ -1710,7 +1773,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2500usb_configure_filter,
.get_stats = rt2x00mac_get_stats,
- .erp_ie_changed = rt2x00mac_erp_ie_changed,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.beacon_update = rt2500usb_beacon_update,
@@ -1720,6 +1783,8 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.probe_hw = rt2500usb_probe_hw,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
+ .init_rxentry = rt2x00usb_init_rxentry,
+ .init_txentry = rt2x00usb_init_txentry,
.set_device_state = rt2500usb_set_device_state,
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
@@ -1737,7 +1802,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
};
static const struct rt2x00_ops rt2500usb_ops = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.eeprom_size = EEPROM_SIZE,
@@ -1809,7 +1874,7 @@ MODULE_DEVICE_TABLE(usb, rt2500usb_device_table);
MODULE_LICENSE("GPL");
static struct usb_driver rt2500usb_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt2500usb_device_table,
.probe = rt2x00usb_probe,
.disconnect = rt2x00usb_disconnect,
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index b18d56e73cf1..9e0433722e3d 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -430,10 +430,21 @@
/*
* MAC configuration registers.
+ */
+
+/*
* PHY_CSR2: TX MAC configuration.
- * PHY_CSR3: RX MAC configuration.
+ * NOTE: Both register fields are complete dummy,
+ * documentation and legacy drivers are unclear un
+ * what this register means or what fields exists.
*/
#define PHY_CSR2 0x04c4
+#define PHY_CSR2_LNA FIELD16(0x0002)
+#define PHY_CSR2_LNA_MODE FIELD16(0x3000)
+
+/*
+ * PHY_CSR3: RX MAC configuration.
+ */
#define PHY_CSR3 0x04c6
/*
@@ -692,8 +703,8 @@
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 5 * sizeof(struct data_desc) )
-#define RXD_DESC_SIZE ( 4 * sizeof(struct data_desc) )
+#define TXD_DESC_SIZE ( 5 * sizeof(__le32) )
+#define RXD_DESC_SIZE ( 4 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index c8f16f161c28..05927b908f80 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -31,6 +31,8 @@
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
+#include <linux/mutex.h>
+#include <linux/etherdevice.h>
#include <net/mac80211.h>
@@ -40,9 +42,8 @@
/*
* Module information.
- * DRV_NAME should be set within the individual module source files.
*/
-#define DRV_VERSION "2.0.10"
+#define DRV_VERSION "2.0.14"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
/*
@@ -55,7 +56,7 @@
#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \
printk(__kernlvl "%s -> %s: %s - " __msg, \
- DRV_NAME, __FUNCTION__, __lvl, ##__args)
+ KBUILD_MODNAME, __FUNCTION__, __lvl, ##__args)
#ifdef CONFIG_RT2X00_DEBUG
#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \
@@ -133,20 +134,26 @@
*/
static inline int is_rts_frame(u16 fc)
{
- return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
- ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS));
+ return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_RTS));
}
static inline int is_cts_frame(u16 fc)
{
- return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
- ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS));
+ return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_CTS));
}
static inline int is_probe_resp(u16 fc)
{
- return !!(((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
- ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP));
+ return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP));
+}
+
+static inline int is_beacon(u16 fc)
+{
+ return (((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON));
}
/*
@@ -180,18 +187,17 @@ struct rf_channel {
};
/*
- * To optimize the quality of the link we need to store
- * the quality of received frames and periodically
- * optimize the link.
+ * Antenna setup values.
*/
-struct link {
- /*
- * Link tuner counter
- * The number of times the link has been tuned
- * since the radio has been switched on.
- */
- u32 count;
+struct antenna_setup {
+ enum antenna rx;
+ enum antenna tx;
+};
+/*
+ * Quality statistics about the currently active link.
+ */
+struct link_qual {
/*
* Statistics required for Link tuning.
* For the average RSSI value we use the "Walking average" approach.
@@ -211,7 +217,6 @@ struct link {
* the new values correctly allowing a effective link tuning.
*/
int avg_rssi;
- int vgc_level;
int false_cca;
/*
@@ -240,6 +245,72 @@ struct link {
#define WEIGHT_RSSI 20
#define WEIGHT_RX 40
#define WEIGHT_TX 40
+};
+
+/*
+ * Antenna settings about the currently active link.
+ */
+struct link_ant {
+ /*
+ * Antenna flags
+ */
+ unsigned int flags;
+#define ANTENNA_RX_DIVERSITY 0x00000001
+#define ANTENNA_TX_DIVERSITY 0x00000002
+#define ANTENNA_MODE_SAMPLE 0x00000004
+
+ /*
+ * Currently active TX/RX antenna setup.
+ * When software diversity is used, this will indicate
+ * which antenna is actually used at this time.
+ */
+ struct antenna_setup active;
+
+ /*
+ * RSSI information for the different antenna's.
+ * These statistics are used to determine when
+ * to switch antenna when using software diversity.
+ *
+ * rssi[0] -> Antenna A RSSI
+ * rssi[1] -> Antenna B RSSI
+ */
+ int rssi_history[2];
+
+ /*
+ * Current RSSI average of the currently active antenna.
+ * Similar to the avg_rssi in the link_qual structure
+ * this value is updated by using the walking average.
+ */
+ int rssi_ant;
+};
+
+/*
+ * To optimize the quality of the link we need to store
+ * the quality of received frames and periodically
+ * optimize the link.
+ */
+struct link {
+ /*
+ * Link tuner counter
+ * The number of times the link has been tuned
+ * since the radio has been switched on.
+ */
+ u32 count;
+
+ /*
+ * Quality measurement values.
+ */
+ struct link_qual qual;
+
+ /*
+ * TX/RX antenna setup.
+ */
+ struct link_ant ant;
+
+ /*
+ * Active VGC level
+ */
+ int vgc_level;
/*
* Work structure for scheduling periodic link tuning.
@@ -248,36 +319,47 @@ struct link {
};
/*
- * Clear all counters inside the link structure.
- * This can be easiest achieved by memsetting everything
- * except for the work structure at the end.
+ * Small helper macro to work with moving/walking averages.
*/
-static inline void rt2x00_clear_link(struct link *link)
-{
- memset(link, 0x00, sizeof(*link) - sizeof(link->work));
- link->rx_percentage = 50;
- link->tx_percentage = 50;
-}
+#define MOVING_AVERAGE(__avg, __val, __samples) \
+ ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) )
/*
- * Update the rssi using the walking average approach.
+ * When we lack RSSI information return something less then -80 to
+ * tell the driver to tune the device to maximum sensitivity.
*/
-static inline void rt2x00_update_link_rssi(struct link *link, int rssi)
-{
- if (!link->avg_rssi)
- link->avg_rssi = rssi;
- else
- link->avg_rssi = ((link->avg_rssi * 7) + rssi) / 8;
-}
+#define DEFAULT_RSSI ( -128 )
/*
- * When the avg_rssi is unset or no frames have been received),
- * we need to return the default value which needs to be less
- * than -80 so the device will select the maximum sensitivity.
+ * Link quality access functions.
*/
static inline int rt2x00_get_link_rssi(struct link *link)
{
- return (link->avg_rssi && link->rx_success) ? link->avg_rssi : -128;
+ if (link->qual.avg_rssi && link->qual.rx_success)
+ return link->qual.avg_rssi;
+ return DEFAULT_RSSI;
+}
+
+static inline int rt2x00_get_link_ant_rssi(struct link *link)
+{
+ if (link->ant.rssi_ant && link->qual.rx_success)
+ return link->ant.rssi_ant;
+ return DEFAULT_RSSI;
+}
+
+static inline int rt2x00_get_link_ant_rssi_history(struct link *link,
+ enum antenna ant)
+{
+ if (link->ant.rssi_history[ant - ANTENNA_A])
+ return link->ant.rssi_history[ant - ANTENNA_A];
+ return DEFAULT_RSSI;
+}
+
+static inline int rt2x00_update_ant_rssi(struct link *link, int rssi)
+{
+ int old_rssi = link->ant.rssi_history[link->ant.active.rx - ANTENNA_A];
+ link->ant.rssi_history[link->ant.active.rx - ANTENNA_A] = rssi;
+ return old_rssi;
}
/*
@@ -290,14 +372,12 @@ struct interface {
* to us by the 80211 stack, and is used to request
* new beacons.
*/
- int id;
+ struct ieee80211_vif *id;
/*
* Current working type (IEEE80211_IF_TYPE_*).
- * When set to INVALID_INTERFACE, no interface is configured.
*/
int type;
-#define INVALID_INTERFACE IEEE80211_IF_TYPE_INVALID
/*
* MAC of the device.
@@ -308,11 +388,6 @@ struct interface {
* BBSID of the AP to associate with.
*/
u8 bssid[ETH_ALEN];
-
- /*
- * Store the packet filter mode for the current interface.
- */
- unsigned int filter;
};
static inline int is_interface_present(struct interface *intf)
@@ -362,6 +437,8 @@ struct rt2x00lib_conf {
struct ieee80211_conf *conf;
struct rf_channel rf;
+ struct antenna_setup ant;
+
int phymode;
int basic_rates;
@@ -397,12 +474,21 @@ struct rt2x00lib_ops {
void (*uninitialize) (struct rt2x00_dev *rt2x00dev);
/*
+ * Ring initialization handlers
+ */
+ void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+ void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+
+ /*
* Radio control handlers.
*/
int (*set_device_state) (struct rt2x00_dev *rt2x00dev,
enum dev_state state);
int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev);
- void (*link_stats) (struct rt2x00_dev *rt2x00dev);
+ void (*link_stats) (struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual);
void (*reset_tuner) (struct rt2x00_dev *rt2x00dev);
void (*link_tuner) (struct rt2x00_dev *rt2x00dev);
@@ -410,10 +496,8 @@ struct rt2x00lib_ops {
* TX control handlers
*/
void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
+ struct sk_buff *skb,
struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
struct ieee80211_tx_control *control);
int (*write_tx_data) (struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
@@ -545,7 +629,7 @@ struct rt2x00_dev {
* required for deregistration of debugfs.
*/
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
- const struct rt2x00debug_intf *debugfs_intf;
+ struct rt2x00debug_intf *debugfs_intf;
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
@@ -566,6 +650,13 @@ struct rt2x00_dev {
struct hw_mode_spec spec;
/*
+ * This is the default TX/RX antenna setup as indicated
+ * by the device's EEPROM. When mac80211 sets its
+ * antenna value to 0 we should be using these values.
+ */
+ struct antenna_setup default_ant;
+
+ /*
* Register pointers
* csr_addr: Base register address. (PCI)
* csr_cache: CSR cache for usb_control_msg. (USB)
@@ -574,6 +665,25 @@ struct rt2x00_dev {
void *csr_cache;
/*
+ * Mutex to protect register accesses on USB devices.
+ * There are 2 reasons this is needed, one is to ensure
+ * use of the csr_cache (for USB devices) by one thread
+ * isn't corrupted by another thread trying to access it.
+ * The other is that access to BBP and RF registers
+ * require multiple BUS transactions and if another thread
+ * attempted to access one of those registers at the same
+ * time one of the writes could silently fail.
+ */
+ struct mutex usb_cache_mutex;
+
+ /*
+ * Current packet filter configuration for the device.
+ * This contains all currently active FIF_* flags send
+ * to us by mac80211 during configure_filter().
+ */
+ unsigned int packet_filter;
+
+ /*
* Interface configuration.
*/
struct interface interface;
@@ -697,13 +807,13 @@ struct rt2x00_dev {
* Generic RF access.
* The RF is being accessed by word index.
*/
-static inline void rt2x00_rf_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
*data = rt2x00dev->rf[word];
}
-static inline void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2x00dev->rf[word] = data;
@@ -713,19 +823,19 @@ static inline void rt2x00_rf_write(const struct rt2x00_dev *rt2x00dev,
* Generic EEPROM access.
* The EEPROM is being accessed by word index.
*/
-static inline void *rt2x00_eeprom_addr(const struct rt2x00_dev *rt2x00dev,
+static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev,
const unsigned int word)
{
return (void *)&rt2x00dev->eeprom[word];
}
-static inline void rt2x00_eeprom_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u16 *data)
{
*data = le16_to_cpu(rt2x00dev->eeprom[word]);
}
-static inline void rt2x00_eeprom_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u16 data)
{
rt2x00dev->eeprom[word] = cpu_to_le16(data);
@@ -804,9 +914,7 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
* TX descriptor initializer
*/
void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
+ struct sk_buff *skb,
struct ieee80211_tx_control *control);
/*
@@ -821,14 +929,17 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
-int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
+int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf);
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
-void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
- int cts_protection, int preamble);
+void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params);
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 12914cf7156c..72cfe00c1ed7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -23,11 +23,6 @@
Abstract: rt2x00 generic configuration routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/kernel.h>
#include <linux/module.h>
@@ -94,12 +89,44 @@ void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type)
rt2x00dev->ops->lib->config_type(rt2x00dev, type, tsf_sync);
}
+void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ enum antenna rx, enum antenna tx)
+{
+ struct rt2x00lib_conf libconf;
+
+ libconf.ant.rx = rx;
+ libconf.ant.tx = tx;
+
+ /*
+ * Antenna setup changes require the RX to be disabled,
+ * else the changes will be ignored by the device.
+ */
+ if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+
+ /*
+ * Write new antenna setup to device and reset the link tuner.
+ * The latter is required since we need to recalibrate the
+ * noise-sensitivity ratio for the new setup.
+ */
+ rt2x00dev->ops->lib->config(rt2x00dev, CONFIG_UPDATE_ANTENNA, &libconf);
+ rt2x00lib_reset_link_tuner(rt2x00dev);
+
+ rt2x00dev->link.ant.active.rx = libconf.ant.rx;
+ rt2x00dev->link.ant.active.tx = libconf.ant.tx;
+
+ if (test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
+ rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
+}
+
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config)
{
struct rt2x00lib_conf libconf;
struct ieee80211_hw_mode *mode;
struct ieee80211_rate *rate;
+ struct antenna_setup *default_ant = &rt2x00dev->default_ant;
+ struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
int flags = 0;
int short_slot_time;
@@ -122,7 +149,39 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
flags |= CONFIG_UPDATE_CHANNEL;
if (rt2x00dev->tx_power != conf->power_level)
flags |= CONFIG_UPDATE_TXPOWER;
- if (rt2x00dev->rx_status.antenna == conf->antenna_sel_rx)
+
+ /*
+ * Determining changes in the antenna setups request several checks:
+ * antenna_sel_{r,t}x = 0
+ * -> Does active_{r,t}x match default_{r,t}x
+ * -> Is default_{r,t}x SW_DIVERSITY
+ * antenna_sel_{r,t}x = 1/2
+ * -> Does active_{r,t}x match antenna_sel_{r,t}x
+ * The reason for not updating the antenna while SW diversity
+ * should be used is simple: Software diversity means that
+ * we should switch between the antenna's based on the
+ * quality. This means that the current antenna is good enough
+ * to work with untill the link tuner decides that an antenna
+ * switch should be performed.
+ */
+ if (!conf->antenna_sel_rx &&
+ default_ant->rx != ANTENNA_SW_DIVERSITY &&
+ default_ant->rx != active_ant->rx)
+ flags |= CONFIG_UPDATE_ANTENNA;
+ else if (conf->antenna_sel_rx &&
+ conf->antenna_sel_rx != active_ant->rx)
+ flags |= CONFIG_UPDATE_ANTENNA;
+ else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
+ flags |= CONFIG_UPDATE_ANTENNA;
+
+ if (!conf->antenna_sel_tx &&
+ default_ant->tx != ANTENNA_SW_DIVERSITY &&
+ default_ant->tx != active_ant->tx)
+ flags |= CONFIG_UPDATE_ANTENNA;
+ else if (conf->antenna_sel_tx &&
+ conf->antenna_sel_tx != active_ant->tx)
+ flags |= CONFIG_UPDATE_ANTENNA;
+ else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
flags |= CONFIG_UPDATE_ANTENNA;
/*
@@ -171,6 +230,22 @@ config:
sizeof(libconf.rf));
}
+ if (flags & CONFIG_UPDATE_ANTENNA) {
+ if (conf->antenna_sel_rx)
+ libconf.ant.rx = conf->antenna_sel_rx;
+ else if (default_ant->rx != ANTENNA_SW_DIVERSITY)
+ libconf.ant.rx = default_ant->rx;
+ else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
+ libconf.ant.rx = ANTENNA_B;
+
+ if (conf->antenna_sel_tx)
+ libconf.ant.tx = conf->antenna_sel_tx;
+ else if (default_ant->tx != ANTENNA_SW_DIVERSITY)
+ libconf.ant.tx = default_ant->tx;
+ else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
+ libconf.ant.tx = ANTENNA_B;
+ }
+
if (flags & CONFIG_UPDATE_SLOT_TIME) {
short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
@@ -196,10 +271,17 @@ config:
if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
rt2x00lib_reset_link_tuner(rt2x00dev);
- rt2x00dev->curr_hwmode = libconf.phymode;
- rt2x00dev->rx_status.phymode = conf->phymode;
+ if (flags & CONFIG_UPDATE_PHYMODE) {
+ rt2x00dev->curr_hwmode = libconf.phymode;
+ rt2x00dev->rx_status.phymode = conf->phymode;
+ }
+
rt2x00dev->rx_status.freq = conf->freq;
rt2x00dev->rx_status.channel = conf->channel;
rt2x00dev->tx_power = conf->power_level;
- rt2x00dev->rx_status.antenna = conf->antenna_sel_rx;
+
+ if (flags & CONFIG_UPDATE_ANTENNA) {
+ rt2x00dev->link.ant.active.rx = libconf.ant.rx;
+ rt2x00dev->link.ant.active.tx = libconf.ant.tx;
+ }
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 9275d6f9517e..b44a9f4b9b7f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -23,18 +23,15 @@
Abstract: rt2x00 debugfs specific routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/poll.h>
#include <linux/uaccess.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
+#include "rt2x00dump.h"
#define PRINT_LINE_LEN_MAX 32
@@ -55,18 +52,22 @@ struct rt2x00debug_intf {
/*
* Debugfs entries for:
* - driver folder
- * - driver file
- * - chipset file
- * - device flags file
- * - register offset/value files
- * - eeprom offset/value files
- * - bbp offset/value files
- * - rf offset/value files
+ * - driver file
+ * - chipset file
+ * - device flags file
+ * - register folder
+ * - csr offset/value files
+ * - eeprom offset/value files
+ * - bbp offset/value files
+ * - rf offset/value files
+ * - frame dump folder
+ * - frame dump file
*/
struct dentry *driver_folder;
struct dentry *driver_entry;
struct dentry *chipset_entry;
struct dentry *dev_flags;
+ struct dentry *register_folder;
struct dentry *csr_off_entry;
struct dentry *csr_val_entry;
struct dentry *eeprom_off_entry;
@@ -75,6 +76,24 @@ struct rt2x00debug_intf {
struct dentry *bbp_val_entry;
struct dentry *rf_off_entry;
struct dentry *rf_val_entry;
+ struct dentry *frame_folder;
+ struct dentry *frame_dump_entry;
+
+ /*
+ * The frame dump file only allows a single reader,
+ * so we need to store the current state here.
+ */
+ unsigned long frame_dump_flags;
+#define FRAME_DUMP_FILE_OPEN 1
+
+ /*
+ * We queue each frame before dumping it to the user,
+ * per read command we will pass a single skb structure
+ * so we should be prepared to queue multiple sk buffers
+ * before sending it to userspace.
+ */
+ struct sk_buff_head frame_dump_skbqueue;
+ wait_queue_head_t frame_dump_waitqueue;
/*
* Driver and chipset files will use a data buffer
@@ -93,6 +112,59 @@ struct rt2x00debug_intf {
unsigned int offset_rf;
};
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb)
+{
+ struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+ struct skb_desc *desc = get_skb_desc(skb);
+ struct sk_buff *skbcopy;
+ struct rt2x00dump_hdr *dump_hdr;
+ struct timeval timestamp;
+
+ do_gettimeofday(&timestamp);
+
+ if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+ return;
+
+ if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
+ DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
+ return;
+ }
+
+ skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + desc->data_len,
+ GFP_ATOMIC);
+ if (!skbcopy) {
+ DEBUG(rt2x00dev, "Failed to copy skb for dump.\n");
+ return;
+ }
+
+ dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr));
+ dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION);
+ dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr));
+ dump_hdr->desc_length = cpu_to_le32(desc->desc_len);
+ dump_hdr->data_length = cpu_to_le32(desc->data_len);
+ dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt);
+ dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf);
+ dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev);
+ dump_hdr->type = cpu_to_le16(desc->frame_type);
+ dump_hdr->ring_index = desc->ring->queue_idx;
+ dump_hdr->entry_index = desc->entry->entry_idx;
+ dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec);
+ dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec);
+
+ memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len);
+ memcpy(skb_put(skbcopy, desc->data_len), desc->data, desc->data_len);
+
+ skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy);
+ wake_up_interruptible(&intf->frame_dump_waitqueue);
+
+ /*
+ * Verify that the file has not been closed while we were working.
+ */
+ if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+ skb_queue_purge(&intf->frame_dump_skbqueue);
+}
+
static int rt2x00debug_file_open(struct inode *inode, struct file *file)
{
struct rt2x00debug_intf *intf = inode->i_private;
@@ -114,13 +186,96 @@ static int rt2x00debug_file_release(struct inode *inode, struct file *file)
return 0;
}
+static int rt2x00debug_open_ring_dump(struct inode *inode, struct file *file)
+{
+ struct rt2x00debug_intf *intf = inode->i_private;
+ int retval;
+
+ retval = rt2x00debug_file_open(inode, file);
+ if (retval)
+ return retval;
+
+ if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) {
+ rt2x00debug_file_release(inode, file);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int rt2x00debug_release_ring_dump(struct inode *inode, struct file *file)
+{
+ struct rt2x00debug_intf *intf = inode->i_private;
+
+ skb_queue_purge(&intf->frame_dump_skbqueue);
+
+ clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags);
+
+ return rt2x00debug_file_release(inode, file);
+}
+
+static ssize_t rt2x00debug_read_ring_dump(struct file *file,
+ char __user *buf,
+ size_t length,
+ loff_t *offset)
+{
+ struct rt2x00debug_intf *intf = file->private_data;
+ struct sk_buff *skb;
+ size_t status;
+ int retval;
+
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+
+ retval =
+ wait_event_interruptible(intf->frame_dump_waitqueue,
+ (skb =
+ skb_dequeue(&intf->frame_dump_skbqueue)));
+ if (retval)
+ return retval;
+
+ status = min((size_t)skb->len, length);
+ if (copy_to_user(buf, skb->data, status)) {
+ status = -EFAULT;
+ goto exit;
+ }
+
+ *offset += status;
+
+exit:
+ kfree_skb(skb);
+
+ return status;
+}
+
+static unsigned int rt2x00debug_poll_ring_dump(struct file *file,
+ poll_table *wait)
+{
+ struct rt2x00debug_intf *intf = file->private_data;
+
+ poll_wait(file, &intf->frame_dump_waitqueue, wait);
+
+ if (!skb_queue_empty(&intf->frame_dump_skbqueue))
+ return POLLOUT | POLLWRNORM;
+
+ return 0;
+}
+
+static const struct file_operations rt2x00debug_fop_ring_dump = {
+ .owner = THIS_MODULE,
+ .read = rt2x00debug_read_ring_dump,
+ .poll = rt2x00debug_poll_ring_dump,
+ .open = rt2x00debug_open_ring_dump,
+ .release = rt2x00debug_release_ring_dump,
+};
+
#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \
static ssize_t rt2x00debug_read_##__name(struct file *file, \
char __user *buf, \
size_t length, \
loff_t *offset) \
{ \
- struct rt2x00debug_intf *intf = file->private_data; \
+ struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
@@ -150,7 +305,7 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
size_t length, \
loff_t *offset) \
{ \
- struct rt2x00debug_intf *intf = file->private_data; \
+ struct rt2x00debug_intf *intf = file->private_data; \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
@@ -254,11 +409,15 @@ static struct dentry *rt2x00debug_create_file_chipset(const char *name,
const struct rt2x00debug *debug = intf->debug;
char *data;
- data = kzalloc(4 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
+ data = kzalloc(8 * PRINT_LINE_LEN_MAX, GFP_KERNEL);
if (!data)
return NULL;
blob->data = data;
+ data += sprintf(data, "rt chip: %04x\n", intf->rt2x00dev->chip.rt);
+ data += sprintf(data, "rf chip: %04x\n", intf->rt2x00dev->chip.rf);
+ data += sprintf(data, "revision:%08x\n", intf->rt2x00dev->chip.rev);
+ data += sprintf(data, "\n");
data += sprintf(data, "csr length: %d\n", debug->csr.word_count);
data += sprintf(data, "eeprom length: %d\n", debug->eeprom.word_count);
data += sprintf(data, "bbp length: %d\n", debug->bbp.word_count);
@@ -306,12 +465,17 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
if (IS_ERR(intf->dev_flags))
goto exit;
-#define RT2X00DEBUGFS_CREATE_ENTRY(__intf, __name) \
+ intf->register_folder =
+ debugfs_create_dir("register", intf->driver_folder);
+ if (IS_ERR(intf->register_folder))
+ goto exit;
+
+#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
({ \
(__intf)->__name##_off_entry = \
debugfs_create_u32(__stringify(__name) "_offset", \
S_IRUGO | S_IWUSR, \
- (__intf)->driver_folder, \
+ (__intf)->register_folder, \
&(__intf)->offset_##__name); \
if (IS_ERR((__intf)->__name##_off_entry)) \
goto exit; \
@@ -319,18 +483,32 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
(__intf)->__name##_val_entry = \
debugfs_create_file(__stringify(__name) "_value", \
S_IRUGO | S_IWUSR, \
- (__intf)->driver_folder, \
+ (__intf)->register_folder, \
(__intf), &rt2x00debug_fop_##__name);\
if (IS_ERR((__intf)->__name##_val_entry)) \
goto exit; \
})
- RT2X00DEBUGFS_CREATE_ENTRY(intf, csr);
- RT2X00DEBUGFS_CREATE_ENTRY(intf, eeprom);
- RT2X00DEBUGFS_CREATE_ENTRY(intf, bbp);
- RT2X00DEBUGFS_CREATE_ENTRY(intf, rf);
+ RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr);
+ RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom);
+ RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp);
+ RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf);
-#undef RT2X00DEBUGFS_CREATE_ENTRY
+#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY
+
+ intf->frame_folder =
+ debugfs_create_dir("frame", intf->driver_folder);
+ if (IS_ERR(intf->frame_folder))
+ goto exit;
+
+ intf->frame_dump_entry =
+ debugfs_create_file("dump", S_IRUGO, intf->frame_folder,
+ intf, &rt2x00debug_fop_ring_dump);
+ if (IS_ERR(intf->frame_dump_entry))
+ goto exit;
+
+ skb_queue_head_init(&intf->frame_dump_skbqueue);
+ init_waitqueue_head(&intf->frame_dump_waitqueue);
return;
@@ -343,11 +521,15 @@ exit:
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
{
- const struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
+ struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf;
if (unlikely(!intf))
return;
+ skb_queue_purge(&intf->frame_dump_skbqueue);
+
+ debugfs_remove(intf->frame_dump_entry);
+ debugfs_remove(intf->frame_folder);
debugfs_remove(intf->rf_val_entry);
debugfs_remove(intf->rf_off_entry);
debugfs_remove(intf->bbp_val_entry);
@@ -356,6 +538,7 @@ void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
debugfs_remove(intf->eeprom_off_entry);
debugfs_remove(intf->csr_val_entry);
debugfs_remove(intf->csr_off_entry);
+ debugfs_remove(intf->register_folder);
debugfs_remove(intf->dev_flags);
debugfs_remove(intf->chipset_entry);
debugfs_remove(intf->driver_entry);
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
index 860e8fa3a0da..d37efbd09c41 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
@@ -30,9 +30,9 @@ struct rt2x00_dev;
#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \
struct reg##__name { \
- void (*read)(const struct rt2x00_dev *rt2x00dev, \
+ void (*read)(struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type *data); \
- void (*write)(const struct rt2x00_dev *rt2x00dev, \
+ void (*write)(struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type data); \
\
unsigned int word_size; \
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index ff399f8083e9..c4be2ac4d7a4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -23,16 +23,12 @@
Abstract: rt2x00 generic device routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/kernel.h>
#include <linux/module.h>
#include "rt2x00.h"
#include "rt2x00lib.h"
+#include "rt2x00dump.h"
/*
* Ring handler.
@@ -67,7 +63,21 @@ EXPORT_SYMBOL_GPL(rt2x00lib_get_ring);
*/
static void rt2x00lib_start_link_tuner(struct rt2x00_dev *rt2x00dev)
{
- rt2x00_clear_link(&rt2x00dev->link);
+ rt2x00dev->link.count = 0;
+ rt2x00dev->link.vgc_level = 0;
+
+ memset(&rt2x00dev->link.qual, 0, sizeof(rt2x00dev->link.qual));
+
+ /*
+ * The RX and TX percentage should start at 50%
+ * this will assure we will get at least get some
+ * decent value when the link tuner starts.
+ * The value will be dropped and overwritten with
+ * the correct (measured )value anyway during the
+ * first run of the link tuner.
+ */
+ rt2x00dev->link.qual.rx_percentage = 50;
+ rt2x00dev->link.qual.tx_percentage = 50;
/*
* Reset the link tuner.
@@ -93,6 +103,46 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev)
}
/*
+ * Ring initialization
+ */
+static void rt2x00lib_init_rxrings(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_ring *ring = rt2x00dev->rx;
+ unsigned int i;
+
+ if (!rt2x00dev->ops->lib->init_rxentry)
+ return;
+
+ if (ring->data_addr)
+ memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+ for (i = 0; i < ring->stats.limit; i++)
+ rt2x00dev->ops->lib->init_rxentry(rt2x00dev, &ring->entry[i]);
+
+ rt2x00_ring_index_clear(ring);
+}
+
+static void rt2x00lib_init_txrings(struct rt2x00_dev *rt2x00dev)
+{
+ struct data_ring *ring;
+ unsigned int i;
+
+ if (!rt2x00dev->ops->lib->init_txentry)
+ return;
+
+ txringall_for_each(rt2x00dev, ring) {
+ if (ring->data_addr)
+ memset(ring->data_addr, 0, rt2x00_get_ring_size(ring));
+
+ for (i = 0; i < ring->stats.limit; i++)
+ rt2x00dev->ops->lib->init_txentry(rt2x00dev,
+ &ring->entry[i]);
+
+ rt2x00_ring_index_clear(ring);
+ }
+}
+
+/*
* Radio control handlers.
*/
int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -108,6 +158,12 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
return 0;
/*
+ * Initialize all data rings.
+ */
+ rt2x00lib_init_rxrings(rt2x00dev);
+ rt2x00lib_init_txrings(rt2x00dev);
+
+ /*
* Enable radio.
*/
status = rt2x00dev->ops->lib->set_device_state(rt2x00dev,
@@ -179,26 +235,153 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
rt2x00lib_start_link_tuner(rt2x00dev);
}
-static void rt2x00lib_precalculate_link_signal(struct link *link)
+static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
{
- if (link->rx_failed || link->rx_success)
- link->rx_percentage =
- (link->rx_success * 100) /
- (link->rx_failed + link->rx_success);
+ enum antenna rx = rt2x00dev->link.ant.active.rx;
+ enum antenna tx = rt2x00dev->link.ant.active.tx;
+ int sample_a =
+ rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A);
+ int sample_b =
+ rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B);
+
+ /*
+ * We are done sampling. Now we should evaluate the results.
+ */
+ rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE;
+
+ /*
+ * During the last period we have sampled the RSSI
+ * from both antenna's. It now is time to determine
+ * which antenna demonstrated the best performance.
+ * When we are already on the antenna with the best
+ * performance, then there really is nothing for us
+ * left to do.
+ */
+ if (sample_a == sample_b)
+ return;
+
+ if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) {
+ if (sample_a > sample_b && rx == ANTENNA_B)
+ rx = ANTENNA_A;
+ else if (rx == ANTENNA_A)
+ rx = ANTENNA_B;
+ }
+
+ if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY) {
+ if (sample_a > sample_b && tx == ANTENNA_B)
+ tx = ANTENNA_A;
+ else if (tx == ANTENNA_A)
+ tx = ANTENNA_B;
+ }
+
+ rt2x00lib_config_antenna(rt2x00dev, rx, tx);
+}
+
+static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
+{
+ enum antenna rx = rt2x00dev->link.ant.active.rx;
+ enum antenna tx = rt2x00dev->link.ant.active.tx;
+ int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link);
+ int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr);
+
+ /*
+ * Legacy driver indicates that we should swap antenna's
+ * when the difference in RSSI is greater that 5. This
+ * also should be done when the RSSI was actually better
+ * then the previous sample.
+ * When the difference exceeds the threshold we should
+ * sample the rssi from the other antenna to make a valid
+ * comparison between the 2 antennas.
+ */
+ if ((rssi_curr - rssi_old) > -5 || (rssi_curr - rssi_old) < 5)
+ return;
+
+ rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE;
+
+ if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
+ rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+ if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
+ tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+
+ rt2x00lib_config_antenna(rt2x00dev, rx, tx);
+}
+
+static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev)
+{
+ /*
+ * Determine if software diversity is enabled for
+ * either the TX or RX antenna (or both).
+ * Always perform this check since within the link
+ * tuner interval the configuration might have changed.
+ */
+ rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY;
+ rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY;
+
+ if (rt2x00dev->hw->conf.antenna_sel_rx == 0 &&
+ rt2x00dev->default_ant.rx != ANTENNA_SW_DIVERSITY)
+ rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY;
+ if (rt2x00dev->hw->conf.antenna_sel_tx == 0 &&
+ rt2x00dev->default_ant.tx != ANTENNA_SW_DIVERSITY)
+ rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY;
+
+ if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) &&
+ !(rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)) {
+ rt2x00dev->link.ant.flags &= ~ANTENNA_MODE_SAMPLE;
+ return;
+ }
+
+ /*
+ * If we have only sampled the data over the last period
+ * we should now harvest the data. Otherwise just evaluate
+ * the data. The latter should only be performed once
+ * every 2 seconds.
+ */
+ if (rt2x00dev->link.ant.flags & ANTENNA_MODE_SAMPLE)
+ rt2x00lib_evaluate_antenna_sample(rt2x00dev);
+ else if (rt2x00dev->link.count & 1)
+ rt2x00lib_evaluate_antenna_eval(rt2x00dev);
+}
+
+static void rt2x00lib_update_link_stats(struct link *link, int rssi)
+{
+ int avg_rssi = rssi;
+
+ /*
+ * Update global RSSI
+ */
+ if (link->qual.avg_rssi)
+ avg_rssi = MOVING_AVERAGE(link->qual.avg_rssi, rssi, 8);
+ link->qual.avg_rssi = avg_rssi;
+
+ /*
+ * Update antenna RSSI
+ */
+ if (link->ant.rssi_ant)
+ rssi = MOVING_AVERAGE(link->ant.rssi_ant, rssi, 8);
+ link->ant.rssi_ant = rssi;
+}
+
+static void rt2x00lib_precalculate_link_signal(struct link_qual *qual)
+{
+ if (qual->rx_failed || qual->rx_success)
+ qual->rx_percentage =
+ (qual->rx_success * 100) /
+ (qual->rx_failed + qual->rx_success);
else
- link->rx_percentage = 50;
+ qual->rx_percentage = 50;
- if (link->tx_failed || link->tx_success)
- link->tx_percentage =
- (link->tx_success * 100) /
- (link->tx_failed + link->tx_success);
+ if (qual->tx_failed || qual->tx_success)
+ qual->tx_percentage =
+ (qual->tx_success * 100) /
+ (qual->tx_failed + qual->tx_success);
else
- link->tx_percentage = 50;
+ qual->tx_percentage = 50;
- link->rx_success = 0;
- link->rx_failed = 0;
- link->tx_success = 0;
- link->tx_failed = 0;
+ qual->rx_success = 0;
+ qual->rx_failed = 0;
+ qual->tx_success = 0;
+ qual->tx_failed = 0;
}
static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev,
@@ -225,8 +408,8 @@ static int rt2x00lib_calculate_link_signal(struct rt2x00_dev *rt2x00dev,
* defines to calculate the current link signal.
*/
signal = ((WEIGHT_RSSI * rssi_percentage) +
- (WEIGHT_TX * rt2x00dev->link.tx_percentage) +
- (WEIGHT_RX * rt2x00dev->link.rx_percentage)) / 100;
+ (WEIGHT_TX * rt2x00dev->link.qual.tx_percentage) +
+ (WEIGHT_RX * rt2x00dev->link.qual.rx_percentage)) / 100;
return (signal > 100) ? 100 : signal;
}
@@ -246,10 +429,9 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
/*
* Update statistics.
*/
- rt2x00dev->ops->lib->link_stats(rt2x00dev);
-
+ rt2x00dev->ops->lib->link_stats(rt2x00dev, &rt2x00dev->link.qual);
rt2x00dev->low_level_stats.dot11FCSErrorCount +=
- rt2x00dev->link.rx_failed;
+ rt2x00dev->link.qual.rx_failed;
/*
* Only perform the link tuning when Link tuning
@@ -259,10 +441,15 @@ static void rt2x00lib_link_tuner(struct work_struct *work)
rt2x00dev->ops->lib->link_tuner(rt2x00dev);
/*
+ * Evaluate antenna setup.
+ */
+ rt2x00lib_evaluate_antenna(rt2x00dev);
+
+ /*
* Precalculate a portion of the link signal which is
* in based on the tx/rx success/failure counters.
*/
- rt2x00lib_precalculate_link_signal(&rt2x00dev->link);
+ rt2x00lib_precalculate_link_signal(&rt2x00dev->link.qual);
/*
* Increase tuner counter, and reschedule the next link tuner run.
@@ -276,7 +463,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, filter_work);
- unsigned int filter = rt2x00dev->interface.filter;
+ unsigned int filter = rt2x00dev->packet_filter;
/*
* Since we had stored the filter inside interface.filter,
@@ -284,7 +471,7 @@ static void rt2x00lib_packetfilter_scheduled(struct work_struct *work)
* assume nothing has changed (*total_flags will be compared
* to interface.filter to determine if any action is required).
*/
- rt2x00dev->interface.filter = 0;
+ rt2x00dev->packet_filter = 0;
rt2x00dev->ops->hw->configure_filter(rt2x00dev->hw,
filter, &filter, 0, NULL);
@@ -294,10 +481,17 @@ static void rt2x00lib_configuration_scheduled(struct work_struct *work)
{
struct rt2x00_dev *rt2x00dev =
container_of(work, struct rt2x00_dev, config_work);
- int preamble = !test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+ struct ieee80211_bss_conf bss_conf;
- rt2x00mac_erp_ie_changed(rt2x00dev->hw,
- IEEE80211_ERP_CHANGE_PREAMBLE, 0, preamble);
+ bss_conf.use_short_preamble =
+ test_bit(CONFIG_SHORT_PREAMBLE, &rt2x00dev->flags);
+
+ /*
+ * FIXME: shouldn't invoke it this way because all other contents
+ * of bss_conf is invalid.
+ */
+ rt2x00mac_bss_info_changed(rt2x00dev->hw, rt2x00dev->interface.id,
+ &bss_conf, BSS_CHANGED_ERP_PREAMBLE);
}
/*
@@ -350,8 +544,8 @@ void rt2x00lib_txdone(struct data_entry *entry,
tx_status->ack_signal = 0;
tx_status->excessive_retries = (status == TX_FAIL_RETRY);
tx_status->retry_count = retry;
- rt2x00dev->link.tx_success += success;
- rt2x00dev->link.tx_failed += retry + fail;
+ rt2x00dev->link.qual.tx_success += success;
+ rt2x00dev->link.qual.tx_failed += retry + fail;
if (!(tx_status->control.flags & IEEE80211_TXCTL_NO_ACK)) {
if (success)
@@ -371,9 +565,11 @@ void rt2x00lib_txdone(struct data_entry *entry,
}
/*
- * Send the tx_status to mac80211,
- * that method also cleans up the skb structure.
+ * Send the tx_status to mac80211 & debugfs.
+ * mac80211 will clean up the skb structure.
*/
+ get_skb_desc(entry->skb)->frame_type = DUMP_FRAME_TXDONE;
+ rt2x00debug_dump_frame(rt2x00dev, entry->skb);
ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb, tx_status);
entry->skb = NULL;
}
@@ -386,8 +582,10 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status;
struct ieee80211_hw_mode *mode;
struct ieee80211_rate *rate;
+ struct ieee80211_hdr *hdr;
unsigned int i;
int val = 0;
+ u16 fc;
/*
* Update RX statistics.
@@ -412,17 +610,28 @@ void rt2x00lib_rxdone(struct data_entry *entry, struct sk_buff *skb,
}
}
- rt2x00_update_link_rssi(&rt2x00dev->link, desc->rssi);
- rt2x00dev->link.rx_success++;
+ /*
+ * Only update link status if this is a beacon frame carrying our bssid.
+ */
+ hdr = (struct ieee80211_hdr*)skb->data;
+ fc = le16_to_cpu(hdr->frame_control);
+ if (is_beacon(fc) && desc->my_bss)
+ rt2x00lib_update_link_stats(&rt2x00dev->link, desc->rssi);
+
+ rt2x00dev->link.qual.rx_success++;
+
rx_status->rate = val;
rx_status->signal =
rt2x00lib_calculate_link_signal(rt2x00dev, desc->rssi);
rx_status->ssi = desc->rssi;
rx_status->flag = desc->flags;
+ rx_status->antenna = rt2x00dev->link.ant.active.rx;
/*
- * Send frame to mac80211
+ * Send frame to mac80211 & debugfs
*/
+ get_skb_desc(skb)->frame_type = DUMP_FRAME_RXDONE;
+ rt2x00debug_dump_frame(rt2x00dev, skb);
ieee80211_rx_irqsafe(rt2x00dev->hw, skb, rx_status);
}
EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
@@ -431,36 +640,25 @@ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
* TX descriptor initializer
*/
void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
+ struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct txdata_entry_desc desc;
- struct data_ring *ring;
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ struct ieee80211_hdr *ieee80211hdr = skbdesc->data;
int tx_rate;
int bitrate;
+ int length;
int duration;
int residual;
u16 frame_control;
u16 seq_ctrl;
- /*
- * Make sure the descriptor is properly cleared.
- */
- memset(&desc, 0x00, sizeof(desc));
+ memset(&desc, 0, sizeof(desc));
- /*
- * Get ring pointer, if we fail to obtain the
- * correct ring, then use the first TX ring.
- */
- ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
- if (!ring)
- ring = rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
-
- desc.cw_min = ring->tx_params.cw_min;
- desc.cw_max = ring->tx_params.cw_max;
- desc.aifs = ring->tx_params.aifs;
+ desc.cw_min = skbdesc->ring->tx_params.cw_min;
+ desc.cw_max = skbdesc->ring->tx_params.cw_max;
+ desc.aifs = skbdesc->ring->tx_params.aifs;
/*
* Identify queue
@@ -482,12 +680,21 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
tx_rate = control->tx_rate;
/*
+ * Check whether this frame is to be acked
+ */
+ if (!(control->flags & IEEE80211_TXCTL_NO_ACK))
+ __set_bit(ENTRY_TXD_ACK, &desc.flags);
+
+ /*
* Check if this is a RTS/CTS frame
*/
if (is_rts_frame(frame_control) || is_cts_frame(frame_control)) {
__set_bit(ENTRY_TXD_BURST, &desc.flags);
- if (is_rts_frame(frame_control))
+ if (is_rts_frame(frame_control)) {
__set_bit(ENTRY_TXD_RTS_FRAME, &desc.flags);
+ __set_bit(ENTRY_TXD_ACK, &desc.flags);
+ } else
+ __clear_bit(ENTRY_TXD_ACK, &desc.flags);
if (control->rts_cts_rate)
tx_rate = control->rts_cts_rate;
}
@@ -532,17 +739,18 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
desc.signal = DEVICE_GET_RATE_FIELD(tx_rate, PLCP);
desc.service = 0x04;
+ length = skbdesc->data_len + FCS_LEN;
if (test_bit(ENTRY_TXD_OFDM_RATE, &desc.flags)) {
- desc.length_high = ((length + FCS_LEN) >> 6) & 0x3f;
- desc.length_low = ((length + FCS_LEN) & 0x3f);
+ desc.length_high = (length >> 6) & 0x3f;
+ desc.length_low = length & 0x3f;
} else {
bitrate = DEVICE_GET_RATE_FIELD(tx_rate, RATE);
/*
* Convert length to microseconds.
*/
- residual = get_duration_res(length + FCS_LEN, bitrate);
- duration = get_duration(length + FCS_LEN, bitrate);
+ residual = get_duration_res(length, bitrate);
+ duration = get_duration(length, bitrate);
if (residual != 0) {
duration++;
@@ -565,8 +773,22 @@ void rt2x00lib_write_tx_desc(struct rt2x00_dev *rt2x00dev,
desc.signal |= 0x08;
}
- rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, txd, &desc,
- ieee80211hdr, length, control);
+ rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, skb, &desc, control);
+
+ /*
+ * Update ring entry.
+ */
+ skbdesc->entry->skb = skb;
+ memcpy(&skbdesc->entry->tx_status.control, control, sizeof(*control));
+
+ /*
+ * The frame has been completely initialized and ready
+ * for sending to the device. The caller will push the
+ * frame to the device, but we are going to push the
+ * frame to debugfs here.
+ */
+ skbdesc->frame_type = DUMP_FRAME_TX;
+ rt2x00debug_dump_frame(rt2x00dev, skb);
}
EXPORT_SYMBOL_GPL(rt2x00lib_write_tx_desc);
@@ -809,6 +1031,7 @@ static int rt2x00lib_alloc_entries(struct data_ring *ring,
entry[i].flags = 0;
entry[i].ring = ring;
entry[i].skb = NULL;
+ entry[i].entry_idx = i;
}
ring->entry = entry;
@@ -866,7 +1089,7 @@ static void rt2x00lib_free_ring_entries(struct rt2x00_dev *rt2x00dev)
}
}
-void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
+static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
{
if (!__test_and_clear_bit(DEVICE_INITIALIZED, &rt2x00dev->flags))
return;
@@ -887,7 +1110,7 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
rt2x00lib_free_ring_entries(rt2x00dev);
}
-int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
+static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
{
int status;
@@ -930,12 +1153,65 @@ exit:
return status;
}
+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
+{
+ int retval;
+
+ if (test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ return 0;
+
+ /*
+ * If this is the first interface which is added,
+ * we should load the firmware now.
+ */
+ if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
+ retval = rt2x00lib_load_firmware(rt2x00dev);
+ if (retval)
+ return retval;
+ }
+
+ /*
+ * Initialize the device.
+ */
+ retval = rt2x00lib_initialize(rt2x00dev);
+ if (retval)
+ return retval;
+
+ /*
+ * Enable radio.
+ */
+ retval = rt2x00lib_enable_radio(rt2x00dev);
+ if (retval) {
+ rt2x00lib_uninitialize(rt2x00dev);
+ return retval;
+ }
+
+ __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
+
+ return 0;
+}
+
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev)
+{
+ if (!test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ return;
+
+ /*
+ * Perhaps we can add something smarter here,
+ * but for now just disabling the radio should do.
+ */
+ rt2x00lib_disable_radio(rt2x00dev);
+
+ __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+}
+
/*
* driver allocation handlers.
*/
static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
+ unsigned int index;
/*
* We need the following rings:
@@ -963,11 +1239,18 @@ static int rt2x00lib_alloc_rings(struct rt2x00_dev *rt2x00dev)
/*
* Initialize ring parameters.
- * cw_min: 2^5 = 32.
- * cw_max: 2^10 = 1024.
+ * RX: queue_idx = 0
+ * TX: queue_idx = IEEE80211_TX_QUEUE_DATA0 + index
+ * TX: cw_min: 2^5 = 32.
+ * TX: cw_max: 2^10 = 1024.
*/
- ring_for_each(rt2x00dev, ring) {
+ rt2x00dev->rx->rt2x00dev = rt2x00dev;
+ rt2x00dev->rx->queue_idx = 0;
+
+ index = IEEE80211_TX_QUEUE_DATA0;
+ txring_for_each(rt2x00dev, ring) {
ring->rt2x00dev = rt2x00dev;
+ ring->queue_idx = index++;
ring->tx_params.aifs = 2;
ring->tx_params.cw_min = 5;
ring->tx_params.cw_max = 10;
@@ -1008,7 +1291,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
/*
* Reset current working type.
*/
- rt2x00dev->interface.type = INVALID_INTERFACE;
+ rt2x00dev->interface.type = IEEE80211_IF_TYPE_INVALID;
/*
* Allocate ring array.
@@ -1112,7 +1395,7 @@ int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state)
* Disable radio and unitialize all items
* that must be recreated on resume.
*/
- rt2x00mac_stop(rt2x00dev->hw);
+ rt2x00lib_stop(rt2x00dev);
rt2x00lib_uninitialize(rt2x00dev);
rt2x00debug_deregister(rt2x00dev);
@@ -1134,7 +1417,6 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
int retval;
NOTICE(rt2x00dev, "Waking up.\n");
- __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
/*
* Open the debugfs entry.
@@ -1150,7 +1432,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* Reinitialize device and all active interfaces.
*/
- retval = rt2x00mac_start(rt2x00dev->hw);
+ retval = rt2x00lib_start(rt2x00dev);
if (retval)
goto exit;
@@ -1166,6 +1448,11 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
rt2x00lib_config_type(rt2x00dev, intf->type);
/*
+ * We are ready again to receive requests from mac80211.
+ */
+ __set_bit(DEVICE_PRESENT, &rt2x00dev->flags);
+
+ /*
* It is possible that during that mac80211 has attempted
* to send frames while we were suspending or resuming.
* In that case we have disabled the TX queue and should
diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h
new file mode 100644
index 000000000000..99f3f367adce
--- /dev/null
+++ b/drivers/net/wireless/rt2x00/rt2x00dump.h
@@ -0,0 +1,121 @@
+/*
+ Copyright (C) 2004 - 2007 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: rt2x00dump
+ Abstract: Data structures for the rt2x00debug & userspace.
+ */
+
+#ifndef RT2X00DUMP_H
+#define RT2X00DUMP_H
+
+/**
+ * DOC: Introduction
+ *
+ * This header is intended to be exported to userspace,
+ * to make the structures and enumerations available to userspace
+ * applications. This means that all data types should be exportable.
+ *
+ * When rt2x00 is compiled with debugfs support enabled,
+ * it is possible to capture all data coming in and out of the device
+ * by reading the frame dump file. This file can have only a single reader.
+ * The following frames will be reported:
+ * - All incoming frames (rx)
+ * - All outgoing frames (tx, including beacon and atim)
+ * - All completed frames (txdone including atim)
+ *
+ * The data is send to the file using the following format:
+ *
+ * [rt2x00dump header][hardware descriptor][ieee802.11 frame]
+ *
+ * rt2x00dump header: The description of the dumped frame, as well as
+ * additional information usefull for debugging. See &rt2x00dump_hdr.
+ * hardware descriptor: Descriptor that was used to receive or transmit
+ * the frame.
+ * ieee802.11 frame: The actual frame that was received or transmitted.
+ */
+
+/**
+ * enum rt2x00_dump_type - Frame type
+ *
+ * These values are used for the @type member of &rt2x00dump_hdr.
+ * @DUMP_FRAME_RXDONE: This frame has been received by the hardware.
+ * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware.
+ * @DUMP_FRAME_TXDONE: This frame indicates the device has handled
+ * the tx event which has either succeeded or failed. A frame
+ * with this type should also have been reported with as a
+ * %DUMP_FRAME_TX frame.
+ */
+enum rt2x00_dump_type {
+ DUMP_FRAME_RXDONE = 1,
+ DUMP_FRAME_TX = 2,
+ DUMP_FRAME_TXDONE = 3,
+};
+
+/**
+ * struct rt2x00dump_hdr - Dump frame header
+ *
+ * Each frame dumped to the debugfs file starts with this header
+ * attached. This header contains the description of the actual
+ * frame which was dumped.
+ *
+ * New fields inside the structure must be appended to the end of
+ * the structure. This way userspace tools compiled for earlier
+ * header versions can still correctly handle the frame dump
+ * (although they will not handle all data passed to them in the dump).
+ *
+ * @version: Header version should always be set to %DUMP_HEADER_VERSION.
+ * This field must be checked by userspace to determine if it can
+ * handle this frame.
+ * @header_length: The length of the &rt2x00dump_hdr structure. This is
+ * used for compatibility reasons so userspace can easily determine
+ * the location of the next field in the dump.
+ * @desc_length: The length of the device descriptor.
+ * @data_length: The length of the frame data (including the ieee802.11 header.
+ * @chip_rt: RT chipset
+ * @chip_rf: RF chipset
+ * @chip_rev: Chipset revision
+ * @type: The frame type (&rt2x00_dump_type)
+ * @ring_index: The index number of the data ring.
+ * @entry_index: The index number of the entry inside the data ring.
+ * @timestamp_sec: Timestamp - seconds
+ * @timestamp_usec: Timestamp - microseconds
+ */
+struct rt2x00dump_hdr {
+ __le32 version;
+#define DUMP_HEADER_VERSION 2
+
+ __le32 header_length;
+ __le32 desc_length;
+ __le32 data_length;
+
+ __le16 chip_rt;
+ __le16 chip_rf;
+ __le32 chip_rev;
+
+ __le16 type;
+ __u8 ring_index;
+ __u8 entry_index;
+
+ __le32 timestamp_sec;
+ __le32 timestamp_usec;
+};
+
+#endif /* RT2X00DUMP_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c
index 236025f8b90f..0a475e4e2442 100644
--- a/drivers/net/wireless/rt2x00/rt2x00firmware.c
+++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c
@@ -23,11 +23,6 @@
Abstract: rt2x00 firmware loading routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/crc-itu-t.h>
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 06d9bc0015c0..1adbd28e0973 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -44,8 +44,8 @@ void rt2x00lib_reset_link_tuner(struct rt2x00_dev *rt2x00dev);
/*
* Initialization handlers.
*/
-int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
+int rt2x00lib_start(struct rt2x00_dev *rt2x00dev);
+void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev);
/*
* Configuration handlers.
@@ -53,6 +53,8 @@ void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev);
void rt2x00lib_config_mac_addr(struct rt2x00_dev *rt2x00dev, u8 *mac);
void rt2x00lib_config_bssid(struct rt2x00_dev *rt2x00dev, u8 *bssid);
void rt2x00lib_config_type(struct rt2x00_dev *rt2x00dev, const int type);
+void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
+ enum antenna rx, enum antenna tx);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
struct ieee80211_conf *conf, const int force_config);
@@ -78,6 +80,7 @@ static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev)
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
void rt2x00debug_register(struct rt2x00_dev *rt2x00dev);
void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev);
+void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
#else
static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
{
@@ -86,6 +89,11 @@ static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev)
{
}
+
+static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
+ struct sk_buff *skb)
+{
+}
#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 85ea8a8e658e..e3f15e518c76 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -23,11 +23,6 @@
Abstract: rt2x00 generic mac80211 routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/kernel.h>
#include <linux/module.h>
@@ -89,7 +84,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
*/
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags)) {
ieee80211_stop_queues(hw);
- return 0;
+ return NETDEV_TX_OK;
}
/*
@@ -115,15 +110,24 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
if (!is_rts_frame(frame_control) && !is_cts_frame(frame_control) &&
(control->flags & (IEEE80211_TXCTL_USE_RTS_CTS |
IEEE80211_TXCTL_USE_CTS_PROTECT))) {
- if (rt2x00_ring_free(ring) <= 1)
+ if (rt2x00_ring_free(ring) <= 1) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }
- if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control))
+ if (rt2x00mac_tx_rts_cts(rt2x00dev, ring, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }
}
- if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control))
+ if (rt2x00dev->ops->lib->write_tx_data(rt2x00dev, ring, skb, control)) {
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return NETDEV_TX_BUSY;
+ }
+
+ if (rt2x00_ring_full(ring))
+ ieee80211_stop_queue(rt2x00dev->hw, control->queue);
if (rt2x00dev->ops->lib->kick_tx_queue)
rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, control->queue);
@@ -135,41 +139,11 @@ EXPORT_SYMBOL_GPL(rt2x00mac_tx);
int rt2x00mac_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- int status;
- if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags) ||
- test_bit(DEVICE_STARTED, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return 0;
- /*
- * If this is the first interface which is added,
- * we should load the firmware now.
- */
- if (test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) {
- status = rt2x00lib_load_firmware(rt2x00dev);
- if (status)
- return status;
- }
-
- /*
- * Initialize the device.
- */
- status = rt2x00lib_initialize(rt2x00dev);
- if (status)
- return status;
-
- /*
- * Enable radio.
- */
- status = rt2x00lib_enable_radio(rt2x00dev);
- if (status) {
- rt2x00lib_uninitialize(rt2x00dev);
- return status;
- }
-
- __set_bit(DEVICE_STARTED, &rt2x00dev->flags);
-
- return 0;
+ return rt2x00lib_start(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_start);
@@ -180,13 +154,7 @@ void rt2x00mac_stop(struct ieee80211_hw *hw)
if (!test_bit(DEVICE_PRESENT, &rt2x00dev->flags))
return;
- /*
- * Perhaps we can add something smarter here,
- * but for now just disabling the radio should do.
- */
- rt2x00lib_disable_radio(rt2x00dev);
-
- __clear_bit(DEVICE_STARTED, &rt2x00dev->flags);
+ rt2x00lib_stop(rt2x00dev);
}
EXPORT_SYMBOL_GPL(rt2x00mac_stop);
@@ -213,7 +181,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
is_interface_present(intf))
return -ENOBUFS;
- intf->id = conf->if_id;
+ intf->id = conf->vif;
intf->type = conf->type;
if (conf->type == IEEE80211_IF_TYPE_AP)
memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN);
@@ -247,7 +215,7 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
return;
intf->id = 0;
- intf->type = INVALID_INTERFACE;
+ intf->type = IEEE80211_IF_TYPE_INVALID;
memset(&intf->bssid, 0x00, ETH_ALEN);
memset(&intf->mac, 0x00, ETH_ALEN);
@@ -297,7 +265,8 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
}
EXPORT_SYMBOL_GPL(rt2x00mac_config);
-int rt2x00mac_config_interface(struct ieee80211_hw *hw, int if_id,
+int rt2x00mac_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -373,23 +342,27 @@ int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats);
-void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
- int cts_protection, int preamble)
+void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
int short_preamble;
int ack_timeout;
int ack_consume_time;
int difs;
+ int preamble;
/*
* We only support changing preamble mode.
*/
- if (!(changes & IEEE80211_ERP_CHANGE_PREAMBLE))
+ if (!(changes & BSS_CHANGED_ERP_PREAMBLE))
return;
- short_preamble = !preamble;
- preamble = !!(preamble) ? PREAMBLE : SHORT_PREAMBLE;
+ short_preamble = bss_conf->use_short_preamble;
+ preamble = bss_conf->use_short_preamble ?
+ SHORT_PREAMBLE : PREAMBLE;
difs = (hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) ?
SHORT_DIFS : DIFS;
@@ -405,7 +378,7 @@ void rt2x00mac_erp_ie_changed(struct ieee80211_hw *hw, u8 changes,
rt2x00dev->ops->lib->config_preamble(rt2x00dev, short_preamble,
ack_timeout, ack_consume_time);
}
-EXPORT_SYMBOL_GPL(rt2x00mac_erp_ie_changed);
+EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed);
int rt2x00mac_conf_tx(struct ieee80211_hw *hw, int queue,
const struct ieee80211_tx_queue_params *params)
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index 04663eb31950..804a9980055d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -23,11 +23,6 @@
Abstract: rt2x00 generic pci device routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00pci"
-
#include <linux/dma-mapping.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -43,9 +38,9 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct data_ring *ring =
- rt2x00lib_get_ring(rt2x00dev, IEEE80211_TX_QUEUE_BEACON);
- struct data_entry *entry = rt2x00_get_data_entry(ring);
+ struct skb_desc *desc;
+ struct data_ring *ring;
+ struct data_entry *entry;
/*
* Just in case mac80211 doesn't set this correctly,
@@ -53,14 +48,22 @@ int rt2x00pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
+ ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+ entry = rt2x00_get_data_entry(ring);
/*
- * Update the beacon entry.
+ * Fill in skb descriptor
*/
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len;
+ desc->desc = entry->priv;
+ desc->data = skb->data;
+ desc->ring = ring;
+ desc->entry = entry;
+
memcpy(entry->data_addr, skb->data, skb->len);
- rt2x00lib_write_tx_desc(rt2x00dev, entry->priv,
- (struct ieee80211_hdr *)skb->data,
- skb->len, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Enable beacon generation.
@@ -78,15 +81,13 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
struct data_entry *entry = rt2x00_get_data_entry(ring);
- struct data_desc *txd = entry->priv;
+ __le32 *txd = entry->priv;
+ struct skb_desc *desc;
u32 word;
- if (rt2x00_ring_full(ring)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ if (rt2x00_ring_full(ring))
return -EINVAL;
- }
rt2x00_desc_read(txd, 0, &word);
@@ -96,37 +97,42 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}
- entry->skb = skb;
- memcpy(&entry->tx_status.control, control, sizeof(*control));
+ /*
+ * Fill in skb descriptor
+ */
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len;
+ desc->desc = entry->priv;
+ desc->data = skb->data;
+ desc->ring = ring;
+ desc->entry = entry;
+
memcpy(entry->data_addr, skb->data, skb->len);
- rt2x00lib_write_tx_desc(rt2x00dev, txd, ieee80211hdr,
- skb->len, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
rt2x00_ring_index_inc(ring);
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
/*
- * RX data handlers.
+ * TX/RX data handlers.
*/
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring = rt2x00dev->rx;
struct data_entry *entry;
- struct data_desc *rxd;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
+ struct skb_desc *skbdesc;
struct rxdata_entry_desc desc;
int header_size;
+ __le32 *rxd;
int align;
u32 word;
@@ -138,7 +144,7 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
break;
- memset(&desc, 0x00, sizeof(desc));
+ memset(&desc, 0, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
hdr = (struct ieee80211_hdr *)entry->data_addr;
@@ -163,6 +169,17 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
memcpy(skb_put(skb, desc.size), entry->data_addr, desc.size);
/*
+ * Fill in skb descriptor
+ */
+ skbdesc = get_skb_desc(skb);
+ skbdesc->desc_len = entry->ring->desc_size;
+ skbdesc->data_len = skb->len;
+ skbdesc->desc = entry->priv;
+ skbdesc->data = skb->data;
+ skbdesc->ring = ring;
+ skbdesc->entry = entry;
+
+ /*
* Send the frame to rt2x00lib for further processing.
*/
rt2x00lib_rxdone(entry, skb, &desc);
@@ -177,6 +194,37 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
}
EXPORT_SYMBOL_GPL(rt2x00pci_rxdone);
+void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+ const int tx_status, const int retry)
+{
+ u32 word;
+
+ rt2x00lib_txdone(entry, tx_status, retry);
+
+ /*
+ * Make this entry available for reuse.
+ */
+ entry->flags = 0;
+
+ rt2x00_desc_read(entry->priv, 0, &word);
+ rt2x00_set_field32(&word, TXD_ENTRY_OWNER_NIC, 0);
+ rt2x00_set_field32(&word, TXD_ENTRY_VALID, 0);
+ rt2x00_desc_write(entry->priv, 0, word);
+
+ rt2x00_ring_index_done_inc(entry->ring);
+
+ /*
+ * If the data ring was full before the txdone handler
+ * we must make sure the packet queue in the mac80211 stack
+ * is reenabled when the txdone handler has finished.
+ */
+ if (!rt2x00_ring_full(entry->ring))
+ ieee80211_wake_queue(rt2x00dev->hw,
+ entry->tx_status.control.queue);
+
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
+
/*
* Device initialization handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 82adeac061d0..2d1eb8144da4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -57,7 +57,7 @@
/*
* Register access.
*/
-static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
u32 *value)
{
@@ -65,14 +65,14 @@ static inline void rt2x00pci_register_read(const struct rt2x00_dev *rt2x00dev,
}
static inline void
-rt2x00pci_register_multiread(const struct rt2x00_dev *rt2x00dev,
+rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
memcpy_fromio(value, rt2x00dev->csr_addr + offset, length);
}
-static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
u32 value)
{
@@ -80,7 +80,7 @@ static inline void rt2x00pci_register_write(const struct rt2x00_dev *rt2x00dev,
}
static inline void
-rt2x00pci_register_multiwrite(const struct rt2x00_dev *rt2x00dev,
+rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned long offset,
void *value, const u16 length)
{
@@ -101,9 +101,11 @@ int rt2x00pci_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct ieee80211_tx_control *control);
/*
- * RX data handlers.
+ * RX/TX data handlers.
*/
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+void rt2x00pci_txdone(struct rt2x00_dev *rt2x00dev, struct data_entry *entry,
+ const int tx_status, const int retry);
/*
* Device initialization handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
index a0f8b8e0a24b..34a96d44e306 100644
--- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c
+++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c
@@ -23,11 +23,6 @@
Abstract: rt2x00 rfkill routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00lib"
-
#include <linux/input-polldev.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -68,8 +63,10 @@ static void rt2x00rfkill_poll(struct input_polled_dev *poll_dev)
struct rt2x00_dev *rt2x00dev = poll_dev->private;
int state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
- if (rt2x00dev->rfkill->state != state)
+ if (rt2x00dev->rfkill->state != state) {
input_report_key(poll_dev->input, KEY_WLAN, 1);
+ input_report_key(poll_dev->input, KEY_WLAN, 0);
+ }
}
int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
@@ -92,6 +89,13 @@ int rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev)
return retval;
}
+ /*
+ * Force initial poll which will detect the initial device state,
+ * and correctly sends the signal to the rfkill layer about this
+ * state.
+ */
+ rt2x00rfkill_poll(rt2x00dev->poll_dev);
+
return 0;
}
@@ -114,26 +118,41 @@ int rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev)
rt2x00dev->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
if (!rt2x00dev->rfkill) {
ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n");
- return -ENOMEM;
+ goto exit;
}
rt2x00dev->rfkill->name = rt2x00dev->ops->name;
rt2x00dev->rfkill->data = rt2x00dev;
- rt2x00dev->rfkill->state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev);
+ rt2x00dev->rfkill->state = -1;
rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio;
rt2x00dev->poll_dev = input_allocate_polled_device();
if (!rt2x00dev->poll_dev) {
ERROR(rt2x00dev, "Failed to allocate polled device.\n");
- rfkill_free(rt2x00dev->rfkill);
- return -ENOMEM;
+ goto exit_free_rfkill;
}
rt2x00dev->poll_dev->private = rt2x00dev;
rt2x00dev->poll_dev->poll = rt2x00rfkill_poll;
rt2x00dev->poll_dev->poll_interval = RFKILL_POLL_INTERVAL;
+ rt2x00dev->poll_dev->input->name = rt2x00dev->ops->name;
+ rt2x00dev->poll_dev->input->phys = wiphy_name(rt2x00dev->hw->wiphy);
+ rt2x00dev->poll_dev->input->id.bustype = BUS_HOST;
+ rt2x00dev->poll_dev->input->id.vendor = 0x1814;
+ rt2x00dev->poll_dev->input->id.product = rt2x00dev->chip.rt;
+ rt2x00dev->poll_dev->input->id.version = rt2x00dev->chip.rev;
+ rt2x00dev->poll_dev->input->dev.parent = device;
+ rt2x00dev->poll_dev->input->evbit[0] = BIT(EV_KEY);
+ set_bit(KEY_WLAN, rt2x00dev->poll_dev->input->keybit);
+
return 0;
+
+exit_free_rfkill:
+ rfkill_free(rt2x00dev->rfkill);
+
+exit:
+ return -ENOMEM;
}
void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00ring.h b/drivers/net/wireless/rt2x00/rt2x00ring.h
index 1a864d32cfbd..1caa6d688c40 100644
--- a/drivers/net/wireless/rt2x00/rt2x00ring.h
+++ b/drivers/net/wireless/rt2x00/rt2x00ring.h
@@ -27,19 +27,27 @@
#define RT2X00RING_H
/*
- * data_desc
- * Each data entry also contains a descriptor which is used by the
- * device to determine what should be done with the packet and
- * what the current status is.
- * This structure is greatly simplified, but the descriptors
- * are basically a list of little endian 32 bit values.
- * Make the array by default 1 word big, this will allow us
- * to use sizeof() correctly.
+ * skb_desc
+ * Descriptor information for the skb buffer
*/
-struct data_desc {
- __le32 word[1];
+struct skb_desc {
+ unsigned int frame_type;
+
+ unsigned int desc_len;
+ unsigned int data_len;
+
+ void *desc;
+ void *data;
+
+ struct data_ring *ring;
+ struct data_entry *entry;
};
+static inline struct skb_desc* get_skb_desc(struct sk_buff *skb)
+{
+ return (struct skb_desc*)&skb->cb[0];
+}
+
/*
* rxdata_entry_desc
* Summary of information that has been read from the
@@ -51,6 +59,7 @@ struct rxdata_entry_desc {
int ofdm;
int size;
int flags;
+ int my_bss;
};
/*
@@ -66,6 +75,7 @@ struct txdata_entry_desc {
#define ENTRY_TXD_MORE_FRAG 4
#define ENTRY_TXD_REQ_TIMESTAMP 5
#define ENTRY_TXD_BURST 6
+#define ENTRY_TXD_ACK 7
/*
* Queue ID. ID's 0-4 are data TX rings
@@ -134,6 +144,11 @@ struct data_entry {
*/
void *data_addr;
dma_addr_t data_dma;
+
+ /*
+ * Entry identification number (index).
+ */
+ unsigned int entry_idx;
};
/*
@@ -172,6 +187,13 @@ struct data_ring {
void *data_addr;
/*
+ * Queue identification number:
+ * RX: 0
+ * TX: IEEE80211_TX_*
+ */
+ unsigned int queue_idx;
+
+ /*
* Index variables.
*/
u16 index;
@@ -253,16 +275,16 @@ static inline int rt2x00_ring_free(struct data_ring *ring)
/*
* TX/RX Descriptor access functions.
*/
-static inline void rt2x00_desc_read(struct data_desc *desc,
+static inline void rt2x00_desc_read(__le32 *desc,
const u8 word, u32 *value)
{
- *value = le32_to_cpu(desc->word[word]);
+ *value = le32_to_cpu(desc[word]);
}
-static inline void rt2x00_desc_write(struct data_desc *desc,
+static inline void rt2x00_desc_write(__le32 *desc,
const u8 word, const u32 value)
{
- desc->word[word] = cpu_to_le32(value);
+ desc[word] = cpu_to_le32(value);
}
#endif /* RT2X00RING_H */
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 568d73847dca..84e9bdb73910 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -23,14 +23,10 @@
Abstract: rt2x00 generic usb device routines.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt2x00usb"
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/usb.h>
+#include <linux/bug.h>
#include "rt2x00.h"
#include "rt2x00usb.h"
@@ -38,7 +34,7 @@
/*
* Interfacing with the HW.
*/
-int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
+int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
@@ -52,6 +48,7 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
(requesttype == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
+
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
status = usb_control_msg(usb_dev, pipe, request, requesttype,
value, offset, buffer, buffer_length,
@@ -76,13 +73,15 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
}
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request);
-int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
- const u8 request, const u8 requesttype,
- const u16 offset, void *buffer,
- const u16 buffer_length, const int timeout)
+int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ const u8 request, const u8 requesttype,
+ const u16 offset, void *buffer,
+ const u16 buffer_length, const int timeout)
{
int status;
+ BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex));
+
/*
* Check for Cache availability.
*/
@@ -103,6 +102,25 @@ int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
return status;
}
+EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock);
+
+int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
+ const u8 request, const u8 requesttype,
+ const u16 offset, void *buffer,
+ const u16 buffer_length, const int timeout)
+{
+ int status;
+
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
+ status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
+ requesttype, offset, buffer,
+ buffer_length, timeout);
+
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
+
+ return status;
+}
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff);
/*
@@ -113,7 +131,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
struct data_entry *entry = (struct data_entry *)urb->context;
struct data_ring *ring = entry->ring;
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
- struct data_desc *txd = (struct data_desc *)entry->skb->data;
+ __le32 *txd = (__le32 *)entry->skb->data;
u32 word;
int tx_status;
@@ -158,20 +176,17 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
struct usb_device *usb_dev =
interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
struct data_entry *entry = rt2x00_get_data_entry(ring);
- int pipe = usb_sndbulkpipe(usb_dev, 1);
+ struct skb_desc *desc;
u32 length;
- if (rt2x00_ring_full(ring)) {
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
+ if (rt2x00_ring_full(ring))
return -EINVAL;
- }
if (test_bit(ENTRY_OWNER_NIC, &entry->flags)) {
ERROR(rt2x00dev,
"Arrived at non-free entry in the non-full queue %d.\n"
"Please file bug report to %s.\n",
control->queue, DRV_PROJECT);
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
return -EINVAL;
}
@@ -181,12 +196,18 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
skb_push(skb, ring->desc_size);
memset(skb->data, 0, ring->desc_size);
- rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
- (struct ieee80211_hdr *)(skb->data +
- ring->desc_size),
- skb->len - ring->desc_size, control);
- memcpy(&entry->tx_status.control, control, sizeof(*control));
- entry->skb = skb;
+ /*
+ * Fill in skb descriptor
+ */
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len - ring->desc_size;
+ desc->desc = skb->data;
+ desc->data = skb->data + ring->desc_size;
+ desc->ring = ring;
+ desc->entry = entry;
+
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* USB devices cannot blindly pass the skb->len as the
@@ -199,15 +220,12 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
* Initialize URB and send the frame to the device.
*/
__set_bit(ENTRY_OWNER_NIC, &entry->flags);
- usb_fill_bulk_urb(entry->priv, usb_dev, pipe,
+ usb_fill_bulk_urb(entry->priv, usb_dev, usb_sndbulkpipe(usb_dev, 1),
skb->data, length, rt2x00usb_interrupt_txdone, entry);
usb_submit_urb(entry->priv, GFP_ATOMIC);
rt2x00_ring_index_inc(ring);
- if (rt2x00_ring_full(ring))
- ieee80211_stop_queue(rt2x00dev->hw, control->queue);
-
return 0;
}
EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
@@ -222,6 +240,7 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
struct rt2x00_dev *rt2x00dev = ring->rt2x00dev;
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
+ struct skb_desc *skbdesc;
struct rxdata_entry_desc desc;
int header_size;
int frame_size;
@@ -238,7 +257,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
if (urb->actual_length < entry->ring->desc_size || urb->status)
goto skip_entry;
- memset(&desc, 0x00, sizeof(desc));
+ /*
+ * Fill in skb descriptor
+ */
+ skbdesc = get_skb_desc(entry->skb);
+ skbdesc->ring = ring;
+ skbdesc->entry = entry;
+
+ memset(&desc, 0, sizeof(desc));
rt2x00dev->ops->lib->fill_rxdone(entry, &desc);
/*
@@ -264,9 +290,6 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
/*
* The data behind the ieee80211 header must be
* aligned on a 4 byte boundary.
- * After that trim the entire buffer down to only
- * contain the valid frame data excluding the device
- * descriptor.
*/
hdr = (struct ieee80211_hdr *)entry->skb->data;
header_size =
@@ -276,6 +299,16 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb)
skb_push(entry->skb, 2);
memmove(entry->skb->data, entry->skb->data + 2, skb->len - 2);
}
+
+ /*
+ * Trim the entire buffer down to only contain the valid frame data
+ * excluding the device descriptor. The position of the descriptor
+ * varies. This means that we should check where the descriptor is
+ * and decide if we need to pull the data pointer to exclude the
+ * device descriptor.
+ */
+ if (skbdesc->data > skbdesc->desc)
+ skb_pull(entry->skb, skbdesc->desc_len);
skb_trim(entry->skb, desc.size);
/*
@@ -303,43 +336,6 @@ skip_entry:
/*
* Radio handlers
*/
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev)
-{
- struct usb_device *usb_dev =
- interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
- struct data_ring *ring;
- struct data_entry *entry;
- unsigned int i;
-
- /*
- * Initialize the TX rings
- */
- txringall_for_each(rt2x00dev, ring) {
- for (i = 0; i < ring->stats.limit; i++)
- ring->entry[i].flags = 0;
-
- rt2x00_ring_index_clear(ring);
- }
-
- /*
- * Initialize and start the RX ring.
- */
- rt2x00_ring_index_clear(rt2x00dev->rx);
-
- for (i = 0; i < rt2x00dev->rx->stats.limit; i++) {
- entry = &rt2x00dev->rx->entry[i];
-
- usb_fill_bulk_urb(entry->priv, usb_dev,
- usb_rcvbulkpipe(usb_dev, 1),
- entry->skb->data, entry->skb->len,
- rt2x00usb_interrupt_rxdone, entry);
-
- __set_bit(ENTRY_OWNER_NIC, &entry->flags);
- usb_submit_urb(entry->priv, GFP_ATOMIC);
- }
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_enable_radio);
-
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
struct data_ring *ring;
@@ -361,6 +357,29 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
/*
* Device initialization handlers.
*/
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
+{
+ struct usb_device *usb_dev =
+ interface_to_usbdev(rt2x00dev_usb(rt2x00dev));
+
+ usb_fill_bulk_urb(entry->priv, usb_dev,
+ usb_rcvbulkpipe(usb_dev, 1),
+ entry->skb->data, entry->skb->len,
+ rt2x00usb_interrupt_rxdone, entry);
+
+ __set_bit(ENTRY_OWNER_NIC, &entry->flags);
+ usb_submit_urb(entry->priv, GFP_ATOMIC);
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
+{
+ entry->flags = 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
+
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_ring *ring)
{
@@ -400,7 +419,7 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
struct sk_buff *skb;
unsigned int entry_size;
unsigned int i;
- int status;
+ int uninitialized_var(status);
/*
* Allocate DMA
@@ -507,6 +526,7 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00dev->dev = usb_intf;
rt2x00dev->ops = ops;
rt2x00dev->hw = hw;
+ mutex_init(&rt2x00dev->usb_cache_mutex);
rt2x00dev->usb_maxpacket =
usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 2681abe4d49e..e40df4050cd0 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -91,7 +91,7 @@
* a buffer allocated by kmalloc. Failure to do so can lead
* to unexpected behavior depending on the architecture.
*/
-int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
+int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, const u16 value,
void *buffer, const u16 buffer_length,
@@ -107,18 +107,25 @@ int rt2x00usb_vendor_request(const struct rt2x00_dev *rt2x00dev,
* kmalloc. Hence the reason for using a previously allocated cache
* which has been allocated properly.
*/
-int rt2x00usb_vendor_request_buff(const struct rt2x00_dev *rt2x00dev,
+int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
const u16 buffer_length, const int timeout);
/*
+ * A version of rt2x00usb_vendor_request_buff which must be called
+ * if the usb_cache_mutex is already held. */
+int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
+ const u8 request, const u8 requesttype,
+ const u16 offset, void *buffer,
+ const u16 buffer_length, const int timeout);
+
+/*
* Simple wrapper around rt2x00usb_vendor_request to write a single
* command to the device. Since we don't use the buffer argument we
* don't have to worry about kmalloc here.
*/
-static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev
- *rt2x00dev,
+static inline int rt2x00usb_vendor_request_sw(struct rt2x00_dev *rt2x00dev,
const u8 request,
const u16 offset,
const u16 value,
@@ -134,8 +141,8 @@ static inline int rt2x00usb_vendor_request_sw(const struct rt2x00_dev
* from the device. Note that the eeprom argument _must_ be allocated using
* kmalloc for correct handling inside the kernel USB layer.
*/
-static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev,
- __le16 *eeprom, const u16 lenght)
+static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
+ __le16 *eeprom, const u16 lenght)
{
int timeout = REGISTER_TIMEOUT * (lenght / sizeof(u16));
@@ -147,7 +154,6 @@ static inline int rt2x00usb_eeprom_read(const struct rt2x00_dev *rt2x00dev,
/*
* Radio handlers
*/
-void rt2x00usb_enable_radio(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
/*
@@ -160,6 +166,10 @@ int rt2x00usb_write_tx_data(struct rt2x00_dev *rt2x00dev,
/*
* Device initialization handlers.
*/
+void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
+void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry);
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index ecae968ce091..ab52f221cd71 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -24,11 +24,6 @@
Supported chipsets: RT2561, RT2561s, RT2661.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt61pci"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -52,7 +47,7 @@
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt61pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
@@ -67,7 +62,7 @@ static u32 rt61pci_bbp_check(const struct rt2x00_dev *rt2x00dev)
return reg;
}
-static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
@@ -93,7 +88,7 @@ static void rt61pci_bbp_write(const struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
}
-static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
@@ -130,7 +125,7 @@ static void rt61pci_bbp_read(const struct rt2x00_dev *rt2x00dev,
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
}
-static void rt61pci_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
@@ -160,7 +155,7 @@ rf_write:
rt2x00_rf_write(rt2x00dev, word, value);
}
-static void rt61pci_mcu_request(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
const u8 command, const u8 token,
const u8 arg0, const u8 arg1)
{
@@ -220,13 +215,13 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-static void rt61pci_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
}
-static void rt61pci_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt61pci_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -322,7 +317,8 @@ static void rt61pci_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -411,8 +407,7 @@ static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
}
static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
@@ -423,32 +418,39 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
rt61pci_bbp_read(rt2x00dev, 77, &r77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
- !rt2x00_rf(&rt2x00dev->chip, RF5225));
+ rt2x00_rf(&rt2x00dev->chip, RF5325));
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- !!(rt2x00dev->curr_hwmode != HWMODE_A));
+ (rt2x00dev->curr_hwmode != HWMODE_A));
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
if (rt2x00dev->curr_hwmode == HWMODE_A)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
if (rt2x00dev->curr_hwmode == HWMODE_A)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
}
@@ -458,8 +460,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
}
static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
@@ -470,22 +471,31 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
rt61pci_bbp_read(rt2x00dev, 77, &r77);
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE,
- !rt2x00_rf(&rt2x00dev->chip, RF2527));
+ rt2x00_rf(&rt2x00dev->chip, RF2529));
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
}
@@ -501,23 +511,18 @@ static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
- if (p1 != 0xff) {
- rt2x00_set_field32(&reg, MAC_CSR13_BIT4, !!p1);
- rt2x00_set_field32(&reg, MAC_CSR13_BIT12, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
- }
- if (p2 != 0xff) {
- rt2x00_set_field32(&reg, MAC_CSR13_BIT3, !p2);
- rt2x00_set_field32(&reg, MAC_CSR13_BIT11, 0);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
- }
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT4, p1);
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT12, 0);
+
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT3, !p2);
+ rt2x00_set_field32(&reg, MAC_CSR13_BIT11, 0);
+
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
}
static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
- u16 eeprom;
u8 r3;
u8 r4;
u8 r77;
@@ -525,70 +530,36 @@ static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev,
rt61pci_bbp_read(rt2x00dev, 3, &r3);
rt61pci_bbp_read(rt2x00dev, 4, &r4);
rt61pci_bbp_read(rt2x00dev, 77, &r77);
- rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
-
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 1);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- } else if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY)) {
- if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED) >= 2) {
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- }
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
- switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
- case 0:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- break;
- case 1:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
- break;
- case 2:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
- break;
- case 3:
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- break;
- }
- } else if (!rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY) &&
- !rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) {
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
+ /* FIXME: Antenna selection for the rf 2529 is very confusing in the
+ * legacy driver. The code below should be ok for non-diversity setups.
+ */
- switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
- case 0:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 1);
- break;
- case 1:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 0);
- break;
- case 2:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
- break;
- case 3:
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
- rt61pci_bbp_write(rt2x00dev, 77, r77);
- rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
- break;
- }
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0);
+ break;
+ case ANTENNA_SW_DIVERSITY:
+ case ANTENNA_HW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
+ case ANTENNA_B:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1);
+ break;
}
+ rt61pci_bbp_write(rt2x00dev, 77, r77);
rt61pci_bbp_write(rt2x00dev, 3, r3);
rt61pci_bbp_write(rt2x00dev, 4, r4);
}
@@ -625,46 +596,44 @@ static const struct antenna_sel antenna_sel_bg[] = {
};
static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx, const int antenna_rx)
+ struct antenna_setup *ant)
{
const struct antenna_sel *sel;
unsigned int lna;
unsigned int i;
u32 reg;
- rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
-
if (rt2x00dev->curr_hwmode == HWMODE_A) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG, 0);
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A, 1);
} else {
sel = antenna_sel_bg;
lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG, 1);
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A, 0);
}
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
+ rt2x00pci_register_read(rt2x00dev, PHY_CSR0, &reg);
+
+ rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+ (rt2x00dev->curr_hwmode == HWMODE_B ||
+ rt2x00dev->curr_hwmode == HWMODE_G));
+ rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+ (rt2x00dev->curr_hwmode == HWMODE_A));
+
rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF5325))
- rt61pci_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx);
+ rt61pci_config_antenna_5x(rt2x00dev, ant);
else if (rt2x00_rf(&rt2x00dev->chip, RF2527))
- rt61pci_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx);
+ rt61pci_config_antenna_2x(rt2x00dev, ant);
else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) {
if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags))
- rt61pci_config_antenna_2x(rt2x00dev, antenna_tx,
- antenna_rx);
+ rt61pci_config_antenna_2x(rt2x00dev, ant);
else
- rt61pci_config_antenna_2529(rt2x00dev, antenna_tx,
- antenna_rx);
+ rt61pci_config_antenna_2529(rt2x00dev, ant);
}
}
@@ -709,8 +678,7 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt61pci_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx,
- libconf->conf->antenna_sel_rx);
+ rt61pci_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
rt61pci_config_duration(rt2x00dev, libconf);
}
@@ -721,7 +689,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- u16 led_reg;
u8 arg0;
u8 arg1;
@@ -730,15 +697,14 @@ static void rt61pci_enable_led(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, 30);
rt2x00pci_register_write(rt2x00dev, MAC_CSR14, reg);
- led_reg = rt2x00dev->led_reg;
- rt2x00_set_field16(&led_reg, MCU_LEDCS_RADIO_STATUS, 1);
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_A_STATUS, 1);
- else
- rt2x00_set_field16(&led_reg, MCU_LEDCS_LINK_BG_STATUS, 1);
+ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
+ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+ (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+ (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
- arg0 = led_reg & 0xff;
- arg1 = (led_reg >> 8) & 0xff;
+ arg0 = rt2x00dev->led_reg & 0xff;
+ arg1 = (rt2x00dev->led_reg >> 8) & 0xff;
rt61pci_mcu_request(rt2x00dev, MCU_LED, 0xff, arg0, arg1);
}
@@ -792,7 +758,8 @@ static void rt61pci_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
/*
* Link tuning
*/
-static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u32 reg;
@@ -800,14 +767,13 @@ static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev)
* Update FCS error count from register.
*/
rt2x00pci_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt2x00pci_register_read(rt2x00dev, STA_CSR1, &reg);
- rt2x00dev->link.false_cca =
- rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
+ qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -904,11 +870,11 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev)
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
*/
- if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) {
+ if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
if (++r17 > up_bound)
r17 = up_bound;
rt61pci_bbp_write(rt2x00dev, 17, r17);
- } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
if (--r17 < low_bound)
r17 = low_bound;
rt61pci_bbp_write(rt2x00dev, 17, r17);
@@ -1023,64 +989,46 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, void *data,
return 0;
}
-static void rt61pci_init_rxring(struct rt2x00_dev *rt2x00dev)
+static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00dev->rx;
- struct data_desc *rxd;
- unsigned int i;
+ __le32 *rxd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- rxd = ring->entry[i].priv;
-
- rt2x00_desc_read(rxd, 5, &word);
- rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(rxd, 5, word);
+ rt2x00_desc_read(rxd, 5, &word);
+ rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+ entry->data_dma);
+ rt2x00_desc_write(rxd, 5, word);
- rt2x00_desc_read(rxd, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(rxd, 0, word);
- }
-
- rt2x00_ring_index_clear(rt2x00dev->rx);
+ rt2x00_desc_read(rxd, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(rxd, 0, word);
}
-static void rt61pci_init_txring(struct rt2x00_dev *rt2x00dev, const int queue)
+static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
+ struct data_entry *entry)
{
- struct data_ring *ring = rt2x00lib_get_ring(rt2x00dev, queue);
- struct data_desc *txd;
- unsigned int i;
+ __le32 *txd = entry->priv;
u32 word;
- memset(ring->data_addr, 0x00, rt2x00_get_ring_size(ring));
-
- for (i = 0; i < ring->stats.limit; i++) {
- txd = ring->entry[i].priv;
-
- rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
- rt2x00_desc_write(txd, 1, word);
-
- rt2x00_desc_read(txd, 5, &word);
- rt2x00_set_field32(&word, TXD_W5_PID_TYPE, queue);
- rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, i);
- rt2x00_desc_write(txd, 5, word);
+ rt2x00_desc_read(txd, 1, &word);
+ rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1);
+ rt2x00_desc_write(txd, 1, word);
- rt2x00_desc_read(txd, 6, &word);
- rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
- ring->entry[i].data_dma);
- rt2x00_desc_write(txd, 6, word);
+ rt2x00_desc_read(txd, 5, &word);
+ rt2x00_set_field32(&word, TXD_W5_PID_TYPE, entry->ring->queue_idx);
+ rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, entry->entry_idx);
+ rt2x00_desc_write(txd, 5, word);
- rt2x00_desc_read(txd, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(txd, 0, word);
- }
+ rt2x00_desc_read(txd, 6, &word);
+ rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS,
+ entry->data_dma);
+ rt2x00_desc_write(txd, 6, word);
- rt2x00_ring_index_clear(ring);
+ rt2x00_desc_read(txd, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(txd, 0, word);
}
static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
@@ -1088,16 +1036,6 @@ static int rt61pci_init_rings(struct rt2x00_dev *rt2x00dev)
u32 reg;
/*
- * Initialize rings.
- */
- rt61pci_init_rxring(rt2x00dev);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA0);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA1);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA2);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA3);
- rt61pci_init_txring(rt2x00dev, IEEE80211_TX_QUEUE_DATA4);
-
- /*
* Initialize registers.
*/
rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, &reg);
@@ -1565,12 +1503,12 @@ static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
- struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
- struct ieee80211_tx_control *control)
+ struct sk_buff *skb,
+ struct txdata_entry_desc *desc,
+ struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
/*
@@ -1599,7 +1537,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 5, word);
rt2x00_desc_read(txd, 11, &word);
- rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, length);
+ rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skbdesc->data_len);
rt2x00_desc_write(txd, 11, word);
rt2x00_desc_read(txd, 0, &word);
@@ -1608,7 +1546,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ test_bit(ENTRY_TXD_ACK, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
@@ -1618,7 +1556,7 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST,
test_bit(ENTRY_TXD_BURST, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
@@ -1649,16 +1587,16 @@ static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
}
rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, &reg);
- if (queue == IEEE80211_TX_QUEUE_DATA0)
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA1)
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA2)
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA3)
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3, 1);
- else if (queue == IEEE80211_TX_QUEUE_DATA4)
- rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_MGMT, 1);
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC0,
+ (queue == IEEE80211_TX_QUEUE_DATA0));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC1,
+ (queue == IEEE80211_TX_QUEUE_DATA1));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC2,
+ (queue == IEEE80211_TX_QUEUE_DATA2));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_AC3,
+ (queue == IEEE80211_TX_QUEUE_DATA3));
+ rt2x00_set_field32(&reg, TX_CNTL_CSR_KICK_TX_MGMT,
+ (queue == IEEE80211_TX_QUEUE_DATA4));
rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg);
}
@@ -1709,7 +1647,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
static void rt61pci_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
- struct data_desc *rxd = entry->priv;
+ __le32 *rxd = entry->priv;
u32 word0;
u32 word1;
@@ -1727,8 +1665,7 @@ static void rt61pci_fill_rxdone(struct data_entry *entry,
desc->rssi = rt61pci_agc_to_rssi(entry->ring->rt2x00dev, word1);
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
-
- return;
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
}
/*
@@ -1739,7 +1676,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
struct data_ring *ring;
struct data_entry *entry;
struct data_entry *entry_done;
- struct data_desc *txd;
+ __le32 *txd;
u32 word;
u32 reg;
u32 old_reg;
@@ -1809,24 +1746,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
tx_status = rt2x00_get_field32(reg, STA_CSR4_TX_RESULT);
retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT);
- rt2x00lib_txdone(entry, tx_status, retry);
-
- /*
- * Make this entry available for reuse.
- */
- entry->flags = 0;
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_desc_write(txd, 0, word);
- rt2x00_ring_index_done_inc(entry->ring);
-
- /*
- * If the data ring was full before the txdone handler
- * we must make sure the packet queue in the mac80211 stack
- * is reenabled when the txdone handler has finished.
- */
- if (!rt2x00_ring_full(ring))
- ieee80211_wake_queue(rt2x00dev->hw,
- entry->tx_status.control.queue);
+ rt2x00pci_txdone(rt2x00dev, entry, tx_status, retry);
}
}
@@ -1920,8 +1840,10 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 2);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+ ANTENNA_B);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+ ANTENNA_B);
rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
@@ -2025,11 +1947,17 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
}
/*
+ * Determine number of antenna's.
+ */
+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
+ __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
+
+ /*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
@@ -2039,12 +1967,6 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
/*
- * Determine number of antenna's.
- */
- if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2)
- __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags);
-
- /*
* Detect if this device has an hardware controlled radio.
*/
#ifdef CONFIG_RT61PCI_RFKILL
@@ -2072,6 +1994,38 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
/*
+ * When working with a RF2529 chip without double antenna
+ * the antenna settings should be gathered from the NIC
+ * eeprom word.
+ */
+ if (rt2x00_rf(&rt2x00dev->chip, RF2529) &&
+ !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) {
+ switch (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_RX_FIXED)) {
+ case 0:
+ rt2x00dev->default_ant.tx = ANTENNA_B;
+ rt2x00dev->default_ant.rx = ANTENNA_A;
+ break;
+ case 1:
+ rt2x00dev->default_ant.tx = ANTENNA_B;
+ rt2x00dev->default_ant.rx = ANTENNA_B;
+ break;
+ case 2:
+ rt2x00dev->default_ant.tx = ANTENNA_A;
+ rt2x00dev->default_ant.rx = ANTENNA_A;
+ break;
+ case 3:
+ rt2x00dev->default_ant.tx = ANTENNA_A;
+ rt2x00dev->default_ant.rx = ANTENNA_B;
+ break;
+ }
+
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY))
+ rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY;
+ if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY))
+ rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY;
+ }
+
+ /*
* Store led settings, for correct led behaviour.
* If the eeprom value is invalid,
* switch to default led mode.
@@ -2325,7 +2279,6 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;
/*
@@ -2344,22 +2297,19 @@ static void rt61pci_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* Start configuration steps.
@@ -2426,6 +2376,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct skb_desc *desc;
+ struct data_ring *ring;
+ struct data_entry *entry;
/*
* Just in case the ieee80211 doesn't set this,
@@ -2433,6 +2386,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
+ ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+ entry = rt2x00_get_data_entry(ring);
/*
* We need to append the descriptor in front of the
@@ -2446,15 +2401,23 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
}
/*
- * First we create the beacon.
+ * Add the descriptor in front of the skb.
+ */
+ skb_push(skb, ring->desc_size);
+ memset(skb->data, 0, ring->desc_size);
+
+ /*
+ * Fill in skb descriptor
*/
- skb_push(skb, TXD_DESC_SIZE);
- memset(skb->data, 0, TXD_DESC_SIZE);
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len - ring->desc_size;
+ desc->desc = skb->data;
+ desc->data = skb->data + ring->desc_size;
+ desc->ring = ring;
+ desc->entry = entry;
- rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
- (struct ieee80211_hdr *)(skb->data +
- TXD_DESC_SIZE),
- skb->len - TXD_DESC_SIZE, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
@@ -2478,7 +2441,7 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.configure_filter = rt61pci_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt61pci_set_retry_limit,
- .erp_ie_changed = rt2x00mac_erp_ie_changed,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt61pci_get_tsf,
@@ -2493,6 +2456,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.load_firmware = rt61pci_load_firmware,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
+ .init_rxentry = rt61pci_init_rxentry,
+ .init_txentry = rt61pci_init_txentry,
.set_device_state = rt61pci_set_device_state,
.rfkill_poll = rt61pci_rfkill_poll,
.link_stats = rt61pci_link_stats,
@@ -2510,7 +2475,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
};
static const struct rt2x00_ops rt61pci_ops = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.eeprom_size = EEPROM_SIZE,
@@ -2547,7 +2512,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2661);
MODULE_LICENSE("GPL");
static struct pci_driver rt61pci_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt61pci_device_table,
.probe = rt2x00pci_probe,
.remove = __devexit_p(rt2x00pci_remove),
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 6721d7dd32bc..4c6524eedad0 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -1077,13 +1077,19 @@ struct hw_pairwise_ta_entry {
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
-#define BBP_R4_RX_ANTENNA FIELD8(0x03)
+
+/*
+ * ANTENNA_CONTROL semantics (guessed):
+ * 0x1: Software controlled antenna switching (fixed or SW diversity)
+ * 0x2: Hardware diversity.
+ */
+#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
-#define BBP_R77_PAIR FIELD8(0x03)
+#define BBP_R77_RX_ANTENNA FIELD8(0x03)
/*
* RF registers
@@ -1240,8 +1246,8 @@ struct hw_pairwise_ta_entry {
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 16 * sizeof(struct data_desc) )
-#define RXD_DESC_SIZE ( 16 * sizeof(struct data_desc) )
+#define TXD_DESC_SIZE ( 16 * sizeof(__le32) )
+#define RXD_DESC_SIZE ( 16 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO and Beacon Ring.
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index c0671c2e6e73..4d576ab3e7f9 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -24,11 +24,6 @@
Supported chipsets: rt2571W & rt2671.
*/
-/*
- * Set enviroment defines for rt2x00.h
- */
-#define DRV_NAME "rt73usb"
-
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
@@ -52,8 +47,9 @@
* 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 usb_cache_mutex
*/
-static inline void rt73usb_register_read(const struct rt2x00_dev *rt2x00dev,
+static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 *value)
{
__le32 reg;
@@ -63,8 +59,17 @@ static inline void rt73usb_register_read(const struct rt2x00_dev *rt2x00dev,
*value = le32_to_cpu(reg);
}
-static inline void rt73usb_register_multiread(const struct rt2x00_dev
- *rt2x00dev,
+static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset, u32 *value)
+{
+ __le32 reg;
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+ USB_VENDOR_REQUEST_IN, offset,
+ &reg, sizeof(u32), REGISTER_TIMEOUT);
+ *value = le32_to_cpu(reg);
+}
+
+static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length)
{
@@ -74,7 +79,7 @@ static inline void rt73usb_register_multiread(const struct rt2x00_dev
value, length, timeout);
}
-static inline void rt73usb_register_write(const struct rt2x00_dev *rt2x00dev,
+static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
const unsigned int offset, u32 value)
{
__le32 reg = cpu_to_le32(value);
@@ -83,8 +88,16 @@ static inline void rt73usb_register_write(const struct rt2x00_dev *rt2x00dev,
&reg, sizeof(u32), REGISTER_TIMEOUT);
}
-static inline void rt73usb_register_multiwrite(const struct rt2x00_dev
- *rt2x00dev,
+static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset, u32 value)
+{
+ __le32 reg = cpu_to_le32(value);
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, offset,
+ &reg, sizeof(u32), REGISTER_TIMEOUT);
+}
+
+static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
void *value, const u32 length)
{
@@ -94,13 +107,13 @@ static inline void rt73usb_register_multiwrite(const struct rt2x00_dev
value, length, timeout);
}
-static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
+static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
unsigned int i;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read(rt2x00dev, PHY_CSR3, &reg);
+ rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, &reg);
if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
break;
udelay(REGISTER_BUSY_DELAY);
@@ -109,17 +122,20 @@ static u32 rt73usb_bbp_check(const struct rt2x00_dev *rt2x00dev)
return reg;
}
-static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
+static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
/*
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
@@ -132,20 +148,24 @@ static void rt73usb_bbp_write(const struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
- rt73usb_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
-static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
+static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u8 *value)
{
u32 reg;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
/*
* Wait until the BBP becomes ready.
*/
reg = rt73usb_bbp_check(rt2x00dev);
if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
return;
}
@@ -157,7 +177,7 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
- rt73usb_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
/*
* Wait until the BBP becomes ready.
@@ -170,9 +190,10 @@ static void rt73usb_bbp_read(const struct rt2x00_dev *rt2x00dev,
}
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
-static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev,
+static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
@@ -181,13 +202,16 @@ static void rt73usb_rf_write(const struct rt2x00_dev *rt2x00dev,
if (!word)
return;
+ mutex_lock(&rt2x00dev->usb_cache_mutex);
+
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read(rt2x00dev, PHY_CSR4, &reg);
+ rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
goto rf_write;
udelay(REGISTER_BUSY_DELAY);
}
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
return;
@@ -200,25 +224,26 @@ rf_write:
* all others contain 20 bits.
*/
rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
- 20 + !!(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF2527)));
+ 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527)));
rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
- rt73usb_register_write(rt2x00dev, PHY_CSR4, reg);
+ rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
rt2x00_rf_write(rt2x00dev, word, value);
+ mutex_unlock(&rt2x00dev->usb_cache_mutex);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-static void rt73usb_read_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 *data)
{
rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data);
}
-static void rt73usb_write_csr(const struct rt2x00_dev *rt2x00dev,
+static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev,
const unsigned int word, u32 data)
{
rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
@@ -302,7 +327,8 @@ static void rt73usb_config_type(struct rt2x00_dev *rt2x00dev, const int type,
*/
rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
- rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
+ rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE,
+ (tsf_sync == TSF_SYNC_BEACON));
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, tsf_sync);
rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
@@ -396,12 +422,12 @@ static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
}
static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
u8 r77;
+ u8 temp;
rt73usb_bbp_read(rt2x00dev, 3, &r3);
rt73usb_bbp_read(rt2x00dev, 4, &r4);
@@ -409,30 +435,38 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0);
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
- !!(rt2x00dev->curr_hwmode != HWMODE_A));
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
+ temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)
+ && (rt2x00dev->curr_hwmode != HWMODE_A);
+ rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp);
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
if (rt2x00dev->curr_hwmode == HWMODE_A)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0);
-
if (rt2x00dev->curr_hwmode == HWMODE_A)
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
else
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
break;
}
@@ -442,8 +476,7 @@ static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
}
static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx,
- const int antenna_rx)
+ struct antenna_setup *ant)
{
u8 r3;
u8 r4;
@@ -457,18 +490,27 @@ static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END,
!test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags));
- switch (antenna_rx) {
- case ANTENNA_SW_DIVERSITY:
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2);
break;
case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 3);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
break;
+ case ANTENNA_SW_DIVERSITY:
+ /*
+ * NOTE: We should never come here because rt2x00lib is
+ * supposed to catch this and send us the correct antenna
+ * explicitely. However we are nog going to bug about this.
+ * Instead, just default to antenna B.
+ */
case ANTENNA_B:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- rt2x00_set_field8(&r77, BBP_R77_PAIR, 0);
+ rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0);
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1);
break;
}
@@ -509,40 +551,40 @@ static const struct antenna_sel antenna_sel_bg[] = {
};
static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
- const int antenna_tx, const int antenna_rx)
+ struct antenna_setup *ant)
{
const struct antenna_sel *sel;
unsigned int lna;
unsigned int i;
u32 reg;
- rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
-
if (rt2x00dev->curr_hwmode == HWMODE_A) {
sel = antenna_sel_a;
lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG, 0);
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A, 1);
} else {
sel = antenna_sel_bg;
lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
-
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG, 1);
- rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A, 0);
}
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
+ rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+
+ rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
+ (rt2x00dev->curr_hwmode == HWMODE_B ||
+ rt2x00dev->curr_hwmode == HWMODE_G));
+ rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
+ (rt2x00dev->curr_hwmode == HWMODE_A));
+
rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
rt2x00_rf(&rt2x00dev->chip, RF5225))
- rt73usb_config_antenna_5x(rt2x00dev, antenna_tx, antenna_rx);
+ rt73usb_config_antenna_5x(rt2x00dev, ant);
else if (rt2x00_rf(&rt2x00dev->chip, RF2528) ||
rt2x00_rf(&rt2x00dev->chip, RF2527))
- rt73usb_config_antenna_2x(rt2x00dev, antenna_tx, antenna_rx);
+ rt73usb_config_antenna_2x(rt2x00dev, ant);
}
static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
@@ -586,8 +628,7 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
if (flags & CONFIG_UPDATE_ANTENNA)
- rt73usb_config_antenna(rt2x00dev, libconf->conf->antenna_sel_tx,
- libconf->conf->antenna_sel_rx);
+ rt73usb_config_antenna(rt2x00dev, &libconf->ant);
if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
rt73usb_config_duration(rt2x00dev, libconf);
}
@@ -605,12 +646,10 @@ static void rt73usb_enable_led(struct rt2x00_dev *rt2x00dev)
rt73usb_register_write(rt2x00dev, MAC_CSR14, reg);
rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_RADIO_STATUS, 1);
- if (rt2x00dev->rx_status.phymode == MODE_IEEE80211A)
- rt2x00_set_field16(&rt2x00dev->led_reg,
- MCU_LEDCS_LINK_A_STATUS, 1);
- else
- rt2x00_set_field16(&rt2x00dev->led_reg,
- MCU_LEDCS_LINK_BG_STATUS, 1);
+ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_A_STATUS,
+ (rt2x00dev->rx_status.phymode == MODE_IEEE80211A));
+ rt2x00_set_field16(&rt2x00dev->led_reg, MCU_LEDCS_LINK_BG_STATUS,
+ (rt2x00dev->rx_status.phymode != MODE_IEEE80211A));
rt2x00usb_vendor_request_sw(rt2x00dev, USB_LED_CONTROL, 0x0000,
rt2x00dev->led_reg, REGISTER_TIMEOUT);
@@ -659,7 +698,8 @@ static void rt73usb_activity_led(struct rt2x00_dev *rt2x00dev, int rssi)
/*
* Link tuning
*/
-static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev)
+static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
+ struct link_qual *qual)
{
u32 reg;
@@ -667,15 +707,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev)
* Update FCS error count from register.
*/
rt73usb_register_read(rt2x00dev, STA_CSR0, &reg);
- rt2x00dev->link.rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
+ qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
rt73usb_register_read(rt2x00dev, STA_CSR1, &reg);
- reg = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
- rt2x00dev->link.false_cca =
- rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
+ qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev)
@@ -781,12 +819,12 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev)
* r17 does not yet exceed upper limit, continue and base
* the r17 tuning on the false CCA count.
*/
- if (rt2x00dev->link.false_cca > 512 && r17 < up_bound) {
+ if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
r17 += 4;
if (r17 > up_bound)
r17 = up_bound;
rt73usb_bbp_write(rt2x00dev, 17, r17);
- } else if (rt2x00dev->link.false_cca < 100 && r17 > low_bound) {
+ } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
r17 -= 4;
if (r17 < low_bound)
r17 = low_bound;
@@ -1098,8 +1136,6 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
return -EIO;
}
- rt2x00usb_enable_radio(rt2x00dev);
-
/*
* Enable LED
*/
@@ -1193,12 +1229,12 @@ static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev,
* TX descriptor initialization
*/
static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
- struct data_desc *txd,
- struct txdata_entry_desc *desc,
- struct ieee80211_hdr *ieee80211hdr,
- unsigned int length,
- struct ieee80211_tx_control *control)
+ struct sk_buff *skb,
+ struct txdata_entry_desc *desc,
+ struct ieee80211_tx_control *control)
{
+ struct skb_desc *skbdesc = get_skb_desc(skb);
+ __le32 *txd = skbdesc->desc;
u32 word;
/*
@@ -1233,7 +1269,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
test_bit(ENTRY_TXD_MORE_FRAG, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_ACK,
- !(control->flags & IEEE80211_TXCTL_NO_ACK));
+ test_bit(ENTRY_TXD_ACK, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_TIMESTAMP,
test_bit(ENTRY_TXD_REQ_TIMESTAMP, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_OFDM,
@@ -1243,7 +1279,7 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
!!(control->flags &
IEEE80211_TXCTL_LONG_RETRY_LIMIT));
rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, 0);
- rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, length);
+ rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skbdesc->data_len);
rt2x00_set_field32(&word, TXD_W0_BURST2,
test_bit(ENTRY_TXD_BURST, &desc->flags));
rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
@@ -1340,7 +1376,8 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
static void rt73usb_fill_rxdone(struct data_entry *entry,
struct rxdata_entry_desc *desc)
{
- struct data_desc *rxd = (struct data_desc *)entry->skb->data;
+ struct skb_desc *skbdesc = get_skb_desc(entry->skb);
+ __le32 *rxd = (__le32 *)entry->skb->data;
u32 word0;
u32 word1;
@@ -1358,13 +1395,15 @@ static void rt73usb_fill_rxdone(struct data_entry *entry,
desc->rssi = rt73usb_agc_to_rssi(entry->ring->rt2x00dev, word1);
desc->ofdm = rt2x00_get_field32(word0, RXD_W0_OFDM);
desc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
+ desc->my_bss = !!rt2x00_get_field32(word0, RXD_W0_MY_BSS);
/*
- * Pull the skb to clear the descriptor area.
+ * Set descriptor and data pointer.
*/
- skb_pull(entry->skb, entry->ring->desc_size);
-
- return;
+ skbdesc->desc = entry->skb->data;
+ skbdesc->desc_len = entry->ring->desc_size;
+ skbdesc->data = entry->skb->data + entry->ring->desc_size;
+ skbdesc->data_len = desc->size;
}
/*
@@ -1392,8 +1431,10 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
if (word == 0xffff) {
rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, 2);
- rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, 2);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT,
+ ANTENNA_B);
+ rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT,
+ ANTENNA_B);
rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0);
rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0);
@@ -1502,9 +1543,9 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Identify default antenna configuration.
*/
- rt2x00dev->hw->conf.antenna_sel_tx =
+ rt2x00dev->default_ant.tx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT);
- rt2x00dev->hw->conf.antenna_sel_rx =
+ rt2x00dev->default_ant.rx =
rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT);
/*
@@ -1806,7 +1847,6 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw,
struct dev_addr_list *mc_list)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- struct interface *intf = &rt2x00dev->interface;
u32 reg;
/*
@@ -1825,22 +1865,19 @@ static void rt73usb_configure_filter(struct ieee80211_hw *hw,
* Apply some rules to the filters:
* - Some filters imply different filters to be set.
* - Some things we can't filter out at all.
- * - Some filters are set based on interface type.
*/
if (mc_count)
*total_flags |= FIF_ALLMULTI;
if (*total_flags & FIF_OTHER_BSS ||
*total_flags & FIF_PROMISC_IN_BSS)
*total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
- if (is_interface_type(intf, IEEE80211_IF_TYPE_AP))
- *total_flags |= FIF_PROMISC_IN_BSS;
/*
* Check if there is any work left for us.
*/
- if (intf->filter == *total_flags)
+ if (rt2x00dev->packet_filter == *total_flags)
return;
- intf->filter = *total_flags;
+ rt2x00dev->packet_filter = *total_flags;
/*
* When in atomic context, reschedule and let rt2x00lib
@@ -1926,6 +1963,9 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_control *control)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct skb_desc *desc;
+ struct data_ring *ring;
+ struct data_entry *entry;
int timeout;
/*
@@ -1934,17 +1974,27 @@ static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb,
* initialization.
*/
control->queue = IEEE80211_TX_QUEUE_BEACON;
+ ring = rt2x00lib_get_ring(rt2x00dev, control->queue);
+ entry = rt2x00_get_data_entry(ring);
+
+ /*
+ * Add the descriptor in front of the skb.
+ */
+ skb_push(skb, ring->desc_size);
+ memset(skb->data, 0, ring->desc_size);
/*
- * First we create the beacon.
+ * Fill in skb descriptor
*/
- skb_push(skb, TXD_DESC_SIZE);
- memset(skb->data, 0, TXD_DESC_SIZE);
+ desc = get_skb_desc(skb);
+ desc->desc_len = ring->desc_size;
+ desc->data_len = skb->len - ring->desc_size;
+ desc->desc = skb->data;
+ desc->data = skb->data + ring->desc_size;
+ desc->ring = ring;
+ desc->entry = entry;
- rt2x00lib_write_tx_desc(rt2x00dev, (struct data_desc *)skb->data,
- (struct ieee80211_hdr *)(skb->data +
- TXD_DESC_SIZE),
- skb->len - TXD_DESC_SIZE, control);
+ rt2x00lib_write_tx_desc(rt2x00dev, skb, control);
/*
* Write entire beacon with descriptor to register,
@@ -1971,7 +2021,7 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.configure_filter = rt73usb_configure_filter,
.get_stats = rt2x00mac_get_stats,
.set_retry_limit = rt73usb_set_retry_limit,
- .erp_ie_changed = rt2x00mac_erp_ie_changed,
+ .bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
.get_tsf = rt73usb_get_tsf,
@@ -1985,6 +2035,8 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.load_firmware = rt73usb_load_firmware,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
+ .init_rxentry = rt2x00usb_init_rxentry,
+ .init_txentry = rt2x00usb_init_txentry,
.set_device_state = rt73usb_set_device_state,
.link_stats = rt73usb_link_stats,
.reset_tuner = rt73usb_reset_tuner,
@@ -2002,7 +2054,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
};
static const struct rt2x00_ops rt73usb_ops = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.rxd_size = RXD_DESC_SIZE,
.txd_size = TXD_DESC_SIZE,
.eeprom_size = EEPROM_SIZE,
@@ -2089,7 +2141,7 @@ MODULE_FIRMWARE(FIRMWARE_RT2571);
MODULE_LICENSE("GPL");
static struct usb_driver rt73usb_driver = {
- .name = DRV_NAME,
+ .name = KBUILD_MODNAME,
.id_table = rt73usb_device_table,
.probe = rt2x00usb_probe,
.disconnect = rt2x00usb_disconnect,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index f0951519f74b..d49dcaacecee 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -713,13 +713,19 @@ struct hw_pairwise_ta_entry {
* R4: RX antenna control
* FRAME_END: 1 - DPDT, 0 - SPDT (Only valid for 802.11G, RF2527 & RF2529)
*/
-#define BBP_R4_RX_ANTENNA FIELD8(0x03)
+
+/*
+ * ANTENNA_CONTROL semantics (guessed):
+ * 0x1: Software controlled antenna switching (fixed or SW diversity)
+ * 0x2: Hardware diversity.
+ */
+#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03)
#define BBP_R4_RX_FRAME_END FIELD8(0x20)
/*
* R77
*/
-#define BBP_R77_PAIR FIELD8(0x03)
+#define BBP_R77_RX_ANTENNA FIELD8(0x03)
/*
* RF registers
@@ -860,8 +866,8 @@ struct hw_pairwise_ta_entry {
/*
* DMA descriptor defines.
*/
-#define TXD_DESC_SIZE ( 6 * sizeof(struct data_desc) )
-#define RXD_DESC_SIZE ( 6 * sizeof(struct data_desc) )
+#define TXD_DESC_SIZE ( 6 * sizeof(__le32) )
+#define RXD_DESC_SIZE ( 6 * sizeof(__le32) )
/*
* TX descriptor format for TX, PRIO and Beacon Ring.
diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl8180.h
new file mode 100644
index 000000000000..2cbfe3c8081f
--- /dev/null
+++ b/drivers/net/wireless/rtl8180.h
@@ -0,0 +1,151 @@
+#ifndef RTL8180_H
+#define RTL8180_H
+
+#include "rtl818x.h"
+
+#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD
+
+#define RF_PARAM_ANALOGPHY (1 << 0)
+#define RF_PARAM_ANTBDEFAULT (1 << 1)
+#define RF_PARAM_CARRIERSENSE1 (1 << 2)
+#define RF_PARAM_CARRIERSENSE2 (1 << 3)
+
+#define BB_ANTATTEN_CHAN14 0x0C
+#define BB_ANTENNA_B 0x40
+
+#define BB_HOST_BANG (1 << 30)
+#define BB_HOST_BANG_EN (1 << 2)
+#define BB_HOST_BANG_CLK (1 << 1)
+#define BB_HOST_BANG_DATA 1
+
+#define ANAPARAM_TXDACOFF_SHIFT 27
+#define ANAPARAM_PWR0_SHIFT 28
+#define ANAPARAM_PWR0_MASK (0x07 << ANAPARAM_PWR0_SHIFT)
+#define ANAPARAM_PWR1_SHIFT 20
+#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT)
+
+enum rtl8180_tx_desc_flags {
+ RTL8180_TX_DESC_FLAG_NO_ENC = (1 << 15),
+ RTL8180_TX_DESC_FLAG_TX_OK = (1 << 15),
+ RTL8180_TX_DESC_FLAG_SPLCP = (1 << 16),
+ RTL8180_TX_DESC_FLAG_RX_UNDER = (1 << 16),
+ RTL8180_TX_DESC_FLAG_MOREFRAG = (1 << 17),
+ RTL8180_TX_DESC_FLAG_CTS = (1 << 18),
+ RTL8180_TX_DESC_FLAG_RTS = (1 << 23),
+ RTL8180_TX_DESC_FLAG_LS = (1 << 28),
+ RTL8180_TX_DESC_FLAG_FS = (1 << 29),
+ RTL8180_TX_DESC_FLAG_DMA = (1 << 30),
+ RTL8180_TX_DESC_FLAG_OWN = (1 << 31)
+};
+
+struct rtl8180_tx_desc {
+ __le32 flags;
+ __le16 rts_duration;
+ __le16 plcp_len;
+ __le32 tx_buf;
+ __le32 frame_len;
+ __le32 next_tx_desc;
+ u8 cw;
+ u8 retry_limit;
+ u8 agc;
+ u8 flags2;
+ u32 reserved[2];
+} __attribute__ ((packed));
+
+enum rtl8180_rx_desc_flags {
+ RTL8180_RX_DESC_FLAG_ICV_ERR = (1 << 12),
+ RTL8180_RX_DESC_FLAG_CRC32_ERR = (1 << 13),
+ RTL8180_RX_DESC_FLAG_PM = (1 << 14),
+ RTL8180_RX_DESC_FLAG_RX_ERR = (1 << 15),
+ RTL8180_RX_DESC_FLAG_BCAST = (1 << 16),
+ RTL8180_RX_DESC_FLAG_PAM = (1 << 17),
+ RTL8180_RX_DESC_FLAG_MCAST = (1 << 18),
+ RTL8180_RX_DESC_FLAG_SPLCP = (1 << 25),
+ RTL8180_RX_DESC_FLAG_FOF = (1 << 26),
+ RTL8180_RX_DESC_FLAG_DMA_FAIL = (1 << 27),
+ RTL8180_RX_DESC_FLAG_LS = (1 << 28),
+ RTL8180_RX_DESC_FLAG_FS = (1 << 29),
+ RTL8180_RX_DESC_FLAG_EOR = (1 << 30),
+ RTL8180_RX_DESC_FLAG_OWN = (1 << 31)
+};
+
+struct rtl8180_rx_desc {
+ __le32 flags;
+ __le32 flags2;
+ union {
+ __le32 rx_buf;
+ __le64 tsft;
+ };
+} __attribute__ ((packed));
+
+struct rtl8180_tx_ring {
+ struct rtl8180_tx_desc *desc;
+ dma_addr_t dma;
+ unsigned int idx;
+ unsigned int entries;
+ struct sk_buff_head queue;
+};
+
+struct rtl8180_priv {
+ /* common between rtl818x drivers */
+ struct rtl818x_csr __iomem *map;
+ const struct rtl818x_rf_ops *rf;
+ struct ieee80211_vif *vif;
+ int mode;
+
+ /* rtl8180 driver specific */
+ spinlock_t lock;
+ struct rtl8180_rx_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+ unsigned int rx_idx;
+ struct sk_buff *rx_buf[32];
+ struct rtl8180_tx_ring tx_ring[4];
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_hw_mode modes[2];
+ struct pci_dev *pdev;
+ u32 rx_conf;
+
+ int r8185;
+ u32 anaparam;
+ u16 rfparam;
+ u8 csthreshold;
+};
+
+void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
+void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam);
+
+static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr)
+{
+ return ioread8(addr);
+}
+
+static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr)
+{
+ return ioread16(addr);
+}
+
+static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr)
+{
+ return ioread32(addr);
+}
+
+static inline void rtl818x_iowrite8(struct rtl8180_priv *priv,
+ u8 __iomem *addr, u8 val)
+{
+ iowrite8(val, addr);
+}
+
+static inline void rtl818x_iowrite16(struct rtl8180_priv *priv,
+ __le16 __iomem *addr, u16 val)
+{
+ iowrite16(val, addr);
+}
+
+static inline void rtl818x_iowrite32(struct rtl8180_priv *priv,
+ __le32 __iomem *addr, u32 val)
+{
+ iowrite32(val, addr);
+}
+
+#endif /* RTL8180_H */
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c
new file mode 100644
index 000000000000..07f37b0ccf91
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_dev.c
@@ -0,0 +1,1051 @@
+
+/*
+ * Linux device driver for RTL8180 / RTL8185
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2004-2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/eeprom_93cx6.h>
+#include <net/mac80211.h>
+
+#include "rtl8180.h"
+#include "rtl8180_rtl8225.h"
+#include "rtl8180_sa2400.h"
+#include "rtl8180_max2820.h"
+#include "rtl8180_grf5101.h"
+
+MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
+MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver");
+MODULE_LICENSE("GPL");
+
+static struct pci_device_id rtl8180_table[] __devinitdata = {
+ /* rtl8185 */
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) },
+ { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) },
+
+ /* rtl8180 */
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8180) },
+ { PCI_DEVICE(0x1799, 0x6001) },
+ { PCI_DEVICE(0x1799, 0x6020) },
+ { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) },
+ { }
+};
+
+MODULE_DEVICE_TABLE(pci, rtl8180_table);
+
+void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int i = 10;
+ u32 buf;
+
+ buf = (data << 8) | addr;
+
+ rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf | 0x80);
+ while (i--) {
+ rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf);
+ if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF))
+ return;
+ }
+}
+
+static void rtl8180_handle_rx(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ unsigned int count = 32;
+
+ while (count--) {
+ struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx];
+ struct sk_buff *skb = priv->rx_buf[priv->rx_idx];
+ u32 flags = le32_to_cpu(entry->flags);
+
+ if (flags & RTL8180_RX_DESC_FLAG_OWN)
+ return;
+
+ if (unlikely(flags & (RTL8180_RX_DESC_FLAG_DMA_FAIL |
+ RTL8180_RX_DESC_FLAG_FOF |
+ RTL8180_RX_DESC_FLAG_RX_ERR)))
+ goto done;
+ else {
+ u32 flags2 = le32_to_cpu(entry->flags2);
+ struct ieee80211_rx_status rx_status = {0};
+ struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE);
+
+ if (unlikely(!new_skb))
+ goto done;
+
+ pci_unmap_single(priv->pdev,
+ *((dma_addr_t *)skb->cb),
+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+ skb_put(skb, flags & 0xFFF);
+
+ rx_status.antenna = (flags2 >> 15) & 1;
+ /* TODO: improve signal/rssi reporting */
+ rx_status.signal = flags2 & 0xFF;
+ rx_status.ssi = (flags2 >> 8) & 0x7F;
+ rx_status.rate = (flags >> 20) & 0xF;
+ rx_status.freq = dev->conf.freq;
+ rx_status.channel = dev->conf.channel;
+ rx_status.phymode = dev->conf.phymode;
+ rx_status.mactime = le64_to_cpu(entry->tsft);
+ rx_status.flag |= RX_FLAG_TSFT;
+ if (flags & RTL8180_RX_DESC_FLAG_CRC32_ERR)
+ rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
+
+ ieee80211_rx_irqsafe(dev, skb, &rx_status);
+
+ skb = new_skb;
+ priv->rx_buf[priv->rx_idx] = skb;
+ *((dma_addr_t *) skb->cb) =
+ pci_map_single(priv->pdev, skb_tail_pointer(skb),
+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+ }
+
+ done:
+ entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb));
+ entry->flags = cpu_to_le32(RTL8180_RX_DESC_FLAG_OWN |
+ MAX_RX_SIZE);
+ if (priv->rx_idx == 31)
+ entry->flags |= cpu_to_le32(RTL8180_RX_DESC_FLAG_EOR);
+ priv->rx_idx = (priv->rx_idx + 1) % 32;
+ }
+}
+
+static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
+
+ while (skb_queue_len(&ring->queue)) {
+ struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
+ struct sk_buff *skb;
+ struct ieee80211_tx_status status = { {0} };
+ struct ieee80211_tx_control *control;
+ u32 flags = le32_to_cpu(entry->flags);
+
+ if (flags & RTL8180_TX_DESC_FLAG_OWN)
+ return;
+
+ ring->idx = (ring->idx + 1) % ring->entries;
+ skb = __skb_dequeue(&ring->queue);
+ pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
+ skb->len, PCI_DMA_TODEVICE);
+
+ control = *((struct ieee80211_tx_control **)skb->cb);
+ if (control)
+ memcpy(&status.control, control, sizeof(*control));
+ kfree(control);
+
+ if (!(status.control.flags & IEEE80211_TXCTL_NO_ACK)) {
+ if (flags & RTL8180_TX_DESC_FLAG_TX_OK)
+ status.flags = IEEE80211_TX_STATUS_ACK;
+ else
+ status.excessive_retries = 1;
+ }
+ status.retry_count = flags & 0xFF;
+
+ ieee80211_tx_status_irqsafe(dev, skb, &status);
+ if (ring->entries - skb_queue_len(&ring->queue) == 2)
+ ieee80211_wake_queue(dev, prio);
+ }
+}
+
+static irqreturn_t rtl8180_interrupt(int irq, void *dev_id)
+{
+ struct ieee80211_hw *dev = dev_id;
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg;
+
+ spin_lock(&priv->lock);
+ reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS);
+ if (unlikely(reg == 0xFFFF)) {
+ spin_unlock(&priv->lock);
+ return IRQ_HANDLED;
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg);
+
+ if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR))
+ rtl8180_handle_tx(dev, 3);
+
+ if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR))
+ rtl8180_handle_tx(dev, 2);
+
+ if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR))
+ rtl8180_handle_tx(dev, 1);
+
+ if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR))
+ rtl8180_handle_tx(dev, 0);
+
+ if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR))
+ rtl8180_handle_rx(dev);
+
+ spin_unlock(&priv->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ struct rtl8180_tx_ring *ring;
+ struct rtl8180_tx_desc *entry;
+ unsigned long flags;
+ unsigned int idx, prio;
+ dma_addr_t mapping;
+ u32 tx_flags;
+ u16 plcp_len = 0;
+ __le16 rts_duration = 0;
+
+ prio = control->queue;
+ ring = &priv->tx_ring[prio];
+
+ mapping = pci_map_single(priv->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+
+ tx_flags = RTL8180_TX_DESC_FLAG_OWN | RTL8180_TX_DESC_FLAG_FS |
+ RTL8180_TX_DESC_FLAG_LS | (control->tx_rate << 24) |
+ (control->rts_cts_rate << 19) | skb->len;
+
+ if (priv->r8185)
+ tx_flags |= RTL8180_TX_DESC_FLAG_DMA |
+ RTL8180_TX_DESC_FLAG_NO_ENC;
+
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ tx_flags |= RTL8180_TX_DESC_FLAG_RTS;
+ else if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
+ tx_flags |= RTL8180_TX_DESC_FLAG_CTS;
+
+ *((struct ieee80211_tx_control **) skb->cb) =
+ kmemdup(control, sizeof(*control), GFP_ATOMIC);
+
+ if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS)
+ rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
+ control);
+
+ if (!priv->r8185) {
+ unsigned int remainder;
+
+ plcp_len = DIV_ROUND_UP(16 * (skb->len + 4),
+ (control->rate->rate * 2) / 10);
+ remainder = (16 * (skb->len + 4)) %
+ ((control->rate->rate * 2) / 10);
+ if (remainder > 0 && remainder <= 6)
+ plcp_len |= 1 << 15;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
+ idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries;
+ entry = &ring->desc[idx];
+
+ entry->rts_duration = rts_duration;
+ entry->plcp_len = cpu_to_le16(plcp_len);
+ entry->tx_buf = cpu_to_le32(mapping);
+ entry->frame_len = cpu_to_le32(skb->len);
+ entry->flags2 = control->alt_retry_rate != -1 ?
+ control->alt_retry_rate << 4 : 0;
+ entry->retry_limit = control->retry_limit;
+ entry->flags = cpu_to_le32(tx_flags);
+ __skb_queue_tail(&ring->queue, skb);
+ if (ring->entries - skb_queue_len(&ring->queue) < 2)
+ ieee80211_stop_queue(dev, control->queue);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
+
+ return 0;
+}
+
+void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
+{
+ u8 reg;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3,
+ reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3,
+ reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+static int rtl8180_init_hw(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg;
+
+ rtl818x_iowrite8(priv, &priv->map->CMD, 0);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ msleep(10);
+
+ /* reset */
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= (1 << 1);
+ reg |= RTL818X_CMD_RESET;
+ rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ msleep(200);
+
+ /* check success of reset */
+ if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) {
+ printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy));
+ return -ETIMEDOUT;
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD);
+ rtl818x_ioread8(priv, &priv->map->CMD);
+ msleep(200);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) {
+ /* For cardbus */
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ reg |= 1 << 1;
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg);
+ reg = rtl818x_ioread16(priv, &priv->map->FEMR);
+ reg |= (1 << 15) | (1 << 14) | (1 << 4);
+ rtl818x_iowrite16(priv, &priv->map->FEMR, reg);
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->MSR, 0);
+
+ if (!priv->r8185)
+ rtl8180_set_anaparam(priv, priv->anaparam);
+
+ rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
+ rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
+ rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
+ rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
+ rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
+
+ /* TODO: necessary? specs indicate not */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG2);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3));
+ if (priv->r8185) {
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG2);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4));
+ }
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */
+
+ /* TODO: turn off hw wep on rtl8180 */
+
+ rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0);
+
+ if (priv->r8185) {
+ rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0);
+ rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81);
+ rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0);
+
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+
+ /* TODO: set ClkRun enable? necessary? */
+ reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+ } else {
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x1);
+ rtl818x_iowrite8(priv, &priv->map->SECURITY, 0);
+
+ rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6);
+ rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C);
+ }
+
+ priv->rf->init(dev);
+ if (priv->r8185)
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
+ return 0;
+}
+
+static int rtl8180_init_rx_ring(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ struct rtl8180_rx_desc *entry;
+ int i;
+
+ priv->rx_ring = pci_alloc_consistent(priv->pdev,
+ sizeof(*priv->rx_ring) * 32,
+ &priv->rx_ring_dma);
+
+ if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
+ printk(KERN_ERR "%s: Cannot allocate RX ring\n",
+ wiphy_name(dev->wiphy));
+ return -ENOMEM;
+ }
+
+ memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * 32);
+ priv->rx_idx = 0;
+
+ for (i = 0; i < 32; i++) {
+ struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE);
+ dma_addr_t *mapping;
+ entry = &priv->rx_ring[i];
+ if (!skb)
+ return 0;
+
+ priv->rx_buf[i] = skb;
+ mapping = (dma_addr_t *)skb->cb;
+ *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb),
+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+ entry->rx_buf = cpu_to_le32(*mapping);
+ entry->flags = cpu_to_le32(RTL8180_RX_DESC_FLAG_OWN |
+ MAX_RX_SIZE);
+ }
+ entry->flags |= cpu_to_le32(RTL8180_RX_DESC_FLAG_EOR);
+ return 0;
+}
+
+static void rtl8180_free_rx_ring(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < 32; i++) {
+ struct sk_buff *skb = priv->rx_buf[i];
+ if (!skb)
+ continue;
+
+ pci_unmap_single(priv->pdev,
+ *((dma_addr_t *)skb->cb),
+ MAX_RX_SIZE, PCI_DMA_FROMDEVICE);
+ kfree_skb(skb);
+ }
+
+ pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * 32,
+ priv->rx_ring, priv->rx_ring_dma);
+ priv->rx_ring = NULL;
+}
+
+static int rtl8180_init_tx_ring(struct ieee80211_hw *dev,
+ unsigned int prio, unsigned int entries)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ struct rtl8180_tx_desc *ring;
+ dma_addr_t dma;
+ int i;
+
+ ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
+ if (!ring || (unsigned long)ring & 0xFF) {
+ printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n",
+ wiphy_name(dev->wiphy), prio);
+ return -ENOMEM;
+ }
+
+ memset(ring, 0, sizeof(*ring)*entries);
+ priv->tx_ring[prio].desc = ring;
+ priv->tx_ring[prio].dma = dma;
+ priv->tx_ring[prio].idx = 0;
+ priv->tx_ring[prio].entries = entries;
+ skb_queue_head_init(&priv->tx_ring[prio].queue);
+
+ for (i = 0; i < entries; i++)
+ ring[i].next_tx_desc =
+ cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring));
+
+ return 0;
+}
+
+static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ struct rtl8180_tx_ring *ring = &priv->tx_ring[prio];
+
+ while (skb_queue_len(&ring->queue)) {
+ struct rtl8180_tx_desc *entry = &ring->desc[ring->idx];
+ struct sk_buff *skb = __skb_dequeue(&ring->queue);
+
+ pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf),
+ skb->len, PCI_DMA_TODEVICE);
+ kfree(*((struct ieee80211_tx_control **) skb->cb));
+ kfree_skb(skb);
+ ring->idx = (ring->idx + 1) % ring->entries;
+ }
+
+ pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries,
+ ring->desc, ring->dma);
+ ring->desc = NULL;
+}
+
+static int rtl8180_start(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int ret, i;
+ u32 reg;
+
+ ret = rtl8180_init_rx_ring(dev);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < 4; i++)
+ if ((ret = rtl8180_init_tx_ring(dev, i, 16)))
+ goto err_free_rings;
+
+ ret = rtl8180_init_hw(dev);
+ if (ret)
+ goto err_free_rings;
+
+ rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma);
+ rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma);
+ rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma);
+ rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma);
+ rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma);
+
+ ret = request_irq(priv->pdev->irq, &rtl8180_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, dev);
+ if (ret) {
+ printk(KERN_ERR "%s: failed to register IRQ handler\n",
+ wiphy_name(dev->wiphy));
+ goto err_free_rings;
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF);
+
+ rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0);
+ rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0);
+
+ reg = RTL818X_RX_CONF_ONLYERLPKT |
+ RTL818X_RX_CONF_RX_AUTORESETPHY |
+ RTL818X_RX_CONF_MGMT |
+ RTL818X_RX_CONF_DATA |
+ (7 << 8 /* MAX RX DMA */) |
+ RTL818X_RX_CONF_BROADCAST |
+ RTL818X_RX_CONF_NICMAC;
+
+ if (priv->r8185)
+ reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2;
+ else {
+ reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1)
+ ? RTL818X_RX_CONF_CSDM1 : 0;
+ reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2)
+ ? RTL818X_RX_CONF_CSDM2 : 0;
+ }
+
+ priv->rx_conf = reg;
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg);
+
+ if (priv->r8185) {
+ reg = rtl818x_ioread8(priv, &priv->map->CW_CONF);
+ reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT;
+ reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT;
+ rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL);
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT;
+ reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT;
+ reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT;
+ rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg);
+
+ /* disable early TX */
+ rtl818x_iowrite8(priv, (u8 __iomem *)priv->map + 0xec, 0x3f);
+ }
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ reg |= (6 << 21 /* MAX TX DMA */) |
+ RTL818X_TX_CONF_NO_ICV;
+
+ if (priv->r8185)
+ reg &= ~RTL818X_TX_CONF_PROBE_DTS;
+ else
+ reg &= ~RTL818X_TX_CONF_HW_SEQNUM;
+
+ /* different meaning, same value on both rtl8185 and rtl8180 */
+ reg &= ~RTL818X_TX_CONF_SAT_HWPLCP;
+
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg |= RTL818X_CMD_RX_ENABLE;
+ reg |= RTL818X_CMD_TX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ priv->mode = IEEE80211_IF_TYPE_MNTR;
+ return 0;
+
+ err_free_rings:
+ rtl8180_free_rx_ring(dev);
+ for (i = 0; i < 4; i++)
+ if (priv->tx_ring[i].desc)
+ rtl8180_free_tx_ring(dev, i);
+
+ return ret;
+}
+
+static void rtl8180_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 reg;
+ int i;
+
+ priv->mode = IEEE80211_IF_TYPE_INVALID;
+
+ rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0);
+
+ reg = rtl818x_ioread8(priv, &priv->map->CMD);
+ reg &= ~RTL818X_CMD_TX_ENABLE;
+ reg &= ~RTL818X_CMD_RX_ENABLE;
+ rtl818x_iowrite8(priv, &priv->map->CMD, reg);
+
+ priv->rf->stop(dev);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ free_irq(priv->pdev->irq, dev);
+
+ rtl8180_free_rx_ring(dev);
+ for (i = 0; i < 4; i++)
+ rtl8180_free_tx_ring(dev, i);
+}
+
+static int rtl8180_add_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ if (priv->mode != IEEE80211_IF_TYPE_MNTR)
+ return -EOPNOTSUPP;
+
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_STA:
+ priv->mode = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ priv->vif = conf->vif;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0],
+ cpu_to_le32(*(u32 *)conf->mac_addr));
+ rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4],
+ cpu_to_le16(*(u16 *)(conf->mac_addr + 4)));
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ return 0;
+}
+
+static void rtl8180_remove_interface(struct ieee80211_hw *dev,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ priv->mode = IEEE80211_IF_TYPE_MNTR;
+ priv->vif = NULL;
+}
+
+static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ priv->rf->set_chan(dev, conf);
+
+ return 0;
+}
+
+static int rtl8180_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
+
+ if (is_valid_ether_addr(conf->bssid))
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_INFRA);
+ else
+ rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_NO_LINK);
+
+ return 0;
+}
+
+static void rtl8180_configure_filter(struct ieee80211_hw *dev,
+ unsigned int changed_flags,
+ unsigned int *total_flags,
+ int mc_count, struct dev_addr_list *mclist)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ if (changed_flags & FIF_FCSFAIL)
+ priv->rx_conf ^= RTL818X_RX_CONF_FCS;
+ if (changed_flags & FIF_CONTROL)
+ priv->rx_conf ^= RTL818X_RX_CONF_CTRL;
+ if (changed_flags & FIF_OTHER_BSS)
+ priv->rx_conf ^= RTL818X_RX_CONF_MONITOR;
+ if (*total_flags & FIF_ALLMULTI || mc_count > 0)
+ priv->rx_conf |= RTL818X_RX_CONF_MULTICAST;
+ else
+ priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST;
+
+ *total_flags = 0;
+
+ if (priv->rx_conf & RTL818X_RX_CONF_FCS)
+ *total_flags |= FIF_FCSFAIL;
+ if (priv->rx_conf & RTL818X_RX_CONF_CTRL)
+ *total_flags |= FIF_CONTROL;
+ if (priv->rx_conf & RTL818X_RX_CONF_MONITOR)
+ *total_flags |= FIF_OTHER_BSS;
+ if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST)
+ *total_flags |= FIF_ALLMULTI;
+
+ rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf);
+}
+
+static const struct ieee80211_ops rtl8180_ops = {
+ .tx = rtl8180_tx,
+ .start = rtl8180_start,
+ .stop = rtl8180_stop,
+ .add_interface = rtl8180_add_interface,
+ .remove_interface = rtl8180_remove_interface,
+ .config = rtl8180_config,
+ .config_interface = rtl8180_config_interface,
+ .configure_filter = rtl8180_configure_filter,
+};
+
+static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8180_priv *priv = dev->priv;
+ u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+
+ eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE;
+ eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ;
+ eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK;
+ eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS;
+}
+
+static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom)
+{
+ struct ieee80211_hw *dev = eeprom->data;
+ struct rtl8180_priv *priv = dev->priv;
+ u8 reg = 2 << 6;
+
+ if (eeprom->reg_data_in)
+ reg |= RTL818X_EEPROM_CMD_WRITE;
+ if (eeprom->reg_data_out)
+ reg |= RTL818X_EEPROM_CMD_READ;
+ if (eeprom->reg_data_clock)
+ reg |= RTL818X_EEPROM_CMD_CK;
+ if (eeprom->reg_chip_select)
+ reg |= RTL818X_EEPROM_CMD_CS;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+}
+
+static int __devinit rtl8180_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct ieee80211_hw *dev;
+ struct rtl8180_priv *priv;
+ unsigned long mem_addr, mem_len;
+ unsigned int io_addr, io_len;
+ int err, i;
+ struct eeprom_93cx6 eeprom;
+ const char *chip_name, *rf_name = NULL;
+ u32 reg;
+ u16 eeprom_val;
+ DECLARE_MAC_BUF(mac);
+
+ err = pci_enable_device(pdev);
+ if (err) {
+ printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n",
+ pci_name(pdev));
+ return err;
+ }
+
+ err = pci_request_regions(pdev, KBUILD_MODNAME);
+ if (err) {
+ printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n",
+ pci_name(pdev));
+ return err;
+ }
+
+ io_addr = pci_resource_start(pdev, 0);
+ io_len = pci_resource_len(pdev, 0);
+ mem_addr = pci_resource_start(pdev, 1);
+ mem_len = pci_resource_len(pdev, 1);
+
+ if (mem_len < sizeof(struct rtl818x_csr) ||
+ io_len < sizeof(struct rtl818x_csr)) {
+ printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto err_free_reg;
+ }
+
+ if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) ||
+ (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) {
+ printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n",
+ pci_name(pdev));
+ goto err_free_reg;
+ }
+
+ pci_set_master(pdev);
+
+ dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops);
+ if (!dev) {
+ printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n",
+ pci_name(pdev));
+ err = -ENOMEM;
+ goto err_free_reg;
+ }
+
+ priv = dev->priv;
+ priv->pdev = pdev;
+
+ SET_IEEE80211_DEV(dev, &pdev->dev);
+ pci_set_drvdata(pdev, dev);
+
+ priv->map = pci_iomap(pdev, 1, mem_len);
+ if (!priv->map)
+ priv->map = pci_iomap(pdev, 0, io_len);
+
+ if (!priv->map) {
+ printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n",
+ pci_name(pdev));
+ goto err_free_dev;
+ }
+
+ memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels));
+ memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates));
+ priv->modes[0].mode = MODE_IEEE80211G;
+ priv->modes[0].num_rates = ARRAY_SIZE(rtl818x_rates);
+ priv->modes[0].rates = priv->rates;
+ priv->modes[0].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[0].channels = priv->channels;
+ priv->modes[1].mode = MODE_IEEE80211B;
+ priv->modes[1].num_rates = 4;
+ priv->modes[1].rates = priv->rates;
+ priv->modes[1].num_channels = ARRAY_SIZE(rtl818x_channels);
+ priv->modes[1].channels = priv->channels;
+ priv->mode = IEEE80211_IF_TYPE_INVALID;
+ dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_RX_INCLUDES_FCS;
+ dev->queues = 1;
+ dev->max_rssi = 65;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ reg &= RTL818X_TX_CONF_HWVER_MASK;
+ switch (reg) {
+ case RTL818X_TX_CONF_R8180_ABCD:
+ chip_name = "RTL8180";
+ break;
+ case RTL818X_TX_CONF_R8180_F:
+ chip_name = "RTL8180vF";
+ break;
+ case RTL818X_TX_CONF_R8185_ABC:
+ chip_name = "RTL8185";
+ break;
+ case RTL818X_TX_CONF_R8185_D:
+ chip_name = "RTL8185vD";
+ break;
+ default:
+ printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n",
+ pci_name(pdev), reg >> 25);
+ goto err_iounmap;
+ }
+
+ priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC;
+ if (priv->r8185) {
+ if ((err = ieee80211_register_hwmode(dev, &priv->modes[0])))
+ goto err_iounmap;
+
+ pci_try_set_mwi(pdev);
+ }
+
+ if ((err = ieee80211_register_hwmode(dev, &priv->modes[1])))
+ goto err_iounmap;
+
+ eeprom.data = dev;
+ eeprom.register_read = rtl8180_eeprom_register_read;
+ eeprom.register_write = rtl8180_eeprom_register_write;
+ if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6))
+ eeprom.width = PCI_EEPROM_WIDTH_93C66;
+ else
+ eeprom.width = PCI_EEPROM_WIDTH_93C46;
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val);
+ eeprom_val &= 0xFF;
+ switch (eeprom_val) {
+ case 1: rf_name = "Intersil";
+ break;
+ case 2: rf_name = "RFMD";
+ break;
+ case 3: priv->rf = &sa2400_rf_ops;
+ break;
+ case 4: priv->rf = &max2820_rf_ops;
+ break;
+ case 5: priv->rf = &grf5101_rf_ops;
+ break;
+ case 9: priv->rf = rtl8180_detect_rf(dev);
+ break;
+ case 10:
+ rf_name = "RTL8255";
+ break;
+ default:
+ printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n",
+ pci_name(pdev), eeprom_val);
+ goto err_iounmap;
+ }
+
+ if (!priv->rf) {
+ printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n",
+ pci_name(pdev), rf_name);
+ goto err_iounmap;
+ }
+
+ eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val);
+ priv->csthreshold = eeprom_val >> 8;
+ if (!priv->r8185) {
+ __le32 anaparam;
+ eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2);
+ priv->anaparam = le32_to_cpu(anaparam);
+ eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam);
+ }
+
+ eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3);
+ if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
+ printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using"
+ " randomly generated MAC addr\n", pci_name(pdev));
+ random_ether_addr(dev->wiphy->perm_addr);
+ }
+
+ /* CCK TX power */
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr);
+ priv->channels[i].val = txpwr & 0xFF;
+ priv->channels[i + 1].val = txpwr >> 8;
+ }
+
+ /* OFDM TX power */
+ if (priv->r8185) {
+ for (i = 0; i < 14; i += 2) {
+ u16 txpwr;
+ eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr);
+ priv->channels[i].val |= (txpwr & 0xFF) << 8;
+ priv->channels[i + 1].val |= txpwr & 0xFF00;
+ }
+ }
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ spin_lock_init(&priv->lock);
+
+ err = ieee80211_register_hw(dev);
+ if (err) {
+ printk(KERN_ERR "%s (rtl8180): Cannot register device\n",
+ pci_name(pdev));
+ goto err_iounmap;
+ }
+
+ printk(KERN_INFO "%s: hwaddr %s, %s + %s\n",
+ wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+ chip_name, priv->rf->name);
+
+ return 0;
+
+ err_iounmap:
+ iounmap(priv->map);
+
+ err_free_dev:
+ pci_set_drvdata(pdev, NULL);
+ ieee80211_free_hw(dev);
+
+ err_free_reg:
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ return err;
+}
+
+static void __devexit rtl8180_remove(struct pci_dev *pdev)
+{
+ struct ieee80211_hw *dev = pci_get_drvdata(pdev);
+ struct rtl8180_priv *priv;
+
+ if (!dev)
+ return;
+
+ ieee80211_unregister_hw(dev);
+
+ priv = dev->priv;
+
+ pci_iounmap(pdev, priv->map);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ ieee80211_free_hw(dev);
+}
+
+#ifdef CONFIG_PM
+static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ return 0;
+}
+
+static int rtl8180_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+ return 0;
+}
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver rtl8180_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = rtl8180_table,
+ .probe = rtl8180_probe,
+ .remove = __devexit_p(rtl8180_remove),
+#ifdef CONFIG_PM
+ .suspend = rtl8180_suspend,
+ .resume = rtl8180_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init rtl8180_init(void)
+{
+ return pci_register_driver(&rtl8180_driver);
+}
+
+static void __exit rtl8180_exit(void)
+{
+ pci_unregister_driver(&rtl8180_driver);
+}
+
+module_init(rtl8180_init);
+module_exit(rtl8180_exit);
diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl8180_grf5101.c
new file mode 100644
index 000000000000..8293e19c4c59
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_grf5101.c
@@ -0,0 +1,179 @@
+
+/*
+ * Radio tuning for GCT GRF5101 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <net/mac80211.h>
+
+#include "rtl8180.h"
+#include "rtl8180_grf5101.h"
+
+static const int grf5101_encode[] = {
+ 0x0, 0x8, 0x4, 0xC,
+ 0x2, 0xA, 0x6, 0xE,
+ 0x1, 0x9, 0x5, 0xD,
+ 0x3, 0xB, 0x7, 0xF
+};
+
+static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 phy_config;
+
+ phy_config = grf5101_encode[(data >> 8) & 0xF];
+ phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4;
+ phy_config |= grf5101_encode[data & 0xF] << 8;
+ phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12;
+ phy_config |= (addr & 1) << 16;
+ phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24;
+
+ /* MAC will bang bits to the chip */
+ phy_config |= 0x90000000;
+
+ rtl818x_iowrite32(priv,
+ (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+
+ msleep(3);
+}
+
+static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 ant = GRF5101_ANTENNA;
+
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl8180_write_phy(dev, 0x10, ant);
+}
+
+static void grf5101_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+ u32 chan = conf->channel - 1;
+
+ /* set TX power */
+ write_grf5101(dev, 0x15, 0x0);
+ write_grf5101(dev, 0x06, txpw);
+ write_grf5101(dev, 0x15, 0x10);
+ write_grf5101(dev, 0x15, 0x0);
+
+ /* set frequency */
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x0B, chan);
+ write_grf5101(dev, 0x07, 0x1000);
+
+ grf5101_write_phy_antenna(dev, chan);
+}
+
+static void grf5101_rf_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 anaparam;
+
+ anaparam = priv->anaparam;
+ anaparam &= 0x000fffff;
+ anaparam |= 0x3f900000;
+ rtl8180_set_anaparam(priv, anaparam);
+
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x1f, 0x45);
+ write_grf5101(dev, 0x1f, 0x5);
+ write_grf5101(dev, 0x00, 0x8e4);
+}
+
+static void grf5101_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ rtl8180_set_anaparam(priv, priv->anaparam);
+
+ write_grf5101(dev, 0x1f, 0x0);
+ write_grf5101(dev, 0x1f, 0x0);
+ write_grf5101(dev, 0x1f, 0x40);
+ write_grf5101(dev, 0x1f, 0x60);
+ write_grf5101(dev, 0x1f, 0x61);
+ write_grf5101(dev, 0x1f, 0x61);
+ write_grf5101(dev, 0x00, 0xae4);
+ write_grf5101(dev, 0x1f, 0x1);
+ write_grf5101(dev, 0x1f, 0x41);
+ write_grf5101(dev, 0x1f, 0x61);
+
+ write_grf5101(dev, 0x01, 0x1a23);
+ write_grf5101(dev, 0x02, 0x4971);
+ write_grf5101(dev, 0x03, 0x41de);
+ write_grf5101(dev, 0x04, 0x2d80);
+ write_grf5101(dev, 0x05, 0x68ff); /* 0x61ff original value */
+ write_grf5101(dev, 0x06, 0x0);
+ write_grf5101(dev, 0x07, 0x0);
+ write_grf5101(dev, 0x08, 0x7533);
+ write_grf5101(dev, 0x09, 0xc401);
+ write_grf5101(dev, 0x0a, 0x0);
+ write_grf5101(dev, 0x0c, 0x1c7);
+ write_grf5101(dev, 0x0d, 0x29d3);
+ write_grf5101(dev, 0x0e, 0x2e8);
+ write_grf5101(dev, 0x10, 0x192);
+ write_grf5101(dev, 0x11, 0x248);
+ write_grf5101(dev, 0x12, 0x0);
+ write_grf5101(dev, 0x13, 0x20c4);
+ write_grf5101(dev, 0x14, 0xf4fc);
+ write_grf5101(dev, 0x15, 0x0);
+ write_grf5101(dev, 0x16, 0x1500);
+
+ write_grf5101(dev, 0x07, 0x1000);
+
+ /* baseband configuration */
+ rtl8180_write_phy(dev, 0, 0xa8);
+ rtl8180_write_phy(dev, 3, 0x0);
+ rtl8180_write_phy(dev, 4, 0xc0);
+ rtl8180_write_phy(dev, 5, 0x90);
+ rtl8180_write_phy(dev, 6, 0x1e);
+ rtl8180_write_phy(dev, 7, 0x64);
+
+ grf5101_write_phy_antenna(dev, 1);
+
+ rtl8180_write_phy(dev, 0x11, 0x88);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */
+ else
+ rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */
+
+ rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
+
+ rtl8180_write_phy(dev, 0x19, 0x0);
+ rtl8180_write_phy(dev, 0x1a, 0xa0);
+ rtl8180_write_phy(dev, 0x1b, 0x44);
+}
+
+const struct rtl818x_rf_ops grf5101_rf_ops = {
+ .name = "GCT",
+ .init = grf5101_rf_init,
+ .stop = grf5101_rf_stop,
+ .set_chan = grf5101_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_grf5101.h b/drivers/net/wireless/rtl8180_grf5101.h
new file mode 100644
index 000000000000..76647111bcff
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_grf5101.h
@@ -0,0 +1,28 @@
+#ifndef RTL8180_GRF5101_H
+#define RTL8180_GRF5101_H
+
+/*
+ * Radio tuning for GCT GRF5101 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define GRF5101_ANTENNA 0xA3
+
+extern const struct rtl818x_rf_ops grf5101_rf_ops;
+
+#endif /* RTL8180_GRF5101_H */
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl8180_max2820.c
new file mode 100644
index 000000000000..98fe9fd64968
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_max2820.c
@@ -0,0 +1,150 @@
+/*
+ * Radio tuning for Maxim max2820 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <net/mac80211.h>
+
+#include "rtl8180.h"
+#include "rtl8180_max2820.h"
+
+static const u32 max2820_chan[] = {
+ 12, /* CH 1 */
+ 17,
+ 22,
+ 27,
+ 32,
+ 37,
+ 42,
+ 47,
+ 52,
+ 57,
+ 62,
+ 67,
+ 72,
+ 84, /* CH 14 */
+};
+
+static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 phy_config;
+
+ phy_config = 0x90 + (data & 0xf);
+ phy_config <<= 16;
+ phy_config += addr;
+ phy_config <<= 8;
+ phy_config += (data >> 4) & 0xff;
+
+ rtl818x_iowrite32(priv,
+ (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+
+ msleep(1);
+}
+
+static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 ant;
+
+ ant = MAXIM_ANTENNA;
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl8180_write_phy(dev, 0x10, ant);
+}
+
+static void max2820_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ unsigned int chan_idx = conf ? conf->channel - 1 : 0;
+ u32 txpw = priv->channels[chan_idx].val & 0xFF;
+ u32 chan = max2820_chan[chan_idx];
+
+ /* While philips SA2400 drive the PA bias from
+ * sa2400, for MAXIM we do this directly from BB */
+ rtl8180_write_phy(dev, 3, txpw);
+
+ max2820_write_phy_antenna(dev, chan);
+ write_max2820(dev, 3, chan);
+}
+
+static void max2820_rf_stop(struct ieee80211_hw *dev)
+{
+ rtl8180_write_phy(dev, 3, 0x8);
+ write_max2820(dev, 1, 0);
+}
+
+
+static void max2820_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ /* MAXIM from netbsd driver */
+ write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */
+ write_max2820(dev, 1, 0x01e); /* enable register */
+ write_max2820(dev, 2, 0x001); /* synt register */
+
+ max2820_rf_set_channel(dev, NULL);
+
+ write_max2820(dev, 4, 0x313); /* rx register */
+
+ /* PA is driven directly by the BB, we keep the MAXIM bias
+ * at the highest value in case that setting it to lower
+ * values may introduce some further attenuation somewhere..
+ */
+ write_max2820(dev, 5, 0x00f);
+
+ /* baseband configuration */
+ rtl8180_write_phy(dev, 0, 0x88); /* sys1 */
+ rtl8180_write_phy(dev, 3, 0x08); /* txagc */
+ rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */
+ rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */
+ rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */
+ rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */
+
+ max2820_write_phy_antenna(dev, 1);
+
+ rtl8180_write_phy(dev, 0x11, 0x88); /* trl */
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl8180_write_phy(dev, 0x12, 0xc7);
+ else
+ rtl8180_write_phy(dev, 0x12, 0x47);
+
+ rtl8180_write_phy(dev, 0x13, 0x9b);
+
+ rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */
+ rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */
+
+ max2820_rf_set_channel(dev, NULL);
+}
+
+const struct rtl818x_rf_ops max2820_rf_ops = {
+ .name = "Maxim",
+ .init = max2820_rf_init,
+ .stop = max2820_rf_stop,
+ .set_chan = max2820_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_max2820.h b/drivers/net/wireless/rtl8180_max2820.h
new file mode 100644
index 000000000000..61cf6d1e7d57
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_max2820.h
@@ -0,0 +1,28 @@
+#ifndef RTL8180_MAX2820_H
+#define RTL8180_MAX2820_H
+
+/*
+ * Radio tuning for Maxim max2820 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define MAXIM_ANTENNA 0xb3
+
+extern const struct rtl818x_rf_ops max2820_rf_ops;
+
+#endif /* RTL8180_MAX2820_H */
diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl8180_rtl8225.c
new file mode 100644
index 000000000000..ef3832bee85c
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_rtl8225.c
@@ -0,0 +1,779 @@
+
+/*
+ * Radio tuning for RTL8225 on RTL8180
+ *
+ * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Based on the r8180 driver, which is:
+ * Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
+ *
+ * Thanks to Realtek for their support!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <net/mac80211.h>
+
+#include "rtl8180.h"
+#include "rtl8180_rtl8225.h"
+
+static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg80, reg84, reg82;
+ u32 bangdata;
+ int i;
+
+ bangdata = (data << 4) | (addr & 0xf);
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
+
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ for (i = 15; i >= 0; i--) {
+ u16 reg = reg80 | !!(bangdata & (1 << i));
+
+ if (i & 1)
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
+
+ if (!(i & 1))
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(10);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+}
+
+static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg80, reg82, reg84, out;
+ int i;
+
+ reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
+ reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
+ reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400;
+
+ reg80 &= ~0xF;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(4);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(5);
+
+ for (i = 4; i >= 0; i--) {
+ u16 reg = reg80 | ((addr >> i) & 1);
+
+ if (!(i & 1)) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ if (i & 1) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ }
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ out = 0;
+ for (i = 11; i >= 0; i--) {
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(1);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 1));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
+ out |= 1 << i;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+ }
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
+ reg80 | (1 << 3) | (1 << 2));
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ udelay(2);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
+
+ return out;
+}
+
+static const u16 rtl8225bcd_rxgain[] = {
+ 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
+ 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
+ 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
+ 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
+ 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
+ 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
+ 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
+ 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
+ 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
+ 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
+ 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
+ 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
+};
+
+static const u8 rtl8225_agc[] = {
+ 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
+ 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
+ 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
+ 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
+ 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
+ 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
+ 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
+ 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
+ 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
+ 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
+ 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
+ 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
+ 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+};
+
+static const u8 rtl8225_gain[] = {
+ 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */
+ 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */
+ 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */
+ 0x33, 0x80, 0x79, 0xc5, /* -78dbm */
+ 0x43, 0x78, 0x76, 0xc5, /* -74dbm */
+ 0x53, 0x60, 0x73, 0xc5, /* -70dbm */
+ 0x63, 0x58, 0x70, 0xc5, /* -66dbm */
+};
+
+static const u8 rtl8225_threshold[] = {
+ 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
+};
+
+static const u8 rtl8225_tx_gain_cck_ofdm[] = {
+ 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
+};
+
+static const u8 rtl8225_tx_power_cck[] = {
+ 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
+ 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
+ 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
+ 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
+ 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
+ 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
+};
+
+static const u8 rtl8225_tx_power_cck_ch14[] = {
+ 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
+ 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
+ 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
+ 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225_tx_power_ofdm[] = {
+ 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
+};
+
+static const u32 rtl8225_chan[] = {
+ 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
+ 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
+};
+
+static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ u32 reg;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xFF;
+ ofdm_power = priv->channels[channel - 1].val >> 8;
+
+ cck_power = min(cck_power, (u8)35);
+ ofdm_power = min(ofdm_power, (u8)35);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
+ rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
+
+ if (channel == 14)
+ tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
+ else
+ tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ msleep(1); /* FIXME: optional? */
+
+ /* anaparam2 on */
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
+ rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1);
+
+ tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
+
+ rtl8225_write_phy_ofdm(dev, 5, *tmp);
+ rtl8225_write_phy_ofdm(dev, 7, *tmp);
+
+ msleep(1);
+}
+
+static void rtl8225_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int i;
+
+ rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
+
+ /* host_pci_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ msleep(200); /* FIXME: ehh?? */
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008);
+
+ /* TODO: check if we need really to change BRSR to do RF config */
+ rtl818x_ioread16(priv, &priv->map->BRSR);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl8225_write(dev, 0x0, 0x067);
+ rtl8225_write(dev, 0x1, 0xFE0);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x3, 0x441);
+ rtl8225_write(dev, 0x4, 0x8BE);
+ rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */
+ rtl8225_write(dev, 0x6, 0xAE6);
+ rtl8225_write(dev, 0x7, rtl8225_chan[0]);
+ rtl8225_write(dev, 0x8, 0x01F);
+ rtl8225_write(dev, 0x9, 0x334);
+ rtl8225_write(dev, 0xA, 0xFD4);
+ rtl8225_write(dev, 0xB, 0x391);
+ rtl8225_write(dev, 0xC, 0x050);
+ rtl8225_write(dev, 0xD, 0x6DB);
+ rtl8225_write(dev, 0xE, 0x029);
+ rtl8225_write(dev, 0xF, 0x914); msleep(1);
+
+ rtl8225_write(dev, 0x2, 0xC4D); msleep(100);
+
+ rtl8225_write(dev, 0x0, 0x127);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x027);
+ rtl8225_write(dev, 0x0, 0x22F);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1);
+
+ rtl8225_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ rtl8225_write(dev, 0x0c, 0x50);
+ /* set OFDM initial gain */
+ rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]);
+ rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]);
+ rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]);
+ rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]);
+ /* set CCK threshold */
+ rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]);
+}
+
+static const u8 rtl8225z2_tx_power_cck_ch14[] = {
+ 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00
+};
+
+static const u8 rtl8225z2_tx_power_cck_B[] = {
+ 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_cck_A[] = {
+ 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04
+};
+
+static const u8 rtl8225z2_tx_power_cck[] = {
+ 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04
+};
+
+static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 cck_power, ofdm_power;
+ const u8 *tmp;
+ int i;
+
+ cck_power = priv->channels[channel - 1].val & 0xFF;
+ ofdm_power = priv->channels[channel - 1].val >> 8;
+
+ if (channel == 14)
+ tmp = rtl8225z2_tx_power_cck_ch14;
+ else if (cck_power == 12)
+ tmp = rtl8225z2_tx_power_cck_B;
+ else if (cck_power == 13)
+ tmp = rtl8225z2_tx_power_cck_A;
+ else
+ tmp = rtl8225z2_tx_power_cck;
+
+ for (i = 0; i < 8; i++)
+ rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
+
+ cck_power = min(cck_power, (u8)35);
+ if (cck_power == 13 || cck_power == 14)
+ cck_power = 12;
+ if (cck_power >= 15)
+ cck_power -= 2;
+
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power);
+ rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK);
+ msleep(1);
+
+ ofdm_power = min(ofdm_power, (u8)35);
+ rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power);
+
+ rtl8225_write_phy_ofdm(dev, 2, 0x62);
+ rtl8225_write_phy_ofdm(dev, 5, 0x00);
+ rtl8225_write_phy_ofdm(dev, 6, 0x40);
+ rtl8225_write_phy_ofdm(dev, 7, 0x00);
+ rtl8225_write_phy_ofdm(dev, 8, 0x40);
+
+ msleep(1);
+}
+
+static const u16 rtl8225z2_rxgain[] = {
+ 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009,
+ 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141,
+ 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183,
+ 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244,
+ 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288,
+ 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345,
+ 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389,
+ 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393,
+ 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d,
+ 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9,
+ 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
+ 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
+};
+
+static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ int i;
+
+ rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON);
+
+ /* host_pci_init */
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ msleep(200); /* FIXME: ehh?? */
+ rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6));
+
+ rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008);
+
+ /* TODO: check if we need really to change BRSR to do RF config */
+ rtl818x_ioread16(priv, &priv->map->BRSR);
+ rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF);
+ rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
+ rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D); msleep(1);
+ rtl8225_write(dev, 0x3, 0x441); msleep(1);
+ rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
+ rtl8225_write(dev, 0x5, 0xC72); msleep(1);
+ rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
+ rtl8225_write(dev, 0x7, 0x82A); msleep(1);
+ rtl8225_write(dev, 0x8, 0x03F); msleep(1);
+ rtl8225_write(dev, 0x9, 0x335); msleep(1);
+ rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
+ rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
+ rtl8225_write(dev, 0xc, 0x850); msleep(1);
+ rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
+ rtl8225_write(dev, 0xe, 0x02B); msleep(1);
+ rtl8225_write(dev, 0xf, 0x114); msleep(100);
+
+ if (!(rtl8225_read(dev, 6) & (1 << 7))) {
+ rtl8225_write(dev, 0x02, 0x0C4D);
+ msleep(200);
+ rtl8225_write(dev, 0x02, 0x044D);
+ msleep(100);
+ /* TODO: readd calibration failure message when the calibration
+ check works */
+ }
+
+ rtl8225_write(dev, 0x0, 0x1B7);
+ rtl8225_write(dev, 0x3, 0x002);
+ rtl8225_write(dev, 0x5, 0x004);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
+ }
+
+ rtl8225_write(dev, 0x0, 0x0B7); msleep(100);
+ rtl8225_write(dev, 0x2, 0xC4D);
+
+ msleep(200);
+ rtl8225_write(dev, 0x2, 0x44D);
+ msleep(100);
+
+ rtl8225_write(dev, 0x00, 0x2BF);
+ rtl8225_write(dev, 0xFF, 0xFFFF);
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+
+ for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
+ rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
+ msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
+ msleep(1);
+ }
+
+ msleep(1);
+
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+
+ rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x13, 0xd0);
+ rtl8225_write_phy_cck(dev, 0x19, 0x00);
+ rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
+ rtl8225_write_phy_cck(dev, 0x1b, 0x08);
+ rtl8225_write_phy_cck(dev, 0x40, 0x86);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+
+ rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1);
+
+ rtl8225z2_rf_set_tx_power(dev, 1);
+
+ /* RX antenna default to A */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+
+ rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
+ msleep(1);
+ rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+}
+
+static void rtl8225_rf_stop(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 reg;
+
+ rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
+ reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
+ rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+ rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
+ rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
+}
+
+static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ if (priv->rf->init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, conf->channel);
+ else
+ rtl8225z2_rf_set_tx_power(dev, conf->channel);
+
+ rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
+ msleep(10);
+
+ if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 81);
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
+ }
+}
+
+static const struct rtl818x_rf_ops rtl8225_ops = {
+ .name = "rtl8225",
+ .init = rtl8225_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+static const struct rtl818x_rf_ops rtl8225z2_ops = {
+ .name = "rtl8225z2",
+ .init = rtl8225z2_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u16 reg8, reg9;
+
+ rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488);
+ rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
+ rtl818x_ioread8(priv, &priv->map->EEPROM_CMD);
+ msleep(100);
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ reg8 = rtl8225_read(dev, 8);
+ reg9 = rtl8225_read(dev, 9);
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ if (reg8 != 0x588 || reg9 != 0x700)
+ return &rtl8225_ops;
+
+ return &rtl8225z2_ops;
+}
diff --git a/drivers/net/wireless/rtl8180_rtl8225.h b/drivers/net/wireless/rtl8180_rtl8225.h
new file mode 100644
index 000000000000..310013a2d726
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_rtl8225.h
@@ -0,0 +1,23 @@
+#ifndef RTL8180_RTL8225_H
+#define RTL8180_RTL8225_H
+
+#define RTL8225_ANAPARAM_ON 0xa0000b59
+#define RTL8225_ANAPARAM2_ON 0x860dec11
+#define RTL8225_ANAPARAM_OFF 0xa00beb59
+#define RTL8225_ANAPARAM2_OFF 0x840dec11
+
+const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *);
+
+static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
+ u8 addr, u8 data)
+{
+ rtl8180_write_phy(dev, addr, data);
+}
+
+static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev,
+ u8 addr, u8 data)
+{
+ rtl8180_write_phy(dev, addr, data | 0x10000);
+}
+
+#endif /* RTL8180_RTL8225_H */
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl8180_sa2400.c
new file mode 100644
index 000000000000..e08ace7b1cb7
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_sa2400.c
@@ -0,0 +1,201 @@
+
+/*
+ * Radio tuning for Philips SA2400 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <net/mac80211.h>
+
+#include "rtl8180.h"
+#include "rtl8180_sa2400.h"
+
+static const u32 sa2400_chan[] = {
+ 0x00096c, /* ch1 */
+ 0x080970,
+ 0x100974,
+ 0x180978,
+ 0x000980,
+ 0x080984,
+ 0x100988,
+ 0x18098c,
+ 0x000994,
+ 0x080998,
+ 0x10099c,
+ 0x1809a0,
+ 0x0009a8,
+ 0x0009b4, /* ch 14 */
+};
+
+static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 phy_config;
+
+ /* MAC will bang bits to the sa2400. sw 3-wire is NOT used */
+ phy_config = 0xb0000000;
+
+ phy_config |= ((u32)(addr & 0xf)) << 24;
+ phy_config |= data & 0xffffff;
+
+ rtl818x_iowrite32(priv,
+ (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config);
+
+ msleep(3);
+}
+
+static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u8 ant = SA2400_ANTENNA;
+
+ if (priv->rfparam & RF_PARAM_ANTBDEFAULT)
+ ant |= BB_ANTENNA_B;
+
+ if (chan == 14)
+ ant |= BB_ANTATTEN_CHAN14;
+
+ rtl8180_write_phy(dev, 0x10, ant);
+
+}
+
+static void sa2400_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 txpw = priv->channels[conf->channel - 1].val & 0xFF;
+ u32 chan = sa2400_chan[conf->channel - 1];
+
+ write_sa2400(dev, 7, txpw);
+
+ sa2400_write_phy_antenna(dev, chan);
+
+ write_sa2400(dev, 0, chan);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+}
+
+static void sa2400_rf_stop(struct ieee80211_hw *dev)
+{
+ write_sa2400(dev, 4, 0);
+}
+
+static void sa2400_rf_init(struct ieee80211_hw *dev)
+{
+ struct rtl8180_priv *priv = dev->priv;
+ u32 anaparam, txconf;
+ u8 firdac;
+ int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY;
+
+ anaparam = priv->anaparam;
+ anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT);
+ anaparam &= ~ANAPARAM_PWR1_MASK;
+ anaparam &= ~ANAPARAM_PWR0_MASK;
+
+ if (analogphy) {
+ anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT;
+ firdac = 0;
+ } else {
+ anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT);
+ anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT);
+ firdac = 1 << SA2400_REG4_FIRDAC_SHIFT;
+ }
+
+ rtl8180_set_anaparam(priv, anaparam);
+
+ write_sa2400(dev, 0, sa2400_chan[0]);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+ write_sa2400(dev, 4, 0x19340 | firdac);
+ write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15);
+ write_sa2400(dev, 4, 0x19348 | firdac); /* calibrate VCO */
+
+ if (!analogphy)
+ write_sa2400(dev, 4, 0x1938c); /*???*/
+
+ write_sa2400(dev, 4, 0x19340 | firdac);
+
+ write_sa2400(dev, 0, sa2400_chan[0]);
+ write_sa2400(dev, 1, 0xbb50);
+ write_sa2400(dev, 2, 0x80);
+ write_sa2400(dev, 3, 0);
+ write_sa2400(dev, 4, 0x19344 | firdac); /* calibrate filter */
+
+ /* new from rtl8180 embedded driver (rtl8181 project) */
+ write_sa2400(dev, 6, 0x13ff | (1 << 23)); /* MANRX */
+ write_sa2400(dev, 8, 0); /* VCO */
+
+ if (analogphy) {
+ rtl8180_set_anaparam(priv, anaparam |
+ (1 << ANAPARAM_TXDACOFF_SHIFT));
+
+ txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ txconf | RTL818X_TX_CONF_LOOPBACK_CONT);
+
+ write_sa2400(dev, 4, 0x19341); /* calibrates DC */
+
+ /* a 5us sleep is required here,
+ * we rely on the 3ms delay introduced in write_sa2400 */
+ write_sa2400(dev, 4, 0x19345);
+
+ /* a 20us sleep is required here,
+ * we rely on the 3ms delay introduced in write_sa2400 */
+
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf);
+
+ rtl8180_set_anaparam(priv, anaparam);
+ }
+ /* end new code */
+
+ write_sa2400(dev, 4, 0x19341 | firdac); /* RTX MODE */
+
+ /* baseband configuration */
+ rtl8180_write_phy(dev, 0, 0x98);
+ rtl8180_write_phy(dev, 3, 0x38);
+ rtl8180_write_phy(dev, 4, 0xe0);
+ rtl8180_write_phy(dev, 5, 0x90);
+ rtl8180_write_phy(dev, 6, 0x1a);
+ rtl8180_write_phy(dev, 7, 0x64);
+
+ sa2400_write_phy_antenna(dev, 1);
+
+ rtl8180_write_phy(dev, 0x11, 0x80);
+
+ if (rtl818x_ioread8(priv, &priv->map->CONFIG2) &
+ RTL818X_CONFIG2_ANTENNA_DIV)
+ rtl8180_write_phy(dev, 0x12, 0xc7); /* enable ant diversity */
+ else
+ rtl8180_write_phy(dev, 0x12, 0x47); /* disable ant diversity */
+
+ rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold);
+
+ rtl8180_write_phy(dev, 0x19, 0x0);
+ rtl8180_write_phy(dev, 0x1a, 0xa0);
+}
+
+const struct rtl818x_rf_ops sa2400_rf_ops = {
+ .name = "Philips",
+ .init = sa2400_rf_init,
+ .stop = sa2400_rf_stop,
+ .set_chan = sa2400_rf_set_channel
+};
diff --git a/drivers/net/wireless/rtl8180_sa2400.h b/drivers/net/wireless/rtl8180_sa2400.h
new file mode 100644
index 000000000000..a4aaa0d413f1
--- /dev/null
+++ b/drivers/net/wireless/rtl8180_sa2400.h
@@ -0,0 +1,36 @@
+#ifndef RTL8180_SA2400_H
+#define RTL8180_SA2400_H
+
+/*
+ * Radio tuning for Philips SA2400 on RTL8180
+ *
+ * Copyright 2007 Andrea Merello <andreamrl@tiscali.it>
+ *
+ * Code from the BSD driver and the rtl8181 project have been
+ * very useful to understand certain things
+ *
+ * I want to thanks the Authors of such projects and the Ndiswrapper
+ * project Authors.
+ *
+ * A special Big Thanks also is for all people who donated me cards,
+ * making possible the creation of the original rtl8180 driver
+ * from which this code is derived!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define SA2400_ANTENNA 0x91
+#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8
+#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28
+#define SA2400_ANAPARAM_PWR0_ON 0x3
+
+/* RX sensitivity in dbm */
+#define SA2400_MAX_SENS 85
+
+#define SA2400_REG4_FIRDAC_SHIFT 7
+
+extern const struct rtl818x_rf_ops sa2400_rf_ops;
+
+#endif /* RTL8180_SA2400_H */
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl8187.h
index 6ad322ef0da1..8680a0b6433c 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl8187.h
@@ -64,9 +64,9 @@ struct rtl8187_tx_hdr {
struct rtl8187_priv {
/* common between rtl818x drivers */
struct rtl818x_csr *map;
- void (*rf_init)(struct ieee80211_hw *);
+ const struct rtl818x_rf_ops *rf;
+ struct ieee80211_vif *vif;
int mode;
- int if_id;
/* rtl8187 specific */
struct ieee80211_channel channels[14];
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c
index bd1ab3b3afc0..0d71716d750d 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl8187_dev.c
@@ -150,7 +150,8 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
flags |= RTL8187_TX_FLAG_MORE_FRAG;
if (control->flags & IEEE80211_TXCTL_USE_RTS_CTS) {
flags |= RTL8187_TX_FLAG_RTS;
- rts_dur = ieee80211_rts_duration(dev, priv->if_id, skb->len, control);
+ rts_dur = ieee80211_rts_duration(dev, priv->vif,
+ skb->len, control);
}
if (control->flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
flags |= RTL8187_TX_FLAG_CTS;
@@ -227,6 +228,7 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.channel = dev->conf.channel;
rx_status.phymode = dev->conf.phymode;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
+ rx_status.flag |= RX_FLAG_TSFT;
if (flags & (1 << 13))
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
ieee80211_rx_irqsafe(dev, skb, &rx_status);
@@ -392,37 +394,19 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7);
msleep(100);
- priv->rf_init(dev);
+ priv->rf->init(dev);
rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3);
- reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & 0xfffe;
- rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 0x1);
+ reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1;
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1);
rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10);
rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80);
rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60);
- rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
return 0;
}
-static void rtl8187_set_channel(struct ieee80211_hw *dev, int channel)
-{
- u32 reg;
- struct rtl8187_priv *priv = dev->priv;
-
- reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
- /* Enable TX loopback on MAC level to avoid TX during channel
- * changes, as this has be seen to causes problems and the
- * card will stop work until next reset
- */
- rtl818x_iowrite32(priv, &priv->map->TX_CONF,
- reg | RTL818X_TX_CONF_LOOPBACK_MAC);
- msleep(10);
- rtl8225_rf_set_channel(dev, channel);
- msleep(10);
- rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
-}
-
static int rtl8187_start(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
@@ -491,7 +475,7 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
reg &= ~RTL818X_CMD_RX_ENABLE;
rtl818x_iowrite8(priv, &priv->map->CMD, reg);
- rtl8225_rf_stop(dev);
+ priv->rf->stop(dev);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG4);
@@ -542,7 +526,19 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
- rtl8187_set_channel(dev, conf->channel);
+ u32 reg;
+
+ reg = rtl818x_ioread32(priv, &priv->map->TX_CONF);
+ /* Enable TX loopback on MAC level to avoid TX during channel
+ * changes, as this has be seen to causes problems and the
+ * card will stop work until next reset
+ */
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF,
+ reg | RTL818X_TX_CONF_LOOPBACK_MAC);
+ msleep(10);
+ priv->rf->set_chan(dev, conf);
+ msleep(10);
+ rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
@@ -565,14 +561,13 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
return 0;
}
-static int rtl8187_config_interface(struct ieee80211_hw *dev, int if_id,
+static int rtl8187_config_interface(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
int i;
- priv->if_id = if_id;
-
for (i = 0; i < ETH_ALEN; i++)
rtl818x_iowrite8(priv, &priv->map->BSSID[i], conf->bssid[i]);
@@ -752,23 +747,16 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE,
&priv->txpwr_base);
- reg = rtl818x_ioread16(priv, &priv->map->PGSELECT) & ~1;
- rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg | 1);
+ reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1;
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1);
/* 0 means asic B-cut, we should use SW 3 wire
* bit-by-bit banging for radio. 1 means we can use
* USB specific request to write radio registers */
priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3;
- rtl818x_iowrite16(priv, &priv->map->PGSELECT, reg);
+ rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
- rtl8225_write(dev, 0, 0x1B7);
-
- if (rtl8225_read(dev, 8) != 0x588 || rtl8225_read(dev, 9) != 0x700)
- priv->rf_init = rtl8225_rf_init;
- else
- priv->rf_init = rtl8225z2_rf_init;
-
- rtl8225_write(dev, 0, 0x0B7);
+ priv->rf = rtl8187_detect_rf(dev);
err = ieee80211_register_hw(dev);
if (err) {
@@ -778,8 +766,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
printk(KERN_INFO "%s: hwaddr %s, rtl8187 V%d + %s\n",
wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
- priv->asic_rev, priv->rf_init == rtl8225_rf_init ?
- "rtl8225" : "rtl8225z2");
+ priv->asic_rev, priv->rf->name);
return 0;
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl8187_rtl8225.c
index efc41207780e..b713de17ba0a 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl8187_rtl8225.c
@@ -101,7 +101,7 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
msleep(2);
}
-void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
+static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
{
struct rtl8187_priv *priv = dev->priv;
@@ -111,7 +111,7 @@ void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
rtl8225_write_bitbang(dev, addr, data);
}
-u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
+static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
{
struct rtl8187_priv *priv = dev->priv;
u16 reg80, reg82, reg84, out;
@@ -325,7 +325,7 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
msleep(1);
}
-void rtl8225_rf_init(struct ieee80211_hw *dev)
+static void rtl8225_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
@@ -567,7 +567,7 @@ static const u8 rtl8225z2_gain_bg[] = {
0x63, 0x15, 0xc5 /* -66dBm */
};
-void rtl8225z2_rf_init(struct ieee80211_hw *dev)
+static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
int i;
@@ -715,7 +715,7 @@ void rtl8225z2_rf_init(struct ieee80211_hw *dev)
rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
}
-void rtl8225_rf_stop(struct ieee80211_hw *dev)
+static void rtl8225_rf_stop(struct ieee80211_hw *dev)
{
u8 reg;
struct rtl8187_priv *priv = dev->priv;
@@ -731,15 +731,47 @@ void rtl8225_rf_stop(struct ieee80211_hw *dev)
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
}
-void rtl8225_rf_set_channel(struct ieee80211_hw *dev, int channel)
+static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
+ struct ieee80211_conf *conf)
{
struct rtl8187_priv *priv = dev->priv;
- if (priv->rf_init == rtl8225_rf_init)
- rtl8225_rf_set_tx_power(dev, channel);
+ if (priv->rf->init == rtl8225_rf_init)
+ rtl8225_rf_set_tx_power(dev, conf->channel);
else
- rtl8225z2_rf_set_tx_power(dev, channel);
+ rtl8225z2_rf_set_tx_power(dev, conf->channel);
- rtl8225_write(dev, 0x7, rtl8225_chan[channel - 1]);
+ rtl8225_write(dev, 0x7, rtl8225_chan[conf->channel - 1]);
msleep(10);
}
+
+static const struct rtl818x_rf_ops rtl8225_ops = {
+ .name = "rtl8225",
+ .init = rtl8225_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+static const struct rtl818x_rf_ops rtl8225z2_ops = {
+ .name = "rtl8225z2",
+ .init = rtl8225z2_rf_init,
+ .stop = rtl8225_rf_stop,
+ .set_chan = rtl8225_rf_set_channel
+};
+
+const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
+{
+ u16 reg8, reg9;
+
+ rtl8225_write(dev, 0, 0x1B7);
+
+ reg8 = rtl8225_read(dev, 8);
+ reg9 = rtl8225_read(dev, 9);
+
+ rtl8225_write(dev, 0, 0x0B7);
+
+ if (reg8 != 0x588 || reg9 != 0x700)
+ return &rtl8225_ops;
+
+ return &rtl8225z2_ops;
+}
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl8187_rtl8225.h
index 798ba4a97376..d39ed0295b6e 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.h
+++ b/drivers/net/wireless/rtl8187_rtl8225.h
@@ -20,14 +20,7 @@
#define RTL8225_ANAPARAM_OFF 0xa00beb59
#define RTL8225_ANAPARAM2_OFF 0x840dec11
-void rtl8225_write(struct ieee80211_hw *, u8 addr, u16 data);
-u16 rtl8225_read(struct ieee80211_hw *, u8 addr);
-
-void rtl8225_rf_init(struct ieee80211_hw *);
-void rtl8225z2_rf_init(struct ieee80211_hw *);
-void rtl8225_rf_stop(struct ieee80211_hw *);
-void rtl8225_rf_set_channel(struct ieee80211_hw *, int);
-
+const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *);
static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev,
u8 addr, u32 data)
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x.h
index 880d4becae31..1e7d6f8278d7 100644
--- a/drivers/net/wireless/rtl818x.h
+++ b/drivers/net/wireless/rtl818x.h
@@ -58,13 +58,17 @@ struct rtl818x_csr {
#define RTL818X_INT_TX_FO (1 << 15)
__le32 TX_CONF;
#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17)
+#define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17)
#define RTL818X_TX_CONF_NO_ICV (1 << 19)
#define RTL818X_TX_CONF_DISCW (1 << 20)
+#define RTL818X_TX_CONF_SAT_HWPLCP (1 << 24)
#define RTL818X_TX_CONF_R8180_ABCD (2 << 25)
#define RTL818X_TX_CONF_R8180_F (3 << 25)
#define RTL818X_TX_CONF_R8185_ABC (4 << 25)
#define RTL818X_TX_CONF_R8185_D (5 << 25)
#define RTL818X_TX_CONF_HWVER_MASK (7 << 25)
+#define RTL818X_TX_CONF_PROBE_DTS (1 << 29)
+#define RTL818X_TX_CONF_HW_SEQNUM (1 << 30)
#define RTL818X_TX_CONF_CW_MIN (1 << 31)
__le32 RX_CONF;
#define RTL818X_RX_CONF_MONITOR (1 << 0)
@@ -75,8 +79,12 @@ struct rtl818x_csr {
#define RTL818X_RX_CONF_DATA (1 << 18)
#define RTL818X_RX_CONF_CTRL (1 << 19)
#define RTL818X_RX_CONF_MGMT (1 << 20)
+#define RTL818X_RX_CONF_ADDR3 (1 << 21)
+#define RTL818X_RX_CONF_PM (1 << 22)
#define RTL818X_RX_CONF_BSSID (1 << 23)
#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28)
+#define RTL818X_RX_CONF_CSDM1 (1 << 29)
+#define RTL818X_RX_CONF_CSDM2 (1 << 30)
#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31)
__le32 INT_TIMEOUT;
__le32 TBDA;
@@ -92,6 +100,7 @@ struct rtl818x_csr {
u8 CONFIG0;
u8 CONFIG1;
u8 CONFIG2;
+#define RTL818X_CONFIG2_ANTENNA_DIV (1 << 6)
__le32 ANAPARAM;
u8 MSR;
#define RTL818X_MSR_NO_LINK (0 << 2)
@@ -104,14 +113,17 @@ struct rtl818x_csr {
#define RTL818X_CONFIG4_VCOOFF (1 << 7)
u8 TESTR;
u8 reserved_9[2];
- __le16 PGSELECT;
+ u8 PGSELECT;
+ u8 SECURITY;
__le32 ANAPARAM2;
u8 reserved_10[12];
__le16 BEACON_INTERVAL;
__le16 ATIM_WND;
__le16 BEACON_INTERVAL_TIME;
__le16 ATIMTR_INTERVAL;
- u8 reserved_11[4];
+ u8 PHY_DELAY;
+ u8 CARRIER_SENSE_COUNTER;
+ u8 reserved_11[2];
u8 PHY[4];
__le16 RFPinsOutput;
__le16 RFPinsEnable;
@@ -149,11 +161,20 @@ struct rtl818x_csr {
u8 RETRY_CTR;
u8 reserved_18[5];
__le32 RDSAR;
- u8 reserved_19[18];
- u16 TALLY_CNT;
+ u8 reserved_19[12];
+ __le16 FEMR;
+ u8 reserved_20[4];
+ __le16 TALLY_CNT;
u8 TALLY_SEL;
} __attribute__((packed));
+struct rtl818x_rf_ops {
+ char *name;
+ void (*init)(struct ieee80211_hw *);
+ void (*stop)(struct ieee80211_hw *);
+ void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+};
+
static const struct ieee80211_rate rtl818x_rates[] = {
{ .rate = 10,
.val = 0,
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index a1f8a1687842..03384a43186b 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -49,27 +49,6 @@ static int __init wv_psa_to_irq(u8 irqval)
return -1;
}
-#ifdef STRUCT_CHECK
-/*------------------------------------------------------------------*/
-/*
- * Sanity routine to verify the sizes of the various WaveLAN interface
- * structures.
- */
-static char *wv_struct_check(void)
-{
-#define SC(t,s,n) if (sizeof(t) != s) return(n);
-
- SC(psa_t, PSA_SIZE, "psa_t");
- SC(mmw_t, MMW_SIZE, "mmw_t");
- SC(mmr_t, MMR_SIZE, "mmr_t");
- SC(ha_t, HA_SIZE, "ha_t");
-
-#undef SC
-
- return ((char *) NULL);
-} /* wv_struct_check */
-#endif /* STRUCT_CHECK */
-
/********************* HOST ADAPTER SUBROUTINES *********************/
/*
* Useful subroutines to manage the WaveLAN ISA interface
@@ -3740,7 +3719,7 @@ static int wv_check_ioaddr(unsigned long ioaddr, u8 * mac)
* non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on
* how to configure your card.
*/
- for (i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
+ for (i = 0; i < ARRAY_SIZE(MAC_ADDRESSES); i++)
if ((mac[0] == MAC_ADDRESSES[i][0]) &&
(mac[1] == MAC_ADDRESSES[i][1]) &&
(mac[2] == MAC_ADDRESSES[i][2]))
@@ -4215,14 +4194,11 @@ struct net_device * __init wavelan_probe(int unit)
int i;
int r = 0;
-#ifdef STRUCT_CHECK
- if (wv_struct_check() != (char *) NULL) {
- printk(KERN_WARNING
- "%s: wavelan_probe(): structure/compiler botch: \"%s\"\n",
- dev->name, wv_struct_check());
- return -ENODEV;
- }
-#endif /* STRUCT_CHECK */
+ /* compile-time check the sizes of structures */
+ BUILD_BUG_ON(sizeof(psa_t) != PSA_SIZE);
+ BUILD_BUG_ON(sizeof(mmw_t) != MMW_SIZE);
+ BUILD_BUG_ON(sizeof(mmr_t) != MMR_SIZE);
+ BUILD_BUG_ON(sizeof(ha_t) != HA_SIZE);
dev = alloc_etherdev(sizeof(net_local));
if (!dev)
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index fe242812d858..b33ac47dd8df 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -400,7 +400,6 @@
*/
#undef SET_PSA_CRC /* Calculate and set the CRC on PSA (slower) */
#define USE_PSA_CONFIG /* Use info from the PSA. */
-#undef STRUCT_CHECK /* Verify padding of structures. */
#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */
#undef SET_MAC_ADDRESS /* Experimental */
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 577c647824fe..c2037b2a05bf 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -71,27 +71,6 @@ static void wv_nwid_filter(unsigned char mode, net_local *lp);
* (wavelan modem or i82593)
*/
-#ifdef STRUCT_CHECK
-/*------------------------------------------------------------------*/
-/*
- * Sanity routine to verify the sizes of the various WaveLAN interface
- * structures.
- */
-static char *
-wv_structuct_check(void)
-{
-#define SC(t,s,n) if (sizeof(t) != s) return(n);
-
- SC(psa_t, PSA_SIZE, "psa_t");
- SC(mmw_t, MMW_SIZE, "mmw_t");
- SC(mmr_t, MMR_SIZE, "mmr_t");
-
-#undef SC
-
- return((char *) NULL);
-} /* wv_structuct_check */
-#endif /* STRUCT_CHECK */
-
/******************* MODEM MANAGEMENT SUBROUTINES *******************/
/*
* Useful subroutines to manage the modem of the wavelan
@@ -3223,14 +3202,14 @@ wv_mmc_init(struct net_device * dev)
* non-NCR/AT&T/Lucent PCMCIA cards, see wavelan_cs.h for detail on
* how to configure your card...
*/
- for(i = 0; i < (sizeof(MAC_ADDRESSES) / sizeof(char) / 3); i++)
- if((psa.psa_univ_mac_addr[0] == MAC_ADDRESSES[i][0]) &&
- (psa.psa_univ_mac_addr[1] == MAC_ADDRESSES[i][1]) &&
- (psa.psa_univ_mac_addr[2] == MAC_ADDRESSES[i][2]))
+ for (i = 0; i < ARRAY_SIZE(MAC_ADDRESSES); i++)
+ if ((psa.psa_univ_mac_addr[0] == MAC_ADDRESSES[i][0]) &&
+ (psa.psa_univ_mac_addr[1] == MAC_ADDRESSES[i][1]) &&
+ (psa.psa_univ_mac_addr[2] == MAC_ADDRESSES[i][2]))
break;
/* If we have not found it... */
- if(i == (sizeof(MAC_ADDRESSES) / sizeof(char) / 3))
+ if (i == ARRAY_SIZE(MAC_ADDRESSES))
{
#ifdef DEBUG_CONFIG_ERRORS
printk(KERN_WARNING "%s: wv_mmc_init(): Invalid MAC address: %02X:%02X:%02X:...\n",
@@ -3794,14 +3773,10 @@ wv_hw_config(struct net_device * dev)
printk(KERN_DEBUG "%s: ->wv_hw_config()\n", dev->name);
#endif
-#ifdef STRUCT_CHECK
- if(wv_structuct_check() != (char *) NULL)
- {
- printk(KERN_WARNING "%s: wv_hw_config: structure/compiler botch: \"%s\"\n",
- dev->name, wv_structuct_check());
- return FALSE;
- }
-#endif /* STRUCT_CHECK == 1 */
+ /* compile-time check the sizes of structures */
+ BUILD_BUG_ON(sizeof(psa_t) != PSA_SIZE);
+ BUILD_BUG_ON(sizeof(mmw_t) != MMW_SIZE);
+ BUILD_BUG_ON(sizeof(mmr_t) != MMR_SIZE);
/* Reset the pcmcia interface */
if(wv_pcmcia_reset(dev) == FALSE)
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 4b9de0093a7b..33dd97094227 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -459,7 +459,6 @@
#undef WAVELAN_ROAMING_EXT /* Enable roaming wireless extensions */
#undef SET_PSA_CRC /* Set the CRC in PSA (slower) */
#define USE_PSA_CONFIG /* Use info from the PSA */
-#undef STRUCT_CHECK /* Verify padding of structures */
#undef EEPROM_IS_PROTECTED /* Doesn't seem to be necessary */
#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical) */
#undef SET_MAC_ADDRESS /* Experimental */
@@ -548,7 +547,7 @@ typedef struct wavepoint_beacon
spec_id2, /* Unused */
pdu_type, /* Unused */
seq; /* WavePoint beacon sequence number */
- unsigned short domain_id, /* WavePoint Domain ID */
+ __be16 domain_id, /* WavePoint Domain ID */
nwid; /* WavePoint NWID */
} wavepoint_beacon;
diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig
index d1ab24a95630..74b31eafe72d 100644
--- a/drivers/net/wireless/zd1211rw/Kconfig
+++ b/drivers/net/wireless/zd1211rw/Kconfig
@@ -1,14 +1,13 @@
config ZD1211RW
tristate "ZyDAS ZD1211/ZD1211B USB-wireless support"
- depends on USB && IEEE80211_SOFTMAC && WLAN_80211 && EXPERIMENTAL
- select WIRELESS_EXT
+ depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
---help---
This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless
chip, present in many USB-wireless adapters.
- Device firmware is required alongside this driver. You can download the
- firmware distribution from http://zd1211.ath.cx/get-firmware
+ Device firmware is required alongside this driver. You can download
+ the firmware distribution from http://zd1211.ath.cx/get-firmware
config ZD1211RW_DEBUG
bool "ZyDAS ZD1211 debugging"
diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile
index 7a2f2a98edab..cc36126cee88 100644
--- a/drivers/net/wireless/zd1211rw/Makefile
+++ b/drivers/net/wireless/zd1211rw/Makefile
@@ -1,7 +1,6 @@
obj-$(CONFIG_ZD1211RW) += zd1211rw.o
-zd1211rw-objs := zd_chip.o zd_ieee80211.o \
- zd_mac.o zd_netdev.o \
+zd1211rw-objs := zd_chip.o zd_ieee80211.o zd_mac.o \
zd_rf_al2230.o zd_rf_rf2959.o \
zd_rf_al7230b.o zd_rf_uw2453.o \
zd_rf.o zd_usb.o
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index f831b68f1b9c..99e5b03b3f51 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1,4 +1,7 @@
-/* zd_chip.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -30,12 +33,12 @@
#include "zd_rf.h"
void zd_chip_init(struct zd_chip *chip,
- struct net_device *netdev,
+ struct ieee80211_hw *hw,
struct usb_interface *intf)
{
memset(chip, 0, sizeof(*chip));
mutex_init(&chip->mutex);
- zd_usb_init(&chip->usb, netdev, intf);
+ zd_usb_init(&chip->usb, hw, intf);
zd_rf_init(&chip->rf);
}
@@ -50,7 +53,7 @@ void zd_chip_clear(struct zd_chip *chip)
static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size)
{
- u8 *addr = zd_usb_to_netdev(&chip->usb)->dev_addr;
+ u8 *addr = zd_mac_get_perm_addr(zd_chip_to_mac(chip));
return scnprintf(buffer, size, "%02x-%02x-%02x",
addr[0], addr[1], addr[2]);
}
@@ -378,15 +381,18 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
};
DECLARE_MAC_BUF(mac);
- reqs[0].value = (mac_addr[3] << 24)
- | (mac_addr[2] << 16)
- | (mac_addr[1] << 8)
- | mac_addr[0];
- reqs[1].value = (mac_addr[5] << 8)
- | mac_addr[4];
-
- dev_dbg_f(zd_chip_dev(chip),
- "mac addr %s\n", print_mac(mac, mac_addr));
+ if (mac_addr) {
+ reqs[0].value = (mac_addr[3] << 24)
+ | (mac_addr[2] << 16)
+ | (mac_addr[1] << 8)
+ | mac_addr[0];
+ reqs[1].value = (mac_addr[5] << 8)
+ | mac_addr[4];
+ dev_dbg_f(zd_chip_dev(chip),
+ "mac addr %s\n", print_mac(mac, mac_addr));
+ } else {
+ dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
+ }
mutex_lock(&chip->mutex);
r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
@@ -980,7 +986,7 @@ static int print_fw_version(struct zd_chip *chip)
return 0;
}
-static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
+static int set_mandatory_rates(struct zd_chip *chip, int mode)
{
u32 rates;
ZD_ASSERT(mutex_is_locked(&chip->mutex));
@@ -988,11 +994,11 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
* that the device is supporting. Until further notice we should try
* to support 802.11g also for full speed USB.
*/
- switch (std) {
- case IEEE80211B:
+ switch (mode) {
+ case MODE_IEEE80211B:
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M;
break;
- case IEEE80211G:
+ case MODE_IEEE80211G:
rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M|
CR_RATE_6M|CR_RATE_12M|CR_RATE_24M;
break;
@@ -1003,24 +1009,17 @@ static int set_mandatory_rates(struct zd_chip *chip, enum ieee80211_std std)
}
int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
- u8 rts_rate, int preamble)
+ int preamble)
{
- int rts_mod = ZD_RX_CCK;
u32 value = 0;
- /* Modulation bit */
- if (ZD_MODULATION_TYPE(rts_rate) == ZD_OFDM)
- rts_mod = ZD_RX_OFDM;
-
- dev_dbg_f(zd_chip_dev(chip), "rts_rate=%x preamble=%x\n",
- rts_rate, preamble);
-
- value |= ZD_PURE_RATE(rts_rate) << RTSCTS_SH_RTS_RATE;
- value |= rts_mod << RTSCTS_SH_RTS_MOD_TYPE;
+ dev_dbg_f(zd_chip_dev(chip), "preamble=%x\n", preamble);
value |= preamble << RTSCTS_SH_RTS_PMB_TYPE;
value |= preamble << RTSCTS_SH_CTS_PMB_TYPE;
- /* We always send 11M self-CTS messages, like the vendor driver. */
+ /* We always send 11M RTS/self-CTS messages, like the vendor driver. */
+ value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_RTS_RATE;
+ value |= ZD_RX_CCK << RTSCTS_SH_RTS_MOD_TYPE;
value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE;
value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE;
@@ -1109,7 +1108,7 @@ int zd_chip_init_hw(struct zd_chip *chip)
* It might be discussed, whether we should suppport pure b mode for
* full speed USB.
*/
- r = set_mandatory_rates(chip, IEEE80211G);
+ r = set_mandatory_rates(chip, MODE_IEEE80211G);
if (r)
goto out;
/* Disabling interrupts is certainly a smart thing here.
@@ -1320,12 +1319,17 @@ out:
return r;
}
-int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates)
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
{
- ZD_ASSERT((cr_rates & ~(CR_RATES_80211B | CR_RATES_80211G)) == 0);
- dev_dbg_f(zd_chip_dev(chip), "%x\n", cr_rates);
+ int r;
+
+ if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G))
+ return -EINVAL;
- return zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
+ mutex_lock(&chip->mutex);
+ r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL);
+ mutex_unlock(&chip->mutex);
+ return r;
}
static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size)
@@ -1468,56 +1472,44 @@ u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
{
return (status->frame_status&ZD_RX_OFDM) ?
ofdm_qual_percent(status->signal_quality_ofdm,
- zd_rate_from_ofdm_plcp_header(rx_frame),
+ zd_rate_from_ofdm_plcp_header(rx_frame),
size) :
cck_qual_percent(status->signal_quality_cck);
}
-u8 zd_rx_strength_percent(u8 rssi)
-{
- int r = (rssi*100) / 41;
- if (r > 100)
- r = 100;
- return (u8) r;
-}
-
-u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
+/**
+ * zd_rx_rate - report zd-rate
+ * @rx_frame - received frame
+ * @rx_status - rx_status as given by the device
+ *
+ * This function converts the rate as encoded in the received packet to the
+ * zd-rate, we are using on other places in the driver.
+ */
+u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status)
{
- static const u16 ofdm_rates[] = {
- [ZD_OFDM_PLCP_RATE_6M] = 60,
- [ZD_OFDM_PLCP_RATE_9M] = 90,
- [ZD_OFDM_PLCP_RATE_12M] = 120,
- [ZD_OFDM_PLCP_RATE_18M] = 180,
- [ZD_OFDM_PLCP_RATE_24M] = 240,
- [ZD_OFDM_PLCP_RATE_36M] = 360,
- [ZD_OFDM_PLCP_RATE_48M] = 480,
- [ZD_OFDM_PLCP_RATE_54M] = 540,
- };
- u16 rate;
+ u8 zd_rate;
if (status->frame_status & ZD_RX_OFDM) {
- /* Deals with PLCP OFDM rate (not zd_rates) */
- u8 ofdm_rate = zd_ofdm_plcp_header_rate(rx_frame);
- rate = ofdm_rates[ofdm_rate & 0xf];
+ zd_rate = zd_rate_from_ofdm_plcp_header(rx_frame);
} else {
switch (zd_cck_plcp_header_signal(rx_frame)) {
case ZD_CCK_PLCP_SIGNAL_1M:
- rate = 10;
+ zd_rate = ZD_CCK_RATE_1M;
break;
case ZD_CCK_PLCP_SIGNAL_2M:
- rate = 20;
+ zd_rate = ZD_CCK_RATE_2M;
break;
case ZD_CCK_PLCP_SIGNAL_5M5:
- rate = 55;
+ zd_rate = ZD_CCK_RATE_5_5M;
break;
case ZD_CCK_PLCP_SIGNAL_11M:
- rate = 110;
+ zd_rate = ZD_CCK_RATE_11M;
break;
default:
- rate = 0;
+ zd_rate = 0;
}
}
- return rate;
+ return zd_rate;
}
int zd_chip_switch_radio_on(struct zd_chip *chip)
@@ -1557,20 +1549,22 @@ void zd_chip_disable_int(struct zd_chip *chip)
mutex_unlock(&chip->mutex);
}
-int zd_chip_enable_rx(struct zd_chip *chip)
+int zd_chip_enable_rxtx(struct zd_chip *chip)
{
int r;
mutex_lock(&chip->mutex);
+ zd_usb_enable_tx(&chip->usb);
r = zd_usb_enable_rx(&chip->usb);
mutex_unlock(&chip->mutex);
return r;
}
-void zd_chip_disable_rx(struct zd_chip *chip)
+void zd_chip_disable_rxtx(struct zd_chip *chip)
{
mutex_lock(&chip->mutex);
zd_usb_disable_rx(&chip->usb);
+ zd_usb_disable_tx(&chip->usb);
mutex_unlock(&chip->mutex);
}
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index 8009b70213e2..009c03777a35 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -1,4 +1,7 @@
-/* zd_chip.h
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -433,9 +436,10 @@ enum {
#define CR_GROUP_HASH_P2 CTL_REG(0x0628)
#define CR_RX_TIMEOUT CTL_REG(0x062C)
+
/* Basic rates supported by the BSS. When producing ACK or CTS messages, the
* device will use a rate in this table that is less than or equal to the rate
- * of the incoming frame which prompted the response */
+ * of the incoming frame which prompted the response. */
#define CR_BASIC_RATE_TBL CTL_REG(0x0630)
#define CR_RATE_1M (1 << 0) /* 802.11b */
#define CR_RATE_2M (1 << 1) /* 802.11b */
@@ -509,14 +513,37 @@ enum {
#define CR_UNDERRUN_CNT CTL_REG(0x0688)
#define CR_RX_FILTER CTL_REG(0x068c)
+#define RX_FILTER_ASSOC_REQUEST (1 << 0)
#define RX_FILTER_ASSOC_RESPONSE (1 << 1)
+#define RX_FILTER_REASSOC_REQUEST (1 << 2)
#define RX_FILTER_REASSOC_RESPONSE (1 << 3)
+#define RX_FILTER_PROBE_REQUEST (1 << 4)
#define RX_FILTER_PROBE_RESPONSE (1 << 5)
+/* bits 6 and 7 reserved */
#define RX_FILTER_BEACON (1 << 8)
+#define RX_FILTER_ATIM (1 << 9)
#define RX_FILTER_DISASSOC (1 << 10)
#define RX_FILTER_AUTH (1 << 11)
-#define AP_RX_FILTER 0x0400feff
-#define STA_RX_FILTER 0x0000ffff
+#define RX_FILTER_DEAUTH (1 << 12)
+#define RX_FILTER_PSPOLL (1 << 26)
+#define RX_FILTER_RTS (1 << 27)
+#define RX_FILTER_CTS (1 << 28)
+#define RX_FILTER_ACK (1 << 29)
+#define RX_FILTER_CFEND (1 << 30)
+#define RX_FILTER_CFACK (1 << 31)
+
+/* Enable bits for all frames you are interested in. */
+#define STA_RX_FILTER (RX_FILTER_ASSOC_REQUEST | RX_FILTER_ASSOC_RESPONSE | \
+ RX_FILTER_REASSOC_REQUEST | RX_FILTER_REASSOC_RESPONSE | \
+ RX_FILTER_PROBE_REQUEST | RX_FILTER_PROBE_RESPONSE | \
+ (0x3 << 6) /* vendor driver sets these reserved bits */ | \
+ RX_FILTER_BEACON | RX_FILTER_ATIM | RX_FILTER_DISASSOC | \
+ RX_FILTER_AUTH | RX_FILTER_DEAUTH | \
+ (0x7 << 13) /* vendor driver sets these reserved bits */ | \
+ RX_FILTER_PSPOLL | RX_FILTER_ACK) /* 0x2400ffff */
+
+#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
+ RX_FILTER_CFEND | RX_FILTER_CFACK)
/* Monitor mode sets filter to 0xfffff */
@@ -730,7 +757,7 @@ static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf)
#define zd_chip_dev(chip) (&(chip)->usb.intf->dev)
void zd_chip_init(struct zd_chip *chip,
- struct net_device *netdev,
+ struct ieee80211_hw *hw,
struct usb_interface *intf);
void zd_chip_clear(struct zd_chip *chip);
int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr);
@@ -835,14 +862,12 @@ int zd_chip_switch_radio_on(struct zd_chip *chip);
int zd_chip_switch_radio_off(struct zd_chip *chip);
int zd_chip_enable_int(struct zd_chip *chip);
void zd_chip_disable_int(struct zd_chip *chip);
-int zd_chip_enable_rx(struct zd_chip *chip);
-void zd_chip_disable_rx(struct zd_chip *chip);
+int zd_chip_enable_rxtx(struct zd_chip *chip);
+void zd_chip_disable_rxtx(struct zd_chip *chip);
int zd_chip_enable_hwint(struct zd_chip *chip);
int zd_chip_disable_hwint(struct zd_chip *chip);
int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel);
-
-int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip,
- u8 rts_rate, int preamble);
+int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, int preamble);
static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type)
{
@@ -859,17 +884,7 @@ static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates)
return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates);
}
-int zd_chip_set_basic_rates_locked(struct zd_chip *chip, u16 cr_rates);
-
-static inline int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates)
-{
- int r;
-
- mutex_lock(&chip->mutex);
- r = zd_chip_set_basic_rates_locked(chip, cr_rates);
- mutex_unlock(&chip->mutex);
- return r;
-}
+int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates);
int zd_chip_lock_phy_regs(struct zd_chip *chip);
int zd_chip_unlock_phy_regs(struct zd_chip *chip);
@@ -893,9 +908,8 @@ struct rx_status;
u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size,
const struct rx_status *status);
-u8 zd_rx_strength_percent(u8 rssi);
-u16 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
+u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status);
struct zd_mc_hash {
u32 low;
diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h
index 505b4d7dd0e2..5200db405610 100644
--- a/drivers/net/wireless/zd1211rw/zd_def.h
+++ b/drivers/net/wireless/zd1211rw/zd_def.h
@@ -1,4 +1,7 @@
-/* zd_def.h
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.c b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
index 189160efd2ae..7c277ec43f79 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.c
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.c
@@ -1,4 +1,7 @@
-/* zd_ieee80211.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -16,178 +19,85 @@
*/
/*
- * A lot of this code is generic and should be moved into the upper layers
- * at some point.
+ * In the long term, we'll probably find a better way of handling regulatory
+ * requirements outside of the driver.
*/
-#include <linux/errno.h>
-#include <linux/wireless.h>
#include <linux/kernel.h>
-#include <net/ieee80211.h>
+#include <net/mac80211.h>
-#include "zd_def.h"
#include "zd_ieee80211.h"
#include "zd_mac.h"
+struct channel_range {
+ u8 regdomain;
+ u8 start;
+ u8 end; /* exclusive (channel must be less than end) */
+};
+
static const struct channel_range channel_ranges[] = {
- [0] = { 0, 0},
- [ZD_REGDOMAIN_FCC] = { 1, 12},
- [ZD_REGDOMAIN_IC] = { 1, 12},
- [ZD_REGDOMAIN_ETSI] = { 1, 14},
- [ZD_REGDOMAIN_JAPAN] = { 1, 14},
- [ZD_REGDOMAIN_SPAIN] = { 1, 14},
- [ZD_REGDOMAIN_FRANCE] = { 1, 14},
+ { ZD_REGDOMAIN_FCC, 1, 12 },
+ { ZD_REGDOMAIN_IC, 1, 12 },
+ { ZD_REGDOMAIN_ETSI, 1, 14 },
+ { ZD_REGDOMAIN_JAPAN, 1, 14 },
+ { ZD_REGDOMAIN_SPAIN, 1, 14 },
+ { ZD_REGDOMAIN_FRANCE, 1, 14 },
/* Japan originally only had channel 14 available (see CHNL_ID 0x40 in
* 802.11). However, in 2001 the range was extended to include channels
* 1-13. The ZyDAS devices still use the old region code but are
* designed to allow the extra channel access in Japan. */
- [ZD_REGDOMAIN_JAPAN_ADD] = { 1, 15},
+ { ZD_REGDOMAIN_JAPAN_ADD, 1, 15 },
};
-const struct channel_range *zd_channel_range(u8 regdomain)
-{
- if (regdomain >= ARRAY_SIZE(channel_ranges))
- regdomain = 0;
- return &channel_ranges[regdomain];
-}
-
-int zd_regdomain_supports_channel(u8 regdomain, u8 channel)
-{
- const struct channel_range *range = zd_channel_range(regdomain);
- return range->start <= channel && channel < range->end;
-}
-
-int zd_regdomain_supported(u8 regdomain)
-{
- const struct channel_range *range = zd_channel_range(regdomain);
- return range->start != 0;
-}
-
-/* Stores channel frequencies in MHz. */
-static const u16 channel_frequencies[] = {
- 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467, 2472, 2484,
-};
-
-#define NUM_CHANNELS ARRAY_SIZE(channel_frequencies)
-
-static int compute_freq(struct iw_freq *freq, u32 mhz, u32 hz)
-{
- u32 factor;
-
- freq->e = 0;
- if (mhz >= 1000000000U) {
- pr_debug("zd1211 mhz %u to large\n", mhz);
- freq->m = 0;
- return -EINVAL;
- }
-
- factor = 1000;
- while (mhz >= factor) {
-
- freq->e += 1;
- factor *= 10;
- }
-
- factor /= 1000U;
- freq->m = mhz * (1000000U/factor) + hz/factor;
-
- return 0;
-}
-
-int zd_channel_to_freq(struct iw_freq *freq, u8 channel)
+static const struct channel_range *zd_channel_range(u8 regdomain)
{
- if (channel > NUM_CHANNELS) {
- freq->m = 0;
- freq->e = 0;
- return -EINVAL;
- }
- if (!channel) {
- freq->m = 0;
- freq->e = 0;
- return -EINVAL;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) {
+ const struct channel_range *range = &channel_ranges[i];
+ if (range->regdomain == regdomain)
+ return range;
}
- return compute_freq(freq, channel_frequencies[channel-1], 0);
+ return NULL;
}
-static int freq_to_mhz(const struct iw_freq *freq)
-{
- u32 factor;
- int e;
-
- /* Such high frequencies are not supported. */
- if (freq->e > 6)
- return -EINVAL;
-
- factor = 1;
- for (e = freq->e; e > 0; --e) {
- factor *= 10;
- }
- factor = 1000000U / factor;
-
- if (freq->m % factor) {
- return -EINVAL;
- }
-
- return freq->m / factor;
-}
+#define CHAN_TO_IDX(chan) ((chan) - 1)
-int zd_find_channel(u8 *channel, const struct iw_freq *freq)
+static void unmask_bg_channels(struct ieee80211_hw *hw,
+ const struct channel_range *range,
+ struct ieee80211_hw_mode *mode)
{
- int i, r;
- u32 mhz;
-
- if (freq->m < 1000) {
- if (freq->m > NUM_CHANNELS || freq->m == 0)
- return -EINVAL;
- *channel = freq->m;
- return 1;
- }
-
- r = freq_to_mhz(freq);
- if (r < 0)
- return r;
- mhz = r;
+ u8 channel;
- for (i = 0; i < NUM_CHANNELS; i++) {
- if (mhz == channel_frequencies[i]) {
- *channel = i+1;
- return 1;
- }
+ for (channel = range->start; channel < range->end; channel++) {
+ struct ieee80211_channel *chan =
+ &mode->channels[CHAN_TO_IDX(channel)];
+ chan->flag |= IEEE80211_CHAN_W_SCAN |
+ IEEE80211_CHAN_W_ACTIVE_SCAN |
+ IEEE80211_CHAN_W_IBSS;
}
-
- return -EINVAL;
}
-int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain)
+void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain)
{
- struct ieee80211_geo geo;
+ struct zd_mac *mac = zd_hw_mac(hw);
const struct channel_range *range;
- int i;
- u8 channel;
- dev_dbg(zd_mac_dev(zd_netdev_mac(ieee->dev)),
- "regdomain %#04x\n", regdomain);
+ dev_dbg(zd_mac_dev(mac), "regdomain %#02x\n", regdomain);
range = zd_channel_range(regdomain);
- if (range->start == 0) {
- dev_err(zd_mac_dev(zd_netdev_mac(ieee->dev)),
- "zd1211 regdomain %#04x not supported\n",
- regdomain);
- return -EINVAL;
+ if (!range) {
+ /* The vendor driver overrides the regulatory domain and
+ * allowed channel registers and unconditionally restricts
+ * available channels to 1-11 everywhere. Match their
+ * questionable behaviour only for regdomains which we don't
+ * recognise. */
+ dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
+ "%#02x. Defaulting to FCC.\n", regdomain);
+ range = zd_channel_range(ZD_REGDOMAIN_FCC);
}
- memset(&geo, 0, sizeof(geo));
-
- for (i = 0, channel = range->start; channel < range->end; channel++) {
- struct ieee80211_channel *chan = &geo.bg[i++];
- chan->freq = channel_frequencies[channel - 1];
- chan->channel = channel;
- }
-
- geo.bg_channels = i;
- memcpy(geo.name, "XX ", 4);
- ieee80211_set_geo(ieee, &geo);
- return 0;
+ unmask_bg_channels(hw, range, &mac->modes[0]);
+ unmask_bg_channels(hw, range, &mac->modes[1]);
}
+
diff --git a/drivers/net/wireless/zd1211rw/zd_ieee80211.h b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
index fbf6491dce7e..26b79f197587 100644
--- a/drivers/net/wireless/zd1211rw/zd_ieee80211.h
+++ b/drivers/net/wireless/zd1211rw/zd_ieee80211.h
@@ -1,7 +1,27 @@
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ *
+ * 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 _ZD_IEEE80211_H
#define _ZD_IEEE80211_H
-#include <net/ieee80211.h>
+#include <net/mac80211.h>
/* Additional definitions from the standards.
*/
@@ -19,22 +39,7 @@ enum {
MAX_CHANNEL24 = 14,
};
-struct channel_range {
- u8 start;
- u8 end; /* exclusive (channel must be less than end) */
-};
-
-struct iw_freq;
-
-int zd_geo_init(struct ieee80211_device *ieee, u8 regdomain);
-
-const struct channel_range *zd_channel_range(u8 regdomain);
-int zd_regdomain_supports_channel(u8 regdomain, u8 channel);
-int zd_regdomain_supported(u8 regdomain);
-
-/* for 2.4 GHz band */
-int zd_channel_to_freq(struct iw_freq *freq, u8 channel);
-int zd_find_channel(u8 *channel, const struct iw_freq *freq);
+void zd_geo_init(struct ieee80211_hw *hw, u8 regdomain);
#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80
@@ -54,8 +59,8 @@ static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header)
*
* See the struct zd_ctrlset definition in zd_mac.h.
*/
-#define ZD_OFDM_PLCP_RATE_6M 0xb
-#define ZD_OFDM_PLCP_RATE_9M 0xf
+#define ZD_OFDM_PLCP_RATE_6M 0xb
+#define ZD_OFDM_PLCP_RATE_9M 0xf
#define ZD_OFDM_PLCP_RATE_12M 0xa
#define ZD_OFDM_PLCP_RATE_18M 0xe
#define ZD_OFDM_PLCP_RATE_24M 0x9
@@ -87,10 +92,4 @@ static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header)
#define ZD_CCK_PLCP_SIGNAL_5M5 0x37
#define ZD_CCK_PLCP_SIGNAL_11M 0x6e
-enum ieee80211_std {
- IEEE80211B = 0x01,
- IEEE80211A = 0x02,
- IEEE80211G = 0x04,
-};
-
#endif /* _ZD_IEEE80211_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 5298a8bf1129..49127e4b42c2 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1,4 +1,9 @@
-/* zd_mac.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
+ * Copyright (c) 2007 Luis R. Rodriguez <mcgrof@winlab.rutgers.edu>
*
* 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
@@ -17,7 +22,6 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/wireless.h>
#include <linux/usb.h>
#include <linux/jiffies.h>
#include <net/ieee80211_radiotap.h>
@@ -26,81 +30,105 @@
#include "zd_chip.h"
#include "zd_mac.h"
#include "zd_ieee80211.h"
-#include "zd_netdev.h"
#include "zd_rf.h"
-static void ieee_init(struct ieee80211_device *ieee);
-static void softmac_init(struct ieee80211softmac_device *sm);
-static void set_rts_cts_work(struct work_struct *work);
-static void set_basic_rates_work(struct work_struct *work);
+/* This table contains the hardware specific values for the modulation rates. */
+static const struct ieee80211_rate zd_rates[] = {
+ { .rate = 10,
+ .val = ZD_CCK_RATE_1M,
+ .flags = IEEE80211_RATE_CCK },
+ { .rate = 20,
+ .val = ZD_CCK_RATE_2M,
+ .val2 = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT,
+ .flags = IEEE80211_RATE_CCK_2 },
+ { .rate = 55,
+ .val = ZD_CCK_RATE_5_5M,
+ .val2 = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT,
+ .flags = IEEE80211_RATE_CCK_2 },
+ { .rate = 110,
+ .val = ZD_CCK_RATE_11M,
+ .val2 = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT,
+ .flags = IEEE80211_RATE_CCK_2 },
+ { .rate = 60,
+ .val = ZD_OFDM_RATE_6M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 90,
+ .val = ZD_OFDM_RATE_9M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 120,
+ .val = ZD_OFDM_RATE_12M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 180,
+ .val = ZD_OFDM_RATE_18M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 240,
+ .val = ZD_OFDM_RATE_24M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 360,
+ .val = ZD_OFDM_RATE_36M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 480,
+ .val = ZD_OFDM_RATE_48M,
+ .flags = IEEE80211_RATE_OFDM },
+ { .rate = 540,
+ .val = ZD_OFDM_RATE_54M,
+ .flags = IEEE80211_RATE_OFDM },
+};
+
+static const struct ieee80211_channel zd_channels[] = {
+ { .chan = 1,
+ .freq = 2412},
+ { .chan = 2,
+ .freq = 2417},
+ { .chan = 3,
+ .freq = 2422},
+ { .chan = 4,
+ .freq = 2427},
+ { .chan = 5,
+ .freq = 2432},
+ { .chan = 6,
+ .freq = 2437},
+ { .chan = 7,
+ .freq = 2442},
+ { .chan = 8,
+ .freq = 2447},
+ { .chan = 9,
+ .freq = 2452},
+ { .chan = 10,
+ .freq = 2457},
+ { .chan = 11,
+ .freq = 2462},
+ { .chan = 12,
+ .freq = 2467},
+ { .chan = 13,
+ .freq = 2472},
+ { .chan = 14,
+ .freq = 2484}
+};
static void housekeeping_init(struct zd_mac *mac);
static void housekeeping_enable(struct zd_mac *mac);
static void housekeeping_disable(struct zd_mac *mac);
-static void set_multicast_hash_handler(struct work_struct *work);
-
-static void do_rx(unsigned long mac_ptr);
-
-int zd_mac_init(struct zd_mac *mac,
- struct net_device *netdev,
- struct usb_interface *intf)
-{
- struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev);
-
- memset(mac, 0, sizeof(*mac));
- spin_lock_init(&mac->lock);
- mac->netdev = netdev;
- INIT_DELAYED_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
- INIT_DELAYED_WORK(&mac->set_basic_rates_work, set_basic_rates_work);
-
- skb_queue_head_init(&mac->rx_queue);
- tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac);
- tasklet_disable(&mac->rx_tasklet);
-
- ieee_init(ieee);
- softmac_init(ieee80211_priv(netdev));
- zd_chip_init(&mac->chip, netdev, intf);
- housekeeping_init(mac);
- INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
- return 0;
-}
-
-static int reset_channel(struct zd_mac *mac)
-{
- int r;
- unsigned long flags;
- const struct channel_range *range;
-
- spin_lock_irqsave(&mac->lock, flags);
- range = zd_channel_range(mac->regdomain);
- if (!range->start) {
- r = -EINVAL;
- goto out;
- }
- mac->requested_channel = range->start;
- r = 0;
-out:
- spin_unlock_irqrestore(&mac->lock, flags);
- return r;
-}
-
-int zd_mac_preinit_hw(struct zd_mac *mac)
+int zd_mac_preinit_hw(struct ieee80211_hw *hw)
{
int r;
u8 addr[ETH_ALEN];
+ struct zd_mac *mac = zd_hw_mac(hw);
r = zd_chip_read_mac_addr_fw(&mac->chip, addr);
if (r)
return r;
- memcpy(mac->netdev->dev_addr, addr, ETH_ALEN);
+ SET_IEEE80211_PERM_ADDR(hw, addr);
+
return 0;
}
-int zd_mac_init_hw(struct zd_mac *mac)
+int zd_mac_init_hw(struct ieee80211_hw *hw)
{
int r;
+ struct zd_mac *mac = zd_hw_mac(hw);
struct zd_chip *chip = &mac->chip;
u8 default_regdomain;
@@ -116,22 +144,9 @@ int zd_mac_init_hw(struct zd_mac *mac)
r = zd_read_regdomain(chip, &default_regdomain);
if (r)
goto disable_int;
- if (!zd_regdomain_supported(default_regdomain)) {
- /* The vendor driver overrides the regulatory domain and
- * allowed channel registers and unconditionally restricts
- * available channels to 1-11 everywhere. Match their
- * questionable behaviour only for regdomains which we don't
- * recognise. */
- dev_warn(zd_mac_dev(mac), "Unrecognised regulatory domain: "
- "%#04x. Defaulting to FCC.\n", default_regdomain);
- default_regdomain = ZD_REGDOMAIN_FCC;
- }
spin_lock_irq(&mac->lock);
mac->regdomain = mac->default_regdomain = default_regdomain;
spin_unlock_irq(&mac->lock);
- r = reset_channel(mac);
- if (r)
- goto disable_int;
/* We must inform the device that we are doing encryption/decryption in
* software at the moment. */
@@ -139,9 +154,7 @@ int zd_mac_init_hw(struct zd_mac *mac)
if (r)
goto disable_int;
- r = zd_geo_init(zd_mac_to_ieee80211(mac), mac->regdomain);
- if (r)
- goto disable_int;
+ zd_geo_init(hw, mac->regdomain);
r = 0;
disable_int:
@@ -153,8 +166,6 @@ out:
void zd_mac_clear(struct zd_mac *mac)
{
flush_workqueue(zd_workqueue);
- skb_queue_purge(&mac->rx_queue);
- tasklet_kill(&mac->rx_tasklet);
zd_chip_clear(&mac->chip);
ZD_ASSERT(!spin_is_locked(&mac->lock));
ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -162,34 +173,27 @@ void zd_mac_clear(struct zd_mac *mac)
static int set_rx_filter(struct zd_mac *mac)
{
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- u32 filter = (ieee->iw_mode == IW_MODE_MONITOR) ? ~0 : STA_RX_FILTER;
- return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
-}
+ unsigned long flags;
+ u32 filter = STA_RX_FILTER;
-static int set_sniffer(struct zd_mac *mac)
-{
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- return zd_iowrite32(&mac->chip, CR_SNIFFER_ON,
- ieee->iw_mode == IW_MODE_MONITOR ? 1 : 0);
- return 0;
+ spin_lock_irqsave(&mac->lock, flags);
+ if (mac->pass_ctrl)
+ filter |= RX_FILTER_CTRL;
+ spin_unlock_irqrestore(&mac->lock, flags);
+
+ return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
}
static int set_mc_hash(struct zd_mac *mac)
{
struct zd_mc_hash hash;
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-
zd_mc_clear(&hash);
- if (ieee->iw_mode == IW_MODE_MONITOR)
- zd_mc_add_all(&hash);
-
return zd_chip_set_multicast_hash(&mac->chip, &hash);
}
-int zd_mac_open(struct net_device *netdev)
+static int zd_op_start(struct ieee80211_hw *hw)
{
- struct zd_mac *mac = zd_netdev_mac(netdev);
+ struct zd_mac *mac = zd_hw_mac(hw);
struct zd_chip *chip = &mac->chip;
struct zd_usb *usb = &chip->usb;
int r;
@@ -200,46 +204,33 @@ int zd_mac_open(struct net_device *netdev)
goto out;
}
- tasklet_enable(&mac->rx_tasklet);
-
r = zd_chip_enable_int(chip);
if (r < 0)
goto out;
- r = zd_write_mac_addr(chip, netdev->dev_addr);
- if (r)
- goto disable_int;
-
r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G);
if (r < 0)
goto disable_int;
r = set_rx_filter(mac);
if (r)
goto disable_int;
- r = set_sniffer(mac);
- if (r)
- goto disable_int;
r = set_mc_hash(mac);
if (r)
goto disable_int;
r = zd_chip_switch_radio_on(chip);
if (r < 0)
goto disable_int;
- r = zd_chip_set_channel(chip, mac->requested_channel);
- if (r < 0)
- goto disable_radio;
- r = zd_chip_enable_rx(chip);
+ r = zd_chip_enable_rxtx(chip);
if (r < 0)
goto disable_radio;
r = zd_chip_enable_hwint(chip);
if (r < 0)
- goto disable_rx;
+ goto disable_rxtx;
housekeeping_enable(mac);
- ieee80211softmac_start(netdev);
return 0;
-disable_rx:
- zd_chip_disable_rx(chip);
+disable_rxtx:
+ zd_chip_disable_rxtx(chip);
disable_radio:
zd_chip_switch_radio_off(chip);
disable_int:
@@ -248,494 +239,190 @@ out:
return r;
}
-int zd_mac_stop(struct net_device *netdev)
+/**
+ * clear_tx_skb_control_block - clears the control block of tx skbuffs
+ * @skb: a &struct sk_buff pointer
+ *
+ * This clears the control block of skbuff buffers, which were transmitted to
+ * the device. Notify that the function is not thread-safe, so prevent
+ * multiple calls.
+ */
+static void clear_tx_skb_control_block(struct sk_buff *skb)
{
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct zd_chip *chip = &mac->chip;
+ struct zd_tx_skb_control_block *cb =
+ (struct zd_tx_skb_control_block *)skb->cb;
- netif_stop_queue(netdev);
+ kfree(cb->control);
+ cb->control = NULL;
+}
- /*
- * The order here deliberately is a little different from the open()
+/**
+ * kfree_tx_skb - frees a tx skbuff
+ * @skb: a &struct sk_buff pointer
+ *
+ * Frees the tx skbuff. Frees also the allocated control structure in the
+ * control block if necessary.
+ */
+static void kfree_tx_skb(struct sk_buff *skb)
+{
+ clear_tx_skb_control_block(skb);
+ dev_kfree_skb_any(skb);
+}
+
+static void zd_op_stop(struct ieee80211_hw *hw)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+ struct zd_chip *chip = &mac->chip;
+ struct sk_buff *skb;
+ struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
+
+ /* The order here deliberately is a little different from the open()
* method, since we need to make sure there is no opportunity for RX
- * frames to be processed by softmac after we have stopped it.
+ * frames to be processed by mac80211 after we have stopped it.
*/
- zd_chip_disable_rx(chip);
- skb_queue_purge(&mac->rx_queue);
- tasklet_disable(&mac->rx_tasklet);
+ zd_chip_disable_rxtx(chip);
housekeeping_disable(mac);
- ieee80211softmac_stop(netdev);
-
- /* Ensure no work items are running or queued from this point */
- cancel_delayed_work(&mac->set_rts_cts_work);
- cancel_delayed_work(&mac->set_basic_rates_work);
flush_workqueue(zd_workqueue);
- mac->updating_rts_rate = 0;
- mac->updating_basic_rates = 0;
zd_chip_disable_hwint(chip);
zd_chip_switch_radio_off(chip);
zd_chip_disable_int(chip);
- return 0;
-}
-
-int zd_mac_set_mac_address(struct net_device *netdev, void *p)
-{
- int r;
- unsigned long flags;
- struct sockaddr *addr = p;
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct zd_chip *chip = &mac->chip;
- DECLARE_MAC_BUF(mac2);
-
- if (!is_valid_ether_addr(addr->sa_data))
- return -EADDRNOTAVAIL;
-
- dev_dbg_f(zd_mac_dev(mac),
- "Setting MAC to %s\n", print_mac(mac2, addr->sa_data));
-
- if (netdev->flags & IFF_UP) {
- r = zd_write_mac_addr(chip, addr->sa_data);
- if (r)
- return r;
- }
-
- spin_lock_irqsave(&mac->lock, flags);
- memcpy(netdev->dev_addr, addr->sa_data, ETH_ALEN);
- spin_unlock_irqrestore(&mac->lock, flags);
-
- return 0;
-}
-
-static void set_multicast_hash_handler(struct work_struct *work)
-{
- struct zd_mac *mac = container_of(work, struct zd_mac,
- set_multicast_hash_work);
- struct zd_mc_hash hash;
-
- spin_lock_irq(&mac->lock);
- hash = mac->multicast_hash;
- spin_unlock_irq(&mac->lock);
- zd_chip_set_multicast_hash(&mac->chip, &hash);
+ while ((skb = skb_dequeue(ack_wait_queue)))
+ kfree_tx_skb(skb);
}
-void zd_mac_set_multicast_list(struct net_device *dev)
-{
- struct zd_mac *mac = zd_netdev_mac(dev);
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- struct zd_mc_hash hash;
- struct dev_mc_list *mc;
- unsigned long flags;
- DECLARE_MAC_BUF(mac2);
-
- if (dev->flags & (IFF_PROMISC|IFF_ALLMULTI) ||
- ieee->iw_mode == IW_MODE_MONITOR) {
- zd_mc_add_all(&hash);
- } else {
- zd_mc_clear(&hash);
- for (mc = dev->mc_list; mc; mc = mc->next) {
- dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
- print_mac(mac2, mc->dmi_addr));
- zd_mc_add_addr(&hash, mc->dmi_addr);
- }
- }
-
- spin_lock_irqsave(&mac->lock, flags);
- mac->multicast_hash = hash;
- spin_unlock_irqrestore(&mac->lock, flags);
- queue_work(zd_workqueue, &mac->set_multicast_hash_work);
-}
-
-int zd_mac_set_regdomain(struct zd_mac *mac, u8 regdomain)
-{
- int r;
- u8 channel;
-
- ZD_ASSERT(!irqs_disabled());
- spin_lock_irq(&mac->lock);
- if (regdomain == 0) {
- regdomain = mac->default_regdomain;
- }
- if (!zd_regdomain_supported(regdomain)) {
- spin_unlock_irq(&mac->lock);
- return -EINVAL;
- }
- mac->regdomain = regdomain;
- channel = mac->requested_channel;
- spin_unlock_irq(&mac->lock);
-
- r = zd_geo_init(zd_mac_to_ieee80211(mac), regdomain);
- if (r)
- return r;
- if (!zd_regdomain_supports_channel(regdomain, channel)) {
- r = reset_channel(mac);
- if (r)
- return r;
- }
+/**
+ * init_tx_skb_control_block - initializes skb control block
+ * @skb: a &sk_buff pointer
+ * @dev: pointer to the mac80221 device
+ * @control: mac80211 tx control applying for the frame in @skb
+ *
+ * Initializes the control block of the skbuff to be transmitted.
+ */
+static int init_tx_skb_control_block(struct sk_buff *skb,
+ struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control)
+{
+ struct zd_tx_skb_control_block *cb =
+ (struct zd_tx_skb_control_block *)skb->cb;
+
+ ZD_ASSERT(sizeof(*cb) <= sizeof(skb->cb));
+ memset(cb, 0, sizeof(*cb));
+ cb->hw= hw;
+ cb->control = kmalloc(sizeof(*control), GFP_ATOMIC);
+ if (cb->control == NULL)
+ return -ENOMEM;
+ memcpy(cb->control, control, sizeof(*control));
return 0;
}
-u8 zd_mac_get_regdomain(struct zd_mac *mac)
-{
- unsigned long flags;
- u8 regdomain;
-
- spin_lock_irqsave(&mac->lock, flags);
- regdomain = mac->regdomain;
- spin_unlock_irqrestore(&mac->lock, flags);
- return regdomain;
-}
-
-/* Fallback to lowest rate, if rate is unknown. */
-static u8 rate_to_zd_rate(u8 rate)
-{
- switch (rate) {
- case IEEE80211_CCK_RATE_2MB:
- return ZD_CCK_RATE_2M;
- case IEEE80211_CCK_RATE_5MB:
- return ZD_CCK_RATE_5_5M;
- case IEEE80211_CCK_RATE_11MB:
- return ZD_CCK_RATE_11M;
- case IEEE80211_OFDM_RATE_6MB:
- return ZD_OFDM_RATE_6M;
- case IEEE80211_OFDM_RATE_9MB:
- return ZD_OFDM_RATE_9M;
- case IEEE80211_OFDM_RATE_12MB:
- return ZD_OFDM_RATE_12M;
- case IEEE80211_OFDM_RATE_18MB:
- return ZD_OFDM_RATE_18M;
- case IEEE80211_OFDM_RATE_24MB:
- return ZD_OFDM_RATE_24M;
- case IEEE80211_OFDM_RATE_36MB:
- return ZD_OFDM_RATE_36M;
- case IEEE80211_OFDM_RATE_48MB:
- return ZD_OFDM_RATE_48M;
- case IEEE80211_OFDM_RATE_54MB:
- return ZD_OFDM_RATE_54M;
- }
- return ZD_CCK_RATE_1M;
-}
-
-static u16 rate_to_cr_rate(u8 rate)
-{
- switch (rate) {
- case IEEE80211_CCK_RATE_2MB:
- return CR_RATE_1M;
- case IEEE80211_CCK_RATE_5MB:
- return CR_RATE_5_5M;
- case IEEE80211_CCK_RATE_11MB:
- return CR_RATE_11M;
- case IEEE80211_OFDM_RATE_6MB:
- return CR_RATE_6M;
- case IEEE80211_OFDM_RATE_9MB:
- return CR_RATE_9M;
- case IEEE80211_OFDM_RATE_12MB:
- return CR_RATE_12M;
- case IEEE80211_OFDM_RATE_18MB:
- return CR_RATE_18M;
- case IEEE80211_OFDM_RATE_24MB:
- return CR_RATE_24M;
- case IEEE80211_OFDM_RATE_36MB:
- return CR_RATE_36M;
- case IEEE80211_OFDM_RATE_48MB:
- return CR_RATE_48M;
- case IEEE80211_OFDM_RATE_54MB:
- return CR_RATE_54M;
- }
- return CR_RATE_1M;
-}
-
-static void try_enable_tx(struct zd_mac *mac)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&mac->lock, flags);
- if (mac->updating_rts_rate == 0 && mac->updating_basic_rates == 0)
- netif_wake_queue(mac->netdev);
- spin_unlock_irqrestore(&mac->lock, flags);
-}
-
-static void set_rts_cts_work(struct work_struct *work)
+/**
+ * tx_status - reports tx status of a packet if required
+ * @hw - a &struct ieee80211_hw pointer
+ * @skb - a sk-buffer
+ * @status - the tx status of the packet without control information
+ * @success - True for successfull transmission of the frame
+ *
+ * This information calls ieee80211_tx_status_irqsafe() if required by the
+ * control information. It copies the control information into the status
+ * information.
+ *
+ * If no status information has been requested, the skb is freed.
+ */
+static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_status *status,
+ bool success)
{
- struct zd_mac *mac =
- container_of(work, struct zd_mac, set_rts_cts_work.work);
- unsigned long flags;
- u8 rts_rate;
- unsigned int short_preamble;
-
- mutex_lock(&mac->chip.mutex);
-
- spin_lock_irqsave(&mac->lock, flags);
- mac->updating_rts_rate = 0;
- rts_rate = mac->rts_rate;
- short_preamble = mac->short_preamble;
- spin_unlock_irqrestore(&mac->lock, flags);
-
- zd_chip_set_rts_cts_rate_locked(&mac->chip, rts_rate, short_preamble);
- mutex_unlock(&mac->chip.mutex);
+ struct zd_tx_skb_control_block *cb = (struct zd_tx_skb_control_block *)
+ skb->cb;
- try_enable_tx(mac);
+ ZD_ASSERT(cb->control != NULL);
+ memcpy(&status->control, cb->control, sizeof(status->control));
+ if (!success)
+ status->excessive_retries = 1;
+ clear_tx_skb_control_block(skb);
+ ieee80211_tx_status_irqsafe(hw, skb, status);
}
-static void set_basic_rates_work(struct work_struct *work)
+/**
+ * zd_mac_tx_failed - callback for failed frames
+ * @dev: the mac80211 wireless device
+ *
+ * This function is called if a frame couldn't be succesfully be
+ * transferred. The first frame from the tx queue, will be selected and
+ * reported as error to the upper layers.
+ */
+void zd_mac_tx_failed(struct ieee80211_hw *hw)
{
- struct zd_mac *mac =
- container_of(work, struct zd_mac, set_basic_rates_work.work);
- unsigned long flags;
- u16 basic_rates;
-
- mutex_lock(&mac->chip.mutex);
-
- spin_lock_irqsave(&mac->lock, flags);
- mac->updating_basic_rates = 0;
- basic_rates = mac->basic_rates;
- spin_unlock_irqrestore(&mac->lock, flags);
-
- zd_chip_set_basic_rates_locked(&mac->chip, basic_rates);
- mutex_unlock(&mac->chip.mutex);
+ struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue;
+ struct sk_buff *skb;
+ struct ieee80211_tx_status status = {{0}};
- try_enable_tx(mac);
+ skb = skb_dequeue(q);
+ if (skb == NULL)
+ return;
+ tx_status(hw, skb, &status, 0);
}
-static void bssinfo_change(struct net_device *netdev, u32 changes)
-{
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct ieee80211softmac_device *softmac = ieee80211_priv(netdev);
- struct ieee80211softmac_bss_info *bssinfo = &softmac->bssinfo;
- int need_set_rts_cts = 0;
- int need_set_rates = 0;
- u16 basic_rates;
- unsigned long flags;
-
- dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
-
- if (changes & IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE) {
- spin_lock_irqsave(&mac->lock, flags);
- mac->short_preamble = bssinfo->short_preamble;
- spin_unlock_irqrestore(&mac->lock, flags);
- need_set_rts_cts = 1;
- }
-
- if (changes & IEEE80211SOFTMAC_BSSINFOCHG_RATES) {
- /* Set RTS rate to highest available basic rate */
- u8 hi_rate = ieee80211softmac_highest_supported_rate(softmac,
- &bssinfo->supported_rates, 1);
- hi_rate = rate_to_zd_rate(hi_rate);
-
- spin_lock_irqsave(&mac->lock, flags);
- if (hi_rate != mac->rts_rate) {
- mac->rts_rate = hi_rate;
- need_set_rts_cts = 1;
- }
- spin_unlock_irqrestore(&mac->lock, flags);
-
- /* Set basic rates */
- need_set_rates = 1;
- if (bssinfo->supported_rates.count == 0) {
- /* Allow the device to be flexible */
- basic_rates = CR_RATES_80211B | CR_RATES_80211G;
+/**
+ * zd_mac_tx_to_dev - callback for USB layer
+ * @skb: a &sk_buff pointer
+ * @error: error value, 0 if transmission successful
+ *
+ * Informs the MAC layer that the frame has successfully transferred to the
+ * device. If an ACK is required and the transfer to the device has been
+ * successful, the packets are put on the @ack_wait_queue with
+ * the control set removed.
+ */
+void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
+{
+ struct zd_tx_skb_control_block *cb =
+ (struct zd_tx_skb_control_block *)skb->cb;
+ struct ieee80211_hw *hw = cb->hw;
+
+ if (likely(cb->control)) {
+ skb_pull(skb, sizeof(struct zd_ctrlset));
+ if (unlikely(error ||
+ (cb->control->flags & IEEE80211_TXCTL_NO_ACK)))
+ {
+ struct ieee80211_tx_status status = {{0}};
+ tx_status(hw, skb, &status, !error);
} else {
- int i = 0;
- basic_rates = 0;
-
- for (i = 0; i < bssinfo->supported_rates.count; i++) {
- u16 rate = bssinfo->supported_rates.rates[i];
- if ((rate & IEEE80211_BASIC_RATE_MASK) == 0)
- continue;
+ struct sk_buff_head *q =
+ &zd_hw_mac(hw)->ack_wait_queue;
- rate &= ~IEEE80211_BASIC_RATE_MASK;
- basic_rates |= rate_to_cr_rate(rate);
- }
+ skb_queue_tail(q, skb);
+ while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS)
+ zd_mac_tx_failed(hw);
}
- spin_lock_irqsave(&mac->lock, flags);
- mac->basic_rates = basic_rates;
- spin_unlock_irqrestore(&mac->lock, flags);
- }
-
- /* Schedule any changes we made above */
-
- spin_lock_irqsave(&mac->lock, flags);
- if (need_set_rts_cts && !mac->updating_rts_rate) {
- mac->updating_rts_rate = 1;
- netif_stop_queue(mac->netdev);
- queue_delayed_work(zd_workqueue, &mac->set_rts_cts_work, 0);
- }
- if (need_set_rates && !mac->updating_basic_rates) {
- mac->updating_basic_rates = 1;
- netif_stop_queue(mac->netdev);
- queue_delayed_work(zd_workqueue, &mac->set_basic_rates_work,
- 0);
- }
- spin_unlock_irqrestore(&mac->lock, flags);
-}
-
-static void set_channel(struct net_device *netdev, u8 channel)
-{
- struct zd_mac *mac = zd_netdev_mac(netdev);
-
- dev_dbg_f(zd_mac_dev(mac), "channel %d\n", channel);
-
- zd_chip_set_channel(&mac->chip, channel);
-}
-
-int zd_mac_request_channel(struct zd_mac *mac, u8 channel)
-{
- unsigned long lock_flags;
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-
- if (ieee->iw_mode == IW_MODE_INFRA)
- return -EPERM;
-
- spin_lock_irqsave(&mac->lock, lock_flags);
- if (!zd_regdomain_supports_channel(mac->regdomain, channel)) {
- spin_unlock_irqrestore(&mac->lock, lock_flags);
- return -EINVAL;
- }
- mac->requested_channel = channel;
- spin_unlock_irqrestore(&mac->lock, lock_flags);
- if (netif_running(mac->netdev))
- return zd_chip_set_channel(&mac->chip, channel);
- else
- return 0;
-}
-
-u8 zd_mac_get_channel(struct zd_mac *mac)
-{
- u8 channel = zd_chip_get_channel(&mac->chip);
-
- dev_dbg_f(zd_mac_dev(mac), "channel %u\n", channel);
- return channel;
-}
-
-int zd_mac_set_mode(struct zd_mac *mac, u32 mode)
-{
- struct ieee80211_device *ieee;
-
- switch (mode) {
- case IW_MODE_AUTO:
- case IW_MODE_ADHOC:
- case IW_MODE_INFRA:
- mac->netdev->type = ARPHRD_ETHER;
- break;
- case IW_MODE_MONITOR:
- mac->netdev->type = ARPHRD_IEEE80211_RADIOTAP;
- break;
- default:
- dev_dbg_f(zd_mac_dev(mac), "wrong mode %u\n", mode);
- return -EINVAL;
- }
-
- ieee = zd_mac_to_ieee80211(mac);
- ZD_ASSERT(!irqs_disabled());
- spin_lock_irq(&ieee->lock);
- ieee->iw_mode = mode;
- spin_unlock_irq(&ieee->lock);
-
- if (netif_running(mac->netdev)) {
- int r = set_rx_filter(mac);
- if (r)
- return r;
- return set_sniffer(mac);
- }
-
- return 0;
-}
-
-int zd_mac_get_mode(struct zd_mac *mac, u32 *mode)
-{
- unsigned long flags;
- struct ieee80211_device *ieee;
-
- ieee = zd_mac_to_ieee80211(mac);
- spin_lock_irqsave(&ieee->lock, flags);
- *mode = ieee->iw_mode;
- spin_unlock_irqrestore(&ieee->lock, flags);
- return 0;
-}
-
-int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range)
-{
- int i;
- const struct channel_range *channel_range;
- u8 regdomain;
-
- memset(range, 0, sizeof(*range));
-
- /* FIXME: Not so important and depends on the mode. For 802.11g
- * usually this value is used. It seems to be that Bit/s number is
- * given here.
- */
- range->throughput = 27 * 1000 * 1000;
-
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
-
- /* FIXME: Needs still to be tuned. */
- range->avg_qual.qual = 71;
- range->avg_qual.level = 80;
-
- /* FIXME: depends on standard? */
- range->min_rts = 256;
- range->max_rts = 2346;
-
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
-
- range->max_encoding_tokens = WEP_KEYS;
- range->num_encoding_sizes = 2;
- range->encoding_size[0] = 5;
- range->encoding_size[1] = WEP_KEY_LEN;
-
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 20;
-
- range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
-
- ZD_ASSERT(!irqs_disabled());
- spin_lock_irq(&mac->lock);
- regdomain = mac->regdomain;
- spin_unlock_irq(&mac->lock);
- channel_range = zd_channel_range(regdomain);
-
- range->num_channels = channel_range->end - channel_range->start;
- range->old_num_channels = range->num_channels;
- range->num_frequency = range->num_channels;
- range->old_num_frequency = range->num_frequency;
-
- for (i = 0; i < range->num_frequency; i++) {
- struct iw_freq *freq = &range->freq[i];
- freq->i = channel_range->start + i;
- zd_channel_to_freq(freq, freq->i);
+ } else {
+ kfree_tx_skb(skb);
}
-
- return 0;
}
static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
{
/* ZD_PURE_RATE() must be used to remove the modulation type flag of
- * the zd-rate values. */
+ * the zd-rate values.
+ */
static const u8 rate_divisor[] = {
- [ZD_PURE_RATE(ZD_CCK_RATE_1M)] = 1,
- [ZD_PURE_RATE(ZD_CCK_RATE_2M)] = 2,
-
- /* bits must be doubled */
- [ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
-
- [ZD_PURE_RATE(ZD_CCK_RATE_11M)] = 11,
- [ZD_PURE_RATE(ZD_OFDM_RATE_6M)] = 6,
- [ZD_PURE_RATE(ZD_OFDM_RATE_9M)] = 9,
- [ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
- [ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
- [ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
- [ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
- [ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
- [ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
+ [ZD_PURE_RATE(ZD_CCK_RATE_1M)] = 1,
+ [ZD_PURE_RATE(ZD_CCK_RATE_2M)] = 2,
+ /* Bits must be doubled. */
+ [ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11,
+ [ZD_PURE_RATE(ZD_CCK_RATE_11M)] = 11,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_6M)] = 6,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_9M)] = 9,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48,
+ [ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54,
};
u32 bits = (u32)tx_length * 8;
@@ -764,34 +451,10 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
return bits/divisor;
}
-static void cs_set_modulation(struct zd_mac *mac, struct zd_ctrlset *cs,
- struct ieee80211_hdr_4addr *hdr)
-{
- struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
- u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(hdr->frame_ctl));
- u8 rate;
- int is_mgt = (ftype == IEEE80211_FTYPE_MGMT) != 0;
- int is_multicast = is_multicast_ether_addr(hdr->addr1);
- int short_preamble = ieee80211softmac_short_preamble_ok(softmac,
- is_multicast, is_mgt);
-
- rate = ieee80211softmac_suggest_txrate(softmac, is_multicast, is_mgt);
- cs->modulation = rate_to_zd_rate(rate);
-
- /* Set short preamble bit when appropriate */
- if (short_preamble && ZD_MODULATION_TYPE(cs->modulation) == ZD_CCK
- && cs->modulation != ZD_CCK_RATE_1M)
- cs->modulation |= ZD_CCK_PREA_SHORT;
-}
-
static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
- struct ieee80211_hdr_4addr *header)
+ struct ieee80211_hdr *header, u32 flags)
{
- struct ieee80211softmac_device *softmac = ieee80211_priv(mac->netdev);
- unsigned int tx_length = le16_to_cpu(cs->tx_length);
- u16 fctl = le16_to_cpu(header->frame_ctl);
- u16 ftype = WLAN_FC_GET_TYPE(fctl);
- u16 stype = WLAN_FC_GET_STYPE(fctl);
+ u16 fctl = le16_to_cpu(header->frame_control);
/*
* CONTROL TODO:
@@ -802,7 +465,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
cs->control = 0;
/* First fragment */
- if (WLAN_GET_SEQ_FRAG(le16_to_cpu(header->seq_ctl)) == 0)
+ if (flags & IEEE80211_TXCTL_FIRST_FRAGMENT)
cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
/* Multicast */
@@ -810,54 +473,37 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
cs->control |= ZD_CS_MULTICAST;
/* PS-POLL */
- if (ftype == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL)
+ if ((fctl & (IEEE80211_FCTL_FTYPE|IEEE80211_FCTL_STYPE)) ==
+ (IEEE80211_FTYPE_CTL|IEEE80211_STYPE_PSPOLL))
cs->control |= ZD_CS_PS_POLL_FRAME;
- /* Unicast data frames over the threshold should have RTS */
- if (!is_multicast_ether_addr(header->addr1) &&
- ftype != IEEE80211_FTYPE_MGMT &&
- tx_length > zd_netdev_ieee80211(mac->netdev)->rts)
+ if (flags & IEEE80211_TXCTL_USE_RTS_CTS)
cs->control |= ZD_CS_RTS;
- /* Use CTS-to-self protection if required */
- if (ZD_MODULATION_TYPE(cs->modulation) == ZD_OFDM &&
- ieee80211softmac_protection_needed(softmac)) {
- /* FIXME: avoid sending RTS *and* self-CTS, is that correct? */
- cs->control &= ~ZD_CS_RTS;
+ if (flags & IEEE80211_TXCTL_USE_CTS_PROTECT)
cs->control |= ZD_CS_SELF_CTS;
- }
/* FIXME: Management frame? */
}
static int fill_ctrlset(struct zd_mac *mac,
- struct ieee80211_txb *txb,
- int frag_num)
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
{
int r;
- struct sk_buff *skb = txb->fragments[frag_num];
- struct ieee80211_hdr_4addr *hdr =
- (struct ieee80211_hdr_4addr *) skb->data;
- unsigned int frag_len = skb->len + IEEE80211_FCS_LEN;
- unsigned int next_frag_len;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ unsigned int frag_len = skb->len + FCS_LEN;
unsigned int packet_length;
struct zd_ctrlset *cs = (struct zd_ctrlset *)
skb_push(skb, sizeof(struct zd_ctrlset));
- if (frag_num+1 < txb->nr_frags) {
- next_frag_len = txb->fragments[frag_num+1]->len +
- IEEE80211_FCS_LEN;
- } else {
- next_frag_len = 0;
- }
ZD_ASSERT(frag_len <= 0xffff);
- ZD_ASSERT(next_frag_len <= 0xffff);
- cs_set_modulation(mac, cs, hdr);
+ cs->modulation = control->tx_rate;
cs->tx_length = cpu_to_le16(frag_len);
- cs_set_control(mac, cs, hdr);
+ cs_set_control(mac, cs, hdr, control->flags);
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
ZD_ASSERT(packet_length <= 0xffff);
@@ -886,419 +532,417 @@ static int fill_ctrlset(struct zd_mac *mac,
if (r < 0)
return r;
cs->current_length = cpu_to_le16(r);
-
- if (next_frag_len == 0) {
- cs->next_frame_length = 0;
- } else {
- r = zd_calc_tx_length_us(NULL, ZD_RATE(cs->modulation),
- next_frag_len);
- if (r < 0)
- return r;
- cs->next_frame_length = cpu_to_le16(r);
- }
+ cs->next_frame_length = 0;
return 0;
}
-static int zd_mac_tx(struct zd_mac *mac, struct ieee80211_txb *txb, int pri)
+/**
+ * zd_op_tx - transmits a network frame to the device
+ *
+ * @dev: mac80211 hardware device
+ * @skb: socket buffer
+ * @control: the control structure
+ *
+ * This function transmit an IEEE 802.11 network frame to the device. The
+ * control block of the skbuff will be initialized. If necessary the incoming
+ * mac80211 queues will be stopped.
+ */
+static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+ struct ieee80211_tx_control *control)
{
- int i, r;
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
+ struct zd_mac *mac = zd_hw_mac(hw);
+ int r;
- for (i = 0; i < txb->nr_frags; i++) {
- struct sk_buff *skb = txb->fragments[i];
+ r = fill_ctrlset(mac, skb, control);
+ if (r)
+ return r;
- r = fill_ctrlset(mac, txb, i);
- if (r) {
- ieee->stats.tx_dropped++;
- return r;
- }
- r = zd_usb_tx(&mac->chip.usb, skb->data, skb->len);
- if (r) {
- ieee->stats.tx_dropped++;
- return r;
- }
+ r = init_tx_skb_control_block(skb, hw, control);
+ if (r)
+ return r;
+ r = zd_usb_tx(&mac->chip.usb, skb);
+ if (r) {
+ clear_tx_skb_control_block(skb);
+ return r;
}
-
- /* FIXME: shouldn't this be handled by the upper layers? */
- mac->netdev->trans_start = jiffies;
-
- ieee80211_txb_free(txb);
return 0;
}
-struct zd_rt_hdr {
- struct ieee80211_radiotap_header rt_hdr;
- u8 rt_flags;
- u8 rt_rate;
- u16 rt_channel;
- u16 rt_chbitmask;
-} __attribute__((packed));
-
-static void fill_rt_header(void *buffer, struct zd_mac *mac,
- const struct ieee80211_rx_stats *stats,
- const struct rx_status *status)
-{
- struct zd_rt_hdr *hdr = buffer;
-
- hdr->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
- hdr->rt_hdr.it_pad = 0;
- hdr->rt_hdr.it_len = cpu_to_le16(sizeof(struct zd_rt_hdr));
- hdr->rt_hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) |
- (1 << IEEE80211_RADIOTAP_CHANNEL) |
- (1 << IEEE80211_RADIOTAP_RATE));
-
- hdr->rt_flags = 0;
- if (status->decryption_type & (ZD_RX_WEP64|ZD_RX_WEP128|ZD_RX_WEP256))
- hdr->rt_flags |= IEEE80211_RADIOTAP_F_WEP;
-
- hdr->rt_rate = stats->rate / 5;
-
- /* FIXME: 802.11a */
- hdr->rt_channel = cpu_to_le16(ieee80211chan2mhz(
- _zd_chip_get_channel(&mac->chip)));
- hdr->rt_chbitmask = cpu_to_le16(IEEE80211_CHAN_2GHZ |
- ((status->frame_status & ZD_RX_FRAME_MODULATION_MASK) ==
- ZD_RX_OFDM ? IEEE80211_CHAN_OFDM : IEEE80211_CHAN_CCK));
-}
-
-/* Returns 1 if the data packet is for us and 0 otherwise. */
-static int is_data_packet_for_us(struct ieee80211_device *ieee,
- struct ieee80211_hdr_4addr *hdr)
-{
- struct net_device *netdev = ieee->dev;
- u16 fc = le16_to_cpu(hdr->frame_ctl);
-
- ZD_ASSERT(WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA);
-
- switch (ieee->iw_mode) {
- case IW_MODE_ADHOC:
- if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) != 0 ||
- compare_ether_addr(hdr->addr3, ieee->bssid) != 0)
- return 0;
- break;
- case IW_MODE_AUTO:
- case IW_MODE_INFRA:
- if ((fc & (IEEE80211_FCTL_TODS|IEEE80211_FCTL_FROMDS)) !=
- IEEE80211_FCTL_FROMDS ||
- compare_ether_addr(hdr->addr2, ieee->bssid) != 0)
- return 0;
- break;
- default:
- ZD_ASSERT(ieee->iw_mode != IW_MODE_MONITOR);
- return 0;
- }
-
- return compare_ether_addr(hdr->addr1, netdev->dev_addr) == 0 ||
- (is_multicast_ether_addr(hdr->addr1) &&
- compare_ether_addr(hdr->addr3, netdev->dev_addr) != 0) ||
- (netdev->flags & IFF_PROMISC);
-}
-
-/* Filters received packets. The function returns 1 if the packet should be
- * forwarded to ieee80211_rx(). If the packet should be ignored the function
- * returns 0. If an invalid packet is found the function returns -EINVAL.
+/**
+ * filter_ack - filters incoming packets for acknowledgements
+ * @dev: the mac80211 device
+ * @rx_hdr: received header
+ * @stats: the status for the received packet
*
- * The function calls ieee80211_rx_mgt() directly.
+ * This functions looks for ACK packets and tries to match them with the
+ * frames in the tx queue. If a match is found the frame will be dequeued and
+ * the upper layers is informed about the successful transmission. If
+ * mac80211 queues have been stopped and the number of frames still to be
+ * transmitted is low the queues will be opened again.
*
- * It has been based on ieee80211_rx_any.
+ * Returns 1 if the frame was an ACK, 0 if it was ignored.
*/
-static int filter_rx(struct ieee80211_device *ieee,
- const u8 *buffer, unsigned int length,
- struct ieee80211_rx_stats *stats)
+static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
+ struct ieee80211_rx_status *stats)
{
- struct ieee80211_hdr_4addr *hdr;
- u16 fc;
-
- if (ieee->iw_mode == IW_MODE_MONITOR)
- return 1;
-
- hdr = (struct ieee80211_hdr_4addr *)buffer;
- fc = le16_to_cpu(hdr->frame_ctl);
- if ((fc & IEEE80211_FCTL_VERS) != 0)
- return -EINVAL;
+ u16 fc = le16_to_cpu(rx_hdr->frame_control);
+ struct sk_buff *skb;
+ struct sk_buff_head *q;
+ unsigned long flags;
- switch (WLAN_FC_GET_TYPE(fc)) {
- case IEEE80211_FTYPE_MGMT:
- if (length < sizeof(struct ieee80211_hdr_3addr))
- return -EINVAL;
- ieee80211_rx_mgt(ieee, hdr, stats);
- return 0;
- case IEEE80211_FTYPE_CTL:
+ if ((fc & (IEEE80211_FCTL_FTYPE | IEEE80211_FCTL_STYPE)) !=
+ (IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK))
return 0;
- case IEEE80211_FTYPE_DATA:
- /* Ignore invalid short buffers */
- if (length < sizeof(struct ieee80211_hdr_3addr))
- return -EINVAL;
- return is_data_packet_for_us(ieee, hdr);
- }
- return -EINVAL;
+ q = &zd_hw_mac(hw)->ack_wait_queue;
+ spin_lock_irqsave(&q->lock, flags);
+ for (skb = q->next; skb != (struct sk_buff *)q; skb = skb->next) {
+ struct ieee80211_hdr *tx_hdr;
+
+ tx_hdr = (struct ieee80211_hdr *)skb->data;
+ if (likely(!compare_ether_addr(tx_hdr->addr2, rx_hdr->addr1)))
+ {
+ struct ieee80211_tx_status status = {{0}};
+ status.flags = IEEE80211_TX_STATUS_ACK;
+ status.ack_signal = stats->ssi;
+ __skb_unlink(skb, q);
+ tx_status(hw, skb, &status, 1);
+ goto out;
+ }
+ }
+out:
+ spin_unlock_irqrestore(&q->lock, flags);
+ return 1;
}
-static void update_qual_rssi(struct zd_mac *mac,
- const u8 *buffer, unsigned int length,
- u8 qual_percent, u8 rssi_percent)
+int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length)
{
- unsigned long flags;
- struct ieee80211_hdr_3addr *hdr;
- int i;
+ struct zd_mac *mac = zd_hw_mac(hw);
+ struct ieee80211_rx_status stats;
+ const struct rx_status *status;
+ struct sk_buff *skb;
+ int bad_frame = 0;
+ u16 fc;
+ bool is_qos, is_4addr, need_padding;
- hdr = (struct ieee80211_hdr_3addr *)buffer;
- if (length < offsetof(struct ieee80211_hdr_3addr, addr3))
- return;
- if (compare_ether_addr(hdr->addr2, zd_mac_to_ieee80211(mac)->bssid) != 0)
- return;
+ if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ +
+ FCS_LEN + sizeof(struct rx_status))
+ return -EINVAL;
- spin_lock_irqsave(&mac->lock, flags);
- i = mac->stats_count % ZD_MAC_STATS_BUFFER_SIZE;
- mac->qual_buffer[i] = qual_percent;
- mac->rssi_buffer[i] = rssi_percent;
- mac->stats_count++;
- spin_unlock_irqrestore(&mac->lock, flags);
-}
+ memset(&stats, 0, sizeof(stats));
-static int fill_rx_stats(struct ieee80211_rx_stats *stats,
- const struct rx_status **pstatus,
- struct zd_mac *mac,
- const u8 *buffer, unsigned int length)
-{
- const struct rx_status *status;
+ /* Note about pass_failed_fcs and pass_ctrl access below:
+ * mac locking intentionally omitted here, as this is the only unlocked
+ * reader and the only writer is configure_filter. Plus, if there were
+ * any races accessing these variables, it wouldn't really matter.
+ * If mac80211 ever provides a way for us to access filter flags
+ * from outside configure_filter, we could improve on this. Also, this
+ * situation may change once we implement some kind of DMA-into-skb
+ * RX path. */
- *pstatus = status = (struct rx_status *)
+ /* Caller has to ensure that length >= sizeof(struct rx_status). */
+ status = (struct rx_status *)
(buffer + (length - sizeof(struct rx_status)));
if (status->frame_status & ZD_RX_ERROR) {
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- ieee->stats.rx_errors++;
- if (status->frame_status & ZD_RX_TIMEOUT_ERROR)
- ieee->stats.rx_missed_errors++;
- else if (status->frame_status & ZD_RX_FIFO_OVERRUN_ERROR)
- ieee->stats.rx_fifo_errors++;
- else if (status->frame_status & ZD_RX_DECRYPTION_ERROR)
- ieee->ieee_stats.rx_discards_undecryptable++;
- else if (status->frame_status & ZD_RX_CRC32_ERROR) {
- ieee->stats.rx_crc_errors++;
- ieee->ieee_stats.rx_fcs_errors++;
+ if (mac->pass_failed_fcs &&
+ (status->frame_status & ZD_RX_CRC32_ERROR)) {
+ stats.flag |= RX_FLAG_FAILED_FCS_CRC;
+ bad_frame = 1;
+ } else {
+ return -EINVAL;
}
- else if (status->frame_status & ZD_RX_CRC16_ERROR)
- ieee->stats.rx_crc_errors++;
- return -EINVAL;
}
- memset(stats, 0, sizeof(struct ieee80211_rx_stats));
- stats->len = length - (ZD_PLCP_HEADER_SIZE + IEEE80211_FCS_LEN +
- + sizeof(struct rx_status));
- /* FIXME: 802.11a */
- stats->freq = IEEE80211_24GHZ_BAND;
- stats->received_channel = _zd_chip_get_channel(&mac->chip);
- stats->rssi = zd_rx_strength_percent(status->signal_strength);
- stats->signal = zd_rx_qual_percent(buffer,
+ stats.channel = _zd_chip_get_channel(&mac->chip);
+ stats.freq = zd_channels[stats.channel - 1].freq;
+ stats.phymode = MODE_IEEE80211G;
+ stats.ssi = status->signal_strength;
+ stats.signal = zd_rx_qual_percent(buffer,
length - sizeof(struct rx_status),
status);
- stats->mask = IEEE80211_STATMASK_RSSI | IEEE80211_STATMASK_SIGNAL;
- stats->rate = zd_rx_rate(buffer, status);
- if (stats->rate)
- stats->mask |= IEEE80211_STATMASK_RATE;
+ stats.rate = zd_rx_rate(buffer, status);
+
+ length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status);
+ buffer += ZD_PLCP_HEADER_SIZE;
+
+ /* Except for bad frames, filter each frame to see if it is an ACK, in
+ * which case our internal TX tracking is updated. Normally we then
+ * bail here as there's no need to pass ACKs on up to the stack, but
+ * there is also the case where the stack has requested us to pass
+ * control frames on up (pass_ctrl) which we must consider. */
+ if (!bad_frame &&
+ filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats)
+ && !mac->pass_ctrl)
+ return 0;
- return 0;
-}
+ fc = le16_to_cpu(*((__le16 *) buffer));
-static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
-{
- int r;
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- struct ieee80211_rx_stats stats;
- const struct rx_status *status;
+ is_qos = ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) &&
+ ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_QOS_DATA);
+ is_4addr = (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS);
+ need_padding = is_qos ^ is_4addr;
- if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
- IEEE80211_FCS_LEN + sizeof(struct rx_status))
- {
- ieee->stats.rx_errors++;
- ieee->stats.rx_length_errors++;
- goto free_skb;
+ skb = dev_alloc_skb(length + (need_padding ? 2 : 0));
+ if (skb == NULL)
+ return -ENOMEM;
+ if (need_padding) {
+ /* Make sure the the payload data is 4 byte aligned. */
+ skb_reserve(skb, 2);
}
- r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
- if (r) {
- /* Only packets with rx errors are included here.
- * The error stats have already been set in fill_rx_stats.
- */
- goto free_skb;
- }
+ memcpy(skb_put(skb, length), buffer, length);
- __skb_pull(skb, ZD_PLCP_HEADER_SIZE);
- __skb_trim(skb, skb->len -
- (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
+ ieee80211_rx_irqsafe(hw, skb, &stats);
+ return 0;
+}
- ZD_ASSERT(IS_ALIGNED((unsigned long)skb->data, 4));
+static int zd_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
- update_qual_rssi(mac, skb->data, skb->len, stats.signal,
- status->signal_strength);
+ /* using IEEE80211_IF_TYPE_INVALID to indicate no mode selected */
+ if (mac->type != IEEE80211_IF_TYPE_INVALID)
+ return -EOPNOTSUPP;
- r = filter_rx(ieee, skb->data, skb->len, &stats);
- if (r <= 0) {
- if (r < 0) {
- ieee->stats.rx_errors++;
- dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
- }
- goto free_skb;
+ switch (conf->type) {
+ case IEEE80211_IF_TYPE_MNTR:
+ case IEEE80211_IF_TYPE_STA:
+ mac->type = conf->type;
+ break;
+ default:
+ return -EOPNOTSUPP;
}
- if (ieee->iw_mode == IW_MODE_MONITOR)
- fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
- &stats, status);
-
- r = ieee80211_rx(ieee, skb, &stats);
- if (r)
- return;
-free_skb:
- /* We are always in a soft irq. */
- dev_kfree_skb(skb);
+ return zd_write_mac_addr(&mac->chip, conf->mac_addr);
}
-static void do_rx(unsigned long mac_ptr)
+static void zd_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
- struct zd_mac *mac = (struct zd_mac *)mac_ptr;
- struct sk_buff *skb;
+ struct zd_mac *mac = zd_hw_mac(hw);
+ mac->type = IEEE80211_IF_TYPE_INVALID;
+ zd_write_mac_addr(&mac->chip, NULL);
+}
- while ((skb = skb_dequeue(&mac->rx_queue)) != NULL)
- zd_mac_rx(mac, skb);
+static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+{
+ struct zd_mac *mac = zd_hw_mac(hw);
+ return zd_chip_set_channel(&mac->chip, conf->channel);
}
-int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+static int zd_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
- struct sk_buff *skb;
- unsigned int reserved =
- ALIGN(max_t(unsigned int,
- sizeof(struct zd_rt_hdr), ZD_PLCP_HEADER_SIZE), 4) -
- ZD_PLCP_HEADER_SIZE;
-
- skb = dev_alloc_skb(reserved + length);
- if (!skb) {
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
- ieee->stats.rx_dropped++;
- return -ENOMEM;
- }
- skb_reserve(skb, reserved);
- memcpy(__skb_put(skb, length), buffer, length);
- skb_queue_tail(&mac->rx_queue, skb);
- tasklet_schedule(&mac->rx_tasklet);
+ struct zd_mac *mac = zd_hw_mac(hw);
+
+ spin_lock_irq(&mac->lock);
+ mac->associated = is_valid_ether_addr(conf->bssid);
+ spin_unlock_irq(&mac->lock);
+
+ /* TODO: do hardware bssid filtering */
return 0;
}
-static int netdev_tx(struct ieee80211_txb *txb, struct net_device *netdev,
- int pri)
+static void set_multicast_hash_handler(struct work_struct *work)
{
- return zd_mac_tx(zd_netdev_mac(netdev), txb, pri);
+ struct zd_mac *mac =
+ container_of(work, struct zd_mac, set_multicast_hash_work);
+ struct zd_mc_hash hash;
+
+ spin_lock_irq(&mac->lock);
+ hash = mac->multicast_hash;
+ spin_unlock_irq(&mac->lock);
+
+ zd_chip_set_multicast_hash(&mac->chip, &hash);
}
-static void set_security(struct net_device *netdev,
- struct ieee80211_security *sec)
+static void set_rx_filter_handler(struct work_struct *work)
{
- struct ieee80211_device *ieee = zd_netdev_ieee80211(netdev);
- struct ieee80211_security *secinfo = &ieee->sec;
- int keyidx;
-
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
-
- for (keyidx = 0; keyidx<WEP_KEYS; keyidx++)
- if (sec->flags & (1<<keyidx)) {
- secinfo->encode_alg[keyidx] = sec->encode_alg[keyidx];
- secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx];
- memcpy(secinfo->keys[keyidx], sec->keys[keyidx],
- SCM_KEY_LEN);
- }
+ struct zd_mac *mac =
+ container_of(work, struct zd_mac, set_rx_filter_work);
+ int r;
- if (sec->flags & SEC_ACTIVE_KEY) {
- secinfo->active_key = sec->active_key;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .active_key = %d\n", sec->active_key);
- }
- if (sec->flags & SEC_UNICAST_GROUP) {
- secinfo->unicast_uses_group = sec->unicast_uses_group;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .unicast_uses_group = %d\n",
- sec->unicast_uses_group);
- }
- if (sec->flags & SEC_LEVEL) {
- secinfo->level = sec->level;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .level = %d\n", sec->level);
- }
- if (sec->flags & SEC_ENABLED) {
- secinfo->enabled = sec->enabled;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .enabled = %d\n", sec->enabled);
- }
- if (sec->flags & SEC_ENCRYPT) {
- secinfo->encrypt = sec->encrypt;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .encrypt = %d\n", sec->encrypt);
- }
- if (sec->flags & SEC_AUTH_MODE) {
- secinfo->auth_mode = sec->auth_mode;
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)),
- " .auth_mode = %d\n", sec->auth_mode);
+ dev_dbg_f(zd_mac_dev(mac), "\n");
+ r = set_rx_filter(mac);
+ if (r)
+ dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
+}
+
+#define SUPPORTED_FIF_FLAGS \
+ (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \
+ FIF_OTHER_BSS)
+static void zd_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed_flags,
+ unsigned int *new_flags,
+ int mc_count, struct dev_mc_list *mclist)
+{
+ struct zd_mc_hash hash;
+ struct zd_mac *mac = zd_hw_mac(hw);
+ unsigned long flags;
+ int i;
+
+ /* Only deal with supported flags */
+ changed_flags &= SUPPORTED_FIF_FLAGS;
+ *new_flags &= SUPPORTED_FIF_FLAGS;
+
+ /* changed_flags is always populated but this driver
+ * doesn't support all FIF flags so its possible we don't
+ * need to do anything */
+ if (!changed_flags)
+ return;
+
+ if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
+ zd_mc_add_all(&hash);
+ } else {
+ DECLARE_MAC_BUF(macbuf);
+
+ zd_mc_clear(&hash);
+ for (i = 0; i < mc_count; i++) {
+ if (!mclist)
+ break;
+ dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
+ print_mac(macbuf, mclist->dmi_addr));
+ zd_mc_add_addr(&hash, mclist->dmi_addr);
+ mclist = mclist->next;
+ }
}
+
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL);
+ mac->pass_ctrl = !!(*new_flags & FIF_CONTROL);
+ mac->multicast_hash = hash;
+ spin_unlock_irqrestore(&mac->lock, flags);
+ queue_work(zd_workqueue, &mac->set_multicast_hash_work);
+
+ if (changed_flags & FIF_CONTROL)
+ queue_work(zd_workqueue, &mac->set_rx_filter_work);
+
+ /* no handling required for FIF_OTHER_BSS as we don't currently
+ * do BSSID filtering */
+ /* FIXME: in future it would be nice to enable the probe response
+ * filter (so that the driver doesn't see them) until
+ * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd
+ * have to schedule work to enable prbresp reception, which might
+ * happen too late. For now we'll just listen and forward them all the
+ * time. */
}
-static void ieee_init(struct ieee80211_device *ieee)
+static void set_rts_cts_work(struct work_struct *work)
{
- ieee->mode = IEEE_B | IEEE_G;
- ieee->freq_band = IEEE80211_24GHZ_BAND;
- ieee->modulation = IEEE80211_OFDM_MODULATION | IEEE80211_CCK_MODULATION;
- ieee->tx_headroom = sizeof(struct zd_ctrlset);
- ieee->set_security = set_security;
- ieee->hard_start_xmit = netdev_tx;
-
- /* Software encryption/decryption for now */
- ieee->host_build_iv = 0;
- ieee->host_encrypt = 1;
- ieee->host_decrypt = 1;
-
- /* FIXME: default to managed mode, until ieee80211 and zd1211rw can
- * correctly support AUTO */
- ieee->iw_mode = IW_MODE_INFRA;
+ struct zd_mac *mac =
+ container_of(work, struct zd_mac, set_rts_cts_work);
+ unsigned long flags;
+ unsigned int short_preamble;
+
+ mutex_lock(&mac->chip.mutex);
+
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->updating_rts_rate = 0;
+ short_preamble = mac->short_preamble;
+ spin_unlock_irqrestore(&mac->lock, flags);
+
+ zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
+ mutex_unlock(&mac->chip.mutex);
}
-static void softmac_init(struct ieee80211softmac_device *sm)
+static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *bss_conf,
+ u32 changes)
{
- sm->set_channel = set_channel;
- sm->bssinfo_change = bssinfo_change;
+ struct zd_mac *mac = zd_hw_mac(hw);
+ unsigned long flags;
+
+ dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
+
+ if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+ spin_lock_irqsave(&mac->lock, flags);
+ mac->short_preamble = bss_conf->use_short_preamble;
+ if (!mac->updating_rts_rate) {
+ mac->updating_rts_rate = 1;
+ /* FIXME: should disable TX here, until work has
+ * completed and RTS_CTS reg is updated */
+ queue_work(zd_workqueue, &mac->set_rts_cts_work);
+ }
+ spin_unlock_irqrestore(&mac->lock, flags);
+ }
}
-struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev)
+static const struct ieee80211_ops zd_ops = {
+ .tx = zd_op_tx,
+ .start = zd_op_start,
+ .stop = zd_op_stop,
+ .add_interface = zd_op_add_interface,
+ .remove_interface = zd_op_remove_interface,
+ .config = zd_op_config,
+ .config_interface = zd_op_config_interface,
+ .configure_filter = zd_op_configure_filter,
+ .bss_info_changed = zd_op_bss_info_changed,
+};
+
+struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
{
- struct zd_mac *mac = zd_netdev_mac(ndev);
- struct iw_statistics *iw_stats = &mac->iw_stats;
- unsigned int i, count, qual_total, rssi_total;
+ struct zd_mac *mac;
+ struct ieee80211_hw *hw;
+ int i;
- memset(iw_stats, 0, sizeof(struct iw_statistics));
- /* We are not setting the status, because ieee->state is not updated
- * at all and this driver doesn't track authentication state.
- */
- spin_lock_irq(&mac->lock);
- count = mac->stats_count < ZD_MAC_STATS_BUFFER_SIZE ?
- mac->stats_count : ZD_MAC_STATS_BUFFER_SIZE;
- qual_total = rssi_total = 0;
- for (i = 0; i < count; i++) {
- qual_total += mac->qual_buffer[i];
- rssi_total += mac->rssi_buffer[i];
+ hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops);
+ if (!hw) {
+ dev_dbg_f(&intf->dev, "out of memory\n");
+ return NULL;
}
- spin_unlock_irq(&mac->lock);
- iw_stats->qual.updated = IW_QUAL_NOISE_INVALID;
- if (count > 0) {
- iw_stats->qual.qual = qual_total / count;
- iw_stats->qual.level = rssi_total / count;
- iw_stats->qual.updated |=
- IW_QUAL_QUAL_UPDATED|IW_QUAL_LEVEL_UPDATED;
- } else {
- iw_stats->qual.updated |=
- IW_QUAL_QUAL_INVALID|IW_QUAL_LEVEL_INVALID;
+
+ mac = zd_hw_mac(hw);
+
+ memset(mac, 0, sizeof(*mac));
+ spin_lock_init(&mac->lock);
+ mac->hw = hw;
+
+ mac->type = IEEE80211_IF_TYPE_INVALID;
+
+ memcpy(mac->channels, zd_channels, sizeof(zd_channels));
+ memcpy(mac->rates, zd_rates, sizeof(zd_rates));
+ mac->modes[0].mode = MODE_IEEE80211G;
+ mac->modes[0].num_rates = ARRAY_SIZE(zd_rates);
+ mac->modes[0].rates = mac->rates;
+ mac->modes[0].num_channels = ARRAY_SIZE(zd_channels);
+ mac->modes[0].channels = mac->channels;
+ mac->modes[1].mode = MODE_IEEE80211B;
+ mac->modes[1].num_rates = 4;
+ mac->modes[1].rates = mac->rates;
+ mac->modes[1].num_channels = ARRAY_SIZE(zd_channels);
+ mac->modes[1].channels = mac->channels;
+
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_DEFAULT_REG_DOMAIN_CONFIGURED;
+ hw->max_rssi = 100;
+ hw->max_signal = 100;
+
+ hw->queues = 1;
+ hw->extra_tx_headroom = sizeof(struct zd_ctrlset);
+
+ skb_queue_head_init(&mac->ack_wait_queue);
+
+ for (i = 0; i < 2; i++) {
+ if (ieee80211_register_hwmode(hw, &mac->modes[i])) {
+ dev_dbg_f(&intf->dev, "cannot register hwmode\n");
+ ieee80211_free_hw(hw);
+ return NULL;
+ }
}
- /* TODO: update counter */
- return iw_stats;
+
+ zd_chip_init(&mac->chip, hw, intf);
+ housekeeping_init(mac);
+ INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
+ INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
+ INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
+
+ SET_IEEE80211_DEV(hw, &intf->dev);
+ return hw;
}
#define LINK_LED_WORK_DELAY HZ
@@ -1308,18 +952,17 @@ static void link_led_handler(struct work_struct *work)
struct zd_mac *mac =
container_of(work, struct zd_mac, housekeeping.link_led_work.work);
struct zd_chip *chip = &mac->chip;
- struct ieee80211softmac_device *sm = ieee80211_priv(mac->netdev);
int is_associated;
int r;
spin_lock_irq(&mac->lock);
- is_associated = sm->associnfo.associated != 0;
+ is_associated = mac->associated;
spin_unlock_irq(&mac->lock);
r = zd_chip_control_leds(chip,
is_associated ? LED_ASSOCIATED : LED_SCANNING);
if (r)
- dev_err(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
+ dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
LINK_LED_WORK_DELAY);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 1b15bde3ff60..2dde108df767 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -1,4 +1,7 @@
-/* zd_mac.h
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -18,14 +21,11 @@
#ifndef _ZD_MAC_H
#define _ZD_MAC_H
-#include <linux/wireless.h>
#include <linux/kernel.h>
-#include <linux/workqueue.h>
-#include <net/ieee80211.h>
-#include <net/ieee80211softmac.h>
+#include <net/mac80211.h>
#include "zd_chip.h"
-#include "zd_netdev.h"
+#include "zd_ieee80211.h"
struct zd_ctrlset {
u8 modulation;
@@ -57,7 +57,7 @@ struct zd_ctrlset {
/* The two possible modulation types. Notify that 802.11b doesn't use the CCK
* codeing for the 1 and 2 MBit/s rate. We stay with the term here to remain
* consistent with uses the term at other places.
- */
+ */
#define ZD_CCK 0x00
#define ZD_OFDM 0x10
@@ -141,58 +141,68 @@ struct rx_status {
#define ZD_RX_CRC16_ERROR 0x40
#define ZD_RX_ERROR 0x80
+enum mac_flags {
+ MAC_FIXED_CHANNEL = 0x01,
+};
+
struct housekeeping {
struct delayed_work link_led_work;
};
+/**
+ * struct zd_tx_skb_control_block - control block for tx skbuffs
+ * @control: &struct ieee80211_tx_control pointer
+ * @context: context pointer
+ *
+ * This structure is used to fill the cb field in an &sk_buff to transmit.
+ * The control field is NULL, if there is no requirement from the mac80211
+ * stack to report about the packet ACK. This is the case if the flag
+ * IEEE80211_TXCTL_NO_ACK is not set in &struct ieee80211_tx_control.
+ */
+struct zd_tx_skb_control_block {
+ struct ieee80211_tx_control *control;
+ struct ieee80211_hw *hw;
+ void *context;
+};
+
#define ZD_MAC_STATS_BUFFER_SIZE 16
+#define ZD_MAC_MAX_ACK_WAITERS 10
+
struct zd_mac {
struct zd_chip chip;
spinlock_t lock;
- struct net_device *netdev;
-
- /* Unlocked reading possible */
- struct iw_statistics iw_stats;
-
+ struct ieee80211_hw *hw;
struct housekeeping housekeeping;
struct work_struct set_multicast_hash_work;
+ struct work_struct set_rts_cts_work;
+ struct work_struct set_rx_filter_work;
struct zd_mc_hash multicast_hash;
- struct delayed_work set_rts_cts_work;
- struct delayed_work set_basic_rates_work;
-
- struct tasklet_struct rx_tasklet;
- struct sk_buff_head rx_queue;
-
- unsigned int stats_count;
- u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
- u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
u8 regdomain;
u8 default_regdomain;
- u8 requested_channel;
-
- /* A bitpattern of cr_rates */
- u16 basic_rates;
-
- /* A zd_rate */
- u8 rts_rate;
+ int type;
+ int associated;
+ struct sk_buff_head ack_wait_queue;
+ struct ieee80211_channel channels[14];
+ struct ieee80211_rate rates[12];
+ struct ieee80211_hw_mode modes[2];
/* Short preamble (used for RTS/CTS) */
unsigned int short_preamble:1;
/* flags to indicate update in progress */
unsigned int updating_rts_rate:1;
- unsigned int updating_basic_rates:1;
-};
-static inline struct ieee80211_device *zd_mac_to_ieee80211(struct zd_mac *mac)
-{
- return zd_netdev_ieee80211(mac->netdev);
-}
+ /* whether to pass frames with CRC errors to stack */
+ unsigned int pass_failed_fcs:1;
-static inline struct zd_mac *zd_netdev_mac(struct net_device *netdev)
+ /* whether to pass control frames to stack */
+ unsigned int pass_ctrl:1;
+};
+
+static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw)
{
- return ieee80211softmac_priv(netdev);
+ return hw->priv;
}
static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip)
@@ -205,35 +215,22 @@ static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb)
return zd_chip_to_mac(zd_usb_to_chip(usb));
}
+static inline u8 *zd_mac_get_perm_addr(struct zd_mac *mac)
+{
+ return mac->hw->wiphy->perm_addr;
+}
+
#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip))
-int zd_mac_init(struct zd_mac *mac,
- struct net_device *netdev,
- struct usb_interface *intf);
+struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf);
void zd_mac_clear(struct zd_mac *mac);
-int zd_mac_preinit_hw(struct zd_mac *mac);
-int zd_mac_init_hw(struct zd_mac *mac);
-
-int zd_mac_open(struct net_device *netdev);
-int zd_mac_stop(struct net_device *netdev);
-int zd_mac_set_mac_address(struct net_device *dev, void *p);
-void zd_mac_set_multicast_list(struct net_device *netdev);
-
-int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length);
-
-int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
-u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
-
-int zd_mac_request_channel(struct zd_mac *mac, u8 channel);
-u8 zd_mac_get_channel(struct zd_mac *mac);
-
-int zd_mac_set_mode(struct zd_mac *mac, u32 mode);
-int zd_mac_get_mode(struct zd_mac *mac, u32 *mode);
-
-int zd_mac_get_range(struct zd_mac *mac, struct iw_range *range);
+int zd_mac_preinit_hw(struct ieee80211_hw *hw);
+int zd_mac_init_hw(struct ieee80211_hw *hw);
-struct iw_statistics *zd_mac_get_wireless_stats(struct net_device *ndev);
+int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length);
+void zd_mac_tx_failed(struct ieee80211_hw *hw);
+void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
#ifdef DEBUG
void zd_dump_rx_status(const struct rx_status *status);
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.c b/drivers/net/wireless/zd1211rw/zd_netdev.c
deleted file mode 100644
index 047cab3d87df..000000000000
--- a/drivers/net/wireless/zd1211rw/zd_netdev.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/* zd_netdev.c
- *
- * 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
- */
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <net/ieee80211.h>
-#include <net/ieee80211softmac.h>
-#include <net/ieee80211softmac_wx.h>
-#include <net/iw_handler.h>
-
-#include "zd_def.h"
-#include "zd_netdev.h"
-#include "zd_mac.h"
-#include "zd_ieee80211.h"
-
-/* Region 0 means reset regdomain to default. */
-static int zd_set_regdomain(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- const u8 *regdomain = (u8 *)req;
- return zd_mac_set_regdomain(zd_netdev_mac(netdev), *regdomain);
-}
-
-static int zd_get_regdomain(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- u8 *regdomain = (u8 *)req;
- if (!regdomain)
- return -EINVAL;
- *regdomain = zd_mac_get_regdomain(zd_netdev_mac(netdev));
- return 0;
-}
-
-static const struct iw_priv_args zd_priv_args[] = {
- {
- .cmd = ZD_PRIV_SET_REGDOMAIN,
- .set_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- .name = "set_regdomain",
- },
- {
- .cmd = ZD_PRIV_GET_REGDOMAIN,
- .get_args = IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- .name = "get_regdomain",
- },
-};
-
-#define PRIV_OFFSET(x) [(x)-SIOCIWFIRSTPRIV]
-
-static const iw_handler zd_priv_handler[] = {
- PRIV_OFFSET(ZD_PRIV_SET_REGDOMAIN) = zd_set_regdomain,
- PRIV_OFFSET(ZD_PRIV_GET_REGDOMAIN) = zd_get_regdomain,
-};
-
-static int iw_get_name(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- /* FIXME: check whether 802.11a will also supported */
- strlcpy(req->name, "IEEE 802.11b/g", IFNAMSIZ);
- return 0;
-}
-
-static int iw_get_nick(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- strcpy(extra, "zd1211");
- req->data.length = strlen(extra);
- req->data.flags = 1;
- return 0;
-}
-
-static int iw_set_freq(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- int r;
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct iw_freq *freq = &req->freq;
- u8 channel;
-
- r = zd_find_channel(&channel, freq);
- if (r < 0)
- return r;
- r = zd_mac_request_channel(mac, channel);
- return r;
-}
-
-static int iw_get_freq(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- struct zd_mac *mac = zd_netdev_mac(netdev);
- struct iw_freq *freq = &req->freq;
-
- return zd_channel_to_freq(freq, zd_mac_get_channel(mac));
-}
-
-static int iw_set_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- return zd_mac_set_mode(zd_netdev_mac(netdev), req->mode);
-}
-
-static int iw_get_mode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- return zd_mac_get_mode(zd_netdev_mac(netdev), &req->mode);
-}
-
-static int iw_get_range(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *req, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
-
- dev_dbg_f(zd_mac_dev(zd_netdev_mac(netdev)), "\n");
- req->data.length = sizeof(*range);
- return zd_mac_get_range(zd_netdev_mac(netdev), range);
-}
-
-static int iw_set_encode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
-{
- return ieee80211_wx_set_encode(zd_netdev_ieee80211(netdev), info,
- data, extra);
-}
-
-static int iw_get_encode(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
-{
- return ieee80211_wx_get_encode(zd_netdev_ieee80211(netdev), info,
- data, extra);
-}
-
-static int iw_set_encodeext(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
-{
- return ieee80211_wx_set_encodeext(zd_netdev_ieee80211(netdev), info,
- data, extra);
-}
-
-static int iw_get_encodeext(struct net_device *netdev,
- struct iw_request_info *info,
- union iwreq_data *data,
- char *extra)
-{
- return ieee80211_wx_get_encodeext(zd_netdev_ieee80211(netdev), info,
- data, extra);
-}
-
-#define WX(x) [(x)-SIOCIWFIRST]
-
-static const iw_handler zd_standard_iw_handlers[] = {
- WX(SIOCGIWNAME) = iw_get_name,
- WX(SIOCGIWNICKN) = iw_get_nick,
- WX(SIOCSIWFREQ) = iw_set_freq,
- WX(SIOCGIWFREQ) = iw_get_freq,
- WX(SIOCSIWMODE) = iw_set_mode,
- WX(SIOCGIWMODE) = iw_get_mode,
- WX(SIOCGIWRANGE) = iw_get_range,
- WX(SIOCSIWENCODE) = iw_set_encode,
- WX(SIOCGIWENCODE) = iw_get_encode,
- WX(SIOCSIWENCODEEXT) = iw_set_encodeext,
- WX(SIOCGIWENCODEEXT) = iw_get_encodeext,
- WX(SIOCSIWAUTH) = ieee80211_wx_set_auth,
- WX(SIOCGIWAUTH) = ieee80211_wx_get_auth,
- WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan,
- WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results,
- WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid,
- WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid,
- WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap,
- WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap,
- WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate,
- WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate,
- WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie,
- WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie,
- WX(SIOCSIWMLME) = ieee80211softmac_wx_set_mlme,
-};
-
-static const struct iw_handler_def iw_handler_def = {
- .standard = zd_standard_iw_handlers,
- .num_standard = ARRAY_SIZE(zd_standard_iw_handlers),
- .private = zd_priv_handler,
- .num_private = ARRAY_SIZE(zd_priv_handler),
- .private_args = zd_priv_args,
- .num_private_args = ARRAY_SIZE(zd_priv_args),
- .get_wireless_stats = zd_mac_get_wireless_stats,
-};
-
-struct net_device *zd_netdev_alloc(struct usb_interface *intf)
-{
- int r;
- struct net_device *netdev;
- struct zd_mac *mac;
-
- netdev = alloc_ieee80211softmac(sizeof(struct zd_mac));
- if (!netdev) {
- dev_dbg_f(&intf->dev, "out of memory\n");
- return NULL;
- }
-
- mac = zd_netdev_mac(netdev);
- r = zd_mac_init(mac, netdev, intf);
- if (r) {
- usb_set_intfdata(intf, NULL);
- free_ieee80211(netdev);
- return NULL;
- }
-
- SET_NETDEV_DEV(netdev, &intf->dev);
-
- dev_dbg_f(&intf->dev, "netdev->flags %#06hx\n", netdev->flags);
- dev_dbg_f(&intf->dev, "netdev->features %#010lx\n", netdev->features);
-
- netdev->open = zd_mac_open;
- netdev->stop = zd_mac_stop;
- /* netdev->get_stats = */
- netdev->set_multicast_list = zd_mac_set_multicast_list;
- netdev->set_mac_address = zd_mac_set_mac_address;
- netdev->wireless_handlers = &iw_handler_def;
- /* netdev->ethtool_ops = */
-
- return netdev;
-}
-
-void zd_netdev_free(struct net_device *netdev)
-{
- if (!netdev)
- return;
-
- zd_mac_clear(zd_netdev_mac(netdev));
- free_ieee80211(netdev);
-}
-
-void zd_netdev_disconnect(struct net_device *netdev)
-{
- unregister_netdev(netdev);
-}
diff --git a/drivers/net/wireless/zd1211rw/zd_netdev.h b/drivers/net/wireless/zd1211rw/zd_netdev.h
deleted file mode 100644
index 374a957073c1..000000000000
--- a/drivers/net/wireless/zd1211rw/zd_netdev.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* zd_netdev.h: Header for net device related functions.
- *
- * 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 _ZD_NETDEV_H
-#define _ZD_NETDEV_H
-
-#include <linux/usb.h>
-#include <linux/netdevice.h>
-#include <net/ieee80211.h>
-
-#define ZD_PRIV_SET_REGDOMAIN (SIOCIWFIRSTPRIV)
-#define ZD_PRIV_GET_REGDOMAIN (SIOCIWFIRSTPRIV+1)
-
-static inline struct ieee80211_device *zd_netdev_ieee80211(
- struct net_device *ndev)
-{
- return netdev_priv(ndev);
-}
-
-static inline struct net_device *zd_ieee80211_to_netdev(
- struct ieee80211_device *ieee)
-{
- return ieee->dev;
-}
-
-struct net_device *zd_netdev_alloc(struct usb_interface *intf);
-void zd_netdev_free(struct net_device *netdev);
-
-void zd_netdev_disconnect(struct net_device *netdev);
-
-#endif /* _ZD_NETDEV_H */
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c
index abe5d38f7f4d..ec4129312813 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf.c
@@ -1,4 +1,7 @@
-/* zd_rf.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h
index 30502f26b71c..79dc1035592d 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf.h
+++ b/drivers/net/wireless/zd1211rw/zd_rf.h
@@ -1,4 +1,7 @@
-/* zd_rf.h
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
index 006774de3202..74a8f7a55591 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c
@@ -1,4 +1,7 @@
-/* zd_rf_al2230.c: Functions for the AL2230 RF controller
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
index 73d0bb26f810..65095d661e6b 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c
@@ -1,4 +1,7 @@
-/* zd_rf_al7230b.c: Functions for the AL7230B RF controller
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
index cc70d40684ea..0597d862fbd2 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
@@ -1,4 +1,7 @@
-/* zd_rf_rfmd.c: Functions for the RFMD RF controller
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
index 857dcf3eae61..439799b84876 100644
--- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
+++ b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
@@ -1,4 +1,7 @@
-/* zd_rf_uw2453.c: Functions for the UW2453 RF controller
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -403,7 +406,7 @@ static int uw2453_init_hw(struct zd_rf *rf)
if (r)
return r;
- if (!intr_status & 0xf) {
+ if (!(intr_status & 0xf)) {
dev_dbg_f(zd_chip_dev(chip),
"PLL locked on configuration %d\n", i);
found_config = i;
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index c755b6923812..7942b15acfe7 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -1,4 +1,8 @@
-/* zd_usb.c
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
+ * Copyright (C) 2006-2007 Michael Wu <flamingice@sourmilk.net>
*
* 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
@@ -17,18 +21,16 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/workqueue.h>
-#include <net/ieee80211.h>
+#include <net/mac80211.h>
#include <asm/unaligned.h>
#include "zd_def.h"
-#include "zd_netdev.h"
#include "zd_mac.h"
#include "zd_usb.h"
@@ -55,6 +57,7 @@ static struct usb_device_id usb_ids[] = {
{ USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 },
{ USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 },
+ { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
/* ZD1211B */
{ USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B },
{ USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B },
@@ -353,18 +356,6 @@ out:
spin_unlock(&intr->lock);
}
-static inline void handle_retry_failed_int(struct urb *urb)
-{
- struct zd_usb *usb = urb->context;
- struct zd_mac *mac = zd_usb_to_mac(usb);
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
-
- ieee->stats.tx_errors++;
- ieee->ieee_stats.tx_retry_limit_exceeded++;
- dev_dbg_f(urb_dev(urb), "retry failed interrupt\n");
-}
-
-
static void int_urb_complete(struct urb *urb)
{
int r;
@@ -400,7 +391,7 @@ static void int_urb_complete(struct urb *urb)
handle_regs_int(urb);
break;
case USB_INT_ID_RETRY_FAILED:
- handle_retry_failed_int(urb);
+ zd_mac_tx_failed(zd_usb_to_hw(urb->context));
break;
default:
dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb,
@@ -530,14 +521,10 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
unsigned int length)
{
int i;
- struct zd_mac *mac = zd_usb_to_mac(usb);
const struct rx_length_info *length_info;
if (length < sizeof(struct rx_length_info)) {
/* It's not a complete packet anyhow. */
- struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
- ieee->stats.rx_errors++;
- ieee->stats.rx_length_errors++;
return;
}
length_info = (struct rx_length_info *)
@@ -561,13 +548,13 @@ static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
n = l+k;
if (n > length)
return;
- zd_mac_rx_irq(mac, buffer+l, k);
+ zd_mac_rx(zd_usb_to_hw(usb), buffer+l, k);
if (i >= 2)
return;
l = (n+3) & ~3;
}
} else {
- zd_mac_rx_irq(mac, buffer, length);
+ zd_mac_rx(zd_usb_to_hw(usb), buffer, length);
}
}
@@ -629,7 +616,7 @@ resubmit:
usb_submit_urb(urb, GFP_ATOMIC);
}
-static struct urb *alloc_urb(struct zd_usb *usb)
+static struct urb *alloc_rx_urb(struct zd_usb *usb)
{
struct usb_device *udev = zd_usb_to_usbdev(usb);
struct urb *urb;
@@ -653,7 +640,7 @@ static struct urb *alloc_urb(struct zd_usb *usb)
return urb;
}
-static void free_urb(struct urb *urb)
+static void free_rx_urb(struct urb *urb)
{
if (!urb)
return;
@@ -671,11 +658,11 @@ int zd_usb_enable_rx(struct zd_usb *usb)
dev_dbg_f(zd_usb_dev(usb), "\n");
r = -ENOMEM;
- urbs = kcalloc(URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
+ urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL);
if (!urbs)
goto error;
- for (i = 0; i < URBS_COUNT; i++) {
- urbs[i] = alloc_urb(usb);
+ for (i = 0; i < RX_URBS_COUNT; i++) {
+ urbs[i] = alloc_rx_urb(usb);
if (!urbs[i])
goto error;
}
@@ -688,10 +675,10 @@ int zd_usb_enable_rx(struct zd_usb *usb)
goto error;
}
rx->urbs = urbs;
- rx->urbs_count = URBS_COUNT;
+ rx->urbs_count = RX_URBS_COUNT;
spin_unlock_irq(&rx->lock);
- for (i = 0; i < URBS_COUNT; i++) {
+ for (i = 0; i < RX_URBS_COUNT; i++) {
r = usb_submit_urb(urbs[i], GFP_KERNEL);
if (r)
goto error_submit;
@@ -699,7 +686,7 @@ int zd_usb_enable_rx(struct zd_usb *usb)
return 0;
error_submit:
- for (i = 0; i < URBS_COUNT; i++) {
+ for (i = 0; i < RX_URBS_COUNT; i++) {
usb_kill_urb(urbs[i]);
}
spin_lock_irq(&rx->lock);
@@ -708,8 +695,8 @@ error_submit:
spin_unlock_irq(&rx->lock);
error:
if (urbs) {
- for (i = 0; i < URBS_COUNT; i++)
- free_urb(urbs[i]);
+ for (i = 0; i < RX_URBS_COUNT; i++)
+ free_rx_urb(urbs[i]);
}
return r;
}
@@ -731,7 +718,7 @@ void zd_usb_disable_rx(struct zd_usb *usb)
for (i = 0; i < count; i++) {
usb_kill_urb(urbs[i]);
- free_urb(urbs[i]);
+ free_rx_urb(urbs[i]);
}
kfree(urbs);
@@ -741,9 +728,142 @@ void zd_usb_disable_rx(struct zd_usb *usb)
spin_unlock_irqrestore(&rx->lock, flags);
}
+/**
+ * zd_usb_disable_tx - disable transmission
+ * @usb: the zd1211rw-private USB structure
+ *
+ * Frees all URBs in the free list and marks the transmission as disabled.
+ */
+void zd_usb_disable_tx(struct zd_usb *usb)
+{
+ struct zd_usb_tx *tx = &usb->tx;
+ unsigned long flags;
+ struct list_head *pos, *n;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ list_for_each_safe(pos, n, &tx->free_urb_list) {
+ list_del(pos);
+ usb_free_urb(list_entry(pos, struct urb, urb_list));
+ }
+ tx->enabled = 0;
+ tx->submitted_urbs = 0;
+ /* The stopped state is ignored, relying on ieee80211_wake_queues()
+ * in a potentionally following zd_usb_enable_tx().
+ */
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+/**
+ * zd_usb_enable_tx - enables transmission
+ * @usb: a &struct zd_usb pointer
+ *
+ * This function enables transmission and prepares the &zd_usb_tx data
+ * structure.
+ */
+void zd_usb_enable_tx(struct zd_usb *usb)
+{
+ unsigned long flags;
+ struct zd_usb_tx *tx = &usb->tx;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ tx->enabled = 1;
+ tx->submitted_urbs = 0;
+ ieee80211_wake_queues(zd_usb_to_hw(usb));
+ tx->stopped = 0;
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+/**
+ * alloc_tx_urb - provides an tx URB
+ * @usb: a &struct zd_usb pointer
+ *
+ * Allocates a new URB. If possible takes the urb from the free list in
+ * usb->tx.
+ */
+static struct urb *alloc_tx_urb(struct zd_usb *usb)
+{
+ struct zd_usb_tx *tx = &usb->tx;
+ unsigned long flags;
+ struct list_head *entry;
+ struct urb *urb;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ if (list_empty(&tx->free_urb_list)) {
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ goto out;
+ }
+ entry = tx->free_urb_list.next;
+ list_del(entry);
+ urb = list_entry(entry, struct urb, urb_list);
+out:
+ spin_unlock_irqrestore(&tx->lock, flags);
+ return urb;
+}
+
+/**
+ * free_tx_urb - frees a used tx URB
+ * @usb: a &struct zd_usb pointer
+ * @urb: URB to be freed
+ *
+ * Frees the the transmission URB, which means to put it on the free URB
+ * list.
+ */
+static void free_tx_urb(struct zd_usb *usb, struct urb *urb)
+{
+ struct zd_usb_tx *tx = &usb->tx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ if (!tx->enabled) {
+ usb_free_urb(urb);
+ goto out;
+ }
+ list_add(&urb->urb_list, &tx->free_urb_list);
+out:
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void tx_dec_submitted_urbs(struct zd_usb *usb)
+{
+ struct zd_usb_tx *tx = &usb->tx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ --tx->submitted_urbs;
+ if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) {
+ ieee80211_wake_queues(zd_usb_to_hw(usb));
+ tx->stopped = 0;
+ }
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+static void tx_inc_submitted_urbs(struct zd_usb *usb)
+{
+ struct zd_usb_tx *tx = &usb->tx;
+ unsigned long flags;
+
+ spin_lock_irqsave(&tx->lock, flags);
+ ++tx->submitted_urbs;
+ if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) {
+ ieee80211_stop_queues(zd_usb_to_hw(usb));
+ tx->stopped = 1;
+ }
+ spin_unlock_irqrestore(&tx->lock, flags);
+}
+
+/**
+ * tx_urb_complete - completes the execution of an URB
+ * @urb: a URB
+ *
+ * This function is called if the URB has been transferred to a device or an
+ * error has happened.
+ */
static void tx_urb_complete(struct urb *urb)
{
int r;
+ struct sk_buff *skb;
+ struct zd_tx_skb_control_block *cb;
+ struct zd_usb *usb;
switch (urb->status) {
case 0:
@@ -761,9 +881,12 @@ static void tx_urb_complete(struct urb *urb)
goto resubmit;
}
free_urb:
- usb_buffer_free(urb->dev, urb->transfer_buffer_length,
- urb->transfer_buffer, urb->transfer_dma);
- usb_free_urb(urb);
+ skb = (struct sk_buff *)urb->context;
+ zd_mac_tx_to_dev(skb, urb->status);
+ cb = (struct zd_tx_skb_control_block *)skb->cb;
+ usb = &zd_hw_mac(cb->hw)->chip.usb;
+ free_tx_urb(usb, urb);
+ tx_dec_submitted_urbs(usb);
return;
resubmit:
r = usb_submit_urb(urb, GFP_ATOMIC);
@@ -773,43 +896,40 @@ resubmit:
}
}
-/* Puts the frame on the USB endpoint. It doesn't wait for
- * completion. The frame must contain the control set.
+/**
+ * zd_usb_tx: initiates transfer of a frame of the device
+ *
+ * @usb: the zd1211rw-private USB structure
+ * @skb: a &struct sk_buff pointer
+ *
+ * This function tranmits a frame to the device. It doesn't wait for
+ * completion. The frame must contain the control set and have all the
+ * control set information available.
+ *
+ * The function returns 0 if the transfer has been successfully initiated.
*/
-int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length)
+int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
{
int r;
struct usb_device *udev = zd_usb_to_usbdev(usb);
struct urb *urb;
- void *buffer;
- urb = usb_alloc_urb(0, GFP_ATOMIC);
+ urb = alloc_tx_urb(usb);
if (!urb) {
r = -ENOMEM;
goto out;
}
- buffer = usb_buffer_alloc(zd_usb_to_usbdev(usb), length, GFP_ATOMIC,
- &urb->transfer_dma);
- if (!buffer) {
- r = -ENOMEM;
- goto error_free_urb;
- }
- memcpy(buffer, frame, length);
-
usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
- buffer, length, tx_urb_complete, NULL);
- urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ skb->data, skb->len, tx_urb_complete, skb);
r = usb_submit_urb(urb, GFP_ATOMIC);
if (r)
goto error;
+ tx_inc_submitted_urbs(usb);
return 0;
error:
- usb_buffer_free(zd_usb_to_usbdev(usb), length, buffer,
- urb->transfer_dma);
-error_free_urb:
- usb_free_urb(urb);
+ free_tx_urb(usb, urb);
out:
return r;
}
@@ -838,16 +958,20 @@ static inline void init_usb_rx(struct zd_usb *usb)
static inline void init_usb_tx(struct zd_usb *usb)
{
- /* FIXME: at this point we will allocate a fixed number of urb's for
- * use in a cyclic scheme */
+ struct zd_usb_tx *tx = &usb->tx;
+ spin_lock_init(&tx->lock);
+ tx->enabled = 0;
+ tx->stopped = 0;
+ INIT_LIST_HEAD(&tx->free_urb_list);
+ tx->submitted_urbs = 0;
}
-void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
+void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
struct usb_interface *intf)
{
memset(usb, 0, sizeof(*usb));
usb->intf = usb_get_intf(intf);
- usb_set_intfdata(usb->intf, netdev);
+ usb_set_intfdata(usb->intf, hw);
init_usb_interrupt(usb);
init_usb_tx(usb);
init_usb_rx(usb);
@@ -973,7 +1097,7 @@ int zd_usb_init_hw(struct zd_usb *usb)
return r;
}
- r = zd_mac_init_hw(mac);
+ r = zd_mac_init_hw(mac->hw);
if (r) {
dev_dbg_f(zd_usb_dev(usb),
"couldn't initialize mac. Error number %d\n", r);
@@ -987,9 +1111,9 @@ int zd_usb_init_hw(struct zd_usb *usb)
static int probe(struct usb_interface *intf, const struct usb_device_id *id)
{
int r;
- struct zd_usb *usb;
struct usb_device *udev = interface_to_usbdev(intf);
- struct net_device *netdev = NULL;
+ struct zd_usb *usb;
+ struct ieee80211_hw *hw = NULL;
print_id(udev);
@@ -1007,57 +1131,65 @@ static int probe(struct usb_interface *intf, const struct usb_device_id *id)
goto error;
}
- usb_reset_device(interface_to_usbdev(intf));
+ r = usb_reset_device(udev);
+ if (r) {
+ dev_err(&intf->dev,
+ "couldn't reset usb device. Error number %d\n", r);
+ goto error;
+ }
- netdev = zd_netdev_alloc(intf);
- if (netdev == NULL) {
+ hw = zd_mac_alloc_hw(intf);
+ if (hw == NULL) {
r = -ENOMEM;
goto error;
}
- usb = &zd_netdev_mac(netdev)->chip.usb;
+ usb = &zd_hw_mac(hw)->chip.usb;
usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0;
- r = zd_mac_preinit_hw(zd_netdev_mac(netdev));
+ r = zd_mac_preinit_hw(hw);
if (r) {
dev_dbg_f(&intf->dev,
"couldn't initialize mac. Error number %d\n", r);
goto error;
}
- r = register_netdev(netdev);
+ r = ieee80211_register_hw(hw);
if (r) {
dev_dbg_f(&intf->dev,
- "couldn't register netdev. Error number %d\n", r);
+ "couldn't register device. Error number %d\n", r);
goto error;
}
dev_dbg_f(&intf->dev, "successful\n");
- dev_info(&intf->dev,"%s\n", netdev->name);
+ dev_info(&intf->dev, "%s\n", wiphy_name(hw->wiphy));
return 0;
error:
usb_reset_device(interface_to_usbdev(intf));
- zd_netdev_free(netdev);
+ if (hw) {
+ zd_mac_clear(zd_hw_mac(hw));
+ ieee80211_free_hw(hw);
+ }
return r;
}
static void disconnect(struct usb_interface *intf)
{
- struct net_device *netdev = zd_intf_to_netdev(intf);
+ struct ieee80211_hw *hw = zd_intf_to_hw(intf);
struct zd_mac *mac;
struct zd_usb *usb;
/* Either something really bad happened, or we're just dealing with
* a DEVICE_INSTALLER. */
- if (netdev == NULL)
+ if (hw == NULL)
return;
- mac = zd_netdev_mac(netdev);
+ mac = zd_hw_mac(hw);
usb = &mac->chip.usb;
dev_dbg_f(zd_usb_dev(usb), "\n");
- zd_netdev_disconnect(netdev);
+ ieee80211_unregister_hw(hw);
/* Just in case something has gone wrong! */
zd_usb_disable_rx(usb);
@@ -1070,12 +1202,13 @@ static void disconnect(struct usb_interface *intf)
*/
usb_reset_device(interface_to_usbdev(intf));
- zd_netdev_free(netdev);
+ zd_mac_clear(mac);
+ ieee80211_free_hw(hw);
dev_dbg(&intf->dev, "disconnected\n");
}
static struct usb_driver driver = {
- .name = "zd1211rw",
+ .name = KBUILD_MODNAME,
.id_table = usb_ids,
.probe = probe,
.disconnect = disconnect,
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h
index 961a7a12ad68..049f8b91f020 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.h
+++ b/drivers/net/wireless/zd1211rw/zd_usb.h
@@ -1,4 +1,7 @@
-/* zd_usb.h: Header for USB interface implemented by ZD1211 chip
+/* ZD1211 USB-WLAN driver for Linux
+ *
+ * Copyright (C) 2005-2007 Ulrich Kunitz <kune@deine-taler.de>
+ * Copyright (C) 2006-2007 Daniel Drake <dsd@gentoo.org>
*
* 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
@@ -26,6 +29,9 @@
#include "zd_def.h"
+#define ZD_USB_TX_HIGH 5
+#define ZD_USB_TX_LOW 2
+
enum devicetype {
DEVICE_ZD1211 = 0,
DEVICE_ZD1211B = 1,
@@ -165,7 +171,7 @@ static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr)
return (struct usb_int_regs *)intr->read_regs.buffer;
}
-#define URBS_COUNT 5
+#define RX_URBS_COUNT 5
struct zd_usb_rx {
spinlock_t lock;
@@ -176,8 +182,21 @@ struct zd_usb_rx {
int urbs_count;
};
+/**
+ * struct zd_usb_tx - structure used for transmitting frames
+ * @lock: lock for transmission
+ * @free_urb_list: list of free URBs, contains all the URBs, which can be used
+ * @submitted_urbs: atomic integer that counts the URBs having sent to the
+ * device, which haven't been completed
+ * @enabled: enabled flag, indicates whether tx is enabled
+ * @stopped: indicates whether higher level tx queues are stopped
+ */
struct zd_usb_tx {
spinlock_t lock;
+ struct list_head free_urb_list;
+ int submitted_urbs;
+ int enabled;
+ int stopped;
};
/* Contains the usb parts. The structure doesn't require a lock because intf
@@ -198,17 +217,17 @@ static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb)
return interface_to_usbdev(usb->intf);
}
-static inline struct net_device *zd_intf_to_netdev(struct usb_interface *intf)
+static inline struct ieee80211_hw *zd_intf_to_hw(struct usb_interface *intf)
{
return usb_get_intfdata(intf);
}
-static inline struct net_device *zd_usb_to_netdev(struct zd_usb *usb)
+static inline struct ieee80211_hw *zd_usb_to_hw(struct zd_usb *usb)
{
- return zd_intf_to_netdev(usb->intf);
+ return zd_intf_to_hw(usb->intf);
}
-void zd_usb_init(struct zd_usb *usb, struct net_device *netdev,
+void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
struct usb_interface *intf);
int zd_usb_init_hw(struct zd_usb *usb);
void zd_usb_clear(struct zd_usb *usb);
@@ -221,7 +240,10 @@ void zd_usb_disable_int(struct zd_usb *usb);
int zd_usb_enable_rx(struct zd_usb *usb);
void zd_usb_disable_rx(struct zd_usb *usb);
-int zd_usb_tx(struct zd_usb *usb, const u8 *frame, unsigned int length);
+void zd_usb_enable_tx(struct zd_usb *usb);
+void zd_usb_disable_tx(struct zd_usb *usb);
+
+int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb);
int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
const zd_addr_t *addresses, unsigned int count);