aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS14
-rw-r--r--drivers/net/usb/usbnet.c44
-rw-r--r--drivers/net/wireless/ath/Kconfig4
-rw-r--r--drivers/net/wireless/ath/ath.h30
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h17
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c60
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c138
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h6
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c47
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c155
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig8
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c195
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c3870
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h245
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c1186
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c1183
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c1385
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h19
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.c12
-rw-r--r--drivers/net/wireless/ath/ath9k/phy.h21
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c48
-rw-r--r--drivers/net/wireless/ath/main.c36
-rw-r--r--drivers/net/wireless/b43/b43.h11
-rw-r--r--drivers/net/wireless/b43/main.c210
-rw-r--r--drivers/net/wireless/b43/phy_lp.c768
-rw-r--r--drivers/net/wireless/b43/phy_lp.h19
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.c2151
-rw-r--r--drivers/net/wireless/b43/tables_lpphy.h13
-rw-r--r--drivers/net/wireless/b43/xmit.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c72
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c81
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c129
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c354
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c951
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h104
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c496
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h80
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c101
-rw-r--r--drivers/net/wireless/libertas/main.c3
-rw-r--r--drivers/net/wireless/orinoco/hw.c120
-rw-r--r--drivers/net/wireless/orinoco/hw.h7
-rw-r--r--drivers/net/wireless/orinoco/main.c35
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h16
-rw-r--r--drivers/net/wireless/orinoco/wext.c173
-rw-r--r--drivers/net/wireless/p54/fwio.c5
-rw-r--r--drivers/net/wireless/p54/main.c7
-rw-r--r--drivers/net/wireless/p54/txrx.c6
-rw-r--r--drivers/net/wireless/rndis_wlan.c13
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c15
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c11
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h33
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c22
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c14
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c154
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c72
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c10
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c10
-rw-r--r--drivers/net/wireless/rtl818x/rtl818x.h14
-rw-r--r--drivers/net/wireless/wl12xx/Kconfig38
-rw-r--r--drivers/net/wireless/wl12xx/Makefile13
-rw-r--r--drivers/net/wireless/wl12xx/wl1251.h78
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.c84
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_acx.h146
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.c266
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_boot.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.c62
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_cmd.h4
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_event.c7
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_init.c213
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_init.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_io.c196
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_io.h64
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_main.c375
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ops.c728
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ops.h165
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_ps.c18
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_reg.h644
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_rx.c9
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_sdio.c205
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.c327
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_spi.h56
-rw-r--r--drivers/net/wireless/wl12xx/wl1251_tx.c64
-rw-r--r--drivers/net/wireless/wl12xx/wl1271.h407
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.c961
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_acx.h1221
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.c541
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_boot.h72
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c813
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h464
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.c518
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_debugfs.h33
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c125
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.h110
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c397
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.h115
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c1397
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.c142
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_ps.h35
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_reg.h (renamed from drivers/net/wireless/wl12xx/reg.h)222
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.c200
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_rx.h121
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_spi.c382
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_spi.h113
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c378
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.h130
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.h6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c4
-rw-r--r--drivers/ssb/pci.c53
-rw-r--r--include/linux/nl80211.h17
-rw-r--r--include/linux/ssb/ssb.h44
-rw-r--r--include/linux/ssb/ssb_regs.h66
-rw-r--r--include/linux/usb/usbnet.h6
-rw-r--r--include/net/cfg80211.h26
-rw-r--r--include/net/mac80211.h29
-rw-r--r--net/mac80211/Kconfig8
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/main.c16
-rw-r--r--net/mac80211/mesh.c145
-rw-r--r--net/mac80211/mesh.h30
-rw-r--r--net/mac80211/mesh_hwmp.c17
-rw-r--r--net/mac80211/mesh_pathtbl.c151
-rw-r--r--net/mac80211/mesh_plink.c2
-rw-r--r--net/mac80211/mlme.c31
-rw-r--r--net/mac80211/rc80211_minstrel.c16
-rw-r--r--net/mac80211/rx.c45
-rw-r--r--net/mac80211/scan.c10
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/tx.c158
-rw-r--r--net/wireless/Makefile3
-rw-r--r--net/wireless/chan.c89
-rw-r--r--net/wireless/core.c21
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/ibss.c61
-rw-r--r--net/wireless/mlme.c17
-rw-r--r--net/wireless/nl80211.c88
-rw-r--r--net/wireless/reg.c5
-rw-r--r--net/wireless/scan.c31
-rw-r--r--net/wireless/sme.c104
-rw-r--r--net/wireless/util.c16
-rw-r--r--net/wireless/wext-compat.c55
-rw-r--r--net/wireless/wext-compat.h3
-rw-r--r--net/wireless/wext-sme.c83
175 files changed, 21960 insertions, 7592 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 22af4965c16c..866253d7abd7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3583,9 +3583,12 @@ M: "John W. Linville" <linville@tuxdriver.com>
3583L: linux-wireless@vger.kernel.org 3583L: linux-wireless@vger.kernel.org
3584T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git 3584T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git
3585S: Maintained 3585S: Maintained
3586F: net/mac80211/
3587F: net/rfkill/
3586F: net/wireless/ 3588F: net/wireless/
3587F: include/net/ieee80211* 3589F: include/net/ieee80211*
3588F: include/linux/wireless.h 3590F: include/linux/wireless.h
3591F: drivers/net/wireless/
3589 3592
3590NETWORKING DRIVERS 3593NETWORKING DRIVERS
3591L: netdev@vger.kernel.org 3594L: netdev@vger.kernel.org
@@ -5577,7 +5580,16 @@ L: linux-wireless@vger.kernel.org
5577W: http://wireless.kernel.org 5580W: http://wireless.kernel.org
5578T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git 5581T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
5579S: Maintained 5582S: Maintained
5580F: drivers/net/wireless/wl12xx/wl1251* 5583F: drivers/net/wireless/wl12xx/*
5584X: drivers/net/wireless/wl12xx/wl1271*
5585
5586WL1271 WIRELESS DRIVER
5587M: Luciano Coelho <luciano.coelho@nokia.com>
5588L: linux-wireless@vger.kernel.org
5589W: http://wireless.kernel.org
5590T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
5591S: Maintained
5592F: drivers/net/wireless/wl12xx/wl1271*
5581 5593
5582WL3501 WIRELESS PCMCIA CARD DRIVER 5594WL3501 WIRELESS PCMCIA CARD DRIVER
5583M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> 5595M: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index af1fe4696509..7d471fca2743 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -233,6 +233,11 @@ void usbnet_skb_return (struct usbnet *dev, struct sk_buff *skb)
233{ 233{
234 int status; 234 int status;
235 235
236 if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
237 skb_queue_tail(&dev->rxq_pause, skb);
238 return;
239 }
240
236 skb->protocol = eth_type_trans (skb, dev->net); 241 skb->protocol = eth_type_trans (skb, dev->net);
237 dev->net->stats.rx_packets++; 242 dev->net->stats.rx_packets++;
238 dev->net->stats.rx_bytes += skb->len; 243 dev->net->stats.rx_bytes += skb->len;
@@ -526,6 +531,41 @@ static void intr_complete (struct urb *urb)
526} 531}
527 532
528/*-------------------------------------------------------------------------*/ 533/*-------------------------------------------------------------------------*/
534void usbnet_pause_rx(struct usbnet *dev)
535{
536 set_bit(EVENT_RX_PAUSED, &dev->flags);
537
538 if (netif_msg_rx_status(dev))
539 devdbg(dev, "paused rx queue enabled");
540}
541EXPORT_SYMBOL_GPL(usbnet_pause_rx);
542
543void usbnet_resume_rx(struct usbnet *dev)
544{
545 struct sk_buff *skb;
546 int num = 0;
547
548 clear_bit(EVENT_RX_PAUSED, &dev->flags);
549
550 while ((skb = skb_dequeue(&dev->rxq_pause)) != NULL) {
551 usbnet_skb_return(dev, skb);
552 num++;
553 }
554
555 tasklet_schedule(&dev->bh);
556
557 if (netif_msg_rx_status(dev))
558 devdbg(dev, "paused rx queue disabled, %d skbs requeued", num);
559}
560EXPORT_SYMBOL_GPL(usbnet_resume_rx);
561
562void usbnet_purge_paused_rxq(struct usbnet *dev)
563{
564 skb_queue_purge(&dev->rxq_pause);
565}
566EXPORT_SYMBOL_GPL(usbnet_purge_paused_rxq);
567
568/*-------------------------------------------------------------------------*/
529 569
530// unlink pending rx/tx; completion handlers do all other cleanup 570// unlink pending rx/tx; completion handlers do all other cleanup
531 571
@@ -623,6 +663,8 @@ int usbnet_stop (struct net_device *net)
623 663
624 usb_kill_urb(dev->interrupt); 664 usb_kill_urb(dev->interrupt);
625 665
666 usbnet_purge_paused_rxq(dev);
667
626 /* deferred work (task, timer, softirq) must also stop. 668 /* deferred work (task, timer, softirq) must also stop.
627 * can't flush_scheduled_work() until we drop rtnl (later), 669 * can't flush_scheduled_work() until we drop rtnl (later),
628 * else workers could deadlock; so make workers a NOP. 670 * else workers could deadlock; so make workers a NOP.
@@ -1113,7 +1155,6 @@ static void usbnet_bh (unsigned long param)
1113} 1155}
1114 1156
1115 1157
1116
1117/*------------------------------------------------------------------------- 1158/*-------------------------------------------------------------------------
1118 * 1159 *
1119 * USB Device Driver support 1160 * USB Device Driver support
@@ -1210,6 +1251,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
1210 skb_queue_head_init (&dev->rxq); 1251 skb_queue_head_init (&dev->rxq);
1211 skb_queue_head_init (&dev->txq); 1252 skb_queue_head_init (&dev->txq);
1212 skb_queue_head_init (&dev->done); 1253 skb_queue_head_init (&dev->done);
1254 skb_queue_head_init(&dev->rxq_pause);
1213 dev->bh.func = usbnet_bh; 1255 dev->bh.func = usbnet_bh;
1214 dev->bh.data = (unsigned long) dev; 1256 dev->bh.data = (unsigned long) dev;
1215 INIT_WORK (&dev->kevent, kevent); 1257 INIT_WORK (&dev->kevent, kevent);
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 253b95a264b1..11ded150b932 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -5,9 +5,7 @@ menuconfig ATH_COMMON
5 ---help--- 5 ---help---
6 This will enable the support for the Atheros wireless drivers. 6 This will enable the support for the Atheros wireless drivers.
7 ath5k, ath9k and ar9170 drivers share some common code, this option 7 ath5k, ath9k and ar9170 drivers share some common code, this option
8 enables the common ath.ko module which currently shares just common 8 enables the common ath.ko module which shares common helpers.
9 regulatory EEPROM helpers but will likely be extended later to share
10 more between modules.
11 9
12 For more information and documentation on this module you can visit: 10 For more information and documentation on this module you can visit:
13 11
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
new file mode 100644
index 000000000000..e284cd3ac6d4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath.h
@@ -0,0 +1,30 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef ATH_H
18#define ATH_H
19
20#include <linux/skbuff.h>
21
22struct ath_common {
23 u16 cachelsz;
24};
25
26struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
27 u32 len,
28 gfp_t gfp_mask);
29
30#endif /* ATH_H */
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 91375113916b..c09402eea7f3 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -919,6 +919,12 @@ enum ath5k_int {
919 AR5K_INT_NOCARD = 0xffffffff 919 AR5K_INT_NOCARD = 0xffffffff
920}; 920};
921 921
922/* Software interrupts used for calibration */
923enum ath5k_software_interrupt {
924 AR5K_SWI_FULL_CALIBRATION = 0x01,
925 AR5K_SWI_SHORT_CALIBRATION = 0x02,
926};
927
922/* 928/*
923 * Power management 929 * Power management
924 */ 930 */
@@ -1123,6 +1129,15 @@ struct ath5k_hw {
1123 /* noise floor from last periodic calibration */ 1129 /* noise floor from last periodic calibration */
1124 s32 ah_noise_floor; 1130 s32 ah_noise_floor;
1125 1131
1132 /* Calibration timestamp */
1133 unsigned long ah_cal_tstamp;
1134
1135 /* Calibration interval (secs) */
1136 u8 ah_cal_intval;
1137
1138 /* Software interrupt mask */
1139 u8 ah_swi_mask;
1140
1126 /* 1141 /*
1127 * Function pointers 1142 * Function pointers
1128 */ 1143 */
@@ -1157,6 +1172,7 @@ extern void ath5k_unregister_leds(struct ath5k_softc *sc);
1157 1172
1158/* Reset Functions */ 1173/* Reset Functions */
1159extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); 1174extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial);
1175extern int ath5k_hw_on_hold(struct ath5k_hw *ah);
1160extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); 1176extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel);
1161/* Power management functions */ 1177/* Power management functions */
1162extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); 1178extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration);
@@ -1275,6 +1291,7 @@ extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *chann
1275/* PHY calibration */ 1291/* PHY calibration */
1276extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); 1292extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1277extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); 1293extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
1294extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah);
1278/* Spur mitigation */ 1295/* Spur mitigation */
1279bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, 1296bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah,
1280 struct ieee80211_channel *channel); 1297 struct ieee80211_channel *channel);
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index 9a84d9410b27..65d438b59f64 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -145,7 +145,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
145 goto err_free; 145 goto err_free;
146 146
147 /* Bring device out of sleep and reset it's units */ 147 /* Bring device out of sleep and reset it's units */
148 ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, true); 148 ret = ath5k_hw_nic_wakeup(ah, 0, true);
149 if (ret) 149 if (ret)
150 goto err_free; 150 goto err_free;
151 151
@@ -253,28 +253,6 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
253 } 253 }
254 254
255 /* 255 /*
256 * Write PCI-E power save settings
257 */
258 if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
259 ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
260 ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
261 /* Shut off RX when elecidle is asserted */
262 ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
263 ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
264 /* TODO: EEPROM work */
265 ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
266 /* Shut off PLL and CLKREQ active in L1 */
267 ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
268 /* Preserce other settings */
269 ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
270 ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
271 ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
272 /* Reset SERDES to load new settings */
273 ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
274 mdelay(1);
275 }
276
277 /*
278 * POST 256 * POST
279 */ 257 */
280 ret = ath5k_hw_post(ah); 258 ret = ath5k_hw_post(ah);
@@ -283,7 +261,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
283 261
284 /* Enable pci core retry fix on Hainan (5213A) and later chips */ 262 /* Enable pci core retry fix on Hainan (5213A) and later chips */
285 if (srev >= AR5K_SREV_AR5213A) 263 if (srev >= AR5K_SREV_AR5213A)
286 ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG); 264 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_RETRY_FIX);
287 265
288 /* 266 /*
289 * Get card capabilities, calibration values etc 267 * Get card capabilities, calibration values etc
@@ -295,6 +273,40 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
295 goto err_free; 273 goto err_free;
296 } 274 }
297 275
276 /*
277 * Write PCI-E power save settings
278 */
279 if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) {
280 struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
281
282 ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
283 ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
284
285 /* Shut off RX when elecidle is asserted */
286 ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
287 ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
288
289 /* If serdes programing is enabled, increase PCI-E
290 * tx power for systems with long trace from host
291 * to minicard connector. */
292 if (ee->ee_serdes)
293 ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
294 else
295 ath5k_hw_reg_write(ah, 0xf6800579, AR5K_PCIE_SERDES);
296
297 /* Shut off PLL and CLKREQ active in L1 */
298 ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
299
300 /* Preserve other settings */
301 ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
302 ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
303 ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
304
305 /* Reset SERDES to load new settings */
306 ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
307 mdelay(1);
308 }
309
298 /* Get misc capabilities */ 310 /* Get misc capabilities */
299 ret = ath5k_hw_set_capabilities(ah); 311 ret = ath5k_hw_set_capabilities(ah);
300 if (ret) { 312 if (ret) {
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 3a1c156d275f..2b3cf39dd4b1 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -59,7 +59,7 @@
59#include "reg.h" 59#include "reg.h"
60#include "debug.h" 60#include "debug.h"
61 61
62static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ 62static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
63static int modparam_nohwcrypt; 63static int modparam_nohwcrypt;
64module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); 64module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
65MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); 65MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -376,7 +376,7 @@ static int ath5k_stop_hw(struct ath5k_softc *sc);
376static irqreturn_t ath5k_intr(int irq, void *dev_id); 376static irqreturn_t ath5k_intr(int irq, void *dev_id);
377static void ath5k_tasklet_reset(unsigned long data); 377static void ath5k_tasklet_reset(unsigned long data);
378 378
379static void ath5k_calibrate(unsigned long data); 379static void ath5k_tasklet_calibrate(unsigned long data);
380 380
381/* 381/*
382 * Module init/exit functions 382 * Module init/exit functions
@@ -471,7 +471,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
471 * DMA to work so force a reasonable value here if it 471 * DMA to work so force a reasonable value here if it
472 * comes up zero. 472 * comes up zero.
473 */ 473 */
474 csz = L1_CACHE_BYTES / sizeof(u32); 474 csz = L1_CACHE_BYTES >> 2;
475 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); 475 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
476 } 476 }
477 /* 477 /*
@@ -544,7 +544,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
544 __set_bit(ATH_STAT_INVALID, sc->status); 544 __set_bit(ATH_STAT_INVALID, sc->status);
545 545
546 sc->iobase = mem; /* So we can unmap it on detach */ 546 sc->iobase = mem; /* So we can unmap it on detach */
547 sc->cachelsz = csz * sizeof(u32); /* convert to bytes */ 547 sc->common.cachelsz = csz << 2; /* convert to bytes */
548 sc->opmode = NL80211_IFTYPE_STATION; 548 sc->opmode = NL80211_IFTYPE_STATION;
549 sc->bintval = 1000; 549 sc->bintval = 1000;
550 mutex_init(&sc->lock); 550 mutex_init(&sc->lock);
@@ -799,8 +799,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
799 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); 799 tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc);
800 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); 800 tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc);
801 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); 801 tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
802 tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc);
802 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); 803 tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc);
803 setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
804 804
805 ret = ath5k_eeprom_read_mac(ah, mac); 805 ret = ath5k_eeprom_read_mac(ah, mac);
806 if (ret) { 806 if (ret) {
@@ -1071,10 +1071,9 @@ ath5k_setup_bands(struct ieee80211_hw *hw)
1071} 1071}
1072 1072
1073/* 1073/*
1074 * Set/change channels. If the channel is really being changed, 1074 * Set/change channels. We always reset the chip.
1075 * it's done by reseting the chip. To accomplish this we must 1075 * To accomplish this we must first cleanup any pending DMA,
1076 * first cleanup any pending DMA, then restart stuff after a la 1076 * then restart stuff after a la ath5k_init.
1077 * ath5k_init.
1078 * 1077 *
1079 * Called with sc->lock. 1078 * Called with sc->lock.
1080 */ 1079 */
@@ -1084,19 +1083,13 @@ ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan)
1084 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", 1083 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n",
1085 sc->curchan->center_freq, chan->center_freq); 1084 sc->curchan->center_freq, chan->center_freq);
1086 1085
1087 if (chan->center_freq != sc->curchan->center_freq || 1086 /*
1088 chan->hw_value != sc->curchan->hw_value) { 1087 * To switch channels clear any pending DMA operations;
1089 1088 * wait long enough for the RX fifo to drain, reset the
1090 /* 1089 * hardware at the new frequency, and then re-enable
1091 * To switch channels clear any pending DMA operations; 1090 * the relevant bits of the h/w.
1092 * wait long enough for the RX fifo to drain, reset the 1091 */
1093 * hardware at the new frequency, and then re-enable 1092 return ath5k_reset(sc, chan);
1094 * the relevant bits of the h/w.
1095 */
1096 return ath5k_reset(sc, chan);
1097 }
1098
1099 return 0;
1100} 1093}
1101 1094
1102static void 1095static void
@@ -1158,27 +1151,20 @@ static
1158struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) 1151struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
1159{ 1152{
1160 struct sk_buff *skb; 1153 struct sk_buff *skb;
1161 unsigned int off;
1162 1154
1163 /* 1155 /*
1164 * Allocate buffer with headroom_needed space for the 1156 * Allocate buffer with headroom_needed space for the
1165 * fake physical layer header at the start. 1157 * fake physical layer header at the start.
1166 */ 1158 */
1167 skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); 1159 skb = ath_rxbuf_alloc(&sc->common,
1160 sc->rxbufsize + sc->common.cachelsz - 1,
1161 GFP_ATOMIC);
1168 1162
1169 if (!skb) { 1163 if (!skb) {
1170 ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", 1164 ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
1171 sc->rxbufsize + sc->cachelsz - 1); 1165 sc->rxbufsize + sc->common.cachelsz - 1);
1172 return NULL; 1166 return NULL;
1173 } 1167 }
1174 /*
1175 * Cache-line-align. This is important (for the
1176 * 5210 at least) as not doing so causes bogus data
1177 * in rx'd frames.
1178 */
1179 off = ((unsigned long)skb->data) % sc->cachelsz;
1180 if (off != 0)
1181 skb_reserve(skb, sc->cachelsz - off);
1182 1168
1183 *skb_addr = pci_map_single(sc->pdev, 1169 *skb_addr = pci_map_single(sc->pdev,
1184 skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); 1170 skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
@@ -1620,10 +1606,10 @@ ath5k_rx_start(struct ath5k_softc *sc)
1620 struct ath5k_buf *bf; 1606 struct ath5k_buf *bf;
1621 int ret; 1607 int ret;
1622 1608
1623 sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->cachelsz); 1609 sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
1624 1610
1625 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", 1611 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
1626 sc->cachelsz, sc->rxbufsize); 1612 sc->common.cachelsz, sc->rxbufsize);
1627 1613
1628 spin_lock_bh(&sc->rxbuflock); 1614 spin_lock_bh(&sc->rxbuflock);
1629 sc->rxlink = NULL; 1615 sc->rxlink = NULL;
@@ -2371,7 +2357,7 @@ ath5k_init(struct ath5k_softc *sc)
2371 sc->curband = &sc->sbands[sc->curchan->band]; 2357 sc->curband = &sc->sbands[sc->curchan->band];
2372 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | 2358 sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
2373 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | 2359 AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
2374 AR5K_INT_FATAL | AR5K_INT_GLOBAL; 2360 AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI;
2375 ret = ath5k_reset(sc, NULL); 2361 ret = ath5k_reset(sc, NULL);
2376 if (ret) 2362 if (ret)
2377 goto done; 2363 goto done;
@@ -2388,8 +2374,8 @@ ath5k_init(struct ath5k_softc *sc)
2388 /* Set ack to be sent at low bit-rates */ 2374 /* Set ack to be sent at low bit-rates */
2389 ath5k_hw_set_ack_bitrate_high(ah, false); 2375 ath5k_hw_set_ack_bitrate_high(ah, false);
2390 2376
2391 mod_timer(&sc->calib_tim, round_jiffies(jiffies + 2377 /* Set PHY calibration inteval */
2392 msecs_to_jiffies(ath5k_calinterval * 1000))); 2378 ah->ah_cal_intval = ath5k_calinterval;
2393 2379
2394 ret = 0; 2380 ret = 0;
2395done: 2381done:
@@ -2453,37 +2439,39 @@ ath5k_stop_hw(struct ath5k_softc *sc)
2453 ret = ath5k_stop_locked(sc); 2439 ret = ath5k_stop_locked(sc);
2454 if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { 2440 if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) {
2455 /* 2441 /*
2456 * Set the chip in full sleep mode. Note that we are 2442 * Don't set the card in full sleep mode!
2457 * careful to do this only when bringing the interface 2443 *
2458 * completely to a stop. When the chip is in this state 2444 * a) When the device is in this state it must be carefully
2459 * it must be carefully woken up or references to 2445 * woken up or references to registers in the PCI clock
2460 * registers in the PCI clock domain may freeze the bus 2446 * domain may freeze the bus (and system). This varies
2461 * (and system). This varies by chip and is mostly an 2447 * by chip and is mostly an issue with newer parts
2462 * issue with newer parts that go to sleep more quickly. 2448 * (madwifi sources mentioned srev >= 0x78) that go to
2463 */ 2449 * sleep more quickly.
2464 if (sc->ah->ah_mac_srev >= 0x78) { 2450 *
2465 /* 2451 * b) On older chips full sleep results a weird behaviour
2466 * XXX 2452 * during wakeup. I tested various cards with srev < 0x78
2467 * don't put newer MAC revisions > 7.8 to sleep because 2453 * and they don't wake up after module reload, a second
2468 * of the above mentioned problems 2454 * module reload is needed to bring the card up again.
2469 */ 2455 *
2470 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mac version > 7.8, " 2456 * Until we figure out what's going on don't enable
2471 "not putting device to sleep\n"); 2457 * full chip reset on any chip (this is what Legacy HAL
2472 } else { 2458 * and Sam's HAL do anyway). Instead Perform a full reset
2473 ATH5K_DBG(sc, ATH5K_DEBUG_RESET, 2459 * on the device (same as initial state after attach) and
2474 "putting device to full sleep\n"); 2460 * leave it idle (keep MAC/BB on warm reset) */
2475 ath5k_hw_set_power(sc->ah, AR5K_PM_FULL_SLEEP, true, 0); 2461 ret = ath5k_hw_on_hold(sc->ah);
2476 } 2462
2463 ATH5K_DBG(sc, ATH5K_DEBUG_RESET,
2464 "putting device to sleep\n");
2477 } 2465 }
2478 ath5k_txbuf_free(sc, sc->bbuf); 2466 ath5k_txbuf_free(sc, sc->bbuf);
2479 2467
2480 mmiowb(); 2468 mmiowb();
2481 mutex_unlock(&sc->lock); 2469 mutex_unlock(&sc->lock);
2482 2470
2483 del_timer_sync(&sc->calib_tim);
2484 tasklet_kill(&sc->rxtq); 2471 tasklet_kill(&sc->rxtq);
2485 tasklet_kill(&sc->txtq); 2472 tasklet_kill(&sc->txtq);
2486 tasklet_kill(&sc->restq); 2473 tasklet_kill(&sc->restq);
2474 tasklet_kill(&sc->calib);
2487 tasklet_kill(&sc->beacontq); 2475 tasklet_kill(&sc->beacontq);
2488 2476
2489 ath5k_rfkill_hw_stop(sc->ah); 2477 ath5k_rfkill_hw_stop(sc->ah);
@@ -2539,6 +2527,9 @@ ath5k_intr(int irq, void *dev_id)
2539 if (status & AR5K_INT_BMISS) { 2527 if (status & AR5K_INT_BMISS) {
2540 /* TODO */ 2528 /* TODO */
2541 } 2529 }
2530 if (status & AR5K_INT_SWI) {
2531 tasklet_schedule(&sc->calib);
2532 }
2542 if (status & AR5K_INT_MIB) { 2533 if (status & AR5K_INT_MIB) {
2543 /* 2534 /*
2544 * These stats are also used for ANI i think 2535 * These stats are also used for ANI i think
@@ -2555,6 +2546,8 @@ ath5k_intr(int irq, void *dev_id)
2555 if (unlikely(!counter)) 2546 if (unlikely(!counter))
2556 ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); 2547 ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
2557 2548
2549 ath5k_hw_calibration_poll(ah);
2550
2558 return IRQ_HANDLED; 2551 return IRQ_HANDLED;
2559} 2552}
2560 2553
@@ -2571,11 +2564,19 @@ ath5k_tasklet_reset(unsigned long data)
2571 * for temperature/environment changes. 2564 * for temperature/environment changes.
2572 */ 2565 */
2573static void 2566static void
2574ath5k_calibrate(unsigned long data) 2567ath5k_tasklet_calibrate(unsigned long data)
2575{ 2568{
2576 struct ath5k_softc *sc = (void *)data; 2569 struct ath5k_softc *sc = (void *)data;
2577 struct ath5k_hw *ah = sc->ah; 2570 struct ath5k_hw *ah = sc->ah;
2578 2571
2572 /* Only full calibration for now */
2573 if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION)
2574 return;
2575
2576 /* Stop queues so that calibration
2577 * doesn't interfere with tx */
2578 ieee80211_stop_queues(sc->hw);
2579
2579 ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", 2580 ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n",
2580 ieee80211_frequency_to_channel(sc->curchan->center_freq), 2581 ieee80211_frequency_to_channel(sc->curchan->center_freq),
2581 sc->curchan->hw_value); 2582 sc->curchan->hw_value);
@@ -2593,8 +2594,11 @@ ath5k_calibrate(unsigned long data)
2593 ieee80211_frequency_to_channel( 2594 ieee80211_frequency_to_channel(
2594 sc->curchan->center_freq)); 2595 sc->curchan->center_freq));
2595 2596
2596 mod_timer(&sc->calib_tim, round_jiffies(jiffies + 2597 ah->ah_swi_mask = 0;
2597 msecs_to_jiffies(ath5k_calinterval * 1000))); 2598
2599 /* Wake queues */
2600 ieee80211_wake_queues(sc->hw);
2601
2598} 2602}
2599 2603
2600 2604
@@ -2811,9 +2815,11 @@ ath5k_config(struct ieee80211_hw *hw, u32 changed)
2811 2815
2812 mutex_lock(&sc->lock); 2816 mutex_lock(&sc->lock);
2813 2817
2814 ret = ath5k_chan_set(sc, conf->channel); 2818 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
2815 if (ret < 0) 2819 ret = ath5k_chan_set(sc, conf->channel);
2816 goto unlock; 2820 if (ret < 0)
2821 goto unlock;
2822 }
2817 2823
2818 if ((changed & IEEE80211_CONF_CHANGE_POWER) && 2824 if ((changed & IEEE80211_CONF_CHANGE_POWER) &&
2819 (sc->power_level != conf->power_level)) { 2825 (sc->power_level != conf->power_level)) {
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 778e422946ab..25a72a85aaa5 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -50,6 +50,7 @@
50 50
51#include "ath5k.h" 51#include "ath5k.h"
52#include "debug.h" 52#include "debug.h"
53#include "../ath.h"
53 54
54#define ATH_RXBUF 40 /* number of RX buffers */ 55#define ATH_RXBUF 40 /* number of RX buffers */
55#define ATH_TXBUF 200 /* number of TX buffers */ 56#define ATH_TXBUF 200 /* number of TX buffers */
@@ -112,6 +113,7 @@ struct ath5k_rfkill {
112 * associated with an instance of a device */ 113 * associated with an instance of a device */
113struct ath5k_softc { 114struct ath5k_softc {
114 struct pci_dev *pdev; /* for dma mapping */ 115 struct pci_dev *pdev; /* for dma mapping */
116 struct ath_common common;
115 void __iomem *iobase; /* address of the device */ 117 void __iomem *iobase; /* address of the device */
116 struct mutex lock; /* dev-level lock */ 118 struct mutex lock; /* dev-level lock */
117 struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; 119 struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES];
@@ -134,7 +136,6 @@ struct ath5k_softc {
134 struct ath5k_desc *desc; /* TX/RX descriptors */ 136 struct ath5k_desc *desc; /* TX/RX descriptors */
135 dma_addr_t desc_daddr; /* DMA (physical) address */ 137 dma_addr_t desc_daddr; /* DMA (physical) address */
136 size_t desc_len; /* size of TX/RX descriptors */ 138 size_t desc_len; /* size of TX/RX descriptors */
137 u16 cachelsz; /* cache line size */
138 139
139 DECLARE_BITMAP(status, 5); 140 DECLARE_BITMAP(status, 5);
140#define ATH_STAT_INVALID 0 /* disable hardware accesses */ 141#define ATH_STAT_INVALID 0 /* disable hardware accesses */
@@ -177,6 +178,8 @@ struct ath5k_softc {
177 178
178 struct ath5k_rfkill rf_kill; 179 struct ath5k_rfkill rf_kill;
179 180
181 struct tasklet_struct calib; /* calibration tasklet */
182
180 spinlock_t block; /* protects beacon */ 183 spinlock_t block; /* protects beacon */
181 struct tasklet_struct beacontq; /* beacon intr tasklet */ 184 struct tasklet_struct beacontq; /* beacon intr tasklet */
182 struct ath5k_buf *bbuf; /* beacon buffer */ 185 struct ath5k_buf *bbuf; /* beacon buffer */
@@ -187,7 +190,6 @@ struct ath5k_softc {
187 unsigned int nexttbtt; /* next beacon time in TU */ 190 unsigned int nexttbtt; /* next beacon time in TU */
188 struct ath5k_txq *cabq; /* content after beacon */ 191 struct ath5k_txq *cabq; /* content after beacon */
189 192
190 struct timer_list calib_tim; /* calibration timer */
191 int power_level; /* Requested tx power in dbm */ 193 int power_level; /* Requested tx power in dbm */
192 bool assoc; /* assocate state */ 194 bool assoc; /* assocate state */
193 bool enable_beacon; /* true if beacons are on */ 195 bool enable_beacon; /* true if beacons are on */
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index c56b494d417a..8af477dd6fc7 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -167,6 +167,16 @@ ath5k_eeprom_init_header(struct ath5k_hw *ah)
167 ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL); 167 ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL);
168 ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false; 168 ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false;
169 169
170 /* Check if PCIE_OFFSET points to PCIE_SERDES_SECTION
171 * and enable serdes programming if needed.
172 *
173 * XXX: Serdes values seem to be fixed so
174 * no need to read them here, we write them
175 * during ath5k_hw_attach */
176 AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val);
177 ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ?
178 true : false;
179
170 return 0; 180 return 0;
171} 181}
172 182
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h
index 64be73a5edae..0123f3521a0b 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath/ath5k/eeprom.h
@@ -19,6 +19,9 @@
19/* 19/*
20 * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) 20 * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
21 */ 21 */
22#define AR5K_EEPROM_PCIE_OFFSET 0x02 /* Contains offset to PCI-E infos */
23#define AR5K_EEPROM_PCIE_SERDES_SECTION 0x40 /* PCIE_OFFSET points here when
24 * SERDES infos are present */
22#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ 25#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */
23#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ 26#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */
24#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ 27#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */
@@ -391,6 +394,7 @@ struct ath5k_eeprom_info {
391 u8 ee_rfkill_pin; 394 u8 ee_rfkill_pin;
392 bool ee_rfkill_pol; 395 bool ee_rfkill_pol;
393 bool ee_is_hb63; 396 bool ee_is_hb63;
397 bool ee_serdes;
394 u16 ee_misc0; 398 u16 ee_misc0;
395 u16 ee_misc1; 399 u16 ee_misc1;
396 u16 ee_misc2; 400 u16 ee_misc2;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 2075ba993966..298fcf015227 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -740,13 +740,22 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
740 AR5K_RF_XPD_GAIN, true); 740 AR5K_RF_XPD_GAIN, true);
741 741
742 } else { 742 } else {
743 /* TODO: Set high and low gain bits */ 743 u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode];
744 ath5k_hw_rfb_op(ah, rf_regs, 744 if (ee->ee_pd_gains[ee_mode] > 1) {
745 ee->ee_x_gain[ee_mode], 745 ath5k_hw_rfb_op(ah, rf_regs,
746 pdg_curve_to_idx[0],
746 AR5K_RF_PD_GAIN_LO, true); 747 AR5K_RF_PD_GAIN_LO, true);
747 ath5k_hw_rfb_op(ah, rf_regs, 748 ath5k_hw_rfb_op(ah, rf_regs,
748 ee->ee_x_gain[ee_mode], 749 pdg_curve_to_idx[1],
749 AR5K_RF_PD_GAIN_HI, true); 750 AR5K_RF_PD_GAIN_HI, true);
751 } else {
752 ath5k_hw_rfb_op(ah, rf_regs,
753 pdg_curve_to_idx[0],
754 AR5K_RF_PD_GAIN_LO, true);
755 ath5k_hw_rfb_op(ah, rf_regs,
756 pdg_curve_to_idx[0],
757 AR5K_RF_PD_GAIN_HI, true);
758 }
750 759
751 /* Lower synth voltage on Rev 2 */ 760 /* Lower synth voltage on Rev 2 */
752 ath5k_hw_rfb_op(ah, rf_regs, 2, 761 ath5k_hw_rfb_op(ah, rf_regs, 2,
@@ -1095,6 +1104,29 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
1095 PHY calibration 1104 PHY calibration
1096\*****************/ 1105\*****************/
1097 1106
1107void
1108ath5k_hw_calibration_poll(struct ath5k_hw *ah)
1109{
1110 /* Calibration interval in jiffies */
1111 unsigned long cal_intval;
1112
1113 cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000);
1114
1115 /* Initialize timestamp if needed */
1116 if (!ah->ah_cal_tstamp)
1117 ah->ah_cal_tstamp = jiffies;
1118
1119 /* For now we always do full calibration
1120 * Mark software interrupt mask and fire software
1121 * interrupt (bit gets auto-cleared) */
1122 if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) {
1123 ah->ah_cal_tstamp = jiffies;
1124 ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION;
1125 AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI);
1126 }
1127
1128}
1129
1098/** 1130/**
1099 * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration 1131 * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
1100 * 1132 *
@@ -1896,8 +1928,9 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
1896 s16 min_pwrL, min_pwrR; 1928 s16 min_pwrL, min_pwrR;
1897 s16 pwr_i; 1929 s16 pwr_i;
1898 1930
1899 if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1])) 1931 /* Some vendors write the same pcdac value twice !!! */
1900 return 0; 1932 if (stepL[0] == stepL[1] || stepR[0] == stepR[1])
1933 return max(pwrL[0], pwrR[0]);
1901 1934
1902 if (pwrL[0] == pwrL[1]) 1935 if (pwrL[0] == pwrL[1])
1903 min_pwrL = pwrL[0]; 1936 min_pwrL = pwrL[0];
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 6d5aaf00d8bb..eeebb9aef206 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -362,7 +362,7 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
362 } 362 }
363 363
364 if (tq->tqi_ready_time && 364 if (tq->tqi_ready_time &&
365 (tq->tqi_type != AR5K_TX_QUEUE_ID_CAB)) 365 (tq->tqi_type != AR5K_TX_QUEUE_CAB))
366 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, 366 ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
367 AR5K_QCU_RDYTIMECFG_INTVAL) | 367 AR5K_QCU_RDYTIMECFG_INTVAL) |
368 AR5K_QCU_RDYTIMECFG_ENABLE, 368 AR5K_QCU_RDYTIMECFG_ENABLE,
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 86733fdb4774..34e13c700849 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -258,29 +258,35 @@ int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode,
258 if (!set_chip) 258 if (!set_chip)
259 goto commit; 259 goto commit;
260 260
261 /* Preserve sleep duration */
262 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); 261 data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL);
262
263 /* If card is down we 'll get 0xffff... so we
264 * need to clean this up before we write the register
265 */
263 if (data & 0xffc00000) 266 if (data & 0xffc00000)
264 data = 0; 267 data = 0;
265 else 268 else
266 data = data & 0xfffcffff; 269 /* Preserve sleep duration etc */
270 data = data & ~AR5K_SLEEP_CTL_SLE;
267 271
268 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); 272 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
273 AR5K_SLEEP_CTL);
269 udelay(15); 274 udelay(15);
270 275
271 for (i = 50; i > 0; i--) { 276 for (i = 200; i > 0; i--) {
272 /* Check if the chip did wake up */ 277 /* Check if the chip did wake up */
273 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & 278 if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) &
274 AR5K_PCICFG_SPWR_DN) == 0) 279 AR5K_PCICFG_SPWR_DN) == 0)
275 break; 280 break;
276 281
277 /* Wait a bit and retry */ 282 /* Wait a bit and retry */
278 udelay(200); 283 udelay(50);
279 ath5k_hw_reg_write(ah, data, AR5K_SLEEP_CTL); 284 ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE,
285 AR5K_SLEEP_CTL);
280 } 286 }
281 287
282 /* Fail if the chip didn't wake up */ 288 /* Fail if the chip didn't wake up */
283 if (i <= 0) 289 if (i == 0)
284 return -EIO; 290 return -EIO;
285 291
286 break; 292 break;
@@ -296,6 +302,64 @@ commit:
296} 302}
297 303
298/* 304/*
305 * Put device on hold
306 *
307 * Put MAC and Baseband on warm reset and
308 * keep that state (don't clean sleep control
309 * register). After this MAC and Baseband are
310 * disabled and a full reset is needed to come
311 * back. This way we save as much power as possible
312 * without puting the card on full sleep.
313 */
314int ath5k_hw_on_hold(struct ath5k_hw *ah)
315{
316 struct pci_dev *pdev = ah->ah_sc->pdev;
317 u32 bus_flags;
318 int ret;
319
320 /* Make sure device is awake */
321 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
322 if (ret) {
323 ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n");
324 return ret;
325 }
326
327 /*
328 * Put chipset on warm reset...
329 *
330 * Note: puting PCI core on warm reset on PCI-E cards
331 * results card to hang and always return 0xffff... so
332 * we ingore that flag for PCI-E cards. On PCI cards
333 * this flag gets cleared after 64 PCI clocks.
334 */
335 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
336
337 if (ah->ah_version == AR5K_AR5210) {
338 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
339 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
340 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
341 mdelay(2);
342 } else {
343 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
344 AR5K_RESET_CTL_BASEBAND | bus_flags);
345 }
346
347 if (ret) {
348 ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n");
349 return -EIO;
350 }
351
352 /* ...wakeup again!*/
353 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
354 if (ret) {
355 ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n");
356 return ret;
357 }
358
359 return ret;
360}
361
362/*
299 * Bring up MAC + PHY Chips and program PLL 363 * Bring up MAC + PHY Chips and program PLL
300 * TODO: Half/Quarter rate support 364 * TODO: Half/Quarter rate support
301 */ 365 */
@@ -318,6 +382,50 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
318 return ret; 382 return ret;
319 } 383 }
320 384
385 /*
386 * Put chipset on warm reset...
387 *
388 * Note: puting PCI core on warm reset on PCI-E cards
389 * results card to hang and always return 0xffff... so
390 * we ingore that flag for PCI-E cards. On PCI cards
391 * this flag gets cleared after 64 PCI clocks.
392 */
393 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
394
395 if (ah->ah_version == AR5K_AR5210) {
396 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
397 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
398 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
399 mdelay(2);
400 } else {
401 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
402 AR5K_RESET_CTL_BASEBAND | bus_flags);
403 }
404
405 if (ret) {
406 ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
407 return -EIO;
408 }
409
410 /* ...wakeup again!...*/
411 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
412 if (ret) {
413 ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
414 return ret;
415 }
416
417 /* ...clear reset control register and pull device out of
418 * warm reset */
419 if (ath5k_hw_nic_reset(ah, 0)) {
420 ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
421 return -EIO;
422 }
423
424 /* On initialization skip PLL programming since we don't have
425 * a channel / mode set yet */
426 if (initial)
427 return 0;
428
321 if (ah->ah_version != AR5K_AR5210) { 429 if (ah->ah_version != AR5K_AR5210) {
322 /* 430 /*
323 * Get channel mode flags 431 * Get channel mode flags
@@ -383,39 +491,6 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
383 AR5K_PHY_TURBO); 491 AR5K_PHY_TURBO);
384 } 492 }
385 493
386 /* reseting PCI on PCI-E cards results card to hang
387 * and always return 0xffff... so we ingore that flag
388 * for PCI-E cards */
389 bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI;
390
391 /* Reset chipset */
392 if (ah->ah_version == AR5K_AR5210) {
393 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
394 AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
395 AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
396 mdelay(2);
397 } else {
398 ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
399 AR5K_RESET_CTL_BASEBAND | bus_flags);
400 }
401 if (ret) {
402 ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n");
403 return -EIO;
404 }
405
406 /* ...wakeup again!*/
407 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
408 if (ret) {
409 ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n");
410 return ret;
411 }
412
413 /* ...final warm reset */
414 if (ath5k_hw_nic_reset(ah, 0)) {
415 ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n");
416 return -EIO;
417 }
418
419 if (ah->ah_version != AR5K_AR5210) { 494 if (ah->ah_version != AR5K_AR5210) {
420 495
421 /* ...update PLL if needed */ 496 /* ...update PLL if needed */
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 2cb72f8c32d7..ef5f59c4dd80 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -6,7 +6,13 @@ config ATH9K
6 select NEW_LEDS 6 select NEW_LEDS
7 ---help--- 7 ---help---
8 This module adds support for wireless adapters based on 8 This module adds support for wireless adapters based on
9 Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets. 9 Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
10 of chipsets. For a specific list of supported external
11 cards, laptops that already ship with these cards and
12 APs that come with these cards refer to to ath9k wiki
13 products page:
14
15 http://wireless.kernel.org/en/users/Drivers/ath9k/products
10 16
11 If you choose to build a module, it'll be called ath9k. 17 If you choose to build a module, it'll be called ath9k.
12 18
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 783bc39eb2ff..28443e05ec10 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -1,5 +1,8 @@
1ath9k-y += hw.o \ 1ath9k-y += hw.o \
2 eeprom.o \ 2 eeprom.o \
3 eeprom_def.o \
4 eeprom_4k.o \
5 eeprom_9287.o \
3 mac.o \ 6 mac.o \
4 calib.o \ 7 calib.o \
5 ani.o \ 8 ani.o \
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index b7093126dbb8..f264097a2f4e 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -236,36 +236,35 @@ static void ath9k_ani_restart(struct ath_hw *ah)
236 return; 236 return;
237 237
238 aniState = ah->curani; 238 aniState = ah->curani;
239
240 aniState->listenTime = 0; 239 aniState->listenTime = 0;
241 if (ah->has_hw_phycounters) { 240
242 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { 241 if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
243 aniState->ofdmPhyErrBase = 0; 242 aniState->ofdmPhyErrBase = 0;
244 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
245 "OFDM Trigger is too high for hw counters\n");
246 } else {
247 aniState->ofdmPhyErrBase =
248 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
249 }
250 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
251 aniState->cckPhyErrBase = 0;
252 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
253 "CCK Trigger is too high for hw counters\n");
254 } else {
255 aniState->cckPhyErrBase =
256 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
257 }
258 DPRINTF(ah->ah_sc, ATH_DBG_ANI, 243 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
259 "Writing ofdmbase=%u cckbase=%u\n", 244 "OFDM Trigger is too high for hw counters\n");
260 aniState->ofdmPhyErrBase, 245 } else {
261 aniState->cckPhyErrBase); 246 aniState->ofdmPhyErrBase =
262 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); 247 AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
263 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); 248 }
264 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); 249 if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
265 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); 250 aniState->cckPhyErrBase = 0;
266 251 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
267 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 252 "CCK Trigger is too high for hw counters\n");
253 } else {
254 aniState->cckPhyErrBase =
255 AR_PHY_COUNTMAX - aniState->cckTrigHigh;
268 } 256 }
257 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
258 "Writing ofdmbase=%u cckbase=%u\n",
259 aniState->ofdmPhyErrBase,
260 aniState->cckPhyErrBase);
261 REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
262 REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
263 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
264 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
265
266 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
267
269 aniState->ofdmPhyErrCount = 0; 268 aniState->ofdmPhyErrCount = 0;
270 aniState->cckPhyErrCount = 0; 269 aniState->cckPhyErrCount = 0;
271} 270}
@@ -530,18 +529,12 @@ void ath9k_ani_reset(struct ath_hw *ah)
530 if (aniState->firstepLevel != 0) 529 if (aniState->firstepLevel != 0)
531 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 530 ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
532 aniState->firstepLevel); 531 aniState->firstepLevel);
533 if (ah->has_hw_phycounters) {
534 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
535 ~ATH9K_RX_FILTER_PHYERR);
536 ath9k_ani_restart(ah);
537 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
538 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
539 532
540 } else { 533 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
541 ath9k_ani_restart(ah); 534 ~ATH9K_RX_FILTER_PHYERR);
542 ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | 535 ath9k_ani_restart(ah);
543 ATH9K_RX_FILTER_PHYERR); 536 REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
544 } 537 REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
545} 538}
546 539
547void ath9k_hw_ani_monitor(struct ath_hw *ah, 540void ath9k_hw_ani_monitor(struct ath_hw *ah,
@@ -550,6 +543,8 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
550{ 543{
551 struct ar5416AniState *aniState; 544 struct ar5416AniState *aniState;
552 int32_t listenTime; 545 int32_t listenTime;
546 u32 phyCnt1, phyCnt2;
547 u32 ofdmPhyErrCnt, cckPhyErrCnt;
553 548
554 if (!DO_ANI(ah)) 549 if (!DO_ANI(ah))
555 return; 550 return;
@@ -566,50 +561,45 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
566 561
567 aniState->listenTime += listenTime; 562 aniState->listenTime += listenTime;
568 563
569 if (ah->has_hw_phycounters) { 564 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats);
570 u32 phyCnt1, phyCnt2;
571 u32 ofdmPhyErrCnt, cckPhyErrCnt;
572 565
573 ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); 566 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
574 567 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
575 phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); 568
576 phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); 569 if (phyCnt1 < aniState->ofdmPhyErrBase ||
577 570 phyCnt2 < aniState->cckPhyErrBase) {
578 if (phyCnt1 < aniState->ofdmPhyErrBase || 571 if (phyCnt1 < aniState->ofdmPhyErrBase) {
579 phyCnt2 < aniState->cckPhyErrBase) { 572 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
580 if (phyCnt1 < aniState->ofdmPhyErrBase) { 573 "phyCnt1 0x%x, resetting "
581 DPRINTF(ah->ah_sc, ATH_DBG_ANI, 574 "counter value to 0x%x\n",
582 "phyCnt1 0x%x, resetting " 575 phyCnt1, aniState->ofdmPhyErrBase);
583 "counter value to 0x%x\n", 576 REG_WRITE(ah, AR_PHY_ERR_1,
584 phyCnt1, aniState->ofdmPhyErrBase); 577 aniState->ofdmPhyErrBase);
585 REG_WRITE(ah, AR_PHY_ERR_1, 578 REG_WRITE(ah, AR_PHY_ERR_MASK_1,
586 aniState->ofdmPhyErrBase); 579 AR_PHY_ERR_OFDM_TIMING);
587 REG_WRITE(ah, AR_PHY_ERR_MASK_1, 580 }
588 AR_PHY_ERR_OFDM_TIMING); 581 if (phyCnt2 < aniState->cckPhyErrBase) {
589 } 582 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
590 if (phyCnt2 < aniState->cckPhyErrBase) { 583 "phyCnt2 0x%x, resetting "
591 DPRINTF(ah->ah_sc, ATH_DBG_ANI, 584 "counter value to 0x%x\n",
592 "phyCnt2 0x%x, resetting " 585 phyCnt2, aniState->cckPhyErrBase);
593 "counter value to 0x%x\n", 586 REG_WRITE(ah, AR_PHY_ERR_2,
594 phyCnt2, aniState->cckPhyErrBase); 587 aniState->cckPhyErrBase);
595 REG_WRITE(ah, AR_PHY_ERR_2, 588 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
596 aniState->cckPhyErrBase); 589 AR_PHY_ERR_CCK_TIMING);
597 REG_WRITE(ah, AR_PHY_ERR_MASK_2,
598 AR_PHY_ERR_CCK_TIMING);
599 }
600 return;
601 } 590 }
591 return;
592 }
602 593
603 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; 594 ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
604 ah->stats.ast_ani_ofdmerrs += 595 ah->stats.ast_ani_ofdmerrs +=
605 ofdmPhyErrCnt - aniState->ofdmPhyErrCount; 596 ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
606 aniState->ofdmPhyErrCount = ofdmPhyErrCnt; 597 aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
607 598
608 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; 599 cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
609 ah->stats.ast_ani_cckerrs += 600 ah->stats.ast_ani_cckerrs +=
610 cckPhyErrCnt - aniState->cckPhyErrCount; 601 cckPhyErrCnt - aniState->cckPhyErrCount;
611 aniState->cckPhyErrCount = cckPhyErrCnt; 602 aniState->cckPhyErrCount = cckPhyErrCnt;
612 }
613 603
614 if (aniState->listenTime > 5 * ah->aniperiod) { 604 if (aniState->listenTime > 5 * ah->aniperiod) {
615 if (aniState->ofdmPhyErrCount <= aniState->listenTime * 605 if (aniState->ofdmPhyErrCount <= aniState->listenTime *
@@ -632,11 +622,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
632 } 622 }
633} 623}
634 624
635bool ath9k_hw_phycounters(struct ath_hw *ah)
636{
637 return ah->has_hw_phycounters ? true : false;
638}
639
640void ath9k_enable_mib_counters(struct ath_hw *ah) 625void ath9k_enable_mib_counters(struct ath_hw *ah)
641{ 626{
642 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); 627 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
@@ -781,9 +766,7 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
781{ 766{
782 int i; 767 int i;
783 768
784 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n"); 769 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n");
785
786 ah->has_hw_phycounters = 1;
787 770
788 memset(ah->ani, 0, sizeof(ah->ani)); 771 memset(ah->ani, 0, sizeof(ah->ani));
789 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { 772 for (i = 0; i < ARRAY_SIZE(ah->ani); i++) {
@@ -799,24 +782,22 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
799 ATH9K_ANI_CCK_WEAK_SIG_THR; 782 ATH9K_ANI_CCK_WEAK_SIG_THR;
800 ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; 783 ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
801 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; 784 ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
802 if (ah->has_hw_phycounters) { 785 ah->ani[i].ofdmPhyErrBase =
803 ah->ani[i].ofdmPhyErrBase = 786 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
804 AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; 787 ah->ani[i].cckPhyErrBase =
805 ah->ani[i].cckPhyErrBase = 788 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
806 AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
807 }
808 }
809 if (ah->has_hw_phycounters) {
810 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
811 "Setting OfdmErrBase = 0x%08x\n",
812 ah->ani[0].ofdmPhyErrBase);
813 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
814 ah->ani[0].cckPhyErrBase);
815
816 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
817 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
818 ath9k_enable_mib_counters(ah);
819 } 789 }
790
791 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
792 "Setting OfdmErrBase = 0x%08x\n",
793 ah->ani[0].ofdmPhyErrBase);
794 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
795 ah->ani[0].cckPhyErrBase);
796
797 REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase);
798 REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase);
799 ath9k_enable_mib_counters(ah);
800
820 ah->aniperiod = ATH9K_ANI_PERIOD; 801 ah->aniperiod = ATH9K_ANI_PERIOD;
821 if (ah->config.enable_ani) 802 if (ah->config.enable_ani)
822 ah->proc_phyerr |= HAL_PROCESS_ANI; 803 ah->proc_phyerr |= HAL_PROCESS_ANI;
@@ -826,9 +807,7 @@ void ath9k_hw_ani_disable(struct ath_hw *ah)
826{ 807{
827 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); 808 DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n");
828 809
829 if (ah->has_hw_phycounters) { 810 ath9k_hw_disable_mib_counters(ah);
830 ath9k_hw_disable_mib_counters(ah); 811 REG_WRITE(ah, AR_PHY_ERR_1, 0);
831 REG_WRITE(ah, AR_PHY_ERR_1, 0); 812 REG_WRITE(ah, AR_PHY_ERR_2, 0);
832 REG_WRITE(ah, AR_PHY_ERR_2, 0);
833 }
834} 813}
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h
index a36b7bb7c42a..119924511f85 100644
--- a/drivers/net/wireless/ath/ath9k/ani.h
+++ b/drivers/net/wireless/ath/ath9k/ani.h
@@ -124,7 +124,6 @@ void ath9k_ani_reset(struct ath_hw *ah);
124void ath9k_hw_ani_monitor(struct ath_hw *ah, 124void ath9k_hw_ani_monitor(struct ath_hw *ah,
125 const struct ath9k_node_stats *stats, 125 const struct ath9k_node_stats *stats,
126 struct ath9k_channel *chan); 126 struct ath9k_channel *chan);
127bool ath9k_hw_phycounters(struct ath_hw *ah);
128void ath9k_enable_mib_counters(struct ath_hw *ah); 127void ath9k_enable_mib_counters(struct ath_hw *ah);
129void ath9k_hw_disable_mib_counters(struct ath_hw *ah); 128void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
130u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, 129u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 7a5a157e15c4..2fd663c01b8e 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -25,6 +25,7 @@
25#include "hw.h" 25#include "hw.h"
26#include "rc.h" 26#include "rc.h"
27#include "debug.h" 27#include "debug.h"
28#include "../ath.h"
28 29
29struct ath_node; 30struct ath_node;
30 31
@@ -532,6 +533,8 @@ struct ath_softc {
532 struct ieee80211_hw *hw; 533 struct ieee80211_hw *hw;
533 struct device *dev; 534 struct device *dev;
534 535
536 struct ath_common common;
537
535 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ 538 spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */
536 struct ath_wiphy *pri_wiphy; 539 struct ath_wiphy *pri_wiphy;
537 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may 540 struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may
@@ -564,7 +567,6 @@ struct ath_softc {
564 u32 sc_flags; /* SC_OP_* */ 567 u32 sc_flags; /* SC_OP_* */
565 u16 curtxpow; 568 u16 curtxpow;
566 u16 curaid; 569 u16 curaid;
567 u16 cachelsz;
568 u8 nbcnvifs; 570 u8 nbcnvifs;
569 u16 nvifs; 571 u16 nvifs;
570 u8 tx_chainmask; 572 u8 tx_chainmask;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index 4cb64a0900bb..958948bc73fd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -16,9 +16,16 @@
16 16
17#include "ath9k.h" 17#include "ath9k.h"
18 18
19static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, 19static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
20 u32 reg, u32 mask, 20{
21 u32 shift, u32 val) 21 if (fbin == AR5416_BCHAN_UNUSED)
22 return fbin;
23
24 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
25}
26
27void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
28 u32 shift, u32 val)
22{ 29{
23 u32 regVal; 30 u32 regVal;
24 31
@@ -33,19 +40,8 @@ static void ath9k_hw_analog_shift_rmw(struct ath_hw *ah,
33 return; 40 return;
34} 41}
35 42
36static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) 43int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
37{ 44 int16_t targetLeft, int16_t targetRight)
38
39 if (fbin == AR5416_BCHAN_UNUSED)
40 return fbin;
41
42 return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
43}
44
45static inline int16_t ath9k_hw_interpolate(u16 target,
46 u16 srcLeft, u16 srcRight,
47 int16_t targetLeft,
48 int16_t targetRight)
49{ 45{
50 int16_t rv; 46 int16_t rv;
51 47
@@ -59,9 +55,8 @@ static inline int16_t ath9k_hw_interpolate(u16 target,
59 return rv; 55 return rv;
60} 56}
61 57
62static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, 58bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
63 u16 listSize, u16 *indexL, 59 u16 *indexL, u16 *indexR)
64 u16 *indexR)
65{ 60{
66 u16 i; 61 u16 i;
67 62
@@ -88,16 +83,16 @@ static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
88 return false; 83 return false;
89} 84}
90 85
91static inline bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) 86bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
92{ 87{
93 struct ath_softc *sc = ah->ah_sc; 88 struct ath_softc *sc = ah->ah_sc;
94 89
95 return sc->bus_ops->eeprom_read(ah, off, data); 90 return sc->bus_ops->eeprom_read(ah, off, data);
96} 91}
97 92
98static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, 93void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
99 u8 *pVpdList, u16 numIntercepts, 94 u8 *pVpdList, u16 numIntercepts,
100 u8 *pRetVpdList) 95 u8 *pRetVpdList)
101{ 96{
102 u16 i, k; 97 u16 i, k;
103 u8 currPwr = pwrMin; 98 u8 currPwr = pwrMin;
@@ -120,16 +115,14 @@ static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
120 pRetVpdList[i] = (u8) k; 115 pRetVpdList[i] = (u8) k;
121 currPwr += 2; 116 currPwr += 2;
122 } 117 }
123
124 return true;
125} 118}
126 119
127static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, 120void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
128 struct ath9k_channel *chan, 121 struct ath9k_channel *chan,
129 struct cal_target_power_leg *powInfo, 122 struct cal_target_power_leg *powInfo,
130 u16 numChannels, 123 u16 numChannels,
131 struct cal_target_power_leg *pNewPower, 124 struct cal_target_power_leg *pNewPower,
132 u16 numRates, bool isExtTarget) 125 u16 numRates, bool isExtTarget)
133{ 126{
134 struct chan_centers centers; 127 struct chan_centers centers;
135 u16 clo, chi; 128 u16 clo, chi;
@@ -179,75 +172,12 @@ static void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
179 } 172 }
180} 173}
181 174
182static void ath9k_get_txgain_index(struct ath_hw *ah, 175void ath9k_hw_get_target_powers(struct ath_hw *ah,
183 struct ath9k_channel *chan, 176 struct ath9k_channel *chan,
184 struct calDataPerFreqOpLoop *rawDatasetOpLoop, 177 struct cal_target_power_ht *powInfo,
185 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) 178 u16 numChannels,
186{ 179 struct cal_target_power_ht *pNewPower,
187 u8 pcdac, i = 0; 180 u16 numRates, bool isHt40Target)
188 u16 idxL = 0, idxR = 0, numPiers;
189 bool match;
190 struct chan_centers centers;
191
192 ath9k_hw_get_channel_centers(ah, chan, &centers);
193
194 for (numPiers = 0; numPiers < availPiers; numPiers++)
195 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
196 break;
197
198 match = ath9k_hw_get_lower_upper_index(
199 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
200 calChans, numPiers, &idxL, &idxR);
201 if (match) {
202 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
203 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
204 } else {
205 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
206 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
207 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
208 }
209
210 while (pcdac > ah->originalGain[i] &&
211 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
212 i++;
213
214 *pcdacIdx = i;
215 return;
216}
217
218static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
219 u32 initTxGain,
220 int txPower,
221 u8 *pPDADCValues)
222{
223 u32 i;
224 u32 offset;
225
226 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
227 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
228 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
229 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
230
231 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
232 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
233
234 offset = txPower;
235 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
236 if (i < offset)
237 pPDADCValues[i] = 0x0;
238 else
239 pPDADCValues[i] = 0xFF;
240}
241
242
243
244
245static void ath9k_hw_get_target_powers(struct ath_hw *ah,
246 struct ath9k_channel *chan,
247 struct cal_target_power_ht *powInfo,
248 u16 numChannels,
249 struct cal_target_power_ht *pNewPower,
250 u16 numRates, bool isHt40Target)
251{ 181{
252 struct chan_centers centers; 182 struct chan_centers centers;
253 u16 clo, chi; 183 u16 clo, chi;
@@ -297,9 +227,8 @@ static void ath9k_hw_get_target_powers(struct ath_hw *ah,
297 } 227 }
298} 228}
299 229
300static u16 ath9k_hw_get_max_edge_power(u16 freq, 230u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
301 struct cal_ctl_edges *pRdEdgesPower, 231 bool is2GHz, int num_band_edges)
302 bool is2GHz, int num_band_edges)
303{ 232{
304 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; 233 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
305 int i; 234 int i;
@@ -325,3743 +254,10 @@ static u16 ath9k_hw_get_max_edge_power(u16 freq,
325 return twiceMaxEdgePower; 254 return twiceMaxEdgePower;
326} 255}
327 256
328/****************************************/
329/* EEPROM Operations for 4K sized cards */
330/****************************************/
331
332static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
333{
334 return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
335}
336
337static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
338{
339 return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
340}
341
342static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
343{
344#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
345 u16 *eep_data = (u16 *)&ah->eeprom.map4k;
346 int addr, eep_start_loc = 0;
347
348 eep_start_loc = 64;
349
350 if (!ath9k_hw_use_flash(ah)) {
351 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
352 "Reading from EEPROM, not flash\n");
353 }
354
355 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
356 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
357 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
358 "Unable to read eeprom region \n");
359 return false;
360 }
361 eep_data++;
362 }
363
364 return true;
365#undef SIZE_EEPROM_4K
366}
367
368static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
369{
370#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
371 struct ar5416_eeprom_4k *eep =
372 (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
373 u16 *eepdata, temp, magic, magic2;
374 u32 sum = 0, el;
375 bool need_swap = false;
376 int i, addr;
377
378
379 if (!ath9k_hw_use_flash(ah)) {
380 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
381 &magic)) {
382 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
383 "Reading Magic # failed\n");
384 return false;
385 }
386
387 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
388 "Read Magic = 0x%04X\n", magic);
389
390 if (magic != AR5416_EEPROM_MAGIC) {
391 magic2 = swab16(magic);
392
393 if (magic2 == AR5416_EEPROM_MAGIC) {
394 need_swap = true;
395 eepdata = (u16 *) (&ah->eeprom);
396
397 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
398 temp = swab16(*eepdata);
399 *eepdata = temp;
400 eepdata++;
401 }
402 } else {
403 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
404 "Invalid EEPROM Magic. "
405 "endianness mismatch.\n");
406 return -EINVAL;
407 }
408 }
409 }
410
411 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
412 need_swap ? "True" : "False");
413
414 if (need_swap)
415 el = swab16(ah->eeprom.map4k.baseEepHeader.length);
416 else
417 el = ah->eeprom.map4k.baseEepHeader.length;
418
419 if (el > sizeof(struct ar5416_eeprom_4k))
420 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
421 else
422 el = el / sizeof(u16);
423
424 eepdata = (u16 *)(&ah->eeprom);
425
426 for (i = 0; i < el; i++)
427 sum ^= *eepdata++;
428
429 if (need_swap) {
430 u32 integer;
431 u16 word;
432
433 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
434 "EEPROM Endianness is not native.. Changing\n");
435
436 word = swab16(eep->baseEepHeader.length);
437 eep->baseEepHeader.length = word;
438
439 word = swab16(eep->baseEepHeader.checksum);
440 eep->baseEepHeader.checksum = word;
441
442 word = swab16(eep->baseEepHeader.version);
443 eep->baseEepHeader.version = word;
444
445 word = swab16(eep->baseEepHeader.regDmn[0]);
446 eep->baseEepHeader.regDmn[0] = word;
447
448 word = swab16(eep->baseEepHeader.regDmn[1]);
449 eep->baseEepHeader.regDmn[1] = word;
450
451 word = swab16(eep->baseEepHeader.rfSilent);
452 eep->baseEepHeader.rfSilent = word;
453
454 word = swab16(eep->baseEepHeader.blueToothOptions);
455 eep->baseEepHeader.blueToothOptions = word;
456
457 word = swab16(eep->baseEepHeader.deviceCap);
458 eep->baseEepHeader.deviceCap = word;
459
460 integer = swab32(eep->modalHeader.antCtrlCommon);
461 eep->modalHeader.antCtrlCommon = integer;
462
463 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
464 integer = swab32(eep->modalHeader.antCtrlChain[i]);
465 eep->modalHeader.antCtrlChain[i] = integer;
466 }
467
468 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
469 word = swab16(eep->modalHeader.spurChans[i].spurChan);
470 eep->modalHeader.spurChans[i].spurChan = word;
471 }
472 }
473
474 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
475 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
476 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
477 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
478 sum, ah->eep_ops->get_eeprom_ver(ah));
479 return -EINVAL;
480 }
481
482 return 0;
483#undef EEPROM_4K_SIZE
484}
485
486static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
487 enum eeprom_param param)
488{
489 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
490 struct modal_eep_4k_header *pModal = &eep->modalHeader;
491 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
492
493 switch (param) {
494 case EEP_NFTHRESH_2:
495 return pModal->noiseFloorThreshCh[0];
496 case AR_EEPROM_MAC(0):
497 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
498 case AR_EEPROM_MAC(1):
499 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
500 case AR_EEPROM_MAC(2):
501 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
502 case EEP_REG_0:
503 return pBase->regDmn[0];
504 case EEP_REG_1:
505 return pBase->regDmn[1];
506 case EEP_OP_CAP:
507 return pBase->deviceCap;
508 case EEP_OP_MODE:
509 return pBase->opCapFlags;
510 case EEP_RF_SILENT:
511 return pBase->rfSilent;
512 case EEP_OB_2:
513 return pModal->ob_01;
514 case EEP_DB_2:
515 return pModal->db1_01;
516 case EEP_MINOR_REV:
517 return pBase->version & AR5416_EEP_VER_MINOR_MASK;
518 case EEP_TX_MASK:
519 return pBase->txMask;
520 case EEP_RX_MASK:
521 return pBase->rxMask;
522 case EEP_FRAC_N_5G:
523 return 0;
524 default:
525 return 0;
526 }
527}
528
529static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
530 struct ath9k_channel *chan,
531 struct cal_data_per_freq_4k *pRawDataSet,
532 u8 *bChans, u16 availPiers,
533 u16 tPdGainOverlap, int16_t *pMinCalPower,
534 u16 *pPdGainBoundaries, u8 *pPDADCValues,
535 u16 numXpdGains)
536{
537#define TMP_VAL_VPD_TABLE \
538 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
539 int i, j, k;
540 int16_t ss;
541 u16 idxL = 0, idxR = 0, numPiers;
542 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
543 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
544 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
545 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
546 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
547 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
548
549 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
550 u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
551 u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
552 int16_t vpdStep;
553 int16_t tmpVal;
554 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
555 bool match;
556 int16_t minDelta = 0;
557 struct chan_centers centers;
558#define PD_GAIN_BOUNDARY_DEFAULT 58;
559
560 ath9k_hw_get_channel_centers(ah, chan, &centers);
561
562 for (numPiers = 0; numPiers < availPiers; numPiers++) {
563 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
564 break;
565 }
566
567 match = ath9k_hw_get_lower_upper_index(
568 (u8)FREQ2FBIN(centers.synth_center,
569 IS_CHAN_2GHZ(chan)), bChans, numPiers,
570 &idxL, &idxR);
571
572 if (match) {
573 for (i = 0; i < numXpdGains; i++) {
574 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
575 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
576 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
577 pRawDataSet[idxL].pwrPdg[i],
578 pRawDataSet[idxL].vpdPdg[i],
579 AR5416_EEP4K_PD_GAIN_ICEPTS,
580 vpdTableI[i]);
581 }
582 } else {
583 for (i = 0; i < numXpdGains; i++) {
584 pVpdL = pRawDataSet[idxL].vpdPdg[i];
585 pPwrL = pRawDataSet[idxL].pwrPdg[i];
586 pVpdR = pRawDataSet[idxR].vpdPdg[i];
587 pPwrR = pRawDataSet[idxR].pwrPdg[i];
588
589 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
590
591 maxPwrT4[i] =
592 min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
593 pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
594
595
596 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
597 pPwrL, pVpdL,
598 AR5416_EEP4K_PD_GAIN_ICEPTS,
599 vpdTableL[i]);
600 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
601 pPwrR, pVpdR,
602 AR5416_EEP4K_PD_GAIN_ICEPTS,
603 vpdTableR[i]);
604
605 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
606 vpdTableI[i][j] =
607 (u8)(ath9k_hw_interpolate((u16)
608 FREQ2FBIN(centers.
609 synth_center,
610 IS_CHAN_2GHZ
611 (chan)),
612 bChans[idxL], bChans[idxR],
613 vpdTableL[i][j], vpdTableR[i][j]));
614 }
615 }
616 }
617
618 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
619
620 k = 0;
621
622 for (i = 0; i < numXpdGains; i++) {
623 if (i == (numXpdGains - 1))
624 pPdGainBoundaries[i] =
625 (u16)(maxPwrT4[i] / 2);
626 else
627 pPdGainBoundaries[i] =
628 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
629
630 pPdGainBoundaries[i] =
631 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
632
633 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
634 minDelta = pPdGainBoundaries[0] - 23;
635 pPdGainBoundaries[0] = 23;
636 } else {
637 minDelta = 0;
638 }
639
640 if (i == 0) {
641 if (AR_SREV_9280_10_OR_LATER(ah))
642 ss = (int16_t)(0 - (minPwrT4[i] / 2));
643 else
644 ss = 0;
645 } else {
646 ss = (int16_t)((pPdGainBoundaries[i - 1] -
647 (minPwrT4[i] / 2)) -
648 tPdGainOverlap + 1 + minDelta);
649 }
650 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
651 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
652
653 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
654 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
655 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
656 ss++;
657 }
658
659 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
660 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
661 (minPwrT4[i] / 2));
662 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
663 tgtIndex : sizeCurrVpdTable;
664
665 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
666 pPDADCValues[k++] = vpdTableI[i][ss++];
667
668 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
669 vpdTableI[i][sizeCurrVpdTable - 2]);
670 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
671
672 if (tgtIndex >= maxIndex) {
673 while ((ss <= tgtIndex) &&
674 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
675 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
676 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
677 255 : tmpVal);
678 ss++;
679 }
680 }
681 }
682
683 while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
684 pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
685 i++;
686 }
687
688 while (k < AR5416_NUM_PDADC_VALUES) {
689 pPDADCValues[k] = pPDADCValues[k - 1];
690 k++;
691 }
692
693 return;
694#undef TMP_VAL_VPD_TABLE
695}
696
697static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
698 struct ath9k_channel *chan,
699 int16_t *pTxPowerIndexOffset)
700{
701 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
702 struct cal_data_per_freq_4k *pRawDataset;
703 u8 *pCalBChans = NULL;
704 u16 pdGainOverlap_t2;
705 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
706 u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
707 u16 numPiers, i, j;
708 int16_t tMinCalPower;
709 u16 numXpdGain, xpdMask;
710 u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
711 u32 reg32, regOffset, regChainOffset;
712
713 xpdMask = pEepData->modalHeader.xpdGain;
714
715 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
716 AR5416_EEP_MINOR_VER_2) {
717 pdGainOverlap_t2 =
718 pEepData->modalHeader.pdGainOverlap;
719 } else {
720 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
721 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
722 }
723
724 pCalBChans = pEepData->calFreqPier2G;
725 numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
726
727 numXpdGain = 0;
728
729 for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
730 if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
731 if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
732 break;
733 xpdGainValues[numXpdGain] =
734 (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
735 numXpdGain++;
736 }
737 }
738
739 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
740 (numXpdGain - 1) & 0x3);
741 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
742 xpdGainValues[0]);
743 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
744 xpdGainValues[1]);
745 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
746
747 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
748 if (AR_SREV_5416_20_OR_LATER(ah) &&
749 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
750 (i != 0)) {
751 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
752 } else
753 regChainOffset = i * 0x1000;
754
755 if (pEepData->baseEepHeader.txMask & (1 << i)) {
756 pRawDataset = pEepData->calPierData2G[i];
757
758 ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
759 pRawDataset, pCalBChans,
760 numPiers, pdGainOverlap_t2,
761 &tMinCalPower, gainBoundaries,
762 pdadcValues, numXpdGain);
763
764 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
765 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
766 SM(pdGainOverlap_t2,
767 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
768 | SM(gainBoundaries[0],
769 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
770 | SM(gainBoundaries[1],
771 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
772 | SM(gainBoundaries[2],
773 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
774 | SM(gainBoundaries[3],
775 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
776 }
777
778 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
779 for (j = 0; j < 32; j++) {
780 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
781 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
782 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
783 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
784 REG_WRITE(ah, regOffset, reg32);
785
786 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
787 "PDADC (%d,%4x): %4.4x %8.8x\n",
788 i, regChainOffset, regOffset,
789 reg32);
790 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
791 "PDADC: Chain %d | "
792 "PDADC %3d Value %3d | "
793 "PDADC %3d Value %3d | "
794 "PDADC %3d Value %3d | "
795 "PDADC %3d Value %3d |\n",
796 i, 4 * j, pdadcValues[4 * j],
797 4 * j + 1, pdadcValues[4 * j + 1],
798 4 * j + 2, pdadcValues[4 * j + 2],
799 4 * j + 3,
800 pdadcValues[4 * j + 3]);
801
802 regOffset += 4;
803 }
804 }
805 }
806
807 *pTxPowerIndexOffset = 0;
808}
809
810static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
811 struct ath9k_channel *chan,
812 int16_t *ratesArray,
813 u16 cfgCtl,
814 u16 AntennaReduction,
815 u16 twiceMaxRegulatoryPower,
816 u16 powerLimit)
817{
818 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
819 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
820 static const u16 tpScaleReductionTable[5] =
821 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
822
823 int i;
824 int16_t twiceLargestAntenna;
825 struct cal_ctl_data_4k *rep;
826 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
827 0, { 0, 0, 0, 0}
828 };
829 struct cal_target_power_leg targetPowerOfdmExt = {
830 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
831 0, { 0, 0, 0, 0 }
832 };
833 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
834 0, {0, 0, 0, 0}
835 };
836 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
837 u16 ctlModesFor11g[] =
838 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
839 CTL_2GHT40
840 };
841 u16 numCtlModes, *pCtlMode, ctlMode, freq;
842 struct chan_centers centers;
843 int tx_chainmask;
844 u16 twiceMinEdgePower;
845
846 tx_chainmask = ah->txchainmask;
847
848 ath9k_hw_get_channel_centers(ah, chan, &centers);
849
850 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
851
852 twiceLargestAntenna = (int16_t)min(AntennaReduction -
853 twiceLargestAntenna, 0);
854
855 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
856
857 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
858 maxRegAllowedPower -=
859 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
860 }
861
862 scaledPower = min(powerLimit, maxRegAllowedPower);
863 scaledPower = max((u16)0, scaledPower);
864
865 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
866 pCtlMode = ctlModesFor11g;
867
868 ath9k_hw_get_legacy_target_powers(ah, chan,
869 pEepData->calTargetPowerCck,
870 AR5416_NUM_2G_CCK_TARGET_POWERS,
871 &targetPowerCck, 4, false);
872 ath9k_hw_get_legacy_target_powers(ah, chan,
873 pEepData->calTargetPower2G,
874 AR5416_NUM_2G_20_TARGET_POWERS,
875 &targetPowerOfdm, 4, false);
876 ath9k_hw_get_target_powers(ah, chan,
877 pEepData->calTargetPower2GHT20,
878 AR5416_NUM_2G_20_TARGET_POWERS,
879 &targetPowerHt20, 8, false);
880
881 if (IS_CHAN_HT40(chan)) {
882 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
883 ath9k_hw_get_target_powers(ah, chan,
884 pEepData->calTargetPower2GHT40,
885 AR5416_NUM_2G_40_TARGET_POWERS,
886 &targetPowerHt40, 8, true);
887 ath9k_hw_get_legacy_target_powers(ah, chan,
888 pEepData->calTargetPowerCck,
889 AR5416_NUM_2G_CCK_TARGET_POWERS,
890 &targetPowerCckExt, 4, true);
891 ath9k_hw_get_legacy_target_powers(ah, chan,
892 pEepData->calTargetPower2G,
893 AR5416_NUM_2G_20_TARGET_POWERS,
894 &targetPowerOfdmExt, 4, true);
895 }
896
897 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
898 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
899 (pCtlMode[ctlMode] == CTL_2GHT40);
900 if (isHt40CtlMode)
901 freq = centers.synth_center;
902 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
903 freq = centers.ext_center;
904 else
905 freq = centers.ctl_center;
906
907 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
908 ah->eep_ops->get_eeprom_rev(ah) <= 2)
909 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
910
911 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
912 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
913 "EXT_ADDITIVE %d\n",
914 ctlMode, numCtlModes, isHt40CtlMode,
915 (pCtlMode[ctlMode] & EXT_ADDITIVE));
916
917 for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
918 pEepData->ctlIndex[i]; i++) {
919 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
920 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
921 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
922 "chan %d\n",
923 i, cfgCtl, pCtlMode[ctlMode],
924 pEepData->ctlIndex[i], chan->channel);
925
926 if ((((cfgCtl & ~CTL_MODE_M) |
927 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
928 pEepData->ctlIndex[i]) ||
929 (((cfgCtl & ~CTL_MODE_M) |
930 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
931 ((pEepData->ctlIndex[i] & CTL_MODE_M) |
932 SD_NO_CTL))) {
933 rep = &(pEepData->ctlData[i]);
934
935 twiceMinEdgePower =
936 ath9k_hw_get_max_edge_power(freq,
937 rep->ctlEdges[ar5416_get_ntxchains
938 (tx_chainmask) - 1],
939 IS_CHAN_2GHZ(chan),
940 AR5416_EEP4K_NUM_BAND_EDGES);
941
942 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
943 " MATCH-EE_IDX %d: ch %d is2 %d "
944 "2xMinEdge %d chainmask %d chains %d\n",
945 i, freq, IS_CHAN_2GHZ(chan),
946 twiceMinEdgePower, tx_chainmask,
947 ar5416_get_ntxchains
948 (tx_chainmask));
949 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
950 twiceMaxEdgePower =
951 min(twiceMaxEdgePower,
952 twiceMinEdgePower);
953 } else {
954 twiceMaxEdgePower = twiceMinEdgePower;
955 break;
956 }
957 }
958 }
959
960 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
961
962 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
963 " SEL-Min ctlMode %d pCtlMode %d "
964 "2xMaxEdge %d sP %d minCtlPwr %d\n",
965 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
966 scaledPower, minCtlPower);
967
968 switch (pCtlMode[ctlMode]) {
969 case CTL_11B:
970 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
971 i++) {
972 targetPowerCck.tPow2x[i] =
973 min((u16)targetPowerCck.tPow2x[i],
974 minCtlPower);
975 }
976 break;
977 case CTL_11G:
978 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
979 i++) {
980 targetPowerOfdm.tPow2x[i] =
981 min((u16)targetPowerOfdm.tPow2x[i],
982 minCtlPower);
983 }
984 break;
985 case CTL_2GHT20:
986 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
987 i++) {
988 targetPowerHt20.tPow2x[i] =
989 min((u16)targetPowerHt20.tPow2x[i],
990 minCtlPower);
991 }
992 break;
993 case CTL_11B_EXT:
994 targetPowerCckExt.tPow2x[0] = min((u16)
995 targetPowerCckExt.tPow2x[0],
996 minCtlPower);
997 break;
998 case CTL_11G_EXT:
999 targetPowerOfdmExt.tPow2x[0] = min((u16)
1000 targetPowerOfdmExt.tPow2x[0],
1001 minCtlPower);
1002 break;
1003 case CTL_2GHT40:
1004 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
1005 i++) {
1006 targetPowerHt40.tPow2x[i] =
1007 min((u16)targetPowerHt40.tPow2x[i],
1008 minCtlPower);
1009 }
1010 break;
1011 default:
1012 break;
1013 }
1014 }
1015
1016 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1017 ratesArray[rate18mb] = ratesArray[rate24mb] =
1018 targetPowerOfdm.tPow2x[0];
1019 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1020 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1021 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1022 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1023
1024 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1025 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1026
1027 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1028 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
1029 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
1030 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
1031
1032 if (IS_CHAN_HT40(chan)) {
1033 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1034 ratesArray[rateHt40_0 + i] =
1035 targetPowerHt40.tPow2x[i];
1036 }
1037 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1038 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1039 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1040 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
1041 }
1042}
1043
1044static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
1045 struct ath9k_channel *chan,
1046 u16 cfgCtl,
1047 u8 twiceAntennaReduction,
1048 u8 twiceMaxRegulatoryPower,
1049 u8 powerLimit)
1050{
1051 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
1052 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
1053 int16_t ratesArray[Ar5416RateSize];
1054 int16_t txPowerIndexOffset = 0;
1055 u8 ht40PowerIncForPdadc = 2;
1056 int i;
1057
1058 memset(ratesArray, 0, sizeof(ratesArray));
1059
1060 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1061 AR5416_EEP_MINOR_VER_2) {
1062 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1063 }
1064
1065 ath9k_hw_set_4k_power_per_rate_table(ah, chan,
1066 &ratesArray[0], cfgCtl,
1067 twiceAntennaReduction,
1068 twiceMaxRegulatoryPower,
1069 powerLimit);
1070
1071 ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
1072
1073 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1074 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1075 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1076 ratesArray[i] = AR5416_MAX_RATE_POWER;
1077 }
1078
1079 if (AR_SREV_9280_10_OR_LATER(ah)) {
1080 for (i = 0; i < Ar5416RateSize; i++)
1081 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1082 }
1083
1084 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1085 ATH9K_POW_SM(ratesArray[rate18mb], 24)
1086 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
1087 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
1088 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
1089 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1090 ATH9K_POW_SM(ratesArray[rate54mb], 24)
1091 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
1092 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
1093 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
1094
1095 if (IS_CHAN_2GHZ(chan)) {
1096 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1097 ATH9K_POW_SM(ratesArray[rate2s], 24)
1098 | ATH9K_POW_SM(ratesArray[rate2l], 16)
1099 | ATH9K_POW_SM(ratesArray[rateXr], 8)
1100 | ATH9K_POW_SM(ratesArray[rate1l], 0));
1101 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1102 ATH9K_POW_SM(ratesArray[rate11s], 24)
1103 | ATH9K_POW_SM(ratesArray[rate11l], 16)
1104 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
1105 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
1106 }
1107
1108 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
1109 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
1110 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
1111 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
1112 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
1113 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
1114 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
1115 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
1116 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
1117 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
1118
1119 if (IS_CHAN_HT40(chan)) {
1120 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
1121 ATH9K_POW_SM(ratesArray[rateHt40_3] +
1122 ht40PowerIncForPdadc, 24)
1123 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
1124 ht40PowerIncForPdadc, 16)
1125 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
1126 ht40PowerIncForPdadc, 8)
1127 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
1128 ht40PowerIncForPdadc, 0));
1129 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
1130 ATH9K_POW_SM(ratesArray[rateHt40_7] +
1131 ht40PowerIncForPdadc, 24)
1132 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
1133 ht40PowerIncForPdadc, 16)
1134 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
1135 ht40PowerIncForPdadc, 8)
1136 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
1137 ht40PowerIncForPdadc, 0));
1138
1139 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1140 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
1141 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
1142 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
1143 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
1144 }
1145
1146 i = rate6mb;
1147
1148 if (IS_CHAN_HT40(chan))
1149 i = rateHt40_0;
1150 else if (IS_CHAN_HT20(chan))
1151 i = rateHt20_0;
1152
1153 if (AR_SREV_9280_10_OR_LATER(ah))
1154 ah->regulatory.max_power_level =
1155 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
1156 else
1157 ah->regulatory.max_power_level = ratesArray[i];
1158
1159}
1160
1161static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
1162 struct ath9k_channel *chan)
1163{
1164 struct modal_eep_4k_header *pModal;
1165 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1166 u8 biaslevel;
1167
1168 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1169 return;
1170
1171 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1172 return;
1173
1174 pModal = &eep->modalHeader;
1175
1176 if (pModal->xpaBiasLvl != 0xff) {
1177 biaslevel = pModal->xpaBiasLvl;
1178 INI_RA(&ah->iniAddac, 7, 1) =
1179 (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
1180 }
1181}
1182
1183static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
1184 struct modal_eep_4k_header *pModal,
1185 struct ar5416_eeprom_4k *eep,
1186 u8 txRxAttenLocal, int regChainOffset)
1187{
1188 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1189 pModal->antCtrlChain[0]);
1190
1191 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1192 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1193 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1194 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1195 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1196 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1197
1198 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1199 AR5416_EEP_MINOR_VER_3) {
1200 txRxAttenLocal = pModal->txRxAttenCh[0];
1201
1202 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1203 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
1204 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1205 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
1206 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1207 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1208 pModal->xatten2Margin[0]);
1209 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1210 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
1211
1212 /* Set the block 1 value to block 0 value */
1213 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1214 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1215 pModal->bswMargin[0]);
1216 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1217 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
1218 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1219 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1220 pModal->xatten2Margin[0]);
1221 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
1222 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
1223 pModal->xatten2Db[0]);
1224 }
1225
1226 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1227 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1228 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1229 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
1230
1231 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
1232 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1233 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
1234 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
1235
1236 if (AR_SREV_9285_11(ah))
1237 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
1238}
1239
1240/*
1241 * Read EEPROM header info and program the device for correct operation
1242 * given the channel value.
1243 */
1244static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
1245 struct ath9k_channel *chan)
1246{
1247 struct modal_eep_4k_header *pModal;
1248 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1249 u8 txRxAttenLocal;
1250 u8 ob[5], db1[5], db2[5];
1251 u8 ant_div_control1, ant_div_control2;
1252 u32 regVal;
1253
1254 pModal = &eep->modalHeader;
1255 txRxAttenLocal = 23;
1256
1257 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1258 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1259
1260 /* Single chain for 4K EEPROM*/
1261 ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0);
1262
1263 /* Initialize Ant Diversity settings from EEPROM */
1264 if (pModal->version >= 3) {
1265 ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
1266 ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
1267 regVal = REG_READ(ah, 0x99ac);
1268 regVal &= (~(0x7f000000));
1269 regVal |= ((ant_div_control1 & 0x1) << 24);
1270 regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
1271 regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
1272 regVal |= ((ant_div_control2 & 0x3) << 25);
1273 regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
1274 REG_WRITE(ah, 0x99ac, regVal);
1275 regVal = REG_READ(ah, 0x99ac);
1276 regVal = REG_READ(ah, 0xa208);
1277 regVal &= (~(0x1 << 13));
1278 regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
1279 REG_WRITE(ah, 0xa208, regVal);
1280 regVal = REG_READ(ah, 0xa208);
1281 }
1282
1283 if (pModal->version >= 2) {
1284 ob[0] = (pModal->ob_01 & 0xf);
1285 ob[1] = (pModal->ob_01 >> 4) & 0xf;
1286 ob[2] = (pModal->ob_234 & 0xf);
1287 ob[3] = ((pModal->ob_234 >> 4) & 0xf);
1288 ob[4] = ((pModal->ob_234 >> 8) & 0xf);
1289
1290 db1[0] = (pModal->db1_01 & 0xf);
1291 db1[1] = ((pModal->db1_01 >> 4) & 0xf);
1292 db1[2] = (pModal->db1_234 & 0xf);
1293 db1[3] = ((pModal->db1_234 >> 4) & 0xf);
1294 db1[4] = ((pModal->db1_234 >> 8) & 0xf);
1295
1296 db2[0] = (pModal->db2_01 & 0xf);
1297 db2[1] = ((pModal->db2_01 >> 4) & 0xf);
1298 db2[2] = (pModal->db2_234 & 0xf);
1299 db2[3] = ((pModal->db2_234 >> 4) & 0xf);
1300 db2[4] = ((pModal->db2_234 >> 8) & 0xf);
1301
1302 } else if (pModal->version == 1) {
1303 ob[0] = (pModal->ob_01 & 0xf);
1304 ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
1305 db1[0] = (pModal->db1_01 & 0xf);
1306 db1[1] = db1[2] = db1[3] =
1307 db1[4] = ((pModal->db1_01 >> 4) & 0xf);
1308 db2[0] = (pModal->db2_01 & 0xf);
1309 db2[1] = db2[2] = db2[3] =
1310 db2[4] = ((pModal->db2_01 >> 4) & 0xf);
1311 } else {
1312 int i;
1313 for (i = 0; i < 5; i++) {
1314 ob[i] = pModal->ob_01;
1315 db1[i] = pModal->db1_01;
1316 db2[i] = pModal->db1_01;
1317 }
1318 }
1319
1320 if (AR_SREV_9271(ah)) {
1321 ath9k_hw_analog_shift_rmw(ah,
1322 AR9285_AN_RF2G3,
1323 AR9271_AN_RF2G3_OB_cck,
1324 AR9271_AN_RF2G3_OB_cck_S,
1325 ob[0]);
1326 ath9k_hw_analog_shift_rmw(ah,
1327 AR9285_AN_RF2G3,
1328 AR9271_AN_RF2G3_OB_psk,
1329 AR9271_AN_RF2G3_OB_psk_S,
1330 ob[1]);
1331 ath9k_hw_analog_shift_rmw(ah,
1332 AR9285_AN_RF2G3,
1333 AR9271_AN_RF2G3_OB_qam,
1334 AR9271_AN_RF2G3_OB_qam_S,
1335 ob[2]);
1336 ath9k_hw_analog_shift_rmw(ah,
1337 AR9285_AN_RF2G3,
1338 AR9271_AN_RF2G3_DB_1,
1339 AR9271_AN_RF2G3_DB_1_S,
1340 db1[0]);
1341 ath9k_hw_analog_shift_rmw(ah,
1342 AR9285_AN_RF2G4,
1343 AR9271_AN_RF2G4_DB_2,
1344 AR9271_AN_RF2G4_DB_2_S,
1345 db2[0]);
1346 } else {
1347 ath9k_hw_analog_shift_rmw(ah,
1348 AR9285_AN_RF2G3,
1349 AR9285_AN_RF2G3_OB_0,
1350 AR9285_AN_RF2G3_OB_0_S,
1351 ob[0]);
1352 ath9k_hw_analog_shift_rmw(ah,
1353 AR9285_AN_RF2G3,
1354 AR9285_AN_RF2G3_OB_1,
1355 AR9285_AN_RF2G3_OB_1_S,
1356 ob[1]);
1357 ath9k_hw_analog_shift_rmw(ah,
1358 AR9285_AN_RF2G3,
1359 AR9285_AN_RF2G3_OB_2,
1360 AR9285_AN_RF2G3_OB_2_S,
1361 ob[2]);
1362 ath9k_hw_analog_shift_rmw(ah,
1363 AR9285_AN_RF2G3,
1364 AR9285_AN_RF2G3_OB_3,
1365 AR9285_AN_RF2G3_OB_3_S,
1366 ob[3]);
1367 ath9k_hw_analog_shift_rmw(ah,
1368 AR9285_AN_RF2G3,
1369 AR9285_AN_RF2G3_OB_4,
1370 AR9285_AN_RF2G3_OB_4_S,
1371 ob[4]);
1372
1373 ath9k_hw_analog_shift_rmw(ah,
1374 AR9285_AN_RF2G3,
1375 AR9285_AN_RF2G3_DB1_0,
1376 AR9285_AN_RF2G3_DB1_0_S,
1377 db1[0]);
1378 ath9k_hw_analog_shift_rmw(ah,
1379 AR9285_AN_RF2G3,
1380 AR9285_AN_RF2G3_DB1_1,
1381 AR9285_AN_RF2G3_DB1_1_S,
1382 db1[1]);
1383 ath9k_hw_analog_shift_rmw(ah,
1384 AR9285_AN_RF2G3,
1385 AR9285_AN_RF2G3_DB1_2,
1386 AR9285_AN_RF2G3_DB1_2_S,
1387 db1[2]);
1388 ath9k_hw_analog_shift_rmw(ah,
1389 AR9285_AN_RF2G4,
1390 AR9285_AN_RF2G4_DB1_3,
1391 AR9285_AN_RF2G4_DB1_3_S,
1392 db1[3]);
1393 ath9k_hw_analog_shift_rmw(ah,
1394 AR9285_AN_RF2G4,
1395 AR9285_AN_RF2G4_DB1_4,
1396 AR9285_AN_RF2G4_DB1_4_S, db1[4]);
1397
1398 ath9k_hw_analog_shift_rmw(ah,
1399 AR9285_AN_RF2G4,
1400 AR9285_AN_RF2G4_DB2_0,
1401 AR9285_AN_RF2G4_DB2_0_S,
1402 db2[0]);
1403 ath9k_hw_analog_shift_rmw(ah,
1404 AR9285_AN_RF2G4,
1405 AR9285_AN_RF2G4_DB2_1,
1406 AR9285_AN_RF2G4_DB2_1_S,
1407 db2[1]);
1408 ath9k_hw_analog_shift_rmw(ah,
1409 AR9285_AN_RF2G4,
1410 AR9285_AN_RF2G4_DB2_2,
1411 AR9285_AN_RF2G4_DB2_2_S,
1412 db2[2]);
1413 ath9k_hw_analog_shift_rmw(ah,
1414 AR9285_AN_RF2G4,
1415 AR9285_AN_RF2G4_DB2_3,
1416 AR9285_AN_RF2G4_DB2_3_S,
1417 db2[3]);
1418 ath9k_hw_analog_shift_rmw(ah,
1419 AR9285_AN_RF2G4,
1420 AR9285_AN_RF2G4_DB2_4,
1421 AR9285_AN_RF2G4_DB2_4_S,
1422 db2[4]);
1423 }
1424
1425
1426 if (AR_SREV_9285_11(ah))
1427 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
1428
1429 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1430 pModal->switchSettling);
1431 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1432 pModal->adcDesiredSize);
1433
1434 REG_WRITE(ah, AR_PHY_RF_CTL4,
1435 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
1436 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
1437 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
1438 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1439
1440 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1441 pModal->txEndToRxOn);
1442 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1443 pModal->thresh62);
1444 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
1445 pModal->thresh62);
1446
1447 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1448 AR5416_EEP_MINOR_VER_2) {
1449 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
1450 pModal->txFrameToDataStart);
1451 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1452 pModal->txFrameToPaOn);
1453 }
1454
1455 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1456 AR5416_EEP_MINOR_VER_3) {
1457 if (IS_CHAN_HT40(chan))
1458 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1459 AR_PHY_SETTLING_SWITCH,
1460 pModal->swSettleHt40);
1461 }
1462}
1463
1464static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
1465 struct ath9k_channel *chan)
1466{
1467 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1468 struct modal_eep_4k_header *pModal = &eep->modalHeader;
1469
1470 return pModal->antCtrlCommon & 0xFFFF;
1471}
1472
1473static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
1474 enum ieee80211_band freq_band)
1475{
1476 return 1;
1477}
1478
1479static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
1480{
1481#define EEP_MAP4K_SPURCHAN \
1482 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
1483
1484 u16 spur_val = AR_NO_SPUR;
1485
1486 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1487 "Getting spur idx %d is2Ghz. %d val %x\n",
1488 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1489
1490 switch (ah->config.spurmode) {
1491 case SPUR_DISABLE:
1492 break;
1493 case SPUR_ENABLE_IOCTL:
1494 spur_val = ah->config.spurchans[i][is2GHz];
1495 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1496 "Getting spur val from new loc. %d\n", spur_val);
1497 break;
1498 case SPUR_ENABLE_EEPROM:
1499 spur_val = EEP_MAP4K_SPURCHAN;
1500 break;
1501 }
1502
1503 return spur_val;
1504
1505#undef EEP_MAP4K_SPURCHAN
1506}
1507
1508static struct eeprom_ops eep_4k_ops = {
1509 .check_eeprom = ath9k_hw_4k_check_eeprom,
1510 .get_eeprom = ath9k_hw_4k_get_eeprom,
1511 .fill_eeprom = ath9k_hw_4k_fill_eeprom,
1512 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
1513 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
1514 .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
1515 .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
1516 .set_board_values = ath9k_hw_4k_set_board_values,
1517 .set_addac = ath9k_hw_4k_set_addac,
1518 .set_txpower = ath9k_hw_4k_set_txpower,
1519 .get_spur_channel = ath9k_hw_4k_get_spur_channel
1520};
1521
1522/************************************************/
1523/* EEPROM Operations for non-4K (Default) cards */
1524/************************************************/
1525
1526static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
1527{
1528 return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
1529}
1530
1531static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
1532{
1533 return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
1534}
1535
1536static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
1537{
1538#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
1539 u16 *eep_data = (u16 *)&ah->eeprom.def;
1540 int addr, ar5416_eep_start_loc = 0x100;
1541
1542 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
1543 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
1544 eep_data)) {
1545 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1546 "Unable to read eeprom region\n");
1547 return false;
1548 }
1549 eep_data++;
1550 }
1551 return true;
1552#undef SIZE_EEPROM_DEF
1553}
1554
1555static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
1556{
1557 struct ar5416_eeprom_def *eep =
1558 (struct ar5416_eeprom_def *) &ah->eeprom.def;
1559 u16 *eepdata, temp, magic, magic2;
1560 u32 sum = 0, el;
1561 bool need_swap = false;
1562 int i, addr, size;
1563
1564 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
1565 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
1566 return false;
1567 }
1568
1569 if (!ath9k_hw_use_flash(ah)) {
1570 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1571 "Read Magic = 0x%04X\n", magic);
1572
1573 if (magic != AR5416_EEPROM_MAGIC) {
1574 magic2 = swab16(magic);
1575
1576 if (magic2 == AR5416_EEPROM_MAGIC) {
1577 size = sizeof(struct ar5416_eeprom_def);
1578 need_swap = true;
1579 eepdata = (u16 *) (&ah->eeprom);
1580
1581 for (addr = 0; addr < size / sizeof(u16); addr++) {
1582 temp = swab16(*eepdata);
1583 *eepdata = temp;
1584 eepdata++;
1585 }
1586 } else {
1587 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1588 "Invalid EEPROM Magic. "
1589 "Endianness mismatch.\n");
1590 return -EINVAL;
1591 }
1592 }
1593 }
1594
1595 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
1596 need_swap ? "True" : "False");
1597
1598 if (need_swap)
1599 el = swab16(ah->eeprom.def.baseEepHeader.length);
1600 else
1601 el = ah->eeprom.def.baseEepHeader.length;
1602
1603 if (el > sizeof(struct ar5416_eeprom_def))
1604 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
1605 else
1606 el = el / sizeof(u16);
1607
1608 eepdata = (u16 *)(&ah->eeprom);
1609
1610 for (i = 0; i < el; i++)
1611 sum ^= *eepdata++;
1612
1613 if (need_swap) {
1614 u32 integer, j;
1615 u16 word;
1616
1617 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1618 "EEPROM Endianness is not native.. Changing.\n");
1619
1620 word = swab16(eep->baseEepHeader.length);
1621 eep->baseEepHeader.length = word;
1622
1623 word = swab16(eep->baseEepHeader.checksum);
1624 eep->baseEepHeader.checksum = word;
1625
1626 word = swab16(eep->baseEepHeader.version);
1627 eep->baseEepHeader.version = word;
1628
1629 word = swab16(eep->baseEepHeader.regDmn[0]);
1630 eep->baseEepHeader.regDmn[0] = word;
1631
1632 word = swab16(eep->baseEepHeader.regDmn[1]);
1633 eep->baseEepHeader.regDmn[1] = word;
1634
1635 word = swab16(eep->baseEepHeader.rfSilent);
1636 eep->baseEepHeader.rfSilent = word;
1637
1638 word = swab16(eep->baseEepHeader.blueToothOptions);
1639 eep->baseEepHeader.blueToothOptions = word;
1640
1641 word = swab16(eep->baseEepHeader.deviceCap);
1642 eep->baseEepHeader.deviceCap = word;
1643
1644 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
1645 struct modal_eep_header *pModal =
1646 &eep->modalHeader[j];
1647 integer = swab32(pModal->antCtrlCommon);
1648 pModal->antCtrlCommon = integer;
1649
1650 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1651 integer = swab32(pModal->antCtrlChain[i]);
1652 pModal->antCtrlChain[i] = integer;
1653 }
1654
1655 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
1656 word = swab16(pModal->spurChans[i].spurChan);
1657 pModal->spurChans[i].spurChan = word;
1658 }
1659 }
1660 }
1661
1662 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
1663 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
1664 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
1665 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
1666 sum, ah->eep_ops->get_eeprom_ver(ah));
1667 return -EINVAL;
1668 }
1669
1670 return 0;
1671}
1672
1673static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
1674 enum eeprom_param param)
1675{
1676 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1677 struct modal_eep_header *pModal = eep->modalHeader;
1678 struct base_eep_header *pBase = &eep->baseEepHeader;
1679
1680 switch (param) {
1681 case EEP_NFTHRESH_5:
1682 return pModal[0].noiseFloorThreshCh[0];
1683 case EEP_NFTHRESH_2:
1684 return pModal[1].noiseFloorThreshCh[0];
1685 case AR_EEPROM_MAC(0):
1686 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
1687 case AR_EEPROM_MAC(1):
1688 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
1689 case AR_EEPROM_MAC(2):
1690 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
1691 case EEP_REG_0:
1692 return pBase->regDmn[0];
1693 case EEP_REG_1:
1694 return pBase->regDmn[1];
1695 case EEP_OP_CAP:
1696 return pBase->deviceCap;
1697 case EEP_OP_MODE:
1698 return pBase->opCapFlags;
1699 case EEP_RF_SILENT:
1700 return pBase->rfSilent;
1701 case EEP_OB_5:
1702 return pModal[0].ob;
1703 case EEP_DB_5:
1704 return pModal[0].db;
1705 case EEP_OB_2:
1706 return pModal[1].ob;
1707 case EEP_DB_2:
1708 return pModal[1].db;
1709 case EEP_MINOR_REV:
1710 return AR5416_VER_MASK;
1711 case EEP_TX_MASK:
1712 return pBase->txMask;
1713 case EEP_RX_MASK:
1714 return pBase->rxMask;
1715 case EEP_RXGAIN_TYPE:
1716 return pBase->rxGainType;
1717 case EEP_TXGAIN_TYPE:
1718 return pBase->txGainType;
1719 case EEP_OL_PWRCTRL:
1720 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1721 return pBase->openLoopPwrCntl ? true : false;
1722 else
1723 return false;
1724 case EEP_RC_CHAIN_MASK:
1725 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1726 return pBase->rcChainMask;
1727 else
1728 return 0;
1729 case EEP_DAC_HPWR_5G:
1730 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
1731 return pBase->dacHiPwrMode_5G;
1732 else
1733 return 0;
1734 case EEP_FRAC_N_5G:
1735 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
1736 return pBase->frac_n_5g;
1737 else
1738 return 0;
1739 default:
1740 return 0;
1741 }
1742}
1743
1744static void ath9k_hw_def_set_gain(struct ath_hw *ah,
1745 struct modal_eep_header *pModal,
1746 struct ar5416_eeprom_def *eep,
1747 u8 txRxAttenLocal, int regChainOffset, int i)
1748{
1749 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1750 txRxAttenLocal = pModal->txRxAttenCh[i];
1751
1752 if (AR_SREV_9280_10_OR_LATER(ah)) {
1753 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1754 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1755 pModal->bswMargin[i]);
1756 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1757 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
1758 pModal->bswAtten[i]);
1759 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1760 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
1761 pModal->xatten2Margin[i]);
1762 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1763 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
1764 pModal->xatten2Db[i]);
1765 } else {
1766 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1767 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1768 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
1769 | SM(pModal-> bswMargin[i],
1770 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
1771 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1772 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1773 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
1774 | SM(pModal->bswAtten[i],
1775 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
1776 }
1777 }
1778
1779 if (AR_SREV_9280_10_OR_LATER(ah)) {
1780 REG_RMW_FIELD(ah,
1781 AR_PHY_RXGAIN + regChainOffset,
1782 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
1783 REG_RMW_FIELD(ah,
1784 AR_PHY_RXGAIN + regChainOffset,
1785 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
1786 } else {
1787 REG_WRITE(ah,
1788 AR_PHY_RXGAIN + regChainOffset,
1789 (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
1790 ~AR_PHY_RXGAIN_TXRX_ATTEN)
1791 | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
1792 REG_WRITE(ah,
1793 AR_PHY_GAIN_2GHZ + regChainOffset,
1794 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
1795 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
1796 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
1797 }
1798}
1799
1800static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
1801 struct ath9k_channel *chan)
1802{
1803 struct modal_eep_header *pModal;
1804 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1805 int i, regChainOffset;
1806 u8 txRxAttenLocal;
1807
1808 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1809 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
1810
1811 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1812 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1813
1814 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
1815 if (AR_SREV_9280(ah)) {
1816 if (i >= 2)
1817 break;
1818 }
1819
1820 if (AR_SREV_5416_20_OR_LATER(ah) &&
1821 (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
1822 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
1823 else
1824 regChainOffset = i * 0x1000;
1825
1826 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1827 pModal->antCtrlChain[i]);
1828
1829 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1830 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
1831 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1832 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1833 SM(pModal->iqCalICh[i],
1834 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1835 SM(pModal->iqCalQCh[i],
1836 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1837
1838 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
1839 ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
1840 regChainOffset, i);
1841 }
1842
1843 if (AR_SREV_9280_10_OR_LATER(ah)) {
1844 if (IS_CHAN_2GHZ(chan)) {
1845 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1846 AR_AN_RF2G1_CH0_OB,
1847 AR_AN_RF2G1_CH0_OB_S,
1848 pModal->ob);
1849 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
1850 AR_AN_RF2G1_CH0_DB,
1851 AR_AN_RF2G1_CH0_DB_S,
1852 pModal->db);
1853 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1854 AR_AN_RF2G1_CH1_OB,
1855 AR_AN_RF2G1_CH1_OB_S,
1856 pModal->ob_ch1);
1857 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
1858 AR_AN_RF2G1_CH1_DB,
1859 AR_AN_RF2G1_CH1_DB_S,
1860 pModal->db_ch1);
1861 } else {
1862 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1863 AR_AN_RF5G1_CH0_OB5,
1864 AR_AN_RF5G1_CH0_OB5_S,
1865 pModal->ob);
1866 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
1867 AR_AN_RF5G1_CH0_DB5,
1868 AR_AN_RF5G1_CH0_DB5_S,
1869 pModal->db);
1870 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1871 AR_AN_RF5G1_CH1_OB5,
1872 AR_AN_RF5G1_CH1_OB5_S,
1873 pModal->ob_ch1);
1874 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
1875 AR_AN_RF5G1_CH1_DB5,
1876 AR_AN_RF5G1_CH1_DB5_S,
1877 pModal->db_ch1);
1878 }
1879 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1880 AR_AN_TOP2_XPABIAS_LVL,
1881 AR_AN_TOP2_XPABIAS_LVL_S,
1882 pModal->xpaBiasLvl);
1883 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
1884 AR_AN_TOP2_LOCALBIAS,
1885 AR_AN_TOP2_LOCALBIAS_S,
1886 pModal->local_bias);
1887 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
1888 pModal->force_xpaon);
1889 }
1890
1891 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1892 pModal->switchSettling);
1893 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1894 pModal->adcDesiredSize);
1895
1896 if (!AR_SREV_9280_10_OR_LATER(ah))
1897 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
1898 AR_PHY_DESIRED_SZ_PGA,
1899 pModal->pgaDesiredSize);
1900
1901 REG_WRITE(ah, AR_PHY_RF_CTL4,
1902 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
1903 | SM(pModal->txEndToXpaOff,
1904 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
1905 | SM(pModal->txFrameToXpaOn,
1906 AR_PHY_RF_CTL4_FRAME_XPAA_ON)
1907 | SM(pModal->txFrameToXpaOn,
1908 AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1909
1910 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1911 pModal->txEndToRxOn);
1912
1913 if (AR_SREV_9280_10_OR_LATER(ah)) {
1914 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1915 pModal->thresh62);
1916 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
1917 AR_PHY_EXT_CCA0_THRESH62,
1918 pModal->thresh62);
1919 } else {
1920 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
1921 pModal->thresh62);
1922 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
1923 AR_PHY_EXT_CCA_THRESH62,
1924 pModal->thresh62);
1925 }
1926
1927 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
1928 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1929 AR_PHY_TX_END_DATA_START,
1930 pModal->txFrameToDataStart);
1931 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1932 pModal->txFrameToPaOn);
1933 }
1934
1935 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
1936 if (IS_CHAN_HT40(chan))
1937 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1938 AR_PHY_SETTLING_SWITCH,
1939 pModal->swSettleHt40);
1940 }
1941
1942 if (AR_SREV_9280_20_OR_LATER(ah) &&
1943 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
1944 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
1945 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
1946 pModal->miscBits);
1947
1948
1949 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
1950 if (IS_CHAN_2GHZ(chan))
1951 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1952 eep->baseEepHeader.dacLpMode);
1953 else if (eep->baseEepHeader.dacHiPwrMode_5G)
1954 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
1955 else
1956 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
1957 eep->baseEepHeader.dacLpMode);
1958
1959 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
1960 pModal->miscBits >> 2);
1961
1962 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
1963 AR_PHY_TX_DESIRED_SCALE_CCK,
1964 eep->baseEepHeader.desiredScaleCCK);
1965 }
1966}
1967
1968static void ath9k_hw_def_set_addac(struct ath_hw *ah,
1969 struct ath9k_channel *chan)
1970{
1971#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
1972 struct modal_eep_header *pModal;
1973 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1974 u8 biaslevel;
1975
1976 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
1977 return;
1978
1979 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
1980 return;
1981
1982 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1983
1984 if (pModal->xpaBiasLvl != 0xff) {
1985 biaslevel = pModal->xpaBiasLvl;
1986 } else {
1987 u16 resetFreqBin, freqBin, freqCount = 0;
1988 struct chan_centers centers;
1989
1990 ath9k_hw_get_channel_centers(ah, chan, &centers);
1991
1992 resetFreqBin = FREQ2FBIN(centers.synth_center,
1993 IS_CHAN_2GHZ(chan));
1994 freqBin = XPA_LVL_FREQ(0) & 0xff;
1995 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
1996
1997 freqCount++;
1998
1999 while (freqCount < 3) {
2000 if (XPA_LVL_FREQ(freqCount) == 0x0)
2001 break;
2002
2003 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
2004 if (resetFreqBin >= freqBin)
2005 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
2006 else
2007 break;
2008 freqCount++;
2009 }
2010 }
2011
2012 if (IS_CHAN_2GHZ(chan)) {
2013 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
2014 7, 1) & (~0x18)) | biaslevel << 3;
2015 } else {
2016 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
2017 6, 1) & (~0xc0)) | biaslevel << 6;
2018 }
2019#undef XPA_LVL_FREQ
2020}
2021
2022static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
2023 struct ath9k_channel *chan,
2024 struct cal_data_per_freq *pRawDataSet,
2025 u8 *bChans, u16 availPiers,
2026 u16 tPdGainOverlap, int16_t *pMinCalPower,
2027 u16 *pPdGainBoundaries, u8 *pPDADCValues,
2028 u16 numXpdGains)
2029{
2030 int i, j, k;
2031 int16_t ss;
2032 u16 idxL = 0, idxR = 0, numPiers;
2033 static u8 vpdTableL[AR5416_NUM_PD_GAINS]
2034 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
2035 static u8 vpdTableR[AR5416_NUM_PD_GAINS]
2036 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
2037 static u8 vpdTableI[AR5416_NUM_PD_GAINS]
2038 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
2039
2040 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
2041 u8 minPwrT4[AR5416_NUM_PD_GAINS];
2042 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
2043 int16_t vpdStep;
2044 int16_t tmpVal;
2045 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
2046 bool match;
2047 int16_t minDelta = 0;
2048 struct chan_centers centers;
2049
2050 ath9k_hw_get_channel_centers(ah, chan, &centers);
2051
2052 for (numPiers = 0; numPiers < availPiers; numPiers++) {
2053 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
2054 break;
2055 }
2056
2057 match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
2058 IS_CHAN_2GHZ(chan)),
2059 bChans, numPiers, &idxL, &idxR);
2060
2061 if (match) {
2062 for (i = 0; i < numXpdGains; i++) {
2063 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
2064 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
2065 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2066 pRawDataSet[idxL].pwrPdg[i],
2067 pRawDataSet[idxL].vpdPdg[i],
2068 AR5416_PD_GAIN_ICEPTS,
2069 vpdTableI[i]);
2070 }
2071 } else {
2072 for (i = 0; i < numXpdGains; i++) {
2073 pVpdL = pRawDataSet[idxL].vpdPdg[i];
2074 pPwrL = pRawDataSet[idxL].pwrPdg[i];
2075 pVpdR = pRawDataSet[idxR].vpdPdg[i];
2076 pPwrR = pRawDataSet[idxR].pwrPdg[i];
2077
2078 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
2079
2080 maxPwrT4[i] =
2081 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
2082 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
2083
2084
2085 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2086 pPwrL, pVpdL,
2087 AR5416_PD_GAIN_ICEPTS,
2088 vpdTableL[i]);
2089 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
2090 pPwrR, pVpdR,
2091 AR5416_PD_GAIN_ICEPTS,
2092 vpdTableR[i]);
2093
2094 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
2095 vpdTableI[i][j] =
2096 (u8)(ath9k_hw_interpolate((u16)
2097 FREQ2FBIN(centers.
2098 synth_center,
2099 IS_CHAN_2GHZ
2100 (chan)),
2101 bChans[idxL], bChans[idxR],
2102 vpdTableL[i][j], vpdTableR[i][j]));
2103 }
2104 }
2105 }
2106
2107 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
2108
2109 k = 0;
2110
2111 for (i = 0; i < numXpdGains; i++) {
2112 if (i == (numXpdGains - 1))
2113 pPdGainBoundaries[i] =
2114 (u16)(maxPwrT4[i] / 2);
2115 else
2116 pPdGainBoundaries[i] =
2117 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
2118
2119 pPdGainBoundaries[i] =
2120 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
2121
2122 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
2123 minDelta = pPdGainBoundaries[0] - 23;
2124 pPdGainBoundaries[0] = 23;
2125 } else {
2126 minDelta = 0;
2127 }
2128
2129 if (i == 0) {
2130 if (AR_SREV_9280_10_OR_LATER(ah))
2131 ss = (int16_t)(0 - (minPwrT4[i] / 2));
2132 else
2133 ss = 0;
2134 } else {
2135 ss = (int16_t)((pPdGainBoundaries[i - 1] -
2136 (minPwrT4[i] / 2)) -
2137 tPdGainOverlap + 1 + minDelta);
2138 }
2139 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
2140 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2141
2142 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2143 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
2144 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
2145 ss++;
2146 }
2147
2148 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
2149 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
2150 (minPwrT4[i] / 2));
2151 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
2152 tgtIndex : sizeCurrVpdTable;
2153
2154 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2155 pPDADCValues[k++] = vpdTableI[i][ss++];
2156 }
2157
2158 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
2159 vpdTableI[i][sizeCurrVpdTable - 2]);
2160 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
2161
2162 if (tgtIndex > maxIndex) {
2163 while ((ss <= tgtIndex) &&
2164 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
2165 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
2166 (ss - maxIndex + 1) * vpdStep));
2167 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
2168 255 : tmpVal);
2169 ss++;
2170 }
2171 }
2172 }
2173
2174 while (i < AR5416_PD_GAINS_IN_MASK) {
2175 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
2176 i++;
2177 }
2178
2179 while (k < AR5416_NUM_PDADC_VALUES) {
2180 pPDADCValues[k] = pPDADCValues[k - 1];
2181 k++;
2182 }
2183
2184 return;
2185}
2186
2187static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
2188 struct ath9k_channel *chan,
2189 int16_t *pTxPowerIndexOffset)
2190{
2191#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
2192#define SM_PDGAIN_B(x, y) \
2193 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
2194
2195 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2196 struct cal_data_per_freq *pRawDataset;
2197 u8 *pCalBChans = NULL;
2198 u16 pdGainOverlap_t2;
2199 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
2200 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
2201 u16 numPiers, i, j;
2202 int16_t tMinCalPower;
2203 u16 numXpdGain, xpdMask;
2204 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
2205 u32 reg32, regOffset, regChainOffset;
2206 int16_t modalIdx;
2207
2208 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
2209 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
2210
2211 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2212 AR5416_EEP_MINOR_VER_2) {
2213 pdGainOverlap_t2 =
2214 pEepData->modalHeader[modalIdx].pdGainOverlap;
2215 } else {
2216 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
2217 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
2218 }
2219
2220 if (IS_CHAN_2GHZ(chan)) {
2221 pCalBChans = pEepData->calFreqPier2G;
2222 numPiers = AR5416_NUM_2G_CAL_PIERS;
2223 } else {
2224 pCalBChans = pEepData->calFreqPier5G;
2225 numPiers = AR5416_NUM_5G_CAL_PIERS;
2226 }
2227
2228 if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
2229 pRawDataset = pEepData->calPierData2G[0];
2230 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
2231 pRawDataset)->vpdPdg[0][0];
2232 }
2233
2234 numXpdGain = 0;
2235
2236 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
2237 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
2238 if (numXpdGain >= AR5416_NUM_PD_GAINS)
2239 break;
2240 xpdGainValues[numXpdGain] =
2241 (u16)(AR5416_PD_GAINS_IN_MASK - i);
2242 numXpdGain++;
2243 }
2244 }
2245
2246 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
2247 (numXpdGain - 1) & 0x3);
2248 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
2249 xpdGainValues[0]);
2250 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
2251 xpdGainValues[1]);
2252 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
2253 xpdGainValues[2]);
2254
2255 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
2256 if (AR_SREV_5416_20_OR_LATER(ah) &&
2257 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
2258 (i != 0)) {
2259 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
2260 } else
2261 regChainOffset = i * 0x1000;
2262
2263 if (pEepData->baseEepHeader.txMask & (1 << i)) {
2264 if (IS_CHAN_2GHZ(chan))
2265 pRawDataset = pEepData->calPierData2G[i];
2266 else
2267 pRawDataset = pEepData->calPierData5G[i];
2268
2269
2270 if (OLC_FOR_AR9280_20_LATER) {
2271 u8 pcdacIdx;
2272 u8 txPower;
2273
2274 ath9k_get_txgain_index(ah, chan,
2275 (struct calDataPerFreqOpLoop *)pRawDataset,
2276 pCalBChans, numPiers, &txPower, &pcdacIdx);
2277 ath9k_olc_get_pdadcs(ah, pcdacIdx,
2278 txPower/2, pdadcValues);
2279 } else {
2280 ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
2281 chan, pRawDataset,
2282 pCalBChans, numPiers,
2283 pdGainOverlap_t2,
2284 &tMinCalPower,
2285 gainBoundaries,
2286 pdadcValues,
2287 numXpdGain);
2288 }
2289
2290 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
2291 if (OLC_FOR_AR9280_20_LATER) {
2292 REG_WRITE(ah,
2293 AR_PHY_TPCRG5 + regChainOffset,
2294 SM(0x6,
2295 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
2296 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
2297 SM_PD_GAIN(3) | SM_PD_GAIN(4));
2298 } else {
2299 REG_WRITE(ah,
2300 AR_PHY_TPCRG5 + regChainOffset,
2301 SM(pdGainOverlap_t2,
2302 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
2303 SM_PDGAIN_B(0, 1) |
2304 SM_PDGAIN_B(1, 2) |
2305 SM_PDGAIN_B(2, 3) |
2306 SM_PDGAIN_B(3, 4));
2307 }
2308 }
2309
2310 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
2311 for (j = 0; j < 32; j++) {
2312 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
2313 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
2314 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
2315 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
2316 REG_WRITE(ah, regOffset, reg32);
2317
2318 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2319 "PDADC (%d,%4x): %4.4x %8.8x\n",
2320 i, regChainOffset, regOffset,
2321 reg32);
2322 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2323 "PDADC: Chain %d | PDADC %3d "
2324 "Value %3d | PDADC %3d Value %3d | "
2325 "PDADC %3d Value %3d | PDADC %3d "
2326 "Value %3d |\n",
2327 i, 4 * j, pdadcValues[4 * j],
2328 4 * j + 1, pdadcValues[4 * j + 1],
2329 4 * j + 2, pdadcValues[4 * j + 2],
2330 4 * j + 3,
2331 pdadcValues[4 * j + 3]);
2332
2333 regOffset += 4;
2334 }
2335 }
2336 }
2337
2338 *pTxPowerIndexOffset = 0;
2339#undef SM_PD_GAIN
2340#undef SM_PDGAIN_B
2341}
2342
2343static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
2344 struct ath9k_channel *chan,
2345 int16_t *ratesArray,
2346 u16 cfgCtl,
2347 u16 AntennaReduction,
2348 u16 twiceMaxRegulatoryPower,
2349 u16 powerLimit)
2350{
2351#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
2352#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
2353
2354 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2355 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2356 static const u16 tpScaleReductionTable[5] =
2357 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
2358
2359 int i;
2360 int16_t twiceLargestAntenna;
2361 struct cal_ctl_data *rep;
2362 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
2363 0, { 0, 0, 0, 0}
2364 };
2365 struct cal_target_power_leg targetPowerOfdmExt = {
2366 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
2367 0, { 0, 0, 0, 0 }
2368 };
2369 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
2370 0, {0, 0, 0, 0}
2371 };
2372 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
2373 u16 ctlModesFor11a[] =
2374 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
2375 u16 ctlModesFor11g[] =
2376 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
2377 CTL_2GHT40
2378 };
2379 u16 numCtlModes, *pCtlMode, ctlMode, freq;
2380 struct chan_centers centers;
2381 int tx_chainmask;
2382 u16 twiceMinEdgePower;
2383
2384 tx_chainmask = ah->txchainmask;
2385
2386 ath9k_hw_get_channel_centers(ah, chan, &centers);
2387
2388 twiceLargestAntenna = max(
2389 pEepData->modalHeader
2390 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
2391 pEepData->modalHeader
2392 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
2393
2394 twiceLargestAntenna = max((u8)twiceLargestAntenna,
2395 pEepData->modalHeader
2396 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
2397
2398 twiceLargestAntenna = (int16_t)min(AntennaReduction -
2399 twiceLargestAntenna, 0);
2400
2401 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
2402
2403 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
2404 maxRegAllowedPower -=
2405 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
2406 }
2407
2408 scaledPower = min(powerLimit, maxRegAllowedPower);
2409
2410 switch (ar5416_get_ntxchains(tx_chainmask)) {
2411 case 1:
2412 break;
2413 case 2:
2414 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
2415 break;
2416 case 3:
2417 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
2418 break;
2419 }
2420
2421 scaledPower = max((u16)0, scaledPower);
2422
2423 if (IS_CHAN_2GHZ(chan)) {
2424 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
2425 SUB_NUM_CTL_MODES_AT_2G_40;
2426 pCtlMode = ctlModesFor11g;
2427
2428 ath9k_hw_get_legacy_target_powers(ah, chan,
2429 pEepData->calTargetPowerCck,
2430 AR5416_NUM_2G_CCK_TARGET_POWERS,
2431 &targetPowerCck, 4, false);
2432 ath9k_hw_get_legacy_target_powers(ah, chan,
2433 pEepData->calTargetPower2G,
2434 AR5416_NUM_2G_20_TARGET_POWERS,
2435 &targetPowerOfdm, 4, false);
2436 ath9k_hw_get_target_powers(ah, chan,
2437 pEepData->calTargetPower2GHT20,
2438 AR5416_NUM_2G_20_TARGET_POWERS,
2439 &targetPowerHt20, 8, false);
2440
2441 if (IS_CHAN_HT40(chan)) {
2442 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
2443 ath9k_hw_get_target_powers(ah, chan,
2444 pEepData->calTargetPower2GHT40,
2445 AR5416_NUM_2G_40_TARGET_POWERS,
2446 &targetPowerHt40, 8, true);
2447 ath9k_hw_get_legacy_target_powers(ah, chan,
2448 pEepData->calTargetPowerCck,
2449 AR5416_NUM_2G_CCK_TARGET_POWERS,
2450 &targetPowerCckExt, 4, true);
2451 ath9k_hw_get_legacy_target_powers(ah, chan,
2452 pEepData->calTargetPower2G,
2453 AR5416_NUM_2G_20_TARGET_POWERS,
2454 &targetPowerOfdmExt, 4, true);
2455 }
2456 } else {
2457 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
2458 SUB_NUM_CTL_MODES_AT_5G_40;
2459 pCtlMode = ctlModesFor11a;
2460
2461 ath9k_hw_get_legacy_target_powers(ah, chan,
2462 pEepData->calTargetPower5G,
2463 AR5416_NUM_5G_20_TARGET_POWERS,
2464 &targetPowerOfdm, 4, false);
2465 ath9k_hw_get_target_powers(ah, chan,
2466 pEepData->calTargetPower5GHT20,
2467 AR5416_NUM_5G_20_TARGET_POWERS,
2468 &targetPowerHt20, 8, false);
2469
2470 if (IS_CHAN_HT40(chan)) {
2471 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
2472 ath9k_hw_get_target_powers(ah, chan,
2473 pEepData->calTargetPower5GHT40,
2474 AR5416_NUM_5G_40_TARGET_POWERS,
2475 &targetPowerHt40, 8, true);
2476 ath9k_hw_get_legacy_target_powers(ah, chan,
2477 pEepData->calTargetPower5G,
2478 AR5416_NUM_5G_20_TARGET_POWERS,
2479 &targetPowerOfdmExt, 4, true);
2480 }
2481 }
2482
2483 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
2484 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
2485 (pCtlMode[ctlMode] == CTL_2GHT40);
2486 if (isHt40CtlMode)
2487 freq = centers.synth_center;
2488 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
2489 freq = centers.ext_center;
2490 else
2491 freq = centers.ctl_center;
2492
2493 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
2494 ah->eep_ops->get_eeprom_rev(ah) <= 2)
2495 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
2496
2497 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2498 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
2499 "EXT_ADDITIVE %d\n",
2500 ctlMode, numCtlModes, isHt40CtlMode,
2501 (pCtlMode[ctlMode] & EXT_ADDITIVE));
2502
2503 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
2504 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2505 " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
2506 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
2507 "chan %d\n",
2508 i, cfgCtl, pCtlMode[ctlMode],
2509 pEepData->ctlIndex[i], chan->channel);
2510
2511 if ((((cfgCtl & ~CTL_MODE_M) |
2512 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2513 pEepData->ctlIndex[i]) ||
2514 (((cfgCtl & ~CTL_MODE_M) |
2515 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
2516 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
2517 rep = &(pEepData->ctlData[i]);
2518
2519 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
2520 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
2521 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
2522
2523 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2524 " MATCH-EE_IDX %d: ch %d is2 %d "
2525 "2xMinEdge %d chainmask %d chains %d\n",
2526 i, freq, IS_CHAN_2GHZ(chan),
2527 twiceMinEdgePower, tx_chainmask,
2528 ar5416_get_ntxchains
2529 (tx_chainmask));
2530 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
2531 twiceMaxEdgePower = min(twiceMaxEdgePower,
2532 twiceMinEdgePower);
2533 } else {
2534 twiceMaxEdgePower = twiceMinEdgePower;
2535 break;
2536 }
2537 }
2538 }
2539
2540 minCtlPower = min(twiceMaxEdgePower, scaledPower);
2541
2542 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2543 " SEL-Min ctlMode %d pCtlMode %d "
2544 "2xMaxEdge %d sP %d minCtlPwr %d\n",
2545 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
2546 scaledPower, minCtlPower);
2547
2548 switch (pCtlMode[ctlMode]) {
2549 case CTL_11B:
2550 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
2551 targetPowerCck.tPow2x[i] =
2552 min((u16)targetPowerCck.tPow2x[i],
2553 minCtlPower);
2554 }
2555 break;
2556 case CTL_11A:
2557 case CTL_11G:
2558 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
2559 targetPowerOfdm.tPow2x[i] =
2560 min((u16)targetPowerOfdm.tPow2x[i],
2561 minCtlPower);
2562 }
2563 break;
2564 case CTL_5GHT20:
2565 case CTL_2GHT20:
2566 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
2567 targetPowerHt20.tPow2x[i] =
2568 min((u16)targetPowerHt20.tPow2x[i],
2569 minCtlPower);
2570 }
2571 break;
2572 case CTL_11B_EXT:
2573 targetPowerCckExt.tPow2x[0] = min((u16)
2574 targetPowerCckExt.tPow2x[0],
2575 minCtlPower);
2576 break;
2577 case CTL_11A_EXT:
2578 case CTL_11G_EXT:
2579 targetPowerOfdmExt.tPow2x[0] = min((u16)
2580 targetPowerOfdmExt.tPow2x[0],
2581 minCtlPower);
2582 break;
2583 case CTL_5GHT40:
2584 case CTL_2GHT40:
2585 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2586 targetPowerHt40.tPow2x[i] =
2587 min((u16)targetPowerHt40.tPow2x[i],
2588 minCtlPower);
2589 }
2590 break;
2591 default:
2592 break;
2593 }
2594 }
2595
2596 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
2597 ratesArray[rate18mb] = ratesArray[rate24mb] =
2598 targetPowerOfdm.tPow2x[0];
2599 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
2600 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
2601 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
2602 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
2603
2604 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
2605 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
2606
2607 if (IS_CHAN_2GHZ(chan)) {
2608 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
2609 ratesArray[rate2s] = ratesArray[rate2l] =
2610 targetPowerCck.tPow2x[1];
2611 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
2612 targetPowerCck.tPow2x[2];
2613 ratesArray[rate11s] = ratesArray[rate11l] =
2614 targetPowerCck.tPow2x[3];
2615 }
2616 if (IS_CHAN_HT40(chan)) {
2617 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
2618 ratesArray[rateHt40_0 + i] =
2619 targetPowerHt40.tPow2x[i];
2620 }
2621 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
2622 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
2623 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
2624 if (IS_CHAN_2GHZ(chan)) {
2625 ratesArray[rateExtCck] =
2626 targetPowerCckExt.tPow2x[0];
2627 }
2628 }
2629}
2630
2631static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
2632 struct ath9k_channel *chan,
2633 u16 cfgCtl,
2634 u8 twiceAntennaReduction,
2635 u8 twiceMaxRegulatoryPower,
2636 u8 powerLimit)
2637{
2638#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
2639 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
2640 struct modal_eep_header *pModal =
2641 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
2642 int16_t ratesArray[Ar5416RateSize];
2643 int16_t txPowerIndexOffset = 0;
2644 u8 ht40PowerIncForPdadc = 2;
2645 int i, cck_ofdm_delta = 0;
2646
2647 memset(ratesArray, 0, sizeof(ratesArray));
2648
2649 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
2650 AR5416_EEP_MINOR_VER_2) {
2651 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
2652 }
2653
2654 ath9k_hw_set_def_power_per_rate_table(ah, chan,
2655 &ratesArray[0], cfgCtl,
2656 twiceAntennaReduction,
2657 twiceMaxRegulatoryPower,
2658 powerLimit);
2659
2660 ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
2661
2662 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
2663 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
2664 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
2665 ratesArray[i] = AR5416_MAX_RATE_POWER;
2666 }
2667
2668 if (AR_SREV_9280_10_OR_LATER(ah)) {
2669 for (i = 0; i < Ar5416RateSize; i++)
2670 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
2671 }
2672
2673 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
2674 ATH9K_POW_SM(ratesArray[rate18mb], 24)
2675 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
2676 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
2677 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
2678 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
2679 ATH9K_POW_SM(ratesArray[rate54mb], 24)
2680 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
2681 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
2682 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
2683
2684 if (IS_CHAN_2GHZ(chan)) {
2685 if (OLC_FOR_AR9280_20_LATER) {
2686 cck_ofdm_delta = 2;
2687 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2688 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
2689 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
2690 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2691 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
2692 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2693 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
2694 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
2695 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
2696 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
2697 } else {
2698 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
2699 ATH9K_POW_SM(ratesArray[rate2s], 24)
2700 | ATH9K_POW_SM(ratesArray[rate2l], 16)
2701 | ATH9K_POW_SM(ratesArray[rateXr], 8)
2702 | ATH9K_POW_SM(ratesArray[rate1l], 0));
2703 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
2704 ATH9K_POW_SM(ratesArray[rate11s], 24)
2705 | ATH9K_POW_SM(ratesArray[rate11l], 16)
2706 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
2707 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
2708 }
2709 }
2710
2711 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
2712 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
2713 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
2714 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
2715 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
2716 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
2717 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
2718 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
2719 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
2720 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
2721
2722 if (IS_CHAN_HT40(chan)) {
2723 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
2724 ATH9K_POW_SM(ratesArray[rateHt40_3] +
2725 ht40PowerIncForPdadc, 24)
2726 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
2727 ht40PowerIncForPdadc, 16)
2728 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
2729 ht40PowerIncForPdadc, 8)
2730 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
2731 ht40PowerIncForPdadc, 0));
2732 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
2733 ATH9K_POW_SM(ratesArray[rateHt40_7] +
2734 ht40PowerIncForPdadc, 24)
2735 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
2736 ht40PowerIncForPdadc, 16)
2737 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
2738 ht40PowerIncForPdadc, 8)
2739 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
2740 ht40PowerIncForPdadc, 0));
2741 if (OLC_FOR_AR9280_20_LATER) {
2742 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2743 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2744 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
2745 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2746 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
2747 } else {
2748 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
2749 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
2750 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
2751 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
2752 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
2753 }
2754 }
2755
2756 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
2757 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
2758 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
2759
2760 i = rate6mb;
2761
2762 if (IS_CHAN_HT40(chan))
2763 i = rateHt40_0;
2764 else if (IS_CHAN_HT20(chan))
2765 i = rateHt20_0;
2766
2767 if (AR_SREV_9280_10_OR_LATER(ah))
2768 ah->regulatory.max_power_level =
2769 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
2770 else
2771 ah->regulatory.max_power_level = ratesArray[i];
2772
2773 switch(ar5416_get_ntxchains(ah->txchainmask)) {
2774 case 1:
2775 break;
2776 case 2:
2777 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
2778 break;
2779 case 3:
2780 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
2781 break;
2782 default:
2783 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2784 "Invalid chainmask configuration\n");
2785 break;
2786 }
2787}
2788
2789static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
2790 enum ieee80211_band freq_band)
2791{
2792 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2793 struct modal_eep_header *pModal =
2794 &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
2795 struct base_eep_header *pBase = &eep->baseEepHeader;
2796 u8 num_ant_config;
2797
2798 num_ant_config = 1;
2799
2800 if (pBase->version >= 0x0E0D)
2801 if (pModal->useAnt1)
2802 num_ant_config += 1;
2803
2804 return num_ant_config;
2805}
2806
2807static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
2808 struct ath9k_channel *chan)
2809{
2810 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
2811 struct modal_eep_header *pModal =
2812 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
2813
2814 return pModal->antCtrlCommon & 0xFFFF;
2815}
2816
2817static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
2818{
2819#define EEP_DEF_SPURCHAN \
2820 (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
2821
2822 u16 spur_val = AR_NO_SPUR;
2823
2824 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2825 "Getting spur idx %d is2Ghz. %d val %x\n",
2826 i, is2GHz, ah->config.spurchans[i][is2GHz]);
2827
2828 switch (ah->config.spurmode) {
2829 case SPUR_DISABLE:
2830 break;
2831 case SPUR_ENABLE_IOCTL:
2832 spur_val = ah->config.spurchans[i][is2GHz];
2833 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
2834 "Getting spur val from new loc. %d\n", spur_val);
2835 break;
2836 case SPUR_ENABLE_EEPROM:
2837 spur_val = EEP_DEF_SPURCHAN;
2838 break;
2839 }
2840
2841 return spur_val;
2842
2843#undef EEP_DEF_SPURCHAN
2844}
2845
2846static struct eeprom_ops eep_def_ops = {
2847 .check_eeprom = ath9k_hw_def_check_eeprom,
2848 .get_eeprom = ath9k_hw_def_get_eeprom,
2849 .fill_eeprom = ath9k_hw_def_fill_eeprom,
2850 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
2851 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
2852 .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
2853 .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
2854 .set_board_values = ath9k_hw_def_set_board_values,
2855 .set_addac = ath9k_hw_def_set_addac,
2856 .set_txpower = ath9k_hw_def_set_txpower,
2857 .get_spur_channel = ath9k_hw_def_get_spur_channel
2858};
2859
2860
2861static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
2862{
2863 return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
2864}
2865
2866static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
2867{
2868 return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
2869}
2870
2871static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
2872{
2873 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
2874 u16 *eep_data;
2875 int addr, eep_start_loc = AR9287_EEP_START_LOC;
2876 eep_data = (u16 *)eep;
2877 if (!ath9k_hw_use_flash(ah)) {
2878 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2879 "Reading from EEPROM, not flash\n");
2880 }
2881
2882 for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
2883 addr++) {
2884 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
2885 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2886 "Unable to read eeprom region \n");
2887 return false;
2888 }
2889 eep_data++;
2890 }
2891 return true;
2892}
2893static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
2894{
2895 u32 sum = 0, el, integer;
2896 u16 temp, word, magic, magic2, *eepdata;
2897 int i, addr;
2898 bool need_swap = false;
2899 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
2900
2901 if (!ath9k_hw_use_flash(ah)) {
2902 if (!ath9k_hw_nvram_read
2903 (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
2904 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2905 "Reading Magic # failed\n");
2906 return false;
2907 }
2908
2909 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
2910 "Read Magic = 0x%04X\n", magic);
2911 if (magic != AR5416_EEPROM_MAGIC) {
2912
2913
2914 magic2 = swab16(magic);
2915
2916 if (magic2 == AR5416_EEPROM_MAGIC) {
2917 need_swap = true;
2918 eepdata = (u16 *)(&ah->eeprom);
2919
2920 for (addr = 0;
2921 addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
2922 addr++) {
2923 temp = swab16(*eepdata);
2924 *eepdata = temp;
2925 eepdata++;
2926 }
2927 } else {
2928 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2929 "Invalid EEPROM Magic. "
2930 "endianness mismatch.\n");
2931 return -EINVAL; }
2932 }
2933 }
2934 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
2935 "True" : "False");
2936
2937 if (need_swap)
2938 el = swab16(ah->eeprom.map9287.baseEepHeader.length);
2939 else
2940 el = ah->eeprom.map9287.baseEepHeader.length;
2941
2942 if (el > sizeof(struct ar9287_eeprom))
2943 el = sizeof(struct ar9287_eeprom) / sizeof(u16);
2944 else
2945 el = el / sizeof(u16);
2946
2947 eepdata = (u16 *)(&ah->eeprom);
2948 for (i = 0; i < el; i++)
2949 sum ^= *eepdata++;
2950
2951 if (need_swap) {
2952 word = swab16(eep->baseEepHeader.length);
2953 eep->baseEepHeader.length = word;
2954
2955 word = swab16(eep->baseEepHeader.checksum);
2956 eep->baseEepHeader.checksum = word;
2957
2958 word = swab16(eep->baseEepHeader.version);
2959 eep->baseEepHeader.version = word;
2960
2961 word = swab16(eep->baseEepHeader.regDmn[0]);
2962 eep->baseEepHeader.regDmn[0] = word;
2963
2964 word = swab16(eep->baseEepHeader.regDmn[1]);
2965 eep->baseEepHeader.regDmn[1] = word;
2966
2967 word = swab16(eep->baseEepHeader.rfSilent);
2968 eep->baseEepHeader.rfSilent = word;
2969
2970 word = swab16(eep->baseEepHeader.blueToothOptions);
2971 eep->baseEepHeader.blueToothOptions = word;
2972
2973 word = swab16(eep->baseEepHeader.deviceCap);
2974 eep->baseEepHeader.deviceCap = word;
2975
2976 integer = swab32(eep->modalHeader.antCtrlCommon);
2977 eep->modalHeader.antCtrlCommon = integer;
2978
2979 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
2980 integer = swab32(eep->modalHeader.antCtrlChain[i]);
2981 eep->modalHeader.antCtrlChain[i] = integer;
2982 }
2983
2984 for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
2985 word = swab16(eep->modalHeader.spurChans[i].spurChan);
2986 eep->modalHeader.spurChans[i].spurChan = word;
2987 }
2988 }
2989
2990 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
2991 || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
2992 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
2993 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
2994 sum, ah->eep_ops->get_eeprom_ver(ah));
2995 return -EINVAL;
2996 }
2997
2998 return 0;
2999}
3000
3001static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
3002 enum eeprom_param param)
3003{
3004 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
3005 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
3006 struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
3007 u16 ver_minor;
3008
3009 ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
3010 switch (param) {
3011 case EEP_NFTHRESH_2:
3012 return pModal->noiseFloorThreshCh[0];
3013 case AR_EEPROM_MAC(0):
3014 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
3015 case AR_EEPROM_MAC(1):
3016 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
3017 case AR_EEPROM_MAC(2):
3018 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
3019 case EEP_REG_0:
3020 return pBase->regDmn[0];
3021 case EEP_REG_1:
3022 return pBase->regDmn[1];
3023 case EEP_OP_CAP:
3024 return pBase->deviceCap;
3025 case EEP_OP_MODE:
3026 return pBase->opCapFlags;
3027 case EEP_RF_SILENT:
3028 return pBase->rfSilent;
3029 case EEP_MINOR_REV:
3030 return ver_minor;
3031 case EEP_TX_MASK:
3032 return pBase->txMask;
3033 case EEP_RX_MASK:
3034 return pBase->rxMask;
3035 case EEP_DEV_TYPE:
3036 return pBase->deviceType;
3037 case EEP_OL_PWRCTRL:
3038 return pBase->openLoopPwrCntl;
3039 case EEP_TEMPSENSE_SLOPE:
3040 if (ver_minor >= AR9287_EEP_MINOR_VER_2)
3041 return pBase->tempSensSlope;
3042 else
3043 return 0;
3044 case EEP_TEMPSENSE_SLOPE_PAL_ON:
3045 if (ver_minor >= AR9287_EEP_MINOR_VER_3)
3046 return pBase->tempSensSlopePalOn;
3047 else
3048 return 0;
3049 default:
3050 return 0;
3051 }
3052}
3053
3054
3055static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah,
3056 struct ath9k_channel *chan,
3057 struct cal_data_per_freq_ar9287 *pRawDataSet,
3058 u8 *bChans, u16 availPiers,
3059 u16 tPdGainOverlap, int16_t *pMinCalPower,
3060 u16 *pPdGainBoundaries, u8 *pPDADCValues,
3061 u16 numXpdGains)
3062{
3063#define TMP_VAL_VPD_TABLE \
3064 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
3065 int i, j, k;
3066 int16_t ss;
3067 u16 idxL = 0, idxR = 0, numPiers;
3068 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
3069 u8 minPwrT4[AR9287_NUM_PD_GAINS];
3070 u8 maxPwrT4[AR9287_NUM_PD_GAINS];
3071 int16_t vpdStep;
3072 int16_t tmpVal;
3073 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
3074 bool match;
3075 int16_t minDelta = 0;
3076 struct chan_centers centers;
3077 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
3078 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3079 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
3080 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3081 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
3082 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
3083
3084 ath9k_hw_get_channel_centers(ah, chan, &centers);
3085 for (numPiers = 0; numPiers < availPiers; numPiers++) {
3086 if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
3087 break;
3088 }
3089
3090 match = ath9k_hw_get_lower_upper_index(
3091 (u8)FREQ2FBIN(centers.synth_center,
3092 IS_CHAN_2GHZ(chan)), bChans, numPiers,
3093 &idxL, &idxR);
3094
3095 if (match) {
3096 for (i = 0; i < numXpdGains; i++) {
3097 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
3098 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
3099 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3100 pRawDataSet[idxL].pwrPdg[i],
3101 pRawDataSet[idxL].vpdPdg[i],
3102 AR9287_PD_GAIN_ICEPTS, vpdTableI[i]);
3103 }
3104 } else {
3105 for (i = 0; i < numXpdGains; i++) {
3106 pVpdL = pRawDataSet[idxL].vpdPdg[i];
3107 pPwrL = pRawDataSet[idxL].pwrPdg[i];
3108 pVpdR = pRawDataSet[idxR].vpdPdg[i];
3109 pPwrR = pRawDataSet[idxR].pwrPdg[i];
3110
3111 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
3112
3113 maxPwrT4[i] =
3114 min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
3115 pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
3116
3117 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3118 pPwrL, pVpdL,
3119 AR9287_PD_GAIN_ICEPTS,
3120 vpdTableL[i]);
3121 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
3122 pPwrR, pVpdR,
3123 AR9287_PD_GAIN_ICEPTS,
3124 vpdTableR[i]);
3125
3126 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
3127 vpdTableI[i][j] =
3128 (u8)(ath9k_hw_interpolate((u16)
3129 FREQ2FBIN(centers. synth_center,
3130 IS_CHAN_2GHZ(chan)),
3131 bChans[idxL], bChans[idxR],
3132 vpdTableL[i][j], vpdTableR[i][j]));
3133 }
3134 }
3135 }
3136 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
3137
3138 k = 0;
3139 for (i = 0; i < numXpdGains; i++) {
3140 if (i == (numXpdGains - 1))
3141 pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2);
3142 else
3143 pPdGainBoundaries[i] = (u16)((maxPwrT4[i] +
3144 minPwrT4[i+1]) / 4);
3145
3146 pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
3147 pPdGainBoundaries[i]);
3148
3149
3150 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
3151 minDelta = pPdGainBoundaries[0] - 23;
3152 pPdGainBoundaries[0] = 23;
3153 } else
3154 minDelta = 0;
3155
3156 if (i == 0) {
3157 if (AR_SREV_9280_10_OR_LATER(ah))
3158 ss = (int16_t)(0 - (minPwrT4[i] / 2));
3159 else
3160 ss = 0;
3161 } else
3162 ss = (int16_t)((pPdGainBoundaries[i-1] -
3163 (minPwrT4[i] / 2)) -
3164 tPdGainOverlap + 1 + minDelta);
3165
3166 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
3167 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
3168 while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) {
3169 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
3170 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
3171 ss++;
3172 }
3173
3174 sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
3175 tgtIndex = (u8)(pPdGainBoundaries[i] +
3176 tPdGainOverlap - (minPwrT4[i] / 2));
3177 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
3178 tgtIndex : sizeCurrVpdTable;
3179
3180 while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
3181 pPDADCValues[k++] = vpdTableI[i][ss++];
3182
3183 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
3184 vpdTableI[i][sizeCurrVpdTable - 2]);
3185 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
3186 if (tgtIndex > maxIndex) {
3187 while ((ss <= tgtIndex) &&
3188 (k < (AR9287_NUM_PDADC_VALUES - 1))) {
3189 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
3190 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
3191 255 : tmpVal);
3192 ss++;
3193 }
3194 }
3195 }
3196
3197 while (i < AR9287_PD_GAINS_IN_MASK) {
3198 pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
3199 i++;
3200 }
3201
3202 while (k < AR9287_NUM_PDADC_VALUES) {
3203 pPDADCValues[k] = pPDADCValues[k-1];
3204 k++;
3205 }
3206
3207#undef TMP_VAL_VPD_TABLE
3208}
3209
3210static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
3211 struct ath9k_channel *chan,
3212 struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
3213 u8 *pCalChans, u16 availPiers,
3214 int8_t *pPwr)
3215{
3216 u8 pcdac, i = 0;
3217 u16 idxL = 0, idxR = 0, numPiers;
3218 bool match;
3219 struct chan_centers centers;
3220 ath9k_hw_get_channel_centers(ah, chan, &centers);
3221 for (numPiers = 0; numPiers < availPiers; numPiers++) {
3222 if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
3223 break;
3224 }
3225
3226 match = ath9k_hw_get_lower_upper_index(
3227 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
3228 pCalChans, numPiers,
3229 &idxL, &idxR);
3230
3231 if (match) {
3232 pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0];
3233 *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0];
3234 } else {
3235 pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0];
3236 *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
3237 pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
3238 }
3239
3240 while ((pcdac > ah->originalGain[i]) &&
3241 (i < (AR9280_TX_GAIN_TABLE_SIZE - 1)))
3242 i++;
3243}
3244
3245static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
3246 int32_t txPower, u16 chain)
3247{
3248 u32 tmpVal;
3249 u32 a;
3250
3251 tmpVal = REG_READ(ah, 0xa270);
3252 tmpVal = tmpVal & 0xFCFFFFFF;
3253 tmpVal = tmpVal | (0x3 << 24);
3254 REG_WRITE(ah, 0xa270, tmpVal);
3255
3256 tmpVal = REG_READ(ah, 0xb270);
3257 tmpVal = tmpVal & 0xFCFFFFFF;
3258 tmpVal = tmpVal | (0x3 << 24);
3259 REG_WRITE(ah, 0xb270, tmpVal);
3260
3261 if (chain == 0) {
3262 tmpVal = REG_READ(ah, 0xa398);
3263 tmpVal = tmpVal & 0xff00ffff;
3264 a = (txPower)&0xff;
3265 tmpVal = tmpVal | (a << 16);
3266 REG_WRITE(ah, 0xa398, tmpVal);
3267 }
3268
3269 if (chain == 1) {
3270 tmpVal = REG_READ(ah, 0xb398);
3271 tmpVal = tmpVal & 0xff00ffff;
3272 a = (txPower)&0xff;
3273 tmpVal = tmpVal | (a << 16);
3274 REG_WRITE(ah, 0xb398, tmpVal);
3275 }
3276}
3277
3278
3279static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
3280 struct ath9k_channel *chan, int16_t *pTxPowerIndexOffset)
3281{
3282 struct cal_data_per_freq_ar9287 *pRawDataset;
3283 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
3284 u8 *pCalBChans = NULL;
3285 u16 pdGainOverlap_t2;
3286 u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
3287 u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
3288 u16 numPiers = 0, i, j;
3289 int16_t tMinCalPower;
3290 u16 numXpdGain, xpdMask;
3291 u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
3292 u32 reg32, regOffset, regChainOffset;
3293 int16_t modalIdx, diff = 0;
3294 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
3295 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
3296 xpdMask = pEepData->modalHeader.xpdGain;
3297 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
3298 AR9287_EEP_MINOR_VER_2)
3299 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
3300 else
3301 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
3302 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
3303
3304 if (IS_CHAN_2GHZ(chan)) {
3305 pCalBChans = pEepData->calFreqPier2G;
3306 numPiers = AR9287_NUM_2G_CAL_PIERS;
3307 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
3308 pRawDatasetOpenLoop =
3309 (struct cal_data_op_loop_ar9287 *)
3310 pEepData->calPierData2G[0];
3311 ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
3312 }
3313 }
3314
3315 numXpdGain = 0;
3316 for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
3317 if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
3318 if (numXpdGain >= AR9287_NUM_PD_GAINS)
3319 break;
3320 xpdGainValues[numXpdGain] =
3321 (u16)(AR9287_PD_GAINS_IN_MASK-i);
3322 numXpdGain++;
3323 }
3324 }
3325
3326 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
3327 (numXpdGain - 1) & 0x3);
3328 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
3329 xpdGainValues[0]);
3330 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
3331 xpdGainValues[1]);
3332 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
3333 xpdGainValues[2]);
3334
3335 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
3336 regChainOffset = i * 0x1000;
3337 if (pEepData->baseEepHeader.txMask & (1 << i)) {
3338 pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)
3339 pEepData->calPierData2G[i];
3340 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
3341 int8_t txPower;
3342 ar9287_eeprom_get_tx_gain_index(ah, chan,
3343 pRawDatasetOpenLoop,
3344 pCalBChans, numPiers,
3345 &txPower);
3346 ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
3347 } else {
3348 pRawDataset =
3349 (struct cal_data_per_freq_ar9287 *)
3350 pEepData->calPierData2G[i];
3351 ath9k_hw_get_AR9287_gain_boundaries_pdadcs(
3352 ah, chan, pRawDataset,
3353 pCalBChans, numPiers,
3354 pdGainOverlap_t2,
3355 &tMinCalPower, gainBoundaries,
3356 pdadcValues, numXpdGain);
3357 }
3358
3359 if (i == 0) {
3360 if (!ath9k_hw_AR9287_get_eeprom(
3361 ah, EEP_OL_PWRCTRL)) {
3362 REG_WRITE(ah, AR_PHY_TPCRG5 +
3363 regChainOffset,
3364 SM(pdGainOverlap_t2,
3365 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
3366 SM(gainBoundaries[0],
3367 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
3368 | SM(gainBoundaries[1],
3369 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
3370 | SM(gainBoundaries[2],
3371 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
3372 | SM(gainBoundaries[3],
3373 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
3374 }
3375 }
3376
3377 if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
3378 pEepData->baseEepHeader.pwrTableOffset) {
3379 diff = (u16)
3380 (pEepData->baseEepHeader.pwrTableOffset
3381 - (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
3382 diff *= 2;
3383
3384 for (j = 0;
3385 j < ((u16)AR9287_NUM_PDADC_VALUES-diff);
3386 j++)
3387 pdadcValues[j] = pdadcValues[j+diff];
3388
3389 for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
3390 j < AR9287_NUM_PDADC_VALUES; j++)
3391 pdadcValues[j] =
3392 pdadcValues[
3393 AR9287_NUM_PDADC_VALUES-diff];
3394 }
3395 if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
3396 regOffset = AR_PHY_BASE + (672 << 2) +
3397 regChainOffset;
3398 for (j = 0; j < 32; j++) {
3399 reg32 = ((pdadcValues[4*j + 0]
3400 & 0xFF) << 0) |
3401 ((pdadcValues[4*j + 1]
3402 & 0xFF) << 8) |
3403 ((pdadcValues[4*j + 2]
3404 & 0xFF) << 16) |
3405 ((pdadcValues[4*j + 3]
3406 & 0xFF) << 24) ;
3407 REG_WRITE(ah, regOffset, reg32);
3408
3409 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3410 "PDADC (%d,%4x): %4.4x %8.8x\n",
3411 i, regChainOffset, regOffset,
3412 reg32);
3413 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3414 "PDADC: Chain %d | "
3415 "PDADC %3d Value %3d | "
3416 "PDADC %3d Value %3d | "
3417 "PDADC %3d Value %3d | "
3418 "PDADC %3d Value %3d |\n",
3419 i, 4 * j, pdadcValues[4 * j],
3420 4 * j + 1,
3421 pdadcValues[4 * j + 1],
3422 4 * j + 2,
3423 pdadcValues[4 * j + 2],
3424 4 * j + 3,
3425 pdadcValues[4 * j + 3]);
3426
3427 regOffset += 4;
3428 }
3429 }
3430 }
3431 }
3432
3433 *pTxPowerIndexOffset = 0;
3434}
3435
3436
3437static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
3438 struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl,
3439 u16 AntennaReduction, u16 twiceMaxRegulatoryPower,
3440 u16 powerLimit)
3441{
3442#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
3443#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
3444
3445 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
3446 static const u16 tpScaleReductionTable[5] = { 0, 3, 6, 9,
3447 AR5416_MAX_RATE_POWER };
3448 int i;
3449 int16_t twiceLargestAntenna;
3450 struct cal_ctl_data_ar9287 *rep;
3451 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
3452 targetPowerCck = {0, {0, 0, 0, 0} };
3453 struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
3454 targetPowerCckExt = {0, {0, 0, 0, 0} };
3455 struct cal_target_power_ht targetPowerHt20,
3456 targetPowerHt40 = {0, {0, 0, 0, 0} };
3457 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
3458 u16 ctlModesFor11g[] = {CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT,
3459 CTL_11G_EXT, CTL_2GHT40};
3460 u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
3461 struct chan_centers centers;
3462 int tx_chainmask;
3463 u16 twiceMinEdgePower;
3464 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
3465 tx_chainmask = ah->txchainmask;
3466
3467 ath9k_hw_get_channel_centers(ah, chan, &centers);
3468
3469 twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
3470 pEepData->modalHeader.antennaGainCh[1]);
3471
3472 twiceLargestAntenna = (int16_t)min((AntennaReduction) -
3473 twiceLargestAntenna, 0);
3474
3475 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
3476 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX)
3477 maxRegAllowedPower -=
3478 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
3479
3480 scaledPower = min(powerLimit, maxRegAllowedPower);
3481
3482 switch (ar5416_get_ntxchains(tx_chainmask)) {
3483 case 1:
3484 break;
3485 case 2:
3486 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
3487 break;
3488 case 3:
3489 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
3490 break;
3491 }
3492 scaledPower = max((u16)0, scaledPower);
3493
3494 if (IS_CHAN_2GHZ(chan)) {
3495 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
3496 SUB_NUM_CTL_MODES_AT_2G_40;
3497 pCtlMode = ctlModesFor11g;
3498
3499 ath9k_hw_get_legacy_target_powers(ah, chan,
3500 pEepData->calTargetPowerCck,
3501 AR9287_NUM_2G_CCK_TARGET_POWERS,
3502 &targetPowerCck, 4, false);
3503 ath9k_hw_get_legacy_target_powers(ah, chan,
3504 pEepData->calTargetPower2G,
3505 AR9287_NUM_2G_20_TARGET_POWERS,
3506 &targetPowerOfdm, 4, false);
3507 ath9k_hw_get_target_powers(ah, chan,
3508 pEepData->calTargetPower2GHT20,
3509 AR9287_NUM_2G_20_TARGET_POWERS,
3510 &targetPowerHt20, 8, false);
3511
3512 if (IS_CHAN_HT40(chan)) {
3513 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
3514 ath9k_hw_get_target_powers(ah, chan,
3515 pEepData->calTargetPower2GHT40,
3516 AR9287_NUM_2G_40_TARGET_POWERS,
3517 &targetPowerHt40, 8, true);
3518 ath9k_hw_get_legacy_target_powers(ah, chan,
3519 pEepData->calTargetPowerCck,
3520 AR9287_NUM_2G_CCK_TARGET_POWERS,
3521 &targetPowerCckExt, 4, true);
3522 ath9k_hw_get_legacy_target_powers(ah, chan,
3523 pEepData->calTargetPower2G,
3524 AR9287_NUM_2G_20_TARGET_POWERS,
3525 &targetPowerOfdmExt, 4, true);
3526 }
3527 }
3528
3529 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
3530
3531 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
3532 (pCtlMode[ctlMode] == CTL_2GHT40);
3533 if (isHt40CtlMode)
3534 freq = centers.synth_center;
3535 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
3536 freq = centers.ext_center;
3537 else
3538 freq = centers.ctl_center;
3539
3540
3541 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
3542 ah->eep_ops->get_eeprom_rev(ah) <= 2)
3543 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
3544 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3545 "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d,"
3546 "EXT_ADDITIVE %d\n", ctlMode, numCtlModes,
3547 isHt40CtlMode, (pCtlMode[ctlMode] & EXT_ADDITIVE));
3548 for (i = 0; (i < AR9287_NUM_CTLS)
3549 && pEepData->ctlIndex[i]; i++) {
3550 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3551 "LOOP-Ctlidx %d: cfgCtl 0x%2.2x"
3552 "pCtlMode 0x%2.2x ctlIndex 0x%2.2x"
3553 "chan %d chanctl=xxxx\n",
3554 i, cfgCtl, pCtlMode[ctlMode],
3555 pEepData->ctlIndex[i], chan->channel);
3556
3557 if ((((cfgCtl & ~CTL_MODE_M) |
3558 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
3559 pEepData->ctlIndex[i]) ||
3560 (((cfgCtl & ~CTL_MODE_M) |
3561 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
3562 ((pEepData->ctlIndex[i] &
3563 CTL_MODE_M) | SD_NO_CTL))) {
3564
3565 rep = &(pEepData->ctlData[i]);
3566 twiceMinEdgePower = ath9k_hw_get_max_edge_power(
3567 freq,
3568 rep->ctlEdges[ar5416_get_ntxchains(
3569 tx_chainmask) - 1],
3570 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
3571
3572 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3573 "MATCH-EE_IDX %d: ch %d is2 %d"
3574 "2xMinEdge %d chainmask %d chains %d\n",
3575 i, freq, IS_CHAN_2GHZ(chan),
3576 twiceMinEdgePower, tx_chainmask,
3577 ar5416_get_ntxchains(tx_chainmask));
3578
3579 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
3580 twiceMaxEdgePower = min(
3581 twiceMaxEdgePower,
3582 twiceMinEdgePower);
3583 else {
3584 twiceMaxEdgePower = twiceMinEdgePower;
3585 break;
3586 }
3587 }
3588 }
3589
3590 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
3591
3592 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3593 "SEL-Min ctlMode %d pCtlMode %d 2xMaxEdge %d"
3594 "sP %d minCtlPwr %d\n",
3595 ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
3596 scaledPower, minCtlPower);
3597
3598
3599 switch (pCtlMode[ctlMode]) {
3600
3601 case CTL_11B:
3602 for (i = 0;
3603 i < ARRAY_SIZE(targetPowerCck.tPow2x);
3604 i++) {
3605 targetPowerCck.tPow2x[i] = (u8)min(
3606 (u16)targetPowerCck.tPow2x[i],
3607 minCtlPower);
3608 }
3609 break;
3610 case CTL_11A:
3611 case CTL_11G:
3612 for (i = 0;
3613 i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
3614 i++) {
3615 targetPowerOfdm.tPow2x[i] = (u8)min(
3616 (u16)targetPowerOfdm.tPow2x[i],
3617 minCtlPower);
3618 }
3619 break;
3620 case CTL_5GHT20:
3621 case CTL_2GHT20:
3622 for (i = 0;
3623 i < ARRAY_SIZE(targetPowerHt20.tPow2x);
3624 i++) {
3625 targetPowerHt20.tPow2x[i] = (u8)min(
3626 (u16)targetPowerHt20.tPow2x[i],
3627 minCtlPower);
3628 }
3629 break;
3630 case CTL_11B_EXT:
3631 targetPowerCckExt.tPow2x[0] = (u8)min(
3632 (u16)targetPowerCckExt.tPow2x[0],
3633 minCtlPower);
3634 break;
3635 case CTL_11A_EXT:
3636 case CTL_11G_EXT:
3637 targetPowerOfdmExt.tPow2x[0] = (u8)min(
3638 (u16)targetPowerOfdmExt.tPow2x[0],
3639 minCtlPower);
3640 break;
3641 case CTL_5GHT40:
3642 case CTL_2GHT40:
3643 for (i = 0;
3644 i < ARRAY_SIZE(targetPowerHt40.tPow2x);
3645 i++) {
3646 targetPowerHt40.tPow2x[i] = (u8)min(
3647 (u16)targetPowerHt40.tPow2x[i],
3648 minCtlPower);
3649 }
3650 break;
3651 default:
3652 break;
3653 }
3654 }
3655
3656 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
3657 ratesArray[rate18mb] = ratesArray[rate24mb] =
3658 targetPowerOfdm.tPow2x[0];
3659 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
3660 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
3661 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
3662 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
3663
3664 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
3665 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
3666
3667 if (IS_CHAN_2GHZ(chan)) {
3668 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
3669 ratesArray[rate2s] = ratesArray[rate2l] =
3670 targetPowerCck.tPow2x[1];
3671 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
3672 targetPowerCck.tPow2x[2];
3673 ratesArray[rate11s] = ratesArray[rate11l] =
3674 targetPowerCck.tPow2x[3];
3675 }
3676 if (IS_CHAN_HT40(chan)) {
3677 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
3678 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
3679
3680 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
3681 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
3682 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
3683 if (IS_CHAN_2GHZ(chan))
3684 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
3685 }
3686#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
3687#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
3688}
3689
3690static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
3691 struct ath9k_channel *chan, u16 cfgCtl,
3692 u8 twiceAntennaReduction, u8 twiceMaxRegulatoryPower,
3693 u8 powerLimit)
3694{
3695#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
3696#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
3697 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
3698 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
3699 int16_t ratesArray[Ar5416RateSize];
3700 int16_t txPowerIndexOffset = 0;
3701 u8 ht40PowerIncForPdadc = 2;
3702 int i;
3703 memset(ratesArray, 0, sizeof(ratesArray));
3704
3705 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
3706 AR9287_EEP_MINOR_VER_2)
3707 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
3708
3709 ath9k_hw_set_AR9287_power_per_rate_table(ah, chan,
3710 &ratesArray[0], cfgCtl,
3711 twiceAntennaReduction,
3712 twiceMaxRegulatoryPower,
3713 powerLimit);
3714
3715
3716 ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset);
3717
3718 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
3719 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
3720 if (ratesArray[i] > AR9287_MAX_RATE_POWER)
3721 ratesArray[i] = AR9287_MAX_RATE_POWER;
3722 }
3723
3724 if (AR_SREV_9280_10_OR_LATER(ah)) {
3725 for (i = 0; i < Ar5416RateSize; i++)
3726 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
3727 }
3728
3729
3730 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
3731 ATH9K_POW_SM(ratesArray[rate18mb], 24)
3732 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
3733 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
3734 | ATH9K_POW_SM(ratesArray[rate6mb], 0)
3735 );
3736
3737 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
3738 ATH9K_POW_SM(ratesArray[rate54mb], 24)
3739 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
3740 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
3741 | ATH9K_POW_SM(ratesArray[rate24mb], 0)
3742 );
3743
3744 if (IS_CHAN_2GHZ(chan)) {
3745 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
3746 ATH9K_POW_SM(ratesArray[rate2s], 24)
3747 | ATH9K_POW_SM(ratesArray[rate2l], 16)
3748 | ATH9K_POW_SM(ratesArray[rateXr], 8)
3749 | ATH9K_POW_SM(ratesArray[rate1l], 0)
3750 );
3751 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
3752 ATH9K_POW_SM(ratesArray[rate11s], 24)
3753 | ATH9K_POW_SM(ratesArray[rate11l], 16)
3754 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
3755 | ATH9K_POW_SM(ratesArray[rate5_5l], 0)
3756 );
3757 }
3758
3759 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
3760 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
3761 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
3762 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
3763 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)
3764 );
3765
3766 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
3767 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
3768 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
3769 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
3770 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)
3771 );
3772
3773 if (IS_CHAN_HT40(chan)) {
3774 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
3775 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
3776 ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
3777 | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
3778 | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
3779 | ATH9K_POW_SM(ratesArray[rateHt40_0], 0)
3780 );
3781
3782 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
3783 ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
3784 | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
3785 | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
3786 | ATH9K_POW_SM(ratesArray[rateHt40_4], 0)
3787 );
3788 } else {
3789 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
3790 ATH9K_POW_SM(ratesArray[rateHt40_3] +
3791 ht40PowerIncForPdadc, 24)
3792 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
3793 ht40PowerIncForPdadc, 16)
3794 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
3795 ht40PowerIncForPdadc, 8)
3796 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
3797 ht40PowerIncForPdadc, 0)
3798 );
3799
3800 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
3801 ATH9K_POW_SM(ratesArray[rateHt40_7] +
3802 ht40PowerIncForPdadc, 24)
3803 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
3804 ht40PowerIncForPdadc, 16)
3805 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
3806 ht40PowerIncForPdadc, 8)
3807 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
3808 ht40PowerIncForPdadc, 0)
3809 );
3810
3811 }
3812
3813 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
3814 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
3815 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
3816 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
3817 | ATH9K_POW_SM(ratesArray[rateDupCck], 0)
3818 );
3819 }
3820
3821
3822 if (IS_CHAN_2GHZ(chan))
3823 i = rate1l;
3824 else
3825 i = rate6mb;
3826
3827 if (AR_SREV_9280_10_OR_LATER(ah))
3828 ah->regulatory.max_power_level =
3829 ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
3830 else
3831 ah->regulatory.max_power_level = ratesArray[i];
3832
3833 switch (ar5416_get_ntxchains(ah->txchainmask)) {
3834 case 1:
3835 break;
3836 case 2:
3837 ah->regulatory.max_power_level +=
3838 INCREASE_MAXPOW_BY_TWO_CHAIN;
3839 break;
3840 case 3:
3841 ah->regulatory.max_power_level +=
3842 INCREASE_MAXPOW_BY_THREE_CHAIN;
3843 break;
3844 default:
3845 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
3846 "Invalid chainmask configuration\n");
3847 break;
3848 }
3849}
3850
3851static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah,
3852 struct ath9k_channel *chan)
3853{
3854 return;
3855}
3856
3857static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah,
3858 struct ath9k_channel *chan)
3859{
3860 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
3861 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
3862
3863 u16 antWrites[AR9287_ANT_16S];
3864 u32 regChainOffset;
3865 u8 txRxAttenLocal;
3866 int i, j, offset_num;
3867
3868 pModal = &eep->modalHeader;
3869
3870 antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
3871 antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
3872 antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
3873 antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
3874 antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
3875 antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
3876 antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF);
3877 antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
3878
3879 offset_num = 8;
3880
3881 for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
3882 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
3883 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
3884 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
3885 antWrites[j++] = 0;
3886 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
3887 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
3888 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
3889 antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
3890 }
3891
3892
3893 REG_WRITE(ah, AR_PHY_SWITCH_COM,
3894 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
3895
3896 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
3897 regChainOffset = i * 0x1000;
3898
3899 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
3900 pModal->antCtrlChain[i]);
3901
3902 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
3903 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
3904 & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
3905 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
3906 SM(pModal->iqCalICh[i],
3907 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
3908 SM(pModal->iqCalQCh[i],
3909 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
3910
3911 txRxAttenLocal = pModal->txRxAttenCh[i];
3912
3913 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
3914 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
3915 pModal->bswMargin[i]);
3916 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
3917 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
3918 pModal->bswAtten[i]);
3919 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
3920 AR9280_PHY_RXGAIN_TXRX_ATTEN,
3921 txRxAttenLocal);
3922 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
3923 AR9280_PHY_RXGAIN_TXRX_MARGIN,
3924 pModal->rxTxMarginCh[i]);
3925 }
3926
3927
3928 if (IS_CHAN_HT40(chan))
3929 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
3930 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
3931 else
3932 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
3933 AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
3934
3935 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
3936 AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
3937
3938 REG_WRITE(ah, AR_PHY_RF_CTL4,
3939 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
3940 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
3941 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
3942 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
3943
3944 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
3945 AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
3946
3947 REG_RMW_FIELD(ah, AR_PHY_CCA,
3948 AR9280_PHY_CCA_THRESH62, pModal->thresh62);
3949 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
3950 AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
3951
3952 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1,
3953 AR9287_AN_RF2G3_DB1_S, pModal->db1);
3954 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2,
3955 AR9287_AN_RF2G3_DB2_S, pModal->db2);
3956 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
3957 AR9287_AN_RF2G3_OB_CCK,
3958 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
3959 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
3960 AR9287_AN_RF2G3_OB_PSK,
3961 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
3962 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
3963 AR9287_AN_RF2G3_OB_QAM,
3964 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
3965 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
3966 AR9287_AN_RF2G3_OB_PAL_OFF,
3967 AR9287_AN_RF2G3_OB_PAL_OFF_S,
3968 pModal->ob_pal_off);
3969
3970 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
3971 AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S,
3972 pModal->db1);
3973 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2,
3974 AR9287_AN_RF2G3_DB2_S, pModal->db2);
3975 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
3976 AR9287_AN_RF2G3_OB_CCK,
3977 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
3978 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
3979 AR9287_AN_RF2G3_OB_PSK,
3980 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
3981 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
3982 AR9287_AN_RF2G3_OB_QAM,
3983 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
3984 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
3985 AR9287_AN_RF2G3_OB_PAL_OFF,
3986 AR9287_AN_RF2G3_OB_PAL_OFF_S,
3987 pModal->ob_pal_off);
3988
3989 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
3990 AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
3991 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
3992 AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
3993
3994 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
3995 AR9287_AN_TOP2_XPABIAS_LVL,
3996 AR9287_AN_TOP2_XPABIAS_LVL_S,
3997 pModal->xpaBiasLvl);
3998}
3999
4000static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
4001 enum ieee80211_band freq_band)
4002{
4003 return 1;
4004}
4005
4006
4007
4008
4009static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
4010 struct ath9k_channel *chan)
4011{
4012 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
4013 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
4014 return pModal->antCtrlCommon & 0xFFFF;
4015}
4016
4017
4018static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
4019 u16 i, bool is2GHz)
4020{
4021#define EEP_MAP9287_SPURCHAN \
4022 (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
4023 u16 spur_val = AR_NO_SPUR;
4024
4025 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
4026 "Getting spur idx %d is2Ghz. %d val %x\n",
4027 i, is2GHz, ah->config.spurchans[i][is2GHz]);
4028
4029 switch (ah->config.spurmode) {
4030 case SPUR_DISABLE:
4031 break;
4032 case SPUR_ENABLE_IOCTL:
4033 spur_val = ah->config.spurchans[i][is2GHz];
4034 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
4035 "Getting spur val from new loc. %d\n", spur_val);
4036 break;
4037 case SPUR_ENABLE_EEPROM:
4038 spur_val = EEP_MAP9287_SPURCHAN;
4039 break;
4040 }
4041
4042 return spur_val;
4043
4044#undef EEP_MAP9287_SPURCHAN
4045}
4046
4047static struct eeprom_ops eep_AR9287_ops = {
4048 .check_eeprom = ath9k_hw_AR9287_check_eeprom,
4049 .get_eeprom = ath9k_hw_AR9287_get_eeprom,
4050 .fill_eeprom = ath9k_hw_AR9287_fill_eeprom,
4051 .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver,
4052 .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev,
4053 .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config,
4054 .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg,
4055 .set_board_values = ath9k_hw_AR9287_set_board_values,
4056 .set_addac = ath9k_hw_AR9287_set_addac,
4057 .set_txpower = ath9k_hw_AR9287_set_txpower,
4058 .get_spur_channel = ath9k_hw_AR9287_get_spur_channel
4059};
4060
4061
4062int ath9k_hw_eeprom_init(struct ath_hw *ah) 257int ath9k_hw_eeprom_init(struct ath_hw *ah)
4063{ 258{
4064 int status; 259 int status;
260
4065 if (AR_SREV_9287(ah)) { 261 if (AR_SREV_9287(ah)) {
4066 ah->eep_map = EEP_MAP_AR9287; 262 ah->eep_map = EEP_MAP_AR9287;
4067 ah->eep_ops = &eep_AR9287_ops; 263 ah->eep_ops = &eep_AR9287_ops;
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index db77e90ed9ab..4fe33f7eee9d 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -385,106 +385,124 @@ struct calDataPerFreqOpLoop {
385} __packed; 385} __packed;
386 386
387struct modal_eep_4k_header { 387struct modal_eep_4k_header {
388 u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; 388 u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
389 u32 antCtrlCommon; 389 u32 antCtrlCommon;
390 u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; 390 u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
391 u8 switchSettling; 391 u8 switchSettling;
392 u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; 392 u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
393 u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; 393 u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
394 u8 adcDesiredSize; 394 u8 adcDesiredSize;
395 u8 pgaDesiredSize; 395 u8 pgaDesiredSize;
396 u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; 396 u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
397 u8 txEndToXpaOff; 397 u8 txEndToXpaOff;
398 u8 txEndToRxOn; 398 u8 txEndToRxOn;
399 u8 txFrameToXpaOn; 399 u8 txFrameToXpaOn;
400 u8 thresh62; 400 u8 thresh62;
401 u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; 401 u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
402 u8 xpdGain; 402 u8 xpdGain;
403 u8 xpd; 403 u8 xpd;
404 u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; 404 u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
405 u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; 405 u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
406 u8 pdGainOverlap; 406 u8 pdGainOverlap;
407 u8 ob_01; 407#ifdef __BIG_ENDIAN_BITFIELD
408 u8 db1_01; 408 u8 ob_1:4, ob_0:4;
409 u8 xpaBiasLvl; 409 u8 db1_1:4, db1_0:4;
410 u8 txFrameToDataStart; 410#else
411 u8 txFrameToPaOn; 411 u8 ob_0:4, ob_1:4;
412 u8 ht40PowerIncForPdadc; 412 u8 db1_0:4, db1_1:4;
413 u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; 413#endif
414 u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; 414 u8 xpaBiasLvl;
415 u8 swSettleHt40; 415 u8 txFrameToDataStart;
416 u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; 416 u8 txFrameToPaOn;
417 u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; 417 u8 ht40PowerIncForPdadc;
418 u8 db2_01; 418 u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
419 u8 version; 419 u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
420 u16 ob_234; 420 u8 swSettleHt40;
421 u16 db1_234; 421 u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
422 u16 db2_234; 422 u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
423 u8 futureModal[4]; 423#ifdef __BIG_ENDIAN_BITFIELD
424 424 u8 db2_1:4, db2_0:4;
425#else
426 u8 db2_0:4, db2_1:4;
427#endif
428 u8 version;
429#ifdef __BIG_ENDIAN_BITFIELD
430 u8 ob_3:4, ob_2:4;
431 u8 antdiv_ctl1:4, ob_4:4;
432 u8 db1_3:4, db1_2:4;
433 u8 antdiv_ctl2:4, db1_4:4;
434 u8 db2_2:4, db2_3:4;
435 u8 reserved:4, db2_4:4;
436#else
437 u8 ob_2:4, ob_3:4;
438 u8 ob_4:4, antdiv_ctl1:4;
439 u8 db1_2:4, db1_3:4;
440 u8 db1_4:4, antdiv_ctl2:4;
441 u8 db2_2:4, db2_3:4;
442 u8 db2_4:4, reserved:4;
443#endif
444 u8 futureModal[4];
425 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; 445 struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
426} __packed; 446} __packed;
427 447
428struct base_eep_ar9287_header { 448struct base_eep_ar9287_header {
429 u16 length; 449 u16 length;
430 u16 checksum; 450 u16 checksum;
431 u16 version; 451 u16 version;
432 u8 opCapFlags; 452 u8 opCapFlags;
433 u8 eepMisc; 453 u8 eepMisc;
434 u16 regDmn[2]; 454 u16 regDmn[2];
435 u8 macAddr[6]; 455 u8 macAddr[6];
436 u8 rxMask; 456 u8 rxMask;
437 u8 txMask; 457 u8 txMask;
438 u16 rfSilent; 458 u16 rfSilent;
439 u16 blueToothOptions; 459 u16 blueToothOptions;
440 u16 deviceCap; 460 u16 deviceCap;
441 u32 binBuildNumber; 461 u32 binBuildNumber;
442 u8 deviceType; 462 u8 deviceType;
443 u8 openLoopPwrCntl; 463 u8 openLoopPwrCntl;
444 int8_t pwrTableOffset; 464 int8_t pwrTableOffset;
445 int8_t tempSensSlope; 465 int8_t tempSensSlope;
446 int8_t tempSensSlopePalOn; 466 int8_t tempSensSlopePalOn;
447 u8 futureBase[29]; 467 u8 futureBase[29];
448} __packed; 468} __packed;
449 469
450struct modal_eep_ar9287_header { 470struct modal_eep_ar9287_header {
451 u32 antCtrlChain[AR9287_MAX_CHAINS]; 471 u32 antCtrlChain[AR9287_MAX_CHAINS];
452 u32 antCtrlCommon; 472 u32 antCtrlCommon;
453 int8_t antennaGainCh[AR9287_MAX_CHAINS]; 473 int8_t antennaGainCh[AR9287_MAX_CHAINS];
454 u8 switchSettling; 474 u8 switchSettling;
455 u8 txRxAttenCh[AR9287_MAX_CHAINS]; 475 u8 txRxAttenCh[AR9287_MAX_CHAINS];
456 u8 rxTxMarginCh[AR9287_MAX_CHAINS]; 476 u8 rxTxMarginCh[AR9287_MAX_CHAINS];
457 int8_t adcDesiredSize; 477 int8_t adcDesiredSize;
458 u8 txEndToXpaOff; 478 u8 txEndToXpaOff;
459 u8 txEndToRxOn; 479 u8 txEndToRxOn;
460 u8 txFrameToXpaOn; 480 u8 txFrameToXpaOn;
461 u8 thresh62; 481 u8 thresh62;
462 int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; 482 int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS];
463 u8 xpdGain; 483 u8 xpdGain;
464 u8 xpd; 484 u8 xpd;
465 int8_t iqCalICh[AR9287_MAX_CHAINS]; 485 int8_t iqCalICh[AR9287_MAX_CHAINS];
466 int8_t iqCalQCh[AR9287_MAX_CHAINS]; 486 int8_t iqCalQCh[AR9287_MAX_CHAINS];
467 u8 pdGainOverlap; 487 u8 pdGainOverlap;
468 u8 xpaBiasLvl; 488 u8 xpaBiasLvl;
469 u8 txFrameToDataStart; 489 u8 txFrameToDataStart;
470 u8 txFrameToPaOn; 490 u8 txFrameToPaOn;
471 u8 ht40PowerIncForPdadc; 491 u8 ht40PowerIncForPdadc;
472 u8 bswAtten[AR9287_MAX_CHAINS]; 492 u8 bswAtten[AR9287_MAX_CHAINS];
473 u8 bswMargin[AR9287_MAX_CHAINS]; 493 u8 bswMargin[AR9287_MAX_CHAINS];
474 u8 swSettleHt40; 494 u8 swSettleHt40;
475 u8 version; 495 u8 version;
476 u8 db1; 496 u8 db1;
477 u8 db2; 497 u8 db2;
478 u8 ob_cck; 498 u8 ob_cck;
479 u8 ob_psk; 499 u8 ob_psk;
480 u8 ob_qam; 500 u8 ob_qam;
481 u8 ob_pal_off; 501 u8 ob_pal_off;
482 u8 futureModal[30]; 502 u8 futureModal[30];
483 struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; 503 struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS];
484} __packed; 504} __packed;
485 505
486
487
488struct cal_data_per_freq { 506struct cal_data_per_freq {
489 u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; 507 u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
490 u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; 508 u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
@@ -525,7 +543,6 @@ struct cal_data_op_loop_ar9287 {
525 u8 empty[2][5]; 543 u8 empty[2][5];
526} __packed; 544} __packed;
527 545
528
529struct cal_data_per_freq_ar9287 { 546struct cal_data_per_freq_ar9287 {
530 u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; 547 u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
531 u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; 548 u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS];
@@ -601,26 +618,25 @@ struct ar5416_eeprom_4k {
601} __packed; 618} __packed;
602 619
603struct ar9287_eeprom { 620struct ar9287_eeprom {
604 struct base_eep_ar9287_header baseEepHeader; 621 struct base_eep_ar9287_header baseEepHeader;
605 u8 custData[AR9287_DATA_SZ]; 622 u8 custData[AR9287_DATA_SZ];
606 struct modal_eep_ar9287_header modalHeader; 623 struct modal_eep_ar9287_header modalHeader;
607 u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; 624 u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS];
608 union cal_data_per_freq_ar9287_u 625 union cal_data_per_freq_ar9287_u
609 calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; 626 calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS];
610 struct cal_target_power_leg 627 struct cal_target_power_leg
611 calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; 628 calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS];
612 struct cal_target_power_leg 629 struct cal_target_power_leg
613 calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; 630 calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS];
614 struct cal_target_power_ht 631 struct cal_target_power_ht
615 calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; 632 calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS];
616 struct cal_target_power_ht 633 struct cal_target_power_ht
617 calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; 634 calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS];
618 u8 ctlIndex[AR9287_NUM_CTLS]; 635 u8 ctlIndex[AR9287_NUM_CTLS];
619 struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; 636 struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS];
620 u8 padding; 637 u8 padding;
621} __packed; 638} __packed;
622 639
623
624enum reg_ext_bitmap { 640enum reg_ext_bitmap {
625 REG_EXT_JAPAN_MIDBAND = 1, 641 REG_EXT_JAPAN_MIDBAND = 1,
626 REG_EXT_FCC_DFS_HT40 = 2, 642 REG_EXT_FCC_DFS_HT40 = 2,
@@ -661,10 +677,39 @@ struct eeprom_ops {
661 u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); 677 u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
662}; 678};
663 679
680void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
681 u32 shift, u32 val);
682int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
683 int16_t targetLeft,
684 int16_t targetRight);
685bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
686 u16 *indexL, u16 *indexR);
687bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
688void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
689 u8 *pVpdList, u16 numIntercepts,
690 u8 *pRetVpdList);
691void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
692 struct ath9k_channel *chan,
693 struct cal_target_power_leg *powInfo,
694 u16 numChannels,
695 struct cal_target_power_leg *pNewPower,
696 u16 numRates, bool isExtTarget);
697void ath9k_hw_get_target_powers(struct ath_hw *ah,
698 struct ath9k_channel *chan,
699 struct cal_target_power_ht *powInfo,
700 u16 numChannels,
701 struct cal_target_power_ht *pNewPower,
702 u16 numRates, bool isHt40Target);
703u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
704 bool is2GHz, int num_band_edges);
705int ath9k_hw_eeprom_init(struct ath_hw *ah);
706
664#define ar5416_get_ntxchains(_txchainmask) \ 707#define ar5416_get_ntxchains(_txchainmask) \
665 (((_txchainmask >> 2) & 1) + \ 708 (((_txchainmask >> 2) & 1) + \
666 ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) 709 ((_txchainmask >> 1) & 1) + (_txchainmask & 1))
667 710
668int ath9k_hw_eeprom_init(struct ath_hw *ah); 711extern const struct eeprom_ops eep_def_ops;
712extern const struct eeprom_ops eep_4k_ops;
713extern const struct eeprom_ops eep_AR9287_ops;
669 714
670#endif /* EEPROM_H */ 715#endif /* EEPROM_H */
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
new file mode 100644
index 000000000000..d34dd23e806a
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -0,0 +1,1186 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah)
20{
21 return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF);
22}
23
24static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah)
25{
26 return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF);
27}
28
29static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
30{
31#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
32 u16 *eep_data = (u16 *)&ah->eeprom.map4k;
33 int addr, eep_start_loc = 0;
34
35 eep_start_loc = 64;
36
37 if (!ath9k_hw_use_flash(ah)) {
38 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
39 "Reading from EEPROM, not flash\n");
40 }
41
42 for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
43 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
44 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
45 "Unable to read eeprom region \n");
46 return false;
47 }
48 eep_data++;
49 }
50
51 return true;
52#undef SIZE_EEPROM_4K
53}
54
55static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
56{
57#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
58 struct ar5416_eeprom_4k *eep =
59 (struct ar5416_eeprom_4k *) &ah->eeprom.map4k;
60 u16 *eepdata, temp, magic, magic2;
61 u32 sum = 0, el;
62 bool need_swap = false;
63 int i, addr;
64
65
66 if (!ath9k_hw_use_flash(ah)) {
67 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
68 &magic)) {
69 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
70 "Reading Magic # failed\n");
71 return false;
72 }
73
74 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
75 "Read Magic = 0x%04X\n", magic);
76
77 if (magic != AR5416_EEPROM_MAGIC) {
78 magic2 = swab16(magic);
79
80 if (magic2 == AR5416_EEPROM_MAGIC) {
81 need_swap = true;
82 eepdata = (u16 *) (&ah->eeprom);
83
84 for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
85 temp = swab16(*eepdata);
86 *eepdata = temp;
87 eepdata++;
88 }
89 } else {
90 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
91 "Invalid EEPROM Magic. "
92 "endianness mismatch.\n");
93 return -EINVAL;
94 }
95 }
96 }
97
98 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
99 need_swap ? "True" : "False");
100
101 if (need_swap)
102 el = swab16(ah->eeprom.map4k.baseEepHeader.length);
103 else
104 el = ah->eeprom.map4k.baseEepHeader.length;
105
106 if (el > sizeof(struct ar5416_eeprom_4k))
107 el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
108 else
109 el = el / sizeof(u16);
110
111 eepdata = (u16 *)(&ah->eeprom);
112
113 for (i = 0; i < el; i++)
114 sum ^= *eepdata++;
115
116 if (need_swap) {
117 u32 integer;
118 u16 word;
119
120 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
121 "EEPROM Endianness is not native.. Changing\n");
122
123 word = swab16(eep->baseEepHeader.length);
124 eep->baseEepHeader.length = word;
125
126 word = swab16(eep->baseEepHeader.checksum);
127 eep->baseEepHeader.checksum = word;
128
129 word = swab16(eep->baseEepHeader.version);
130 eep->baseEepHeader.version = word;
131
132 word = swab16(eep->baseEepHeader.regDmn[0]);
133 eep->baseEepHeader.regDmn[0] = word;
134
135 word = swab16(eep->baseEepHeader.regDmn[1]);
136 eep->baseEepHeader.regDmn[1] = word;
137
138 word = swab16(eep->baseEepHeader.rfSilent);
139 eep->baseEepHeader.rfSilent = word;
140
141 word = swab16(eep->baseEepHeader.blueToothOptions);
142 eep->baseEepHeader.blueToothOptions = word;
143
144 word = swab16(eep->baseEepHeader.deviceCap);
145 eep->baseEepHeader.deviceCap = word;
146
147 integer = swab32(eep->modalHeader.antCtrlCommon);
148 eep->modalHeader.antCtrlCommon = integer;
149
150 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
151 integer = swab32(eep->modalHeader.antCtrlChain[i]);
152 eep->modalHeader.antCtrlChain[i] = integer;
153 }
154
155 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
156 word = swab16(eep->modalHeader.spurChans[i].spurChan);
157 eep->modalHeader.spurChans[i].spurChan = word;
158 }
159 }
160
161 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
162 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
163 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
164 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
165 sum, ah->eep_ops->get_eeprom_ver(ah));
166 return -EINVAL;
167 }
168
169 return 0;
170#undef EEPROM_4K_SIZE
171}
172
173static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
174 enum eeprom_param param)
175{
176 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
177 struct modal_eep_4k_header *pModal = &eep->modalHeader;
178 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
179
180 switch (param) {
181 case EEP_NFTHRESH_2:
182 return pModal->noiseFloorThreshCh[0];
183 case AR_EEPROM_MAC(0):
184 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
185 case AR_EEPROM_MAC(1):
186 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
187 case AR_EEPROM_MAC(2):
188 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
189 case EEP_REG_0:
190 return pBase->regDmn[0];
191 case EEP_REG_1:
192 return pBase->regDmn[1];
193 case EEP_OP_CAP:
194 return pBase->deviceCap;
195 case EEP_OP_MODE:
196 return pBase->opCapFlags;
197 case EEP_RF_SILENT:
198 return pBase->rfSilent;
199 case EEP_OB_2:
200 return pModal->ob_0;
201 case EEP_DB_2:
202 return pModal->db1_1;
203 case EEP_MINOR_REV:
204 return pBase->version & AR5416_EEP_VER_MINOR_MASK;
205 case EEP_TX_MASK:
206 return pBase->txMask;
207 case EEP_RX_MASK:
208 return pBase->rxMask;
209 case EEP_FRAC_N_5G:
210 return 0;
211 default:
212 return 0;
213 }
214}
215
216static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah,
217 struct ath9k_channel *chan,
218 struct cal_data_per_freq_4k *pRawDataSet,
219 u8 *bChans, u16 availPiers,
220 u16 tPdGainOverlap, int16_t *pMinCalPower,
221 u16 *pPdGainBoundaries, u8 *pPDADCValues,
222 u16 numXpdGains)
223{
224#define TMP_VAL_VPD_TABLE \
225 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
226 int i, j, k;
227 int16_t ss;
228 u16 idxL = 0, idxR = 0, numPiers;
229 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
230 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
231 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
232 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
233 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
234 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
235
236 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
237 u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
238 u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
239 int16_t vpdStep;
240 int16_t tmpVal;
241 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
242 bool match;
243 int16_t minDelta = 0;
244 struct chan_centers centers;
245#define PD_GAIN_BOUNDARY_DEFAULT 58;
246
247 ath9k_hw_get_channel_centers(ah, chan, &centers);
248
249 for (numPiers = 0; numPiers < availPiers; numPiers++) {
250 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
251 break;
252 }
253
254 match = ath9k_hw_get_lower_upper_index(
255 (u8)FREQ2FBIN(centers.synth_center,
256 IS_CHAN_2GHZ(chan)), bChans, numPiers,
257 &idxL, &idxR);
258
259 if (match) {
260 for (i = 0; i < numXpdGains; i++) {
261 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
262 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
263 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
264 pRawDataSet[idxL].pwrPdg[i],
265 pRawDataSet[idxL].vpdPdg[i],
266 AR5416_EEP4K_PD_GAIN_ICEPTS,
267 vpdTableI[i]);
268 }
269 } else {
270 for (i = 0; i < numXpdGains; i++) {
271 pVpdL = pRawDataSet[idxL].vpdPdg[i];
272 pPwrL = pRawDataSet[idxL].pwrPdg[i];
273 pVpdR = pRawDataSet[idxR].vpdPdg[i];
274 pPwrR = pRawDataSet[idxR].pwrPdg[i];
275
276 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
277
278 maxPwrT4[i] =
279 min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
280 pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
281
282
283 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
284 pPwrL, pVpdL,
285 AR5416_EEP4K_PD_GAIN_ICEPTS,
286 vpdTableL[i]);
287 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
288 pPwrR, pVpdR,
289 AR5416_EEP4K_PD_GAIN_ICEPTS,
290 vpdTableR[i]);
291
292 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
293 vpdTableI[i][j] =
294 (u8)(ath9k_hw_interpolate((u16)
295 FREQ2FBIN(centers.
296 synth_center,
297 IS_CHAN_2GHZ
298 (chan)),
299 bChans[idxL], bChans[idxR],
300 vpdTableL[i][j], vpdTableR[i][j]));
301 }
302 }
303 }
304
305 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
306
307 k = 0;
308
309 for (i = 0; i < numXpdGains; i++) {
310 if (i == (numXpdGains - 1))
311 pPdGainBoundaries[i] =
312 (u16)(maxPwrT4[i] / 2);
313 else
314 pPdGainBoundaries[i] =
315 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
316
317 pPdGainBoundaries[i] =
318 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
319
320 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
321 minDelta = pPdGainBoundaries[0] - 23;
322 pPdGainBoundaries[0] = 23;
323 } else {
324 minDelta = 0;
325 }
326
327 if (i == 0) {
328 if (AR_SREV_9280_10_OR_LATER(ah))
329 ss = (int16_t)(0 - (minPwrT4[i] / 2));
330 else
331 ss = 0;
332 } else {
333 ss = (int16_t)((pPdGainBoundaries[i - 1] -
334 (minPwrT4[i] / 2)) -
335 tPdGainOverlap + 1 + minDelta);
336 }
337 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
338 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
339
340 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
341 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
342 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
343 ss++;
344 }
345
346 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
347 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
348 (minPwrT4[i] / 2));
349 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
350 tgtIndex : sizeCurrVpdTable;
351
352 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
353 pPDADCValues[k++] = vpdTableI[i][ss++];
354
355 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
356 vpdTableI[i][sizeCurrVpdTable - 2]);
357 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
358
359 if (tgtIndex >= maxIndex) {
360 while ((ss <= tgtIndex) &&
361 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
362 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
363 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
364 255 : tmpVal);
365 ss++;
366 }
367 }
368 }
369
370 while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
371 pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
372 i++;
373 }
374
375 while (k < AR5416_NUM_PDADC_VALUES) {
376 pPDADCValues[k] = pPDADCValues[k - 1];
377 k++;
378 }
379
380 return;
381#undef TMP_VAL_VPD_TABLE
382}
383
384static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
385 struct ath9k_channel *chan,
386 int16_t *pTxPowerIndexOffset)
387{
388 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
389 struct cal_data_per_freq_4k *pRawDataset;
390 u8 *pCalBChans = NULL;
391 u16 pdGainOverlap_t2;
392 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
393 u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK];
394 u16 numPiers, i, j;
395 int16_t tMinCalPower;
396 u16 numXpdGain, xpdMask;
397 u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 };
398 u32 reg32, regOffset, regChainOffset;
399
400 xpdMask = pEepData->modalHeader.xpdGain;
401
402 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
403 AR5416_EEP_MINOR_VER_2) {
404 pdGainOverlap_t2 =
405 pEepData->modalHeader.pdGainOverlap;
406 } else {
407 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
408 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
409 }
410
411 pCalBChans = pEepData->calFreqPier2G;
412 numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS;
413
414 numXpdGain = 0;
415
416 for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) {
417 if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) {
418 if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS)
419 break;
420 xpdGainValues[numXpdGain] =
421 (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i);
422 numXpdGain++;
423 }
424 }
425
426 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
427 (numXpdGain - 1) & 0x3);
428 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
429 xpdGainValues[0]);
430 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
431 xpdGainValues[1]);
432 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0);
433
434 for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) {
435 if (AR_SREV_5416_20_OR_LATER(ah) &&
436 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
437 (i != 0)) {
438 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
439 } else
440 regChainOffset = i * 0x1000;
441
442 if (pEepData->baseEepHeader.txMask & (1 << i)) {
443 pRawDataset = pEepData->calPierData2G[i];
444
445 ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
446 pRawDataset, pCalBChans,
447 numPiers, pdGainOverlap_t2,
448 &tMinCalPower, gainBoundaries,
449 pdadcValues, numXpdGain);
450
451 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
452 REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
453 SM(pdGainOverlap_t2,
454 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
455 | SM(gainBoundaries[0],
456 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
457 | SM(gainBoundaries[1],
458 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
459 | SM(gainBoundaries[2],
460 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
461 | SM(gainBoundaries[3],
462 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
463 }
464
465 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
466 for (j = 0; j < 32; j++) {
467 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
468 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
469 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
470 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
471 REG_WRITE(ah, regOffset, reg32);
472
473 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
474 "PDADC (%d,%4x): %4.4x %8.8x\n",
475 i, regChainOffset, regOffset,
476 reg32);
477 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
478 "PDADC: Chain %d | "
479 "PDADC %3d Value %3d | "
480 "PDADC %3d Value %3d | "
481 "PDADC %3d Value %3d | "
482 "PDADC %3d Value %3d |\n",
483 i, 4 * j, pdadcValues[4 * j],
484 4 * j + 1, pdadcValues[4 * j + 1],
485 4 * j + 2, pdadcValues[4 * j + 2],
486 4 * j + 3,
487 pdadcValues[4 * j + 3]);
488
489 regOffset += 4;
490 }
491 }
492 }
493
494 *pTxPowerIndexOffset = 0;
495}
496
497static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
498 struct ath9k_channel *chan,
499 int16_t *ratesArray,
500 u16 cfgCtl,
501 u16 AntennaReduction,
502 u16 twiceMaxRegulatoryPower,
503 u16 powerLimit)
504{
505#define CMP_TEST_GRP \
506 (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \
507 pEepData->ctlIndex[i]) \
508 || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \
509 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))
510
511 int i;
512 int16_t twiceLargestAntenna;
513 u16 twiceMinEdgePower;
514 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
515 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
516 u16 numCtlModes, *pCtlMode, ctlMode, freq;
517 struct chan_centers centers;
518 struct cal_ctl_data_4k *rep;
519 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
520 static const u16 tpScaleReductionTable[5] =
521 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
522 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
523 0, { 0, 0, 0, 0}
524 };
525 struct cal_target_power_leg targetPowerOfdmExt = {
526 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
527 0, { 0, 0, 0, 0 }
528 };
529 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
530 0, {0, 0, 0, 0}
531 };
532 u16 ctlModesFor11g[] =
533 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
534 CTL_2GHT40
535 };
536
537 ath9k_hw_get_channel_centers(ah, chan, &centers);
538
539 twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
540 twiceLargestAntenna = (int16_t)min(AntennaReduction -
541 twiceLargestAntenna, 0);
542
543 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
544 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
545 maxRegAllowedPower -=
546 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
547 }
548
549 scaledPower = min(powerLimit, maxRegAllowedPower);
550 scaledPower = max((u16)0, scaledPower);
551
552 numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
553 pCtlMode = ctlModesFor11g;
554
555 ath9k_hw_get_legacy_target_powers(ah, chan,
556 pEepData->calTargetPowerCck,
557 AR5416_NUM_2G_CCK_TARGET_POWERS,
558 &targetPowerCck, 4, false);
559 ath9k_hw_get_legacy_target_powers(ah, chan,
560 pEepData->calTargetPower2G,
561 AR5416_NUM_2G_20_TARGET_POWERS,
562 &targetPowerOfdm, 4, false);
563 ath9k_hw_get_target_powers(ah, chan,
564 pEepData->calTargetPower2GHT20,
565 AR5416_NUM_2G_20_TARGET_POWERS,
566 &targetPowerHt20, 8, false);
567
568 if (IS_CHAN_HT40(chan)) {
569 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
570 ath9k_hw_get_target_powers(ah, chan,
571 pEepData->calTargetPower2GHT40,
572 AR5416_NUM_2G_40_TARGET_POWERS,
573 &targetPowerHt40, 8, true);
574 ath9k_hw_get_legacy_target_powers(ah, chan,
575 pEepData->calTargetPowerCck,
576 AR5416_NUM_2G_CCK_TARGET_POWERS,
577 &targetPowerCckExt, 4, true);
578 ath9k_hw_get_legacy_target_powers(ah, chan,
579 pEepData->calTargetPower2G,
580 AR5416_NUM_2G_20_TARGET_POWERS,
581 &targetPowerOfdmExt, 4, true);
582 }
583
584 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
585 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
586 (pCtlMode[ctlMode] == CTL_2GHT40);
587
588 if (isHt40CtlMode)
589 freq = centers.synth_center;
590 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
591 freq = centers.ext_center;
592 else
593 freq = centers.ctl_center;
594
595 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
596 ah->eep_ops->get_eeprom_rev(ah) <= 2)
597 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
598
599 for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) &&
600 pEepData->ctlIndex[i]; i++) {
601
602 if (CMP_TEST_GRP) {
603 rep = &(pEepData->ctlData[i]);
604
605 twiceMinEdgePower = ath9k_hw_get_max_edge_power(
606 freq,
607 rep->ctlEdges[
608 ar5416_get_ntxchains(ah->txchainmask) - 1],
609 IS_CHAN_2GHZ(chan),
610 AR5416_EEP4K_NUM_BAND_EDGES);
611
612 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
613 twiceMaxEdgePower =
614 min(twiceMaxEdgePower,
615 twiceMinEdgePower);
616 } else {
617 twiceMaxEdgePower = twiceMinEdgePower;
618 break;
619 }
620 }
621 }
622
623 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
624
625 switch (pCtlMode[ctlMode]) {
626 case CTL_11B:
627 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
628 targetPowerCck.tPow2x[i] =
629 min((u16)targetPowerCck.tPow2x[i],
630 minCtlPower);
631 }
632 break;
633 case CTL_11G:
634 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
635 targetPowerOfdm.tPow2x[i] =
636 min((u16)targetPowerOfdm.tPow2x[i],
637 minCtlPower);
638 }
639 break;
640 case CTL_2GHT20:
641 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
642 targetPowerHt20.tPow2x[i] =
643 min((u16)targetPowerHt20.tPow2x[i],
644 minCtlPower);
645 }
646 break;
647 case CTL_11B_EXT:
648 targetPowerCckExt.tPow2x[0] =
649 min((u16)targetPowerCckExt.tPow2x[0],
650 minCtlPower);
651 break;
652 case CTL_11G_EXT:
653 targetPowerOfdmExt.tPow2x[0] =
654 min((u16)targetPowerOfdmExt.tPow2x[0],
655 minCtlPower);
656 break;
657 case CTL_2GHT40:
658 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
659 targetPowerHt40.tPow2x[i] =
660 min((u16)targetPowerHt40.tPow2x[i],
661 minCtlPower);
662 }
663 break;
664 default:
665 break;
666 }
667 }
668
669 ratesArray[rate6mb] =
670 ratesArray[rate9mb] =
671 ratesArray[rate12mb] =
672 ratesArray[rate18mb] =
673 ratesArray[rate24mb] =
674 targetPowerOfdm.tPow2x[0];
675
676 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
677 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
678 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
679 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
680
681 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
682 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
683
684 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
685 ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
686 ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
687 ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
688
689 if (IS_CHAN_HT40(chan)) {
690 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
691 ratesArray[rateHt40_0 + i] =
692 targetPowerHt40.tPow2x[i];
693 }
694 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
695 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
696 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
697 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
698 }
699
700#undef CMP_TEST_GRP
701}
702
703static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
704 struct ath9k_channel *chan,
705 u16 cfgCtl,
706 u8 twiceAntennaReduction,
707 u8 twiceMaxRegulatoryPower,
708 u8 powerLimit)
709{
710 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
711 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
712 int16_t ratesArray[Ar5416RateSize];
713 int16_t txPowerIndexOffset = 0;
714 u8 ht40PowerIncForPdadc = 2;
715 int i;
716
717 memset(ratesArray, 0, sizeof(ratesArray));
718
719 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
720 AR5416_EEP_MINOR_VER_2) {
721 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
722 }
723
724 ath9k_hw_set_4k_power_per_rate_table(ah, chan,
725 &ratesArray[0], cfgCtl,
726 twiceAntennaReduction,
727 twiceMaxRegulatoryPower,
728 powerLimit);
729
730 ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
731
732 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
733 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
734 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
735 ratesArray[i] = AR5416_MAX_RATE_POWER;
736 }
737
738
739 /* Update regulatory */
740
741 i = rate6mb;
742 if (IS_CHAN_HT40(chan))
743 i = rateHt40_0;
744 else if (IS_CHAN_HT20(chan))
745 i = rateHt20_0;
746
747 ah->regulatory.max_power_level = ratesArray[i];
748
749 if (AR_SREV_9280_10_OR_LATER(ah)) {
750 for (i = 0; i < Ar5416RateSize; i++)
751 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
752 }
753
754 /* OFDM power per rate */
755 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
756 ATH9K_POW_SM(ratesArray[rate18mb], 24)
757 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
758 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
759 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
760 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
761 ATH9K_POW_SM(ratesArray[rate54mb], 24)
762 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
763 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
764 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
765
766 /* CCK power per rate */
767 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
768 ATH9K_POW_SM(ratesArray[rate2s], 24)
769 | ATH9K_POW_SM(ratesArray[rate2l], 16)
770 | ATH9K_POW_SM(ratesArray[rateXr], 8)
771 | ATH9K_POW_SM(ratesArray[rate1l], 0));
772 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
773 ATH9K_POW_SM(ratesArray[rate11s], 24)
774 | ATH9K_POW_SM(ratesArray[rate11l], 16)
775 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
776 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
777
778 /* HT20 power per rate */
779 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
780 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
781 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
782 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
783 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
784 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
785 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
786 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
787 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
788 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
789
790 /* HT40 power per rate */
791 if (IS_CHAN_HT40(chan)) {
792 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
793 ATH9K_POW_SM(ratesArray[rateHt40_3] +
794 ht40PowerIncForPdadc, 24)
795 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
796 ht40PowerIncForPdadc, 16)
797 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
798 ht40PowerIncForPdadc, 8)
799 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
800 ht40PowerIncForPdadc, 0));
801 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
802 ATH9K_POW_SM(ratesArray[rateHt40_7] +
803 ht40PowerIncForPdadc, 24)
804 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
805 ht40PowerIncForPdadc, 16)
806 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
807 ht40PowerIncForPdadc, 8)
808 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
809 ht40PowerIncForPdadc, 0));
810 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
811 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
812 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
813 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
814 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
815 }
816}
817
818static void ath9k_hw_4k_set_addac(struct ath_hw *ah,
819 struct ath9k_channel *chan)
820{
821 struct modal_eep_4k_header *pModal;
822 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
823 u8 biaslevel;
824
825 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
826 return;
827
828 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
829 return;
830
831 pModal = &eep->modalHeader;
832
833 if (pModal->xpaBiasLvl != 0xff) {
834 biaslevel = pModal->xpaBiasLvl;
835 INI_RA(&ah->iniAddac, 7, 1) =
836 (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
837 }
838}
839
840static void ath9k_hw_4k_set_gain(struct ath_hw *ah,
841 struct modal_eep_4k_header *pModal,
842 struct ar5416_eeprom_4k *eep,
843 u8 txRxAttenLocal)
844{
845 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0,
846 pModal->antCtrlChain[0]);
847
848 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0),
849 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
850 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
851 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
852 SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
853 SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
854
855 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
856 AR5416_EEP_MINOR_VER_3) {
857 txRxAttenLocal = pModal->txRxAttenCh[0];
858
859 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
860 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
861 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
862 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
863 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
864 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
865 pModal->xatten2Margin[0]);
866 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ,
867 AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
868
869 /* Set the block 1 value to block 0 value */
870 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
871 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
872 pModal->bswMargin[0]);
873 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
874 AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
875 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
876 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
877 pModal->xatten2Margin[0]);
878 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000,
879 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
880 pModal->xatten2Db[0]);
881 }
882
883 REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
884 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
885 REG_RMW_FIELD(ah, AR_PHY_RXGAIN,
886 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
887
888 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
889 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
890 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000,
891 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
892
893 if (AR_SREV_9285_11(ah))
894 REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
895}
896
897/*
898 * Read EEPROM header info and program the device for correct operation
899 * given the channel value.
900 */
901static void ath9k_hw_4k_set_board_values(struct ath_hw *ah,
902 struct ath9k_channel *chan)
903{
904 struct modal_eep_4k_header *pModal;
905 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
906 u8 txRxAttenLocal;
907 u8 ob[5], db1[5], db2[5];
908 u8 ant_div_control1, ant_div_control2;
909 u32 regVal;
910
911 pModal = &eep->modalHeader;
912 txRxAttenLocal = 23;
913
914 REG_WRITE(ah, AR_PHY_SWITCH_COM,
915 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
916
917 /* Single chain for 4K EEPROM*/
918 ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal);
919
920 /* Initialize Ant Diversity settings from EEPROM */
921 if (pModal->version >= 3) {
922 ant_div_control1 = pModal->antdiv_ctl1;
923 ant_div_control2 = pModal->antdiv_ctl2;
924
925 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
926 regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL));
927
928 regVal |= SM(ant_div_control1,
929 AR_PHY_9285_ANT_DIV_CTL);
930 regVal |= SM(ant_div_control2,
931 AR_PHY_9285_ANT_DIV_ALT_LNACONF);
932 regVal |= SM((ant_div_control2 >> 2),
933 AR_PHY_9285_ANT_DIV_MAIN_LNACONF);
934 regVal |= SM((ant_div_control1 >> 1),
935 AR_PHY_9285_ANT_DIV_ALT_GAINTB);
936 regVal |= SM((ant_div_control1 >> 2),
937 AR_PHY_9285_ANT_DIV_MAIN_GAINTB);
938
939
940 REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal);
941 regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL);
942 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
943 regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
944 regVal |= SM((ant_div_control1 >> 3),
945 AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV);
946
947 REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal);
948 regVal = REG_READ(ah, AR_PHY_CCK_DETECT);
949 }
950
951 if (pModal->version >= 2) {
952 ob[0] = pModal->ob_0;
953 ob[1] = pModal->ob_1;
954 ob[2] = pModal->ob_2;
955 ob[3] = pModal->ob_3;
956 ob[4] = pModal->ob_4;
957
958 db1[0] = pModal->db1_0;
959 db1[1] = pModal->db1_1;
960 db1[2] = pModal->db1_2;
961 db1[3] = pModal->db1_3;
962 db1[4] = pModal->db1_4;
963
964 db2[0] = pModal->db2_0;
965 db2[1] = pModal->db2_1;
966 db2[2] = pModal->db2_2;
967 db2[3] = pModal->db2_3;
968 db2[4] = pModal->db2_4;
969 } else if (pModal->version == 1) {
970 ob[0] = pModal->ob_0;
971 ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1;
972 db1[0] = pModal->db1_0;
973 db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1;
974 db2[0] = pModal->db2_0;
975 db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1;
976 } else {
977 int i;
978
979 for (i = 0; i < 5; i++) {
980 ob[i] = pModal->ob_0;
981 db1[i] = pModal->db1_0;
982 db2[i] = pModal->db1_0;
983 }
984 }
985
986 if (AR_SREV_9271(ah)) {
987 ath9k_hw_analog_shift_rmw(ah,
988 AR9285_AN_RF2G3,
989 AR9271_AN_RF2G3_OB_cck,
990 AR9271_AN_RF2G3_OB_cck_S,
991 ob[0]);
992 ath9k_hw_analog_shift_rmw(ah,
993 AR9285_AN_RF2G3,
994 AR9271_AN_RF2G3_OB_psk,
995 AR9271_AN_RF2G3_OB_psk_S,
996 ob[1]);
997 ath9k_hw_analog_shift_rmw(ah,
998 AR9285_AN_RF2G3,
999 AR9271_AN_RF2G3_OB_qam,
1000 AR9271_AN_RF2G3_OB_qam_S,
1001 ob[2]);
1002 ath9k_hw_analog_shift_rmw(ah,
1003 AR9285_AN_RF2G3,
1004 AR9271_AN_RF2G3_DB_1,
1005 AR9271_AN_RF2G3_DB_1_S,
1006 db1[0]);
1007 ath9k_hw_analog_shift_rmw(ah,
1008 AR9285_AN_RF2G4,
1009 AR9271_AN_RF2G4_DB_2,
1010 AR9271_AN_RF2G4_DB_2_S,
1011 db2[0]);
1012 } else {
1013 ath9k_hw_analog_shift_rmw(ah,
1014 AR9285_AN_RF2G3,
1015 AR9285_AN_RF2G3_OB_0,
1016 AR9285_AN_RF2G3_OB_0_S,
1017 ob[0]);
1018 ath9k_hw_analog_shift_rmw(ah,
1019 AR9285_AN_RF2G3,
1020 AR9285_AN_RF2G3_OB_1,
1021 AR9285_AN_RF2G3_OB_1_S,
1022 ob[1]);
1023 ath9k_hw_analog_shift_rmw(ah,
1024 AR9285_AN_RF2G3,
1025 AR9285_AN_RF2G3_OB_2,
1026 AR9285_AN_RF2G3_OB_2_S,
1027 ob[2]);
1028 ath9k_hw_analog_shift_rmw(ah,
1029 AR9285_AN_RF2G3,
1030 AR9285_AN_RF2G3_OB_3,
1031 AR9285_AN_RF2G3_OB_3_S,
1032 ob[3]);
1033 ath9k_hw_analog_shift_rmw(ah,
1034 AR9285_AN_RF2G3,
1035 AR9285_AN_RF2G3_OB_4,
1036 AR9285_AN_RF2G3_OB_4_S,
1037 ob[4]);
1038
1039 ath9k_hw_analog_shift_rmw(ah,
1040 AR9285_AN_RF2G3,
1041 AR9285_AN_RF2G3_DB1_0,
1042 AR9285_AN_RF2G3_DB1_0_S,
1043 db1[0]);
1044 ath9k_hw_analog_shift_rmw(ah,
1045 AR9285_AN_RF2G3,
1046 AR9285_AN_RF2G3_DB1_1,
1047 AR9285_AN_RF2G3_DB1_1_S,
1048 db1[1]);
1049 ath9k_hw_analog_shift_rmw(ah,
1050 AR9285_AN_RF2G3,
1051 AR9285_AN_RF2G3_DB1_2,
1052 AR9285_AN_RF2G3_DB1_2_S,
1053 db1[2]);
1054 ath9k_hw_analog_shift_rmw(ah,
1055 AR9285_AN_RF2G4,
1056 AR9285_AN_RF2G4_DB1_3,
1057 AR9285_AN_RF2G4_DB1_3_S,
1058 db1[3]);
1059 ath9k_hw_analog_shift_rmw(ah,
1060 AR9285_AN_RF2G4,
1061 AR9285_AN_RF2G4_DB1_4,
1062 AR9285_AN_RF2G4_DB1_4_S, db1[4]);
1063
1064 ath9k_hw_analog_shift_rmw(ah,
1065 AR9285_AN_RF2G4,
1066 AR9285_AN_RF2G4_DB2_0,
1067 AR9285_AN_RF2G4_DB2_0_S,
1068 db2[0]);
1069 ath9k_hw_analog_shift_rmw(ah,
1070 AR9285_AN_RF2G4,
1071 AR9285_AN_RF2G4_DB2_1,
1072 AR9285_AN_RF2G4_DB2_1_S,
1073 db2[1]);
1074 ath9k_hw_analog_shift_rmw(ah,
1075 AR9285_AN_RF2G4,
1076 AR9285_AN_RF2G4_DB2_2,
1077 AR9285_AN_RF2G4_DB2_2_S,
1078 db2[2]);
1079 ath9k_hw_analog_shift_rmw(ah,
1080 AR9285_AN_RF2G4,
1081 AR9285_AN_RF2G4_DB2_3,
1082 AR9285_AN_RF2G4_DB2_3_S,
1083 db2[3]);
1084 ath9k_hw_analog_shift_rmw(ah,
1085 AR9285_AN_RF2G4,
1086 AR9285_AN_RF2G4_DB2_4,
1087 AR9285_AN_RF2G4_DB2_4_S,
1088 db2[4]);
1089 }
1090
1091
1092 if (AR_SREV_9285_11(ah))
1093 REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
1094
1095 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
1096 pModal->switchSettling);
1097 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
1098 pModal->adcDesiredSize);
1099
1100 REG_WRITE(ah, AR_PHY_RF_CTL4,
1101 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
1102 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
1103 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
1104 SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1105
1106 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
1107 pModal->txEndToRxOn);
1108 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
1109 pModal->thresh62);
1110 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
1111 pModal->thresh62);
1112
1113 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1114 AR5416_EEP_MINOR_VER_2) {
1115 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
1116 pModal->txFrameToDataStart);
1117 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
1118 pModal->txFrameToPaOn);
1119 }
1120
1121 if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1122 AR5416_EEP_MINOR_VER_3) {
1123 if (IS_CHAN_HT40(chan))
1124 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1125 AR_PHY_SETTLING_SWITCH,
1126 pModal->swSettleHt40);
1127 }
1128}
1129
1130static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah,
1131 struct ath9k_channel *chan)
1132{
1133 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
1134 struct modal_eep_4k_header *pModal = &eep->modalHeader;
1135
1136 return pModal->antCtrlCommon & 0xFFFF;
1137}
1138
1139static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah,
1140 enum ieee80211_band freq_band)
1141{
1142 return 1;
1143}
1144
1145static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
1146{
1147#define EEP_MAP4K_SPURCHAN \
1148 (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan)
1149
1150 u16 spur_val = AR_NO_SPUR;
1151
1152 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1153 "Getting spur idx %d is2Ghz. %d val %x\n",
1154 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1155
1156 switch (ah->config.spurmode) {
1157 case SPUR_DISABLE:
1158 break;
1159 case SPUR_ENABLE_IOCTL:
1160 spur_val = ah->config.spurchans[i][is2GHz];
1161 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1162 "Getting spur val from new loc. %d\n", spur_val);
1163 break;
1164 case SPUR_ENABLE_EEPROM:
1165 spur_val = EEP_MAP4K_SPURCHAN;
1166 break;
1167 }
1168
1169 return spur_val;
1170
1171#undef EEP_MAP4K_SPURCHAN
1172}
1173
1174const struct eeprom_ops eep_4k_ops = {
1175 .check_eeprom = ath9k_hw_4k_check_eeprom,
1176 .get_eeprom = ath9k_hw_4k_get_eeprom,
1177 .fill_eeprom = ath9k_hw_4k_fill_eeprom,
1178 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
1179 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
1180 .get_num_ant_config = ath9k_hw_4k_get_num_ant_config,
1181 .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg,
1182 .set_board_values = ath9k_hw_4k_set_board_values,
1183 .set_addac = ath9k_hw_4k_set_addac,
1184 .set_txpower = ath9k_hw_4k_set_txpower,
1185 .get_spur_channel = ath9k_hw_4k_get_spur_channel
1186};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
new file mode 100644
index 000000000000..aeb7f484b6e1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -0,0 +1,1183 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah)
20{
21 return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF;
22}
23
24static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah)
25{
26 return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
27}
28
29static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah)
30{
31 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
32 u16 *eep_data;
33 int addr, eep_start_loc = AR9287_EEP_START_LOC;
34 eep_data = (u16 *)eep;
35
36 if (!ath9k_hw_use_flash(ah)) {
37 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
38 "Reading from EEPROM, not flash\n");
39 }
40
41 for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
42 addr++) {
43 if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
44 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
45 "Unable to read eeprom region \n");
46 return false;
47 }
48 eep_data++;
49 }
50 return true;
51}
52
53static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah)
54{
55 u32 sum = 0, el, integer;
56 u16 temp, word, magic, magic2, *eepdata;
57 int i, addr;
58 bool need_swap = false;
59 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
60
61 if (!ath9k_hw_use_flash(ah)) {
62 if (!ath9k_hw_nvram_read
63 (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
64 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
65 "Reading Magic # failed\n");
66 return false;
67 }
68
69 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
70 "Read Magic = 0x%04X\n", magic);
71 if (magic != AR5416_EEPROM_MAGIC) {
72 magic2 = swab16(magic);
73
74 if (magic2 == AR5416_EEPROM_MAGIC) {
75 need_swap = true;
76 eepdata = (u16 *)(&ah->eeprom);
77
78 for (addr = 0;
79 addr < sizeof(struct ar9287_eeprom) / sizeof(u16);
80 addr++) {
81 temp = swab16(*eepdata);
82 *eepdata = temp;
83 eepdata++;
84 }
85 } else {
86 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
87 "Invalid EEPROM Magic. "
88 "endianness mismatch.\n");
89 return -EINVAL;
90 }
91 }
92 }
93 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ?
94 "True" : "False");
95
96 if (need_swap)
97 el = swab16(ah->eeprom.map9287.baseEepHeader.length);
98 else
99 el = ah->eeprom.map9287.baseEepHeader.length;
100
101 if (el > sizeof(struct ar9287_eeprom))
102 el = sizeof(struct ar9287_eeprom) / sizeof(u16);
103 else
104 el = el / sizeof(u16);
105
106 eepdata = (u16 *)(&ah->eeprom);
107 for (i = 0; i < el; i++)
108 sum ^= *eepdata++;
109
110 if (need_swap) {
111 word = swab16(eep->baseEepHeader.length);
112 eep->baseEepHeader.length = word;
113
114 word = swab16(eep->baseEepHeader.checksum);
115 eep->baseEepHeader.checksum = word;
116
117 word = swab16(eep->baseEepHeader.version);
118 eep->baseEepHeader.version = word;
119
120 word = swab16(eep->baseEepHeader.regDmn[0]);
121 eep->baseEepHeader.regDmn[0] = word;
122
123 word = swab16(eep->baseEepHeader.regDmn[1]);
124 eep->baseEepHeader.regDmn[1] = word;
125
126 word = swab16(eep->baseEepHeader.rfSilent);
127 eep->baseEepHeader.rfSilent = word;
128
129 word = swab16(eep->baseEepHeader.blueToothOptions);
130 eep->baseEepHeader.blueToothOptions = word;
131
132 word = swab16(eep->baseEepHeader.deviceCap);
133 eep->baseEepHeader.deviceCap = word;
134
135 integer = swab32(eep->modalHeader.antCtrlCommon);
136 eep->modalHeader.antCtrlCommon = integer;
137
138 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
139 integer = swab32(eep->modalHeader.antCtrlChain[i]);
140 eep->modalHeader.antCtrlChain[i] = integer;
141 }
142
143 for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) {
144 word = swab16(eep->modalHeader.spurChans[i].spurChan);
145 eep->modalHeader.spurChans[i].spurChan = word;
146 }
147 }
148
149 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
150 || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
151 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
152 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
153 sum, ah->eep_ops->get_eeprom_ver(ah));
154 return -EINVAL;
155 }
156
157 return 0;
158}
159
160static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah,
161 enum eeprom_param param)
162{
163 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
164 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
165 struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
166 u16 ver_minor;
167
168 ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK;
169 switch (param) {
170 case EEP_NFTHRESH_2:
171 return pModal->noiseFloorThreshCh[0];
172 case AR_EEPROM_MAC(0):
173 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
174 case AR_EEPROM_MAC(1):
175 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
176 case AR_EEPROM_MAC(2):
177 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
178 case EEP_REG_0:
179 return pBase->regDmn[0];
180 case EEP_REG_1:
181 return pBase->regDmn[1];
182 case EEP_OP_CAP:
183 return pBase->deviceCap;
184 case EEP_OP_MODE:
185 return pBase->opCapFlags;
186 case EEP_RF_SILENT:
187 return pBase->rfSilent;
188 case EEP_MINOR_REV:
189 return ver_minor;
190 case EEP_TX_MASK:
191 return pBase->txMask;
192 case EEP_RX_MASK:
193 return pBase->rxMask;
194 case EEP_DEV_TYPE:
195 return pBase->deviceType;
196 case EEP_OL_PWRCTRL:
197 return pBase->openLoopPwrCntl;
198 case EEP_TEMPSENSE_SLOPE:
199 if (ver_minor >= AR9287_EEP_MINOR_VER_2)
200 return pBase->tempSensSlope;
201 else
202 return 0;
203 case EEP_TEMPSENSE_SLOPE_PAL_ON:
204 if (ver_minor >= AR9287_EEP_MINOR_VER_3)
205 return pBase->tempSensSlopePalOn;
206 else
207 return 0;
208 default:
209 return 0;
210 }
211}
212
213
214static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah,
215 struct ath9k_channel *chan,
216 struct cal_data_per_freq_ar9287 *pRawDataSet,
217 u8 *bChans, u16 availPiers,
218 u16 tPdGainOverlap, int16_t *pMinCalPower,
219 u16 *pPdGainBoundaries, u8 *pPDADCValues,
220 u16 numXpdGains)
221{
222#define TMP_VAL_VPD_TABLE \
223 ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
224
225 int i, j, k;
226 int16_t ss;
227 u16 idxL = 0, idxR = 0, numPiers;
228 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
229 u8 minPwrT4[AR9287_NUM_PD_GAINS];
230 u8 maxPwrT4[AR9287_NUM_PD_GAINS];
231 int16_t vpdStep;
232 int16_t tmpVal;
233 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
234 bool match;
235 int16_t minDelta = 0;
236 struct chan_centers centers;
237 static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
238 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
239 static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
240 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
241 static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
242 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
243
244 ath9k_hw_get_channel_centers(ah, chan, &centers);
245
246 for (numPiers = 0; numPiers < availPiers; numPiers++) {
247 if (bChans[numPiers] == AR9287_BCHAN_UNUSED)
248 break;
249 }
250
251 match = ath9k_hw_get_lower_upper_index(
252 (u8)FREQ2FBIN(centers.synth_center,
253 IS_CHAN_2GHZ(chan)), bChans, numPiers,
254 &idxL, &idxR);
255
256 if (match) {
257 for (i = 0; i < numXpdGains; i++) {
258 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
259 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
260 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
261 pRawDataSet[idxL].pwrPdg[i],
262 pRawDataSet[idxL].vpdPdg[i],
263 AR9287_PD_GAIN_ICEPTS, vpdTableI[i]);
264 }
265 } else {
266 for (i = 0; i < numXpdGains; i++) {
267 pVpdL = pRawDataSet[idxL].vpdPdg[i];
268 pPwrL = pRawDataSet[idxL].pwrPdg[i];
269 pVpdR = pRawDataSet[idxR].vpdPdg[i];
270 pPwrR = pRawDataSet[idxR].pwrPdg[i];
271
272 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
273
274 maxPwrT4[i] =
275 min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1],
276 pPwrR[AR9287_PD_GAIN_ICEPTS - 1]);
277
278 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
279 pPwrL, pVpdL,
280 AR9287_PD_GAIN_ICEPTS,
281 vpdTableL[i]);
282 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
283 pPwrR, pVpdR,
284 AR9287_PD_GAIN_ICEPTS,
285 vpdTableR[i]);
286
287 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
288 vpdTableI[i][j] =
289 (u8)(ath9k_hw_interpolate((u16)
290 FREQ2FBIN(centers. synth_center,
291 IS_CHAN_2GHZ(chan)),
292 bChans[idxL], bChans[idxR],
293 vpdTableL[i][j], vpdTableR[i][j]));
294 }
295 }
296 }
297 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
298
299 k = 0;
300 for (i = 0; i < numXpdGains; i++) {
301 if (i == (numXpdGains - 1))
302 pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2);
303 else
304 pPdGainBoundaries[i] = (u16)((maxPwrT4[i] +
305 minPwrT4[i+1]) / 4);
306
307 pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER,
308 pPdGainBoundaries[i]);
309
310
311 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
312 minDelta = pPdGainBoundaries[0] - 23;
313 pPdGainBoundaries[0] = 23;
314 } else
315 minDelta = 0;
316
317 if (i == 0) {
318 if (AR_SREV_9280_10_OR_LATER(ah))
319 ss = (int16_t)(0 - (minPwrT4[i] / 2));
320 else
321 ss = 0;
322 } else
323 ss = (int16_t)((pPdGainBoundaries[i-1] -
324 (minPwrT4[i] / 2)) -
325 tPdGainOverlap + 1 + minDelta);
326
327 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
328 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
329 while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) {
330 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
331 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
332 ss++;
333 }
334
335 sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
336 tgtIndex = (u8)(pPdGainBoundaries[i] +
337 tPdGainOverlap - (minPwrT4[i] / 2));
338 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
339 tgtIndex : sizeCurrVpdTable;
340
341 while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1)))
342 pPDADCValues[k++] = vpdTableI[i][ss++];
343
344 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
345 vpdTableI[i][sizeCurrVpdTable - 2]);
346 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
347 if (tgtIndex > maxIndex) {
348 while ((ss <= tgtIndex) &&
349 (k < (AR9287_NUM_PDADC_VALUES - 1))) {
350 tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
351 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
352 255 : tmpVal);
353 ss++;
354 }
355 }
356 }
357
358 while (i < AR9287_PD_GAINS_IN_MASK) {
359 pPdGainBoundaries[i] = pPdGainBoundaries[i-1];
360 i++;
361 }
362
363 while (k < AR9287_NUM_PDADC_VALUES) {
364 pPDADCValues[k] = pPDADCValues[k-1];
365 k++;
366 }
367
368#undef TMP_VAL_VPD_TABLE
369}
370
371static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah,
372 struct ath9k_channel *chan,
373 struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop,
374 u8 *pCalChans, u16 availPiers,
375 int8_t *pPwr)
376{
377 u8 pcdac, i = 0;
378 u16 idxL = 0, idxR = 0, numPiers;
379 bool match;
380 struct chan_centers centers;
381
382 ath9k_hw_get_channel_centers(ah, chan, &centers);
383
384 for (numPiers = 0; numPiers < availPiers; numPiers++) {
385 if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED)
386 break;
387 }
388
389 match = ath9k_hw_get_lower_upper_index(
390 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
391 pCalChans, numPiers,
392 &idxL, &idxR);
393
394 if (match) {
395 pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0];
396 *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0];
397 } else {
398 pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0];
399 *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] +
400 pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
401 }
402
403 while ((pcdac > ah->originalGain[i]) &&
404 (i < (AR9280_TX_GAIN_TABLE_SIZE - 1)))
405 i++;
406}
407
408static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
409 int32_t txPower, u16 chain)
410{
411 u32 tmpVal;
412 u32 a;
413
414 tmpVal = REG_READ(ah, 0xa270);
415 tmpVal = tmpVal & 0xFCFFFFFF;
416 tmpVal = tmpVal | (0x3 << 24);
417 REG_WRITE(ah, 0xa270, tmpVal);
418
419 tmpVal = REG_READ(ah, 0xb270);
420 tmpVal = tmpVal & 0xFCFFFFFF;
421 tmpVal = tmpVal | (0x3 << 24);
422 REG_WRITE(ah, 0xb270, tmpVal);
423
424 if (chain == 0) {
425 tmpVal = REG_READ(ah, 0xa398);
426 tmpVal = tmpVal & 0xff00ffff;
427 a = (txPower)&0xff;
428 tmpVal = tmpVal | (a << 16);
429 REG_WRITE(ah, 0xa398, tmpVal);
430 }
431
432 if (chain == 1) {
433 tmpVal = REG_READ(ah, 0xb398);
434 tmpVal = tmpVal & 0xff00ffff;
435 a = (txPower)&0xff;
436 tmpVal = tmpVal | (a << 16);
437 REG_WRITE(ah, 0xb398, tmpVal);
438 }
439}
440
441static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah,
442 struct ath9k_channel *chan,
443 int16_t *pTxPowerIndexOffset)
444{
445 struct cal_data_per_freq_ar9287 *pRawDataset;
446 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
447 u8 *pCalBChans = NULL;
448 u16 pdGainOverlap_t2;
449 u8 pdadcValues[AR9287_NUM_PDADC_VALUES];
450 u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK];
451 u16 numPiers = 0, i, j;
452 int16_t tMinCalPower;
453 u16 numXpdGain, xpdMask;
454 u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0};
455 u32 reg32, regOffset, regChainOffset;
456 int16_t modalIdx, diff = 0;
457 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
458 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
459 xpdMask = pEepData->modalHeader.xpdGain;
460 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
461 AR9287_EEP_MINOR_VER_2)
462 pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap;
463 else
464 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
465 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
466
467 if (IS_CHAN_2GHZ(chan)) {
468 pCalBChans = pEepData->calFreqPier2G;
469 numPiers = AR9287_NUM_2G_CAL_PIERS;
470 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
471 pRawDatasetOpenLoop =
472 (struct cal_data_op_loop_ar9287 *)
473 pEepData->calPierData2G[0];
474 ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0];
475 }
476 }
477
478 numXpdGain = 0;
479 for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) {
480 if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) {
481 if (numXpdGain >= AR9287_NUM_PD_GAINS)
482 break;
483 xpdGainValues[numXpdGain] =
484 (u16)(AR9287_PD_GAINS_IN_MASK-i);
485 numXpdGain++;
486 }
487 }
488
489 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
490 (numXpdGain - 1) & 0x3);
491 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
492 xpdGainValues[0]);
493 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
494 xpdGainValues[1]);
495 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
496 xpdGainValues[2]);
497
498 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
499 regChainOffset = i * 0x1000;
500 if (pEepData->baseEepHeader.txMask & (1 << i)) {
501 pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *)
502 pEepData->calPierData2G[i];
503 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
504 int8_t txPower;
505 ar9287_eeprom_get_tx_gain_index(ah, chan,
506 pRawDatasetOpenLoop,
507 pCalBChans, numPiers,
508 &txPower);
509 ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i);
510 } else {
511 pRawDataset =
512 (struct cal_data_per_freq_ar9287 *)
513 pEepData->calPierData2G[i];
514 ath9k_hw_get_AR9287_gain_boundaries_pdadcs(
515 ah, chan, pRawDataset,
516 pCalBChans, numPiers,
517 pdGainOverlap_t2,
518 &tMinCalPower, gainBoundaries,
519 pdadcValues, numXpdGain);
520 }
521
522 if (i == 0) {
523 if (!ath9k_hw_AR9287_get_eeprom(
524 ah, EEP_OL_PWRCTRL)) {
525 REG_WRITE(ah, AR_PHY_TPCRG5 +
526 regChainOffset,
527 SM(pdGainOverlap_t2,
528 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
529 SM(gainBoundaries[0],
530 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
531 | SM(gainBoundaries[1],
532 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
533 | SM(gainBoundaries[2],
534 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
535 | SM(gainBoundaries[3],
536 AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
537 }
538 }
539
540 if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB !=
541 pEepData->baseEepHeader.pwrTableOffset) {
542 diff = (u16)
543 (pEepData->baseEepHeader.pwrTableOffset
544 - (int32_t)AR9287_PWR_TABLE_OFFSET_DB);
545 diff *= 2;
546
547 for (j = 0;
548 j < ((u16)AR9287_NUM_PDADC_VALUES-diff);
549 j++)
550 pdadcValues[j] = pdadcValues[j+diff];
551
552 for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff);
553 j < AR9287_NUM_PDADC_VALUES; j++)
554 pdadcValues[j] =
555 pdadcValues[
556 AR9287_NUM_PDADC_VALUES-diff];
557 }
558
559 if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
560 regOffset = AR_PHY_BASE + (672 << 2) +
561 regChainOffset;
562 for (j = 0; j < 32; j++) {
563 reg32 = ((pdadcValues[4*j + 0]
564 & 0xFF) << 0) |
565 ((pdadcValues[4*j + 1]
566 & 0xFF) << 8) |
567 ((pdadcValues[4*j + 2]
568 & 0xFF) << 16) |
569 ((pdadcValues[4*j + 3]
570 & 0xFF) << 24) ;
571 REG_WRITE(ah, regOffset, reg32);
572
573 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
574 "PDADC (%d,%4x): %4.4x %8.8x\n",
575 i, regChainOffset, regOffset,
576 reg32);
577
578 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
579 "PDADC: Chain %d | "
580 "PDADC %3d Value %3d | "
581 "PDADC %3d Value %3d | "
582 "PDADC %3d Value %3d | "
583 "PDADC %3d Value %3d |\n",
584 i, 4 * j, pdadcValues[4 * j],
585 4 * j + 1,
586 pdadcValues[4 * j + 1],
587 4 * j + 2,
588 pdadcValues[4 * j + 2],
589 4 * j + 3,
590 pdadcValues[4 * j + 3]);
591
592 regOffset += 4;
593 }
594 }
595 }
596 }
597
598 *pTxPowerIndexOffset = 0;
599}
600
601static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah,
602 struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl,
603 u16 AntennaReduction, u16 twiceMaxRegulatoryPower,
604 u16 powerLimit)
605{
606#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6
607#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10
608
609 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
610 static const u16 tpScaleReductionTable[5] =
611 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
612 int i;
613 int16_t twiceLargestAntenna;
614 struct cal_ctl_data_ar9287 *rep;
615 struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} },
616 targetPowerCck = {0, {0, 0, 0, 0} };
617 struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} },
618 targetPowerCckExt = {0, {0, 0, 0, 0} };
619 struct cal_target_power_ht targetPowerHt20,
620 targetPowerHt40 = {0, {0, 0, 0, 0} };
621 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
622 u16 ctlModesFor11g[] =
623 {CTL_11B, CTL_11G, CTL_2GHT20,
624 CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40};
625 u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq;
626 struct chan_centers centers;
627 int tx_chainmask;
628 u16 twiceMinEdgePower;
629 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
630 tx_chainmask = ah->txchainmask;
631
632 ath9k_hw_get_channel_centers(ah, chan, &centers);
633
634 twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0],
635 pEepData->modalHeader.antennaGainCh[1]);
636
637 twiceLargestAntenna = (int16_t)min((AntennaReduction) -
638 twiceLargestAntenna, 0);
639
640 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
641 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX)
642 maxRegAllowedPower -=
643 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
644
645 scaledPower = min(powerLimit, maxRegAllowedPower);
646
647 switch (ar5416_get_ntxchains(tx_chainmask)) {
648 case 1:
649 break;
650 case 2:
651 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
652 break;
653 case 3:
654 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
655 break;
656 }
657 scaledPower = max((u16)0, scaledPower);
658
659 if (IS_CHAN_2GHZ(chan)) {
660 numCtlModes =
661 ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
662 pCtlMode = ctlModesFor11g;
663
664 ath9k_hw_get_legacy_target_powers(ah, chan,
665 pEepData->calTargetPowerCck,
666 AR9287_NUM_2G_CCK_TARGET_POWERS,
667 &targetPowerCck, 4, false);
668 ath9k_hw_get_legacy_target_powers(ah, chan,
669 pEepData->calTargetPower2G,
670 AR9287_NUM_2G_20_TARGET_POWERS,
671 &targetPowerOfdm, 4, false);
672 ath9k_hw_get_target_powers(ah, chan,
673 pEepData->calTargetPower2GHT20,
674 AR9287_NUM_2G_20_TARGET_POWERS,
675 &targetPowerHt20, 8, false);
676
677 if (IS_CHAN_HT40(chan)) {
678 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
679 ath9k_hw_get_target_powers(ah, chan,
680 pEepData->calTargetPower2GHT40,
681 AR9287_NUM_2G_40_TARGET_POWERS,
682 &targetPowerHt40, 8, true);
683 ath9k_hw_get_legacy_target_powers(ah, chan,
684 pEepData->calTargetPowerCck,
685 AR9287_NUM_2G_CCK_TARGET_POWERS,
686 &targetPowerCckExt, 4, true);
687 ath9k_hw_get_legacy_target_powers(ah, chan,
688 pEepData->calTargetPower2G,
689 AR9287_NUM_2G_20_TARGET_POWERS,
690 &targetPowerOfdmExt, 4, true);
691 }
692 }
693
694 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
695 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
696 (pCtlMode[ctlMode] == CTL_2GHT40);
697 if (isHt40CtlMode)
698 freq = centers.synth_center;
699 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
700 freq = centers.ext_center;
701 else
702 freq = centers.ctl_center;
703
704 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
705 ah->eep_ops->get_eeprom_rev(ah) <= 2)
706 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
707
708 for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
709 if ((((cfgCtl & ~CTL_MODE_M) |
710 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
711 pEepData->ctlIndex[i]) ||
712 (((cfgCtl & ~CTL_MODE_M) |
713 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
714 ((pEepData->ctlIndex[i] &
715 CTL_MODE_M) | SD_NO_CTL))) {
716
717 rep = &(pEepData->ctlData[i]);
718 twiceMinEdgePower = ath9k_hw_get_max_edge_power(
719 freq,
720 rep->ctlEdges[ar5416_get_ntxchains(
721 tx_chainmask) - 1],
722 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
723
724 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL)
725 twiceMaxEdgePower = min(
726 twiceMaxEdgePower,
727 twiceMinEdgePower);
728 else {
729 twiceMaxEdgePower = twiceMinEdgePower;
730 break;
731 }
732 }
733 }
734
735 minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
736
737 switch (pCtlMode[ctlMode]) {
738 case CTL_11B:
739 for (i = 0;
740 i < ARRAY_SIZE(targetPowerCck.tPow2x);
741 i++) {
742 targetPowerCck.tPow2x[i] = (u8)min(
743 (u16)targetPowerCck.tPow2x[i],
744 minCtlPower);
745 }
746 break;
747 case CTL_11A:
748 case CTL_11G:
749 for (i = 0;
750 i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
751 i++) {
752 targetPowerOfdm.tPow2x[i] = (u8)min(
753 (u16)targetPowerOfdm.tPow2x[i],
754 minCtlPower);
755 }
756 break;
757 case CTL_5GHT20:
758 case CTL_2GHT20:
759 for (i = 0;
760 i < ARRAY_SIZE(targetPowerHt20.tPow2x);
761 i++) {
762 targetPowerHt20.tPow2x[i] = (u8)min(
763 (u16)targetPowerHt20.tPow2x[i],
764 minCtlPower);
765 }
766 break;
767 case CTL_11B_EXT:
768 targetPowerCckExt.tPow2x[0] = (u8)min(
769 (u16)targetPowerCckExt.tPow2x[0],
770 minCtlPower);
771 break;
772 case CTL_11A_EXT:
773 case CTL_11G_EXT:
774 targetPowerOfdmExt.tPow2x[0] = (u8)min(
775 (u16)targetPowerOfdmExt.tPow2x[0],
776 minCtlPower);
777 break;
778 case CTL_5GHT40:
779 case CTL_2GHT40:
780 for (i = 0;
781 i < ARRAY_SIZE(targetPowerHt40.tPow2x);
782 i++) {
783 targetPowerHt40.tPow2x[i] = (u8)min(
784 (u16)targetPowerHt40.tPow2x[i],
785 minCtlPower);
786 }
787 break;
788 default:
789 break;
790 }
791 }
792
793 ratesArray[rate6mb] =
794 ratesArray[rate9mb] =
795 ratesArray[rate12mb] =
796 ratesArray[rate18mb] =
797 ratesArray[rate24mb] =
798 targetPowerOfdm.tPow2x[0];
799
800 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
801 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
802 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
803 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
804
805 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
806 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
807
808 if (IS_CHAN_2GHZ(chan)) {
809 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
810 ratesArray[rate2s] = ratesArray[rate2l] =
811 targetPowerCck.tPow2x[1];
812 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
813 targetPowerCck.tPow2x[2];
814 ratesArray[rate11s] = ratesArray[rate11l] =
815 targetPowerCck.tPow2x[3];
816 }
817 if (IS_CHAN_HT40(chan)) {
818 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++)
819 ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i];
820
821 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
822 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
823 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
824 if (IS_CHAN_2GHZ(chan))
825 ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
826 }
827
828#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN
829#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN
830}
831
832static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah,
833 struct ath9k_channel *chan, u16 cfgCtl,
834 u8 twiceAntennaReduction,
835 u8 twiceMaxRegulatoryPower,
836 u8 powerLimit)
837{
838#define INCREASE_MAXPOW_BY_TWO_CHAIN 6
839#define INCREASE_MAXPOW_BY_THREE_CHAIN 10
840
841 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
842 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
843 int16_t ratesArray[Ar5416RateSize];
844 int16_t txPowerIndexOffset = 0;
845 u8 ht40PowerIncForPdadc = 2;
846 int i;
847
848 memset(ratesArray, 0, sizeof(ratesArray));
849
850 if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >=
851 AR9287_EEP_MINOR_VER_2)
852 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
853
854 ath9k_hw_set_AR9287_power_per_rate_table(ah, chan,
855 &ratesArray[0], cfgCtl,
856 twiceAntennaReduction,
857 twiceMaxRegulatoryPower,
858 powerLimit);
859
860 ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset);
861
862 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
863 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
864 if (ratesArray[i] > AR9287_MAX_RATE_POWER)
865 ratesArray[i] = AR9287_MAX_RATE_POWER;
866 }
867
868 if (AR_SREV_9280_10_OR_LATER(ah)) {
869 for (i = 0; i < Ar5416RateSize; i++)
870 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
871 }
872
873 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
874 ATH9K_POW_SM(ratesArray[rate18mb], 24)
875 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
876 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
877 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
878
879 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
880 ATH9K_POW_SM(ratesArray[rate54mb], 24)
881 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
882 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
883 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
884
885 if (IS_CHAN_2GHZ(chan)) {
886 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
887 ATH9K_POW_SM(ratesArray[rate2s], 24)
888 | ATH9K_POW_SM(ratesArray[rate2l], 16)
889 | ATH9K_POW_SM(ratesArray[rateXr], 8)
890 | ATH9K_POW_SM(ratesArray[rate1l], 0));
891 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
892 ATH9K_POW_SM(ratesArray[rate11s], 24)
893 | ATH9K_POW_SM(ratesArray[rate11l], 16)
894 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
895 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
896 }
897
898 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
899 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
900 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
901 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
902 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
903
904 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
905 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
906 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
907 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
908 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
909
910 if (IS_CHAN_HT40(chan)) {
911 if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) {
912 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
913 ATH9K_POW_SM(ratesArray[rateHt40_3], 24)
914 | ATH9K_POW_SM(ratesArray[rateHt40_2], 16)
915 | ATH9K_POW_SM(ratesArray[rateHt40_1], 8)
916 | ATH9K_POW_SM(ratesArray[rateHt40_0], 0));
917
918 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
919 ATH9K_POW_SM(ratesArray[rateHt40_7], 24)
920 | ATH9K_POW_SM(ratesArray[rateHt40_6], 16)
921 | ATH9K_POW_SM(ratesArray[rateHt40_5], 8)
922 | ATH9K_POW_SM(ratesArray[rateHt40_4], 0));
923 } else {
924 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
925 ATH9K_POW_SM(ratesArray[rateHt40_3] +
926 ht40PowerIncForPdadc, 24)
927 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
928 ht40PowerIncForPdadc, 16)
929 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
930 ht40PowerIncForPdadc, 8)
931 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
932 ht40PowerIncForPdadc, 0));
933
934 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
935 ATH9K_POW_SM(ratesArray[rateHt40_7] +
936 ht40PowerIncForPdadc, 24)
937 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
938 ht40PowerIncForPdadc, 16)
939 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
940 ht40PowerIncForPdadc, 8)
941 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
942 ht40PowerIncForPdadc, 0));
943 }
944
945 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
946 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
947 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
948 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
949 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
950 }
951
952 if (IS_CHAN_2GHZ(chan))
953 i = rate1l;
954 else
955 i = rate6mb;
956
957 if (AR_SREV_9280_10_OR_LATER(ah))
958 ah->regulatory.max_power_level =
959 ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
960 else
961 ah->regulatory.max_power_level = ratesArray[i];
962
963 switch (ar5416_get_ntxchains(ah->txchainmask)) {
964 case 1:
965 break;
966 case 2:
967 ah->regulatory.max_power_level +=
968 INCREASE_MAXPOW_BY_TWO_CHAIN;
969 break;
970 case 3:
971 ah->regulatory.max_power_level +=
972 INCREASE_MAXPOW_BY_THREE_CHAIN;
973 break;
974 default:
975 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
976 "Invalid chainmask configuration\n");
977 break;
978 }
979}
980
981static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah,
982 struct ath9k_channel *chan)
983{
984}
985
986static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah,
987 struct ath9k_channel *chan)
988{
989 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
990 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
991 u16 antWrites[AR9287_ANT_16S];
992 u32 regChainOffset;
993 u8 txRxAttenLocal;
994 int i, j, offset_num;
995
996 pModal = &eep->modalHeader;
997
998 antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF);
999 antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF);
1000 antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF);
1001 antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF);
1002 antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF);
1003 antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF);
1004 antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF);
1005 antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF);
1006
1007 offset_num = 8;
1008
1009 for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) {
1010 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf);
1011 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3);
1012 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3);
1013 antWrites[j++] = 0;
1014 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3);
1015 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3);
1016 antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3);
1017 antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3);
1018 }
1019
1020 REG_WRITE(ah, AR_PHY_SWITCH_COM,
1021 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
1022
1023 for (i = 0; i < AR9287_MAX_CHAINS; i++) {
1024 regChainOffset = i * 0x1000;
1025
1026 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
1027 pModal->antCtrlChain[i]);
1028
1029 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
1030 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset)
1031 & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
1032 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
1033 SM(pModal->iqCalICh[i],
1034 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
1035 SM(pModal->iqCalQCh[i],
1036 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
1037
1038 txRxAttenLocal = pModal->txRxAttenCh[i];
1039
1040 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1041 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
1042 pModal->bswMargin[i]);
1043 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
1044 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
1045 pModal->bswAtten[i]);
1046 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1047 AR9280_PHY_RXGAIN_TXRX_ATTEN,
1048 txRxAttenLocal);
1049 REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
1050 AR9280_PHY_RXGAIN_TXRX_MARGIN,
1051 pModal->rxTxMarginCh[i]);
1052 }
1053
1054
1055 if (IS_CHAN_HT40(chan))
1056 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1057 AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40);
1058 else
1059 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
1060 AR_PHY_SETTLING_SWITCH, pModal->switchSettling);
1061
1062 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
1063 AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize);
1064
1065 REG_WRITE(ah, AR_PHY_RF_CTL4,
1066 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
1067 | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
1068 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON)
1069 | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
1070
1071 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3,
1072 AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn);
1073
1074 REG_RMW_FIELD(ah, AR_PHY_CCA,
1075 AR9280_PHY_CCA_THRESH62, pModal->thresh62);
1076 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
1077 AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62);
1078
1079 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1,
1080 AR9287_AN_RF2G3_DB1_S, pModal->db1);
1081 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2,
1082 AR9287_AN_RF2G3_DB2_S, pModal->db2);
1083 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1084 AR9287_AN_RF2G3_OB_CCK,
1085 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
1086 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1087 AR9287_AN_RF2G3_OB_PSK,
1088 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
1089 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1090 AR9287_AN_RF2G3_OB_QAM,
1091 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
1092 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0,
1093 AR9287_AN_RF2G3_OB_PAL_OFF,
1094 AR9287_AN_RF2G3_OB_PAL_OFF_S,
1095 pModal->ob_pal_off);
1096
1097 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1098 AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S,
1099 pModal->db1);
1100 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2,
1101 AR9287_AN_RF2G3_DB2_S, pModal->db2);
1102 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1103 AR9287_AN_RF2G3_OB_CCK,
1104 AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck);
1105 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1106 AR9287_AN_RF2G3_OB_PSK,
1107 AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk);
1108 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1109 AR9287_AN_RF2G3_OB_QAM,
1110 AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam);
1111 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1,
1112 AR9287_AN_RF2G3_OB_PAL_OFF,
1113 AR9287_AN_RF2G3_OB_PAL_OFF_S,
1114 pModal->ob_pal_off);
1115
1116 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1117 AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart);
1118 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
1119 AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn);
1120
1121 ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2,
1122 AR9287_AN_TOP2_XPABIAS_LVL,
1123 AR9287_AN_TOP2_XPABIAS_LVL_S,
1124 pModal->xpaBiasLvl);
1125}
1126
1127static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah,
1128 enum ieee80211_band freq_band)
1129{
1130 return 1;
1131}
1132
1133static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah,
1134 struct ath9k_channel *chan)
1135{
1136 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
1137 struct modal_eep_ar9287_header *pModal = &eep->modalHeader;
1138
1139 return pModal->antCtrlCommon & 0xFFFF;
1140}
1141
1142static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah,
1143 u16 i, bool is2GHz)
1144{
1145#define EEP_MAP9287_SPURCHAN \
1146 (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan)
1147 u16 spur_val = AR_NO_SPUR;
1148
1149 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1150 "Getting spur idx %d is2Ghz. %d val %x\n",
1151 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1152
1153 switch (ah->config.spurmode) {
1154 case SPUR_DISABLE:
1155 break;
1156 case SPUR_ENABLE_IOCTL:
1157 spur_val = ah->config.spurchans[i][is2GHz];
1158 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1159 "Getting spur val from new loc. %d\n", spur_val);
1160 break;
1161 case SPUR_ENABLE_EEPROM:
1162 spur_val = EEP_MAP9287_SPURCHAN;
1163 break;
1164 }
1165
1166 return spur_val;
1167
1168#undef EEP_MAP9287_SPURCHAN
1169}
1170
1171const struct eeprom_ops eep_AR9287_ops = {
1172 .check_eeprom = ath9k_hw_AR9287_check_eeprom,
1173 .get_eeprom = ath9k_hw_AR9287_get_eeprom,
1174 .fill_eeprom = ath9k_hw_AR9287_fill_eeprom,
1175 .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver,
1176 .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev,
1177 .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config,
1178 .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg,
1179 .set_board_values = ath9k_hw_AR9287_set_board_values,
1180 .set_addac = ath9k_hw_AR9287_set_addac,
1181 .set_txpower = ath9k_hw_AR9287_set_txpower,
1182 .get_spur_channel = ath9k_hw_AR9287_get_spur_channel
1183};
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
new file mode 100644
index 000000000000..5211ad94c8fb
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -0,0 +1,1385 @@
1/*
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "ath9k.h"
18
19static void ath9k_get_txgain_index(struct ath_hw *ah,
20 struct ath9k_channel *chan,
21 struct calDataPerFreqOpLoop *rawDatasetOpLoop,
22 u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx)
23{
24 u8 pcdac, i = 0;
25 u16 idxL = 0, idxR = 0, numPiers;
26 bool match;
27 struct chan_centers centers;
28
29 ath9k_hw_get_channel_centers(ah, chan, &centers);
30
31 for (numPiers = 0; numPiers < availPiers; numPiers++)
32 if (calChans[numPiers] == AR5416_BCHAN_UNUSED)
33 break;
34
35 match = ath9k_hw_get_lower_upper_index(
36 (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)),
37 calChans, numPiers, &idxL, &idxR);
38 if (match) {
39 pcdac = rawDatasetOpLoop[idxL].pcdac[0][0];
40 *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0];
41 } else {
42 pcdac = rawDatasetOpLoop[idxR].pcdac[0][0];
43 *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] +
44 rawDatasetOpLoop[idxR].pwrPdg[0][0])/2;
45 }
46
47 while (pcdac > ah->originalGain[i] &&
48 i < (AR9280_TX_GAIN_TABLE_SIZE - 1))
49 i++;
50
51 *pcdacIdx = i;
52 return;
53}
54
55static void ath9k_olc_get_pdadcs(struct ath_hw *ah,
56 u32 initTxGain,
57 int txPower,
58 u8 *pPDADCValues)
59{
60 u32 i;
61 u32 offset;
62
63 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0,
64 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
65 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1,
66 AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3);
67
68 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7,
69 AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain);
70
71 offset = txPower;
72 for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++)
73 if (i < offset)
74 pPDADCValues[i] = 0x0;
75 else
76 pPDADCValues[i] = 0xFF;
77}
78
79static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah)
80{
81 return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF);
82}
83
84static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah)
85{
86 return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF);
87}
88
89static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
90{
91#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
92 u16 *eep_data = (u16 *)&ah->eeprom.def;
93 int addr, ar5416_eep_start_loc = 0x100;
94
95 for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
96 if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
97 eep_data)) {
98 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
99 "Unable to read eeprom region\n");
100 return false;
101 }
102 eep_data++;
103 }
104 return true;
105#undef SIZE_EEPROM_DEF
106}
107
108static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
109{
110 struct ar5416_eeprom_def *eep =
111 (struct ar5416_eeprom_def *) &ah->eeprom.def;
112 u16 *eepdata, temp, magic, magic2;
113 u32 sum = 0, el;
114 bool need_swap = false;
115 int i, addr, size;
116
117 if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
118 DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n");
119 return false;
120 }
121
122 if (!ath9k_hw_use_flash(ah)) {
123 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
124 "Read Magic = 0x%04X\n", magic);
125
126 if (magic != AR5416_EEPROM_MAGIC) {
127 magic2 = swab16(magic);
128
129 if (magic2 == AR5416_EEPROM_MAGIC) {
130 size = sizeof(struct ar5416_eeprom_def);
131 need_swap = true;
132 eepdata = (u16 *) (&ah->eeprom);
133
134 for (addr = 0; addr < size / sizeof(u16); addr++) {
135 temp = swab16(*eepdata);
136 *eepdata = temp;
137 eepdata++;
138 }
139 } else {
140 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
141 "Invalid EEPROM Magic. "
142 "Endianness mismatch.\n");
143 return -EINVAL;
144 }
145 }
146 }
147
148 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
149 need_swap ? "True" : "False");
150
151 if (need_swap)
152 el = swab16(ah->eeprom.def.baseEepHeader.length);
153 else
154 el = ah->eeprom.def.baseEepHeader.length;
155
156 if (el > sizeof(struct ar5416_eeprom_def))
157 el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
158 else
159 el = el / sizeof(u16);
160
161 eepdata = (u16 *)(&ah->eeprom);
162
163 for (i = 0; i < el; i++)
164 sum ^= *eepdata++;
165
166 if (need_swap) {
167 u32 integer, j;
168 u16 word;
169
170 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
171 "EEPROM Endianness is not native.. Changing.\n");
172
173 word = swab16(eep->baseEepHeader.length);
174 eep->baseEepHeader.length = word;
175
176 word = swab16(eep->baseEepHeader.checksum);
177 eep->baseEepHeader.checksum = word;
178
179 word = swab16(eep->baseEepHeader.version);
180 eep->baseEepHeader.version = word;
181
182 word = swab16(eep->baseEepHeader.regDmn[0]);
183 eep->baseEepHeader.regDmn[0] = word;
184
185 word = swab16(eep->baseEepHeader.regDmn[1]);
186 eep->baseEepHeader.regDmn[1] = word;
187
188 word = swab16(eep->baseEepHeader.rfSilent);
189 eep->baseEepHeader.rfSilent = word;
190
191 word = swab16(eep->baseEepHeader.blueToothOptions);
192 eep->baseEepHeader.blueToothOptions = word;
193
194 word = swab16(eep->baseEepHeader.deviceCap);
195 eep->baseEepHeader.deviceCap = word;
196
197 for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
198 struct modal_eep_header *pModal =
199 &eep->modalHeader[j];
200 integer = swab32(pModal->antCtrlCommon);
201 pModal->antCtrlCommon = integer;
202
203 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
204 integer = swab32(pModal->antCtrlChain[i]);
205 pModal->antCtrlChain[i] = integer;
206 }
207
208 for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
209 word = swab16(pModal->spurChans[i].spurChan);
210 pModal->spurChans[i].spurChan = word;
211 }
212 }
213 }
214
215 if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
216 ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
217 DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
218 "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
219 sum, ah->eep_ops->get_eeprom_ver(ah));
220 return -EINVAL;
221 }
222
223 return 0;
224}
225
226static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
227 enum eeprom_param param)
228{
229 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
230 struct modal_eep_header *pModal = eep->modalHeader;
231 struct base_eep_header *pBase = &eep->baseEepHeader;
232
233 switch (param) {
234 case EEP_NFTHRESH_5:
235 return pModal[0].noiseFloorThreshCh[0];
236 case EEP_NFTHRESH_2:
237 return pModal[1].noiseFloorThreshCh[0];
238 case AR_EEPROM_MAC(0):
239 return pBase->macAddr[0] << 8 | pBase->macAddr[1];
240 case AR_EEPROM_MAC(1):
241 return pBase->macAddr[2] << 8 | pBase->macAddr[3];
242 case AR_EEPROM_MAC(2):
243 return pBase->macAddr[4] << 8 | pBase->macAddr[5];
244 case EEP_REG_0:
245 return pBase->regDmn[0];
246 case EEP_REG_1:
247 return pBase->regDmn[1];
248 case EEP_OP_CAP:
249 return pBase->deviceCap;
250 case EEP_OP_MODE:
251 return pBase->opCapFlags;
252 case EEP_RF_SILENT:
253 return pBase->rfSilent;
254 case EEP_OB_5:
255 return pModal[0].ob;
256 case EEP_DB_5:
257 return pModal[0].db;
258 case EEP_OB_2:
259 return pModal[1].ob;
260 case EEP_DB_2:
261 return pModal[1].db;
262 case EEP_MINOR_REV:
263 return AR5416_VER_MASK;
264 case EEP_TX_MASK:
265 return pBase->txMask;
266 case EEP_RX_MASK:
267 return pBase->rxMask;
268 case EEP_RXGAIN_TYPE:
269 return pBase->rxGainType;
270 case EEP_TXGAIN_TYPE:
271 return pBase->txGainType;
272 case EEP_OL_PWRCTRL:
273 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
274 return pBase->openLoopPwrCntl ? true : false;
275 else
276 return false;
277 case EEP_RC_CHAIN_MASK:
278 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
279 return pBase->rcChainMask;
280 else
281 return 0;
282 case EEP_DAC_HPWR_5G:
283 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20)
284 return pBase->dacHiPwrMode_5G;
285 else
286 return 0;
287 case EEP_FRAC_N_5G:
288 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22)
289 return pBase->frac_n_5g;
290 else
291 return 0;
292 default:
293 return 0;
294 }
295}
296
297static void ath9k_hw_def_set_gain(struct ath_hw *ah,
298 struct modal_eep_header *pModal,
299 struct ar5416_eeprom_def *eep,
300 u8 txRxAttenLocal, int regChainOffset, int i)
301{
302 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
303 txRxAttenLocal = pModal->txRxAttenCh[i];
304
305 if (AR_SREV_9280_10_OR_LATER(ah)) {
306 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
307 AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
308 pModal->bswMargin[i]);
309 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
310 AR_PHY_GAIN_2GHZ_XATTEN1_DB,
311 pModal->bswAtten[i]);
312 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
313 AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
314 pModal->xatten2Margin[i]);
315 REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
316 AR_PHY_GAIN_2GHZ_XATTEN2_DB,
317 pModal->xatten2Db[i]);
318 } else {
319 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
320 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
321 ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
322 | SM(pModal-> bswMargin[i],
323 AR_PHY_GAIN_2GHZ_BSW_MARGIN));
324 REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
325 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
326 ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
327 | SM(pModal->bswAtten[i],
328 AR_PHY_GAIN_2GHZ_BSW_ATTEN));
329 }
330 }
331
332 if (AR_SREV_9280_10_OR_LATER(ah)) {
333 REG_RMW_FIELD(ah,
334 AR_PHY_RXGAIN + regChainOffset,
335 AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
336 REG_RMW_FIELD(ah,
337 AR_PHY_RXGAIN + regChainOffset,
338 AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]);
339 } else {
340 REG_WRITE(ah,
341 AR_PHY_RXGAIN + regChainOffset,
342 (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) &
343 ~AR_PHY_RXGAIN_TXRX_ATTEN)
344 | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN));
345 REG_WRITE(ah,
346 AR_PHY_GAIN_2GHZ + regChainOffset,
347 (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) &
348 ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
349 SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
350 }
351}
352
353static void ath9k_hw_def_set_board_values(struct ath_hw *ah,
354 struct ath9k_channel *chan)
355{
356 struct modal_eep_header *pModal;
357 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
358 int i, regChainOffset;
359 u8 txRxAttenLocal;
360
361 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
362 txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
363
364 REG_WRITE(ah, AR_PHY_SWITCH_COM,
365 ah->eep_ops->get_eeprom_antenna_cfg(ah, chan));
366
367 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
368 if (AR_SREV_9280(ah)) {
369 if (i >= 2)
370 break;
371 }
372
373 if (AR_SREV_5416_20_OR_LATER(ah) &&
374 (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0))
375 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
376 else
377 regChainOffset = i * 0x1000;
378
379 REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
380 pModal->antCtrlChain[i]);
381
382 REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
383 (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
384 ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
385 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
386 SM(pModal->iqCalICh[i],
387 AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
388 SM(pModal->iqCalQCh[i],
389 AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
390
391 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah))
392 ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal,
393 regChainOffset, i);
394 }
395
396 if (AR_SREV_9280_10_OR_LATER(ah)) {
397 if (IS_CHAN_2GHZ(chan)) {
398 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
399 AR_AN_RF2G1_CH0_OB,
400 AR_AN_RF2G1_CH0_OB_S,
401 pModal->ob);
402 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
403 AR_AN_RF2G1_CH0_DB,
404 AR_AN_RF2G1_CH0_DB_S,
405 pModal->db);
406 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
407 AR_AN_RF2G1_CH1_OB,
408 AR_AN_RF2G1_CH1_OB_S,
409 pModal->ob_ch1);
410 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
411 AR_AN_RF2G1_CH1_DB,
412 AR_AN_RF2G1_CH1_DB_S,
413 pModal->db_ch1);
414 } else {
415 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
416 AR_AN_RF5G1_CH0_OB5,
417 AR_AN_RF5G1_CH0_OB5_S,
418 pModal->ob);
419 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
420 AR_AN_RF5G1_CH0_DB5,
421 AR_AN_RF5G1_CH0_DB5_S,
422 pModal->db);
423 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
424 AR_AN_RF5G1_CH1_OB5,
425 AR_AN_RF5G1_CH1_OB5_S,
426 pModal->ob_ch1);
427 ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
428 AR_AN_RF5G1_CH1_DB5,
429 AR_AN_RF5G1_CH1_DB5_S,
430 pModal->db_ch1);
431 }
432 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
433 AR_AN_TOP2_XPABIAS_LVL,
434 AR_AN_TOP2_XPABIAS_LVL_S,
435 pModal->xpaBiasLvl);
436 ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
437 AR_AN_TOP2_LOCALBIAS,
438 AR_AN_TOP2_LOCALBIAS_S,
439 pModal->local_bias);
440 REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
441 pModal->force_xpaon);
442 }
443
444 REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
445 pModal->switchSettling);
446 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
447 pModal->adcDesiredSize);
448
449 if (!AR_SREV_9280_10_OR_LATER(ah))
450 REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
451 AR_PHY_DESIRED_SZ_PGA,
452 pModal->pgaDesiredSize);
453
454 REG_WRITE(ah, AR_PHY_RF_CTL4,
455 SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
456 | SM(pModal->txEndToXpaOff,
457 AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
458 | SM(pModal->txFrameToXpaOn,
459 AR_PHY_RF_CTL4_FRAME_XPAA_ON)
460 | SM(pModal->txFrameToXpaOn,
461 AR_PHY_RF_CTL4_FRAME_XPAB_ON));
462
463 REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
464 pModal->txEndToRxOn);
465
466 if (AR_SREV_9280_10_OR_LATER(ah)) {
467 REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
468 pModal->thresh62);
469 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
470 AR_PHY_EXT_CCA0_THRESH62,
471 pModal->thresh62);
472 } else {
473 REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
474 pModal->thresh62);
475 REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
476 AR_PHY_EXT_CCA_THRESH62,
477 pModal->thresh62);
478 }
479
480 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
481 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
482 AR_PHY_TX_END_DATA_START,
483 pModal->txFrameToDataStart);
484 REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
485 pModal->txFrameToPaOn);
486 }
487
488 if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) {
489 if (IS_CHAN_HT40(chan))
490 REG_RMW_FIELD(ah, AR_PHY_SETTLING,
491 AR_PHY_SETTLING_SWITCH,
492 pModal->swSettleHt40);
493 }
494
495 if (AR_SREV_9280_20_OR_LATER(ah) &&
496 AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19)
497 REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL,
498 AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK,
499 pModal->miscBits);
500
501
502 if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) {
503 if (IS_CHAN_2GHZ(chan))
504 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
505 eep->baseEepHeader.dacLpMode);
506 else if (eep->baseEepHeader.dacHiPwrMode_5G)
507 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0);
508 else
509 REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE,
510 eep->baseEepHeader.dacLpMode);
511
512 REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP,
513 pModal->miscBits >> 2);
514
515 REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9,
516 AR_PHY_TX_DESIRED_SCALE_CCK,
517 eep->baseEepHeader.desiredScaleCCK);
518 }
519}
520
521static void ath9k_hw_def_set_addac(struct ath_hw *ah,
522 struct ath9k_channel *chan)
523{
524#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
525 struct modal_eep_header *pModal;
526 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
527 u8 biaslevel;
528
529 if (ah->hw_version.macVersion != AR_SREV_VERSION_9160)
530 return;
531
532 if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7)
533 return;
534
535 pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
536
537 if (pModal->xpaBiasLvl != 0xff) {
538 biaslevel = pModal->xpaBiasLvl;
539 } else {
540 u16 resetFreqBin, freqBin, freqCount = 0;
541 struct chan_centers centers;
542
543 ath9k_hw_get_channel_centers(ah, chan, &centers);
544
545 resetFreqBin = FREQ2FBIN(centers.synth_center,
546 IS_CHAN_2GHZ(chan));
547 freqBin = XPA_LVL_FREQ(0) & 0xff;
548 biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
549
550 freqCount++;
551
552 while (freqCount < 3) {
553 if (XPA_LVL_FREQ(freqCount) == 0x0)
554 break;
555
556 freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
557 if (resetFreqBin >= freqBin)
558 biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
559 else
560 break;
561 freqCount++;
562 }
563 }
564
565 if (IS_CHAN_2GHZ(chan)) {
566 INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac,
567 7, 1) & (~0x18)) | biaslevel << 3;
568 } else {
569 INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac,
570 6, 1) & (~0xc0)) | biaslevel << 6;
571 }
572#undef XPA_LVL_FREQ
573}
574
575static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah,
576 struct ath9k_channel *chan,
577 struct cal_data_per_freq *pRawDataSet,
578 u8 *bChans, u16 availPiers,
579 u16 tPdGainOverlap, int16_t *pMinCalPower,
580 u16 *pPdGainBoundaries, u8 *pPDADCValues,
581 u16 numXpdGains)
582{
583 int i, j, k;
584 int16_t ss;
585 u16 idxL = 0, idxR = 0, numPiers;
586 static u8 vpdTableL[AR5416_NUM_PD_GAINS]
587 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
588 static u8 vpdTableR[AR5416_NUM_PD_GAINS]
589 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
590 static u8 vpdTableI[AR5416_NUM_PD_GAINS]
591 [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
592
593 u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
594 u8 minPwrT4[AR5416_NUM_PD_GAINS];
595 u8 maxPwrT4[AR5416_NUM_PD_GAINS];
596 int16_t vpdStep;
597 int16_t tmpVal;
598 u16 sizeCurrVpdTable, maxIndex, tgtIndex;
599 bool match;
600 int16_t minDelta = 0;
601 struct chan_centers centers;
602
603 ath9k_hw_get_channel_centers(ah, chan, &centers);
604
605 for (numPiers = 0; numPiers < availPiers; numPiers++) {
606 if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
607 break;
608 }
609
610 match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
611 IS_CHAN_2GHZ(chan)),
612 bChans, numPiers, &idxL, &idxR);
613
614 if (match) {
615 for (i = 0; i < numXpdGains; i++) {
616 minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
617 maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
618 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
619 pRawDataSet[idxL].pwrPdg[i],
620 pRawDataSet[idxL].vpdPdg[i],
621 AR5416_PD_GAIN_ICEPTS,
622 vpdTableI[i]);
623 }
624 } else {
625 for (i = 0; i < numXpdGains; i++) {
626 pVpdL = pRawDataSet[idxL].vpdPdg[i];
627 pPwrL = pRawDataSet[idxL].pwrPdg[i];
628 pVpdR = pRawDataSet[idxR].vpdPdg[i];
629 pPwrR = pRawDataSet[idxR].pwrPdg[i];
630
631 minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
632
633 maxPwrT4[i] =
634 min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
635 pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
636
637
638 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
639 pPwrL, pVpdL,
640 AR5416_PD_GAIN_ICEPTS,
641 vpdTableL[i]);
642 ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
643 pPwrR, pVpdR,
644 AR5416_PD_GAIN_ICEPTS,
645 vpdTableR[i]);
646
647 for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
648 vpdTableI[i][j] =
649 (u8)(ath9k_hw_interpolate((u16)
650 FREQ2FBIN(centers.
651 synth_center,
652 IS_CHAN_2GHZ
653 (chan)),
654 bChans[idxL], bChans[idxR],
655 vpdTableL[i][j], vpdTableR[i][j]));
656 }
657 }
658 }
659
660 *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
661
662 k = 0;
663
664 for (i = 0; i < numXpdGains; i++) {
665 if (i == (numXpdGains - 1))
666 pPdGainBoundaries[i] =
667 (u16)(maxPwrT4[i] / 2);
668 else
669 pPdGainBoundaries[i] =
670 (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
671
672 pPdGainBoundaries[i] =
673 min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
674
675 if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) {
676 minDelta = pPdGainBoundaries[0] - 23;
677 pPdGainBoundaries[0] = 23;
678 } else {
679 minDelta = 0;
680 }
681
682 if (i == 0) {
683 if (AR_SREV_9280_10_OR_LATER(ah))
684 ss = (int16_t)(0 - (minPwrT4[i] / 2));
685 else
686 ss = 0;
687 } else {
688 ss = (int16_t)((pPdGainBoundaries[i - 1] -
689 (minPwrT4[i] / 2)) -
690 tPdGainOverlap + 1 + minDelta);
691 }
692 vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
693 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
694
695 while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
696 tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
697 pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
698 ss++;
699 }
700
701 sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
702 tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
703 (minPwrT4[i] / 2));
704 maxIndex = (tgtIndex < sizeCurrVpdTable) ?
705 tgtIndex : sizeCurrVpdTable;
706
707 while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
708 pPDADCValues[k++] = vpdTableI[i][ss++];
709 }
710
711 vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
712 vpdTableI[i][sizeCurrVpdTable - 2]);
713 vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
714
715 if (tgtIndex > maxIndex) {
716 while ((ss <= tgtIndex) &&
717 (k < (AR5416_NUM_PDADC_VALUES - 1))) {
718 tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
719 (ss - maxIndex + 1) * vpdStep));
720 pPDADCValues[k++] = (u8)((tmpVal > 255) ?
721 255 : tmpVal);
722 ss++;
723 }
724 }
725 }
726
727 while (i < AR5416_PD_GAINS_IN_MASK) {
728 pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
729 i++;
730 }
731
732 while (k < AR5416_NUM_PDADC_VALUES) {
733 pPDADCValues[k] = pPDADCValues[k - 1];
734 k++;
735 }
736
737 return;
738}
739
740static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
741 struct ath9k_channel *chan,
742 int16_t *pTxPowerIndexOffset)
743{
744#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
745#define SM_PDGAIN_B(x, y) \
746 SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y)
747
748 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
749 struct cal_data_per_freq *pRawDataset;
750 u8 *pCalBChans = NULL;
751 u16 pdGainOverlap_t2;
752 static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
753 u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
754 u16 numPiers, i, j;
755 int16_t tMinCalPower;
756 u16 numXpdGain, xpdMask;
757 u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
758 u32 reg32, regOffset, regChainOffset;
759 int16_t modalIdx;
760
761 modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
762 xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
763
764 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
765 AR5416_EEP_MINOR_VER_2) {
766 pdGainOverlap_t2 =
767 pEepData->modalHeader[modalIdx].pdGainOverlap;
768 } else {
769 pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
770 AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
771 }
772
773 if (IS_CHAN_2GHZ(chan)) {
774 pCalBChans = pEepData->calFreqPier2G;
775 numPiers = AR5416_NUM_2G_CAL_PIERS;
776 } else {
777 pCalBChans = pEepData->calFreqPier5G;
778 numPiers = AR5416_NUM_5G_CAL_PIERS;
779 }
780
781 if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) {
782 pRawDataset = pEepData->calPierData2G[0];
783 ah->initPDADC = ((struct calDataPerFreqOpLoop *)
784 pRawDataset)->vpdPdg[0][0];
785 }
786
787 numXpdGain = 0;
788
789 for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
790 if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
791 if (numXpdGain >= AR5416_NUM_PD_GAINS)
792 break;
793 xpdGainValues[numXpdGain] =
794 (u16)(AR5416_PD_GAINS_IN_MASK - i);
795 numXpdGain++;
796 }
797 }
798
799 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
800 (numXpdGain - 1) & 0x3);
801 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
802 xpdGainValues[0]);
803 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
804 xpdGainValues[1]);
805 REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
806 xpdGainValues[2]);
807
808 for (i = 0; i < AR5416_MAX_CHAINS; i++) {
809 if (AR_SREV_5416_20_OR_LATER(ah) &&
810 (ah->rxchainmask == 5 || ah->txchainmask == 5) &&
811 (i != 0)) {
812 regChainOffset = (i == 1) ? 0x2000 : 0x1000;
813 } else
814 regChainOffset = i * 0x1000;
815
816 if (pEepData->baseEepHeader.txMask & (1 << i)) {
817 if (IS_CHAN_2GHZ(chan))
818 pRawDataset = pEepData->calPierData2G[i];
819 else
820 pRawDataset = pEepData->calPierData5G[i];
821
822
823 if (OLC_FOR_AR9280_20_LATER) {
824 u8 pcdacIdx;
825 u8 txPower;
826
827 ath9k_get_txgain_index(ah, chan,
828 (struct calDataPerFreqOpLoop *)pRawDataset,
829 pCalBChans, numPiers, &txPower, &pcdacIdx);
830 ath9k_olc_get_pdadcs(ah, pcdacIdx,
831 txPower/2, pdadcValues);
832 } else {
833 ath9k_hw_get_def_gain_boundaries_pdadcs(ah,
834 chan, pRawDataset,
835 pCalBChans, numPiers,
836 pdGainOverlap_t2,
837 &tMinCalPower,
838 gainBoundaries,
839 pdadcValues,
840 numXpdGain);
841 }
842
843 if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) {
844 if (OLC_FOR_AR9280_20_LATER) {
845 REG_WRITE(ah,
846 AR_PHY_TPCRG5 + regChainOffset,
847 SM(0x6,
848 AR_PHY_TPCRG5_PD_GAIN_OVERLAP) |
849 SM_PD_GAIN(1) | SM_PD_GAIN(2) |
850 SM_PD_GAIN(3) | SM_PD_GAIN(4));
851 } else {
852 REG_WRITE(ah,
853 AR_PHY_TPCRG5 + regChainOffset,
854 SM(pdGainOverlap_t2,
855 AR_PHY_TPCRG5_PD_GAIN_OVERLAP)|
856 SM_PDGAIN_B(0, 1) |
857 SM_PDGAIN_B(1, 2) |
858 SM_PDGAIN_B(2, 3) |
859 SM_PDGAIN_B(3, 4));
860 }
861 }
862
863 regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
864 for (j = 0; j < 32; j++) {
865 reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
866 ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
867 ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
868 ((pdadcValues[4 * j + 3] & 0xFF) << 24);
869 REG_WRITE(ah, regOffset, reg32);
870
871 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
872 "PDADC (%d,%4x): %4.4x %8.8x\n",
873 i, regChainOffset, regOffset,
874 reg32);
875 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
876 "PDADC: Chain %d | PDADC %3d "
877 "Value %3d | PDADC %3d Value %3d | "
878 "PDADC %3d Value %3d | PDADC %3d "
879 "Value %3d |\n",
880 i, 4 * j, pdadcValues[4 * j],
881 4 * j + 1, pdadcValues[4 * j + 1],
882 4 * j + 2, pdadcValues[4 * j + 2],
883 4 * j + 3,
884 pdadcValues[4 * j + 3]);
885
886 regOffset += 4;
887 }
888 }
889 }
890
891 *pTxPowerIndexOffset = 0;
892#undef SM_PD_GAIN
893#undef SM_PDGAIN_B
894}
895
896static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
897 struct ath9k_channel *chan,
898 int16_t *ratesArray,
899 u16 cfgCtl,
900 u16 AntennaReduction,
901 u16 twiceMaxRegulatoryPower,
902 u16 powerLimit)
903{
904#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
905#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
906
907 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
908 u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
909 static const u16 tpScaleReductionTable[5] =
910 { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
911
912 int i;
913 int16_t twiceLargestAntenna;
914 struct cal_ctl_data *rep;
915 struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
916 0, { 0, 0, 0, 0}
917 };
918 struct cal_target_power_leg targetPowerOfdmExt = {
919 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
920 0, { 0, 0, 0, 0 }
921 };
922 struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
923 0, {0, 0, 0, 0}
924 };
925 u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
926 u16 ctlModesFor11a[] =
927 { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
928 u16 ctlModesFor11g[] =
929 { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
930 CTL_2GHT40
931 };
932 u16 numCtlModes, *pCtlMode, ctlMode, freq;
933 struct chan_centers centers;
934 int tx_chainmask;
935 u16 twiceMinEdgePower;
936
937 tx_chainmask = ah->txchainmask;
938
939 ath9k_hw_get_channel_centers(ah, chan, &centers);
940
941 twiceLargestAntenna = max(
942 pEepData->modalHeader
943 [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
944 pEepData->modalHeader
945 [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
946
947 twiceLargestAntenna = max((u8)twiceLargestAntenna,
948 pEepData->modalHeader
949 [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
950
951 twiceLargestAntenna = (int16_t)min(AntennaReduction -
952 twiceLargestAntenna, 0);
953
954 maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
955
956 if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) {
957 maxRegAllowedPower -=
958 (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2);
959 }
960
961 scaledPower = min(powerLimit, maxRegAllowedPower);
962
963 switch (ar5416_get_ntxchains(tx_chainmask)) {
964 case 1:
965 break;
966 case 2:
967 scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
968 break;
969 case 3:
970 scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
971 break;
972 }
973
974 scaledPower = max((u16)0, scaledPower);
975
976 if (IS_CHAN_2GHZ(chan)) {
977 numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
978 SUB_NUM_CTL_MODES_AT_2G_40;
979 pCtlMode = ctlModesFor11g;
980
981 ath9k_hw_get_legacy_target_powers(ah, chan,
982 pEepData->calTargetPowerCck,
983 AR5416_NUM_2G_CCK_TARGET_POWERS,
984 &targetPowerCck, 4, false);
985 ath9k_hw_get_legacy_target_powers(ah, chan,
986 pEepData->calTargetPower2G,
987 AR5416_NUM_2G_20_TARGET_POWERS,
988 &targetPowerOfdm, 4, false);
989 ath9k_hw_get_target_powers(ah, chan,
990 pEepData->calTargetPower2GHT20,
991 AR5416_NUM_2G_20_TARGET_POWERS,
992 &targetPowerHt20, 8, false);
993
994 if (IS_CHAN_HT40(chan)) {
995 numCtlModes = ARRAY_SIZE(ctlModesFor11g);
996 ath9k_hw_get_target_powers(ah, chan,
997 pEepData->calTargetPower2GHT40,
998 AR5416_NUM_2G_40_TARGET_POWERS,
999 &targetPowerHt40, 8, true);
1000 ath9k_hw_get_legacy_target_powers(ah, chan,
1001 pEepData->calTargetPowerCck,
1002 AR5416_NUM_2G_CCK_TARGET_POWERS,
1003 &targetPowerCckExt, 4, true);
1004 ath9k_hw_get_legacy_target_powers(ah, chan,
1005 pEepData->calTargetPower2G,
1006 AR5416_NUM_2G_20_TARGET_POWERS,
1007 &targetPowerOfdmExt, 4, true);
1008 }
1009 } else {
1010 numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
1011 SUB_NUM_CTL_MODES_AT_5G_40;
1012 pCtlMode = ctlModesFor11a;
1013
1014 ath9k_hw_get_legacy_target_powers(ah, chan,
1015 pEepData->calTargetPower5G,
1016 AR5416_NUM_5G_20_TARGET_POWERS,
1017 &targetPowerOfdm, 4, false);
1018 ath9k_hw_get_target_powers(ah, chan,
1019 pEepData->calTargetPower5GHT20,
1020 AR5416_NUM_5G_20_TARGET_POWERS,
1021 &targetPowerHt20, 8, false);
1022
1023 if (IS_CHAN_HT40(chan)) {
1024 numCtlModes = ARRAY_SIZE(ctlModesFor11a);
1025 ath9k_hw_get_target_powers(ah, chan,
1026 pEepData->calTargetPower5GHT40,
1027 AR5416_NUM_5G_40_TARGET_POWERS,
1028 &targetPowerHt40, 8, true);
1029 ath9k_hw_get_legacy_target_powers(ah, chan,
1030 pEepData->calTargetPower5G,
1031 AR5416_NUM_5G_20_TARGET_POWERS,
1032 &targetPowerOfdmExt, 4, true);
1033 }
1034 }
1035
1036 for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
1037 bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
1038 (pCtlMode[ctlMode] == CTL_2GHT40);
1039 if (isHt40CtlMode)
1040 freq = centers.synth_center;
1041 else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
1042 freq = centers.ext_center;
1043 else
1044 freq = centers.ctl_center;
1045
1046 if (ah->eep_ops->get_eeprom_ver(ah) == 14 &&
1047 ah->eep_ops->get_eeprom_rev(ah) <= 2)
1048 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
1049
1050 for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
1051 if ((((cfgCtl & ~CTL_MODE_M) |
1052 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1053 pEepData->ctlIndex[i]) ||
1054 (((cfgCtl & ~CTL_MODE_M) |
1055 (pCtlMode[ctlMode] & CTL_MODE_M)) ==
1056 ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
1057 rep = &(pEepData->ctlData[i]);
1058
1059 twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
1060 rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
1061 IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
1062
1063 if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
1064 twiceMaxEdgePower = min(twiceMaxEdgePower,
1065 twiceMinEdgePower);
1066 } else {
1067 twiceMaxEdgePower = twiceMinEdgePower;
1068 break;
1069 }
1070 }
1071 }
1072
1073 minCtlPower = min(twiceMaxEdgePower, scaledPower);
1074
1075 switch (pCtlMode[ctlMode]) {
1076 case CTL_11B:
1077 for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
1078 targetPowerCck.tPow2x[i] =
1079 min((u16)targetPowerCck.tPow2x[i],
1080 minCtlPower);
1081 }
1082 break;
1083 case CTL_11A:
1084 case CTL_11G:
1085 for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
1086 targetPowerOfdm.tPow2x[i] =
1087 min((u16)targetPowerOfdm.tPow2x[i],
1088 minCtlPower);
1089 }
1090 break;
1091 case CTL_5GHT20:
1092 case CTL_2GHT20:
1093 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
1094 targetPowerHt20.tPow2x[i] =
1095 min((u16)targetPowerHt20.tPow2x[i],
1096 minCtlPower);
1097 }
1098 break;
1099 case CTL_11B_EXT:
1100 targetPowerCckExt.tPow2x[0] = min((u16)
1101 targetPowerCckExt.tPow2x[0],
1102 minCtlPower);
1103 break;
1104 case CTL_11A_EXT:
1105 case CTL_11G_EXT:
1106 targetPowerOfdmExt.tPow2x[0] = min((u16)
1107 targetPowerOfdmExt.tPow2x[0],
1108 minCtlPower);
1109 break;
1110 case CTL_5GHT40:
1111 case CTL_2GHT40:
1112 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1113 targetPowerHt40.tPow2x[i] =
1114 min((u16)targetPowerHt40.tPow2x[i],
1115 minCtlPower);
1116 }
1117 break;
1118 default:
1119 break;
1120 }
1121 }
1122
1123 ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
1124 ratesArray[rate18mb] = ratesArray[rate24mb] =
1125 targetPowerOfdm.tPow2x[0];
1126 ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
1127 ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
1128 ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
1129 ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
1130
1131 for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
1132 ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
1133
1134 if (IS_CHAN_2GHZ(chan)) {
1135 ratesArray[rate1l] = targetPowerCck.tPow2x[0];
1136 ratesArray[rate2s] = ratesArray[rate2l] =
1137 targetPowerCck.tPow2x[1];
1138 ratesArray[rate5_5s] = ratesArray[rate5_5l] =
1139 targetPowerCck.tPow2x[2];
1140 ratesArray[rate11s] = ratesArray[rate11l] =
1141 targetPowerCck.tPow2x[3];
1142 }
1143 if (IS_CHAN_HT40(chan)) {
1144 for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
1145 ratesArray[rateHt40_0 + i] =
1146 targetPowerHt40.tPow2x[i];
1147 }
1148 ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
1149 ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
1150 ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
1151 if (IS_CHAN_2GHZ(chan)) {
1152 ratesArray[rateExtCck] =
1153 targetPowerCckExt.tPow2x[0];
1154 }
1155 }
1156}
1157
1158static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
1159 struct ath9k_channel *chan,
1160 u16 cfgCtl,
1161 u8 twiceAntennaReduction,
1162 u8 twiceMaxRegulatoryPower,
1163 u8 powerLimit)
1164{
1165#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
1166 struct ar5416_eeprom_def *pEepData = &ah->eeprom.def;
1167 struct modal_eep_header *pModal =
1168 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
1169 int16_t ratesArray[Ar5416RateSize];
1170 int16_t txPowerIndexOffset = 0;
1171 u8 ht40PowerIncForPdadc = 2;
1172 int i, cck_ofdm_delta = 0;
1173
1174 memset(ratesArray, 0, sizeof(ratesArray));
1175
1176 if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
1177 AR5416_EEP_MINOR_VER_2) {
1178 ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
1179 }
1180
1181 ath9k_hw_set_def_power_per_rate_table(ah, chan,
1182 &ratesArray[0], cfgCtl,
1183 twiceAntennaReduction,
1184 twiceMaxRegulatoryPower,
1185 powerLimit);
1186
1187 ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
1188
1189 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1190 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1191 if (ratesArray[i] > AR5416_MAX_RATE_POWER)
1192 ratesArray[i] = AR5416_MAX_RATE_POWER;
1193 }
1194
1195 if (AR_SREV_9280_10_OR_LATER(ah)) {
1196 for (i = 0; i < Ar5416RateSize; i++)
1197 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
1198 }
1199
1200 REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
1201 ATH9K_POW_SM(ratesArray[rate18mb], 24)
1202 | ATH9K_POW_SM(ratesArray[rate12mb], 16)
1203 | ATH9K_POW_SM(ratesArray[rate9mb], 8)
1204 | ATH9K_POW_SM(ratesArray[rate6mb], 0));
1205 REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
1206 ATH9K_POW_SM(ratesArray[rate54mb], 24)
1207 | ATH9K_POW_SM(ratesArray[rate48mb], 16)
1208 | ATH9K_POW_SM(ratesArray[rate36mb], 8)
1209 | ATH9K_POW_SM(ratesArray[rate24mb], 0));
1210
1211 if (IS_CHAN_2GHZ(chan)) {
1212 if (OLC_FOR_AR9280_20_LATER) {
1213 cck_ofdm_delta = 2;
1214 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1215 ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24)
1216 | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16)
1217 | ATH9K_POW_SM(ratesArray[rateXr], 8)
1218 | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0));
1219 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1220 ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24)
1221 | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16)
1222 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8)
1223 | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0));
1224 } else {
1225 REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
1226 ATH9K_POW_SM(ratesArray[rate2s], 24)
1227 | ATH9K_POW_SM(ratesArray[rate2l], 16)
1228 | ATH9K_POW_SM(ratesArray[rateXr], 8)
1229 | ATH9K_POW_SM(ratesArray[rate1l], 0));
1230 REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
1231 ATH9K_POW_SM(ratesArray[rate11s], 24)
1232 | ATH9K_POW_SM(ratesArray[rate11l], 16)
1233 | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
1234 | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
1235 }
1236 }
1237
1238 REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
1239 ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
1240 | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
1241 | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
1242 | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
1243 REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
1244 ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
1245 | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
1246 | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
1247 | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
1248
1249 if (IS_CHAN_HT40(chan)) {
1250 REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
1251 ATH9K_POW_SM(ratesArray[rateHt40_3] +
1252 ht40PowerIncForPdadc, 24)
1253 | ATH9K_POW_SM(ratesArray[rateHt40_2] +
1254 ht40PowerIncForPdadc, 16)
1255 | ATH9K_POW_SM(ratesArray[rateHt40_1] +
1256 ht40PowerIncForPdadc, 8)
1257 | ATH9K_POW_SM(ratesArray[rateHt40_0] +
1258 ht40PowerIncForPdadc, 0));
1259 REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
1260 ATH9K_POW_SM(ratesArray[rateHt40_7] +
1261 ht40PowerIncForPdadc, 24)
1262 | ATH9K_POW_SM(ratesArray[rateHt40_6] +
1263 ht40PowerIncForPdadc, 16)
1264 | ATH9K_POW_SM(ratesArray[rateHt40_5] +
1265 ht40PowerIncForPdadc, 8)
1266 | ATH9K_POW_SM(ratesArray[rateHt40_4] +
1267 ht40PowerIncForPdadc, 0));
1268 if (OLC_FOR_AR9280_20_LATER) {
1269 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1270 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
1271 | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16)
1272 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
1273 | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0));
1274 } else {
1275 REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
1276 ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
1277 | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
1278 | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
1279 | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
1280 }
1281 }
1282
1283 REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
1284 ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
1285 | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
1286
1287 i = rate6mb;
1288
1289 if (IS_CHAN_HT40(chan))
1290 i = rateHt40_0;
1291 else if (IS_CHAN_HT20(chan))
1292 i = rateHt20_0;
1293
1294 if (AR_SREV_9280_10_OR_LATER(ah))
1295 ah->regulatory.max_power_level =
1296 ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
1297 else
1298 ah->regulatory.max_power_level = ratesArray[i];
1299
1300 switch(ar5416_get_ntxchains(ah->txchainmask)) {
1301 case 1:
1302 break;
1303 case 2:
1304 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
1305 break;
1306 case 3:
1307 ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
1308 break;
1309 default:
1310 DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
1311 "Invalid chainmask configuration\n");
1312 break;
1313 }
1314}
1315
1316static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
1317 enum ieee80211_band freq_band)
1318{
1319 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1320 struct modal_eep_header *pModal =
1321 &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
1322 struct base_eep_header *pBase = &eep->baseEepHeader;
1323 u8 num_ant_config;
1324
1325 num_ant_config = 1;
1326
1327 if (pBase->version >= 0x0E0D)
1328 if (pModal->useAnt1)
1329 num_ant_config += 1;
1330
1331 return num_ant_config;
1332}
1333
1334static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah,
1335 struct ath9k_channel *chan)
1336{
1337 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
1338 struct modal_eep_header *pModal =
1339 &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
1340
1341 return pModal->antCtrlCommon & 0xFFFF;
1342}
1343
1344static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz)
1345{
1346#define EEP_DEF_SPURCHAN \
1347 (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
1348
1349 u16 spur_val = AR_NO_SPUR;
1350
1351 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1352 "Getting spur idx %d is2Ghz. %d val %x\n",
1353 i, is2GHz, ah->config.spurchans[i][is2GHz]);
1354
1355 switch (ah->config.spurmode) {
1356 case SPUR_DISABLE:
1357 break;
1358 case SPUR_ENABLE_IOCTL:
1359 spur_val = ah->config.spurchans[i][is2GHz];
1360 DPRINTF(ah->ah_sc, ATH_DBG_ANI,
1361 "Getting spur val from new loc. %d\n", spur_val);
1362 break;
1363 case SPUR_ENABLE_EEPROM:
1364 spur_val = EEP_DEF_SPURCHAN;
1365 break;
1366 }
1367
1368 return spur_val;
1369
1370#undef EEP_DEF_SPURCHAN
1371}
1372
1373const struct eeprom_ops eep_def_ops = {
1374 .check_eeprom = ath9k_hw_def_check_eeprom,
1375 .get_eeprom = ath9k_hw_def_get_eeprom,
1376 .fill_eeprom = ath9k_hw_def_fill_eeprom,
1377 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
1378 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
1379 .get_num_ant_config = ath9k_hw_def_get_num_ant_config,
1380 .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg,
1381 .set_board_values = ath9k_hw_def_set_board_values,
1382 .set_addac = ath9k_hw_def_set_addac,
1383 .set_txpower = ath9k_hw_def_set_txpower,
1384 .get_spur_channel = ath9k_hw_def_get_spur_channel
1385};
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 71a3bcc450a2..9f1b34d9861a 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -407,7 +407,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
407 ah->config.cck_trig_high = 200; 407 ah->config.cck_trig_high = 200;
408 ah->config.cck_trig_low = 100; 408 ah->config.cck_trig_low = 100;
409 ah->config.enable_ani = 1; 409 ah->config.enable_ani = 1;
410 ah->config.diversity_control = 0; 410 ah->config.diversity_control = ATH9K_ANT_VARIABLE;
411 ah->config.antenna_switch_swap = 0; 411 ah->config.antenna_switch_swap = 0;
412 412
413 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { 413 for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
@@ -452,9 +452,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
452 ah->regulatory.power_limit = MAX_RATE_POWER; 452 ah->regulatory.power_limit = MAX_RATE_POWER;
453 ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; 453 ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX;
454 ah->atim_window = 0; 454 ah->atim_window = 0;
455 ah->diversity_control = ah->config.diversity_control;
456 ah->antenna_switch_swap =
457 ah->config.antenna_switch_swap;
458 ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; 455 ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
459 ah->beacon_interval = 100; 456 ah->beacon_interval = 100;
460 ah->enable_32kHz_clock = DONT_USE_32KHZ; 457 ah->enable_32kHz_clock = DONT_USE_32KHZ;
@@ -3891,7 +3888,7 @@ bool ath9k_hw_setantennaswitch(struct ath_hw *ah,
3891 break; 3888 break;
3892 } 3889 }
3893 } else { 3890 } else {
3894 ah->diversity_control = settings; 3891 ah->config.diversity_control = settings;
3895 } 3892 }
3896 3893
3897 return true; 3894 return true;
@@ -4019,14 +4016,12 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah)
4019 ath9k_ps_restore(ah->ah_sc); 4016 ath9k_ps_restore(ah->ah_sc);
4020} 4017}
4021 4018
4022bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) 4019void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
4023{ 4020{
4024 if (setting) 4021 if (setting)
4025 ah->misc_mode |= AR_PCU_TX_ADD_TSF; 4022 ah->misc_mode |= AR_PCU_TX_ADD_TSF;
4026 else 4023 else
4027 ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; 4024 ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;
4028
4029 return true;
4030} 4025}
4031 4026
4032bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) 4027bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index d4aaf4f8db29..0336981a70ec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -127,6 +127,12 @@ enum wireless_mode {
127 ATH9K_MODE_MAX, 127 ATH9K_MODE_MAX,
128}; 128};
129 129
130enum ath9k_ant_setting {
131 ATH9K_ANT_VARIABLE = 0,
132 ATH9K_ANT_FIXED_A,
133 ATH9K_ANT_FIXED_B
134};
135
130enum ath9k_hw_caps { 136enum ath9k_hw_caps {
131 ATH9K_HW_CAP_MIC_AESCCM = BIT(0), 137 ATH9K_HW_CAP_MIC_AESCCM = BIT(0),
132 ATH9K_HW_CAP_MIC_CKIP = BIT(1), 138 ATH9K_HW_CAP_MIC_CKIP = BIT(1),
@@ -191,7 +197,7 @@ struct ath9k_ops_config {
191 u32 cck_trig_high; 197 u32 cck_trig_high;
192 u32 cck_trig_low; 198 u32 cck_trig_low;
193 u32 enable_ani; 199 u32 enable_ani;
194 u16 diversity_control; 200 enum ath9k_ant_setting diversity_control;
195 u16 antenna_switch_swap; 201 u16 antenna_switch_swap;
196 int serialize_regmode; 202 int serialize_regmode;
197 bool intr_mitigation; 203 bool intr_mitigation;
@@ -330,12 +336,6 @@ enum ath9k_power_mode {
330 ATH9K_PM_UNDEFINED 336 ATH9K_PM_UNDEFINED
331}; 337};
332 338
333enum ath9k_ant_setting {
334 ATH9K_ANT_VARIABLE = 0,
335 ATH9K_ANT_FIXED_A,
336 ATH9K_ANT_FIXED_B
337};
338
339enum ath9k_tp_scale { 339enum ath9k_tp_scale {
340 ATH9K_TP_SCALE_MAX = 0, 340 ATH9K_TP_SCALE_MAX = 0,
341 ATH9K_TP_SCALE_50, 341 ATH9K_TP_SCALE_50,
@@ -437,8 +437,6 @@ struct ath_hw {
437 u32 txurn_interrupt_mask; 437 u32 txurn_interrupt_mask;
438 bool chip_fullsleep; 438 bool chip_fullsleep;
439 u32 atim_window; 439 u32 atim_window;
440 u16 antenna_switch_swap;
441 enum ath9k_ant_setting diversity_control;
442 440
443 /* Calibration */ 441 /* Calibration */
444 enum ath9k_cal_types supp_cals; 442 enum ath9k_cal_types supp_cals;
@@ -507,7 +505,6 @@ struct ath_hw {
507 505
508 /* ANI */ 506 /* ANI */
509 u32 proc_phyerr; 507 u32 proc_phyerr;
510 bool has_hw_phycounters;
511 u32 aniperiod; 508 u32 aniperiod;
512 struct ar5416AniState *curani; 509 struct ar5416AniState *curani;
513 struct ar5416AniState ani[255]; 510 struct ar5416AniState ani[255];
@@ -601,7 +598,7 @@ void ath9k_hw_write_associd(struct ath_softc *sc);
601u64 ath9k_hw_gettsf64(struct ath_hw *ah); 598u64 ath9k_hw_gettsf64(struct ath_hw *ah);
602void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); 599void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
603void ath9k_hw_reset_tsf(struct ath_hw *ah); 600void ath9k_hw_reset_tsf(struct ath_hw *ah);
604bool ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); 601void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
605bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); 602bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
606void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); 603void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode);
607void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); 604void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 6f923e318727..800bfab94635 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -40,20 +40,15 @@ u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q)
40 return REG_READ(ah, AR_QTXDP(q)); 40 return REG_READ(ah, AR_QTXDP(q));
41} 41}
42 42
43bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) 43void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
44{ 44{
45 REG_WRITE(ah, AR_QTXDP(q), txdp); 45 REG_WRITE(ah, AR_QTXDP(q), txdp);
46
47 return true;
48} 46}
49 47
50bool ath9k_hw_txstart(struct ath_hw *ah, u32 q) 48void ath9k_hw_txstart(struct ath_hw *ah, u32 q)
51{ 49{
52 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); 50 DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
53
54 REG_WRITE(ah, AR_Q_TXE, 1 << q); 51 REG_WRITE(ah, AR_Q_TXE, 1 << q);
55
56 return true;
57} 52}
58 53
59u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) 54u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
@@ -178,7 +173,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
178#undef ATH9K_TIME_QUANTUM 173#undef ATH9K_TIME_QUANTUM
179} 174}
180 175
181bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, 176void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
182 u32 segLen, bool firstSeg, 177 u32 segLen, bool firstSeg,
183 bool lastSeg, const struct ath_desc *ds0) 178 bool lastSeg, const struct ath_desc *ds0)
184{ 179{
@@ -202,8 +197,6 @@ bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
202 ads->ds_txstatus4 = ads->ds_txstatus5 = 0; 197 ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
203 ads->ds_txstatus6 = ads->ds_txstatus7 = 0; 198 ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
204 ads->ds_txstatus8 = ads->ds_txstatus9 = 0; 199 ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
205
206 return true;
207} 200}
208 201
209void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) 202void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds)
@@ -888,7 +881,7 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
888 return 0; 881 return 0;
889} 882}
890 883
891bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, 884void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
892 u32 size, u32 flags) 885 u32 size, u32 flags)
893{ 886{
894 struct ar5416_desc *ads = AR5416DESC(ds); 887 struct ar5416_desc *ads = AR5416DESC(ds);
@@ -901,8 +894,6 @@ bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
901 ads->ds_rxstatus8 &= ~AR_RxDone; 894 ads->ds_rxstatus8 &= ~AR_RxDone;
902 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) 895 if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
903 memset(&(ads->u), 0, sizeof(ads->u)); 896 memset(&(ads->u), 0, sizeof(ads->u));
904
905 return true;
906} 897}
907 898
908bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) 899bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 1176bce8b76c..7b3982295a43 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -628,12 +628,12 @@ struct ath9k_channel;
628struct ath_rate_table; 628struct ath_rate_table;
629 629
630u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); 630u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
631bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); 631void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
632bool ath9k_hw_txstart(struct ath_hw *ah, u32 q); 632void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
633u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); 633u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
634bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); 634bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
635bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); 635bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
636bool ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, 636void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds,
637 u32 segLen, bool firstSeg, 637 u32 segLen, bool firstSeg,
638 bool lastSeg, const struct ath_desc *ds0); 638 bool lastSeg, const struct ath_desc *ds0);
639void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); 639void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds);
@@ -668,7 +668,7 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q);
668bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); 668bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q);
669int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, 669int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
670 u32 pa, struct ath_desc *nds, u64 tsf); 670 u32 pa, struct ath_desc *nds, u64 tsf);
671bool ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, 671void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
672 u32 size, u32 flags); 672 u32 size, u32 flags);
673bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); 673bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
674void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); 674void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index a9e43f7a23f6..fa4c6e74f977 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1327,7 +1327,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc)
1327 */ 1327 */
1328 ath_read_cachesize(sc, &csz); 1328 ath_read_cachesize(sc, &csz);
1329 /* XXX assert csz is non-zero */ 1329 /* XXX assert csz is non-zero */
1330 sc->cachelsz = csz << 2; /* convert to bytes */ 1330 sc->common.cachelsz = csz << 2; /* convert to bytes */
1331 1331
1332 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); 1332 ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
1333 if (!ah) { 1333 if (!ah) {
@@ -2140,6 +2140,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
2140 /* disable HAL and put h/w to sleep */ 2140 /* disable HAL and put h/w to sleep */
2141 ath9k_hw_disable(sc->sc_ah); 2141 ath9k_hw_disable(sc->sc_ah);
2142 ath9k_hw_configpcipowersave(sc->sc_ah, 1); 2142 ath9k_hw_configpcipowersave(sc->sc_ah, 1);
2143 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
2143 2144
2144 sc->sc_flags |= SC_OP_INVALID; 2145 sc->sc_flags |= SC_OP_INVALID;
2145 2146
@@ -2214,8 +2215,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
2214 if ((conf->type == NL80211_IFTYPE_STATION) || 2215 if ((conf->type == NL80211_IFTYPE_STATION) ||
2215 (conf->type == NL80211_IFTYPE_ADHOC) || 2216 (conf->type == NL80211_IFTYPE_ADHOC) ||
2216 (conf->type == NL80211_IFTYPE_MESH_POINT)) { 2217 (conf->type == NL80211_IFTYPE_MESH_POINT)) {
2217 if (ath9k_hw_phycounters(sc->sc_ah)) 2218 sc->imask |= ATH9K_INT_MIB;
2218 sc->imask |= ATH9K_INT_MIB;
2219 sc->imask |= ATH9K_INT_TSFOOR; 2219 sc->imask |= ATH9K_INT_TSFOOR;
2220 } 2220 }
2221 2221
@@ -2380,6 +2380,7 @@ skip_chan_change:
2380 (FIF_PROMISC_IN_BSS | \ 2380 (FIF_PROMISC_IN_BSS | \
2381 FIF_ALLMULTI | \ 2381 FIF_ALLMULTI | \
2382 FIF_CONTROL | \ 2382 FIF_CONTROL | \
2383 FIF_PSPOLL | \
2383 FIF_OTHER_BSS | \ 2384 FIF_OTHER_BSS | \
2384 FIF_BCN_PRBRESP_PROMISC | \ 2385 FIF_BCN_PRBRESP_PROMISC | \
2385 FIF_FCSFAIL) 2386 FIF_FCSFAIL)
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 3546504a83c4..616bdff2b6a1 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -253,10 +253,12 @@ static int ath_pci_resume(struct pci_dev *pdev)
253 u32 val; 253 u32 val;
254 int err; 254 int err;
255 255
256 pci_restore_state(pdev);
257
256 err = pci_enable_device(pdev); 258 err = pci_enable_device(pdev);
257 if (err) 259 if (err)
258 return err; 260 return err;
259 pci_restore_state(pdev); 261
260 /* 262 /*
261 * Suspend/Resume resets the PCI configuration space, so we have to 263 * Suspend/Resume resets the PCI configuration space, so we have to
262 * re-disable the RETRY_TIMEOUT register (0x41) to keep 264 * re-disable the RETRY_TIMEOUT register (0x41) to keep
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c
index 59bb3ce1e646..63bf9a307c6a 100644
--- a/drivers/net/wireless/ath/ath9k/phy.c
+++ b/drivers/net/wireless/ath/ath9k/phy.c
@@ -353,18 +353,16 @@ ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan)
353 u32 bank6SelMask; 353 u32 bank6SelMask;
354 u32 *bank6Temp = ah->bank6Temp; 354 u32 *bank6Temp = ah->bank6Temp;
355 355
356 switch (ah->diversity_control) { 356 switch (ah->config.diversity_control) {
357 case ATH9K_ANT_FIXED_A: 357 case ATH9K_ANT_FIXED_A:
358 bank6SelMask = 358 bank6SelMask =
359 (ah-> 359 (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
360 antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_0 : 360 REDUCE_CHAIN_0 : REDUCE_CHAIN_1;
361 REDUCE_CHAIN_1;
362 break; 361 break;
363 case ATH9K_ANT_FIXED_B: 362 case ATH9K_ANT_FIXED_B:
364 bank6SelMask = 363 bank6SelMask =
365 (ah-> 364 (ah->config.antenna_switch_swap & ANTSWAP_AB) ?
366 antenna_switch_swap & ANTSWAP_AB) ? REDUCE_CHAIN_1 : 365 REDUCE_CHAIN_1 : REDUCE_CHAIN_0;
367 REDUCE_CHAIN_0;
368 break; 366 break;
369 case ATH9K_ANT_VARIABLE: 367 case ATH9K_ANT_VARIABLE:
370 return; 368 return;
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h
index 27bd93c6e74d..e83cd4ab87f0 100644
--- a/drivers/net/wireless/ath/ath9k/phy.h
+++ b/drivers/net/wireless/ath/ath9k/phy.h
@@ -312,7 +312,25 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
312#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) 312#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12))
313#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 313#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000
314#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 314#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000
315#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac 315
316#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac
317#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000
318#define AR_PHY_9285_ANT_DIV_CTL 0x01000000
319#define AR_PHY_9285_ANT_DIV_CTL_S 24
320#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000
321#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25
322#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000
323#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27
324#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000
325#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29
326#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000
327#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30
328#define AR_PHY_9285_ANT_DIV_LNA1 2
329#define AR_PHY_9285_ANT_DIV_LNA2 1
330#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3
331#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0
332#define AR_PHY_9285_ANT_DIV_GAINTB_0 0
333#define AR_PHY_9285_ANT_DIV_GAINTB_1 1
316 334
317#define AR_PHY_EXT_CCA0 0x99b8 335#define AR_PHY_EXT_CCA0 0x99b8
318#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF 336#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF
@@ -401,6 +419,7 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
401#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 419#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0
402#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 420#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6
403#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 421#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000
422#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13
404 423
405#define AR_PHY_GAIN_2GHZ 0xA20C 424#define AR_PHY_GAIN_2GHZ 0xA20C
406#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 425#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 61edfab20ffc..61dbdd227444 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -100,38 +100,6 @@ static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
100 return (tsf & ~0x7fff) | rstamp; 100 return (tsf & ~0x7fff) | rstamp;
101} 101}
102 102
103static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len, gfp_t gfp_mask)
104{
105 struct sk_buff *skb;
106 u32 off;
107
108 /*
109 * Cache-line-align. This is important (for the
110 * 5210 at least) as not doing so causes bogus data
111 * in rx'd frames.
112 */
113
114 /* Note: the kernel can allocate a value greater than
115 * what we ask it to give us. We really only need 4 KB as that
116 * is this hardware supports and in fact we need at least 3849
117 * as that is the MAX AMSDU size this hardware supports.
118 * Unfortunately this means we may get 8 KB here from the
119 * kernel... and that is actually what is observed on some
120 * systems :( */
121 skb = __dev_alloc_skb(len + sc->cachelsz - 1, gfp_mask);
122 if (skb != NULL) {
123 off = ((unsigned long) skb->data) % sc->cachelsz;
124 if (off != 0)
125 skb_reserve(skb, sc->cachelsz - off);
126 } else {
127 DPRINTF(sc, ATH_DBG_FATAL,
128 "skbuff alloc of size %u failed\n", len);
129 return NULL;
130 }
131
132 return skb;
133}
134
135/* 103/*
136 * For Decrypt or Demic errors, we only mark packet status here and always push 104 * For Decrypt or Demic errors, we only mark packet status here and always push
137 * up the frame up to let mac80211 handle the actual error case, be it no 105 * up the frame up to let mac80211 handle the actual error case, be it no
@@ -252,6 +220,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
252 else if (ds->ds_rxstat.rs_rssi > 127) 220 else if (ds->ds_rxstat.rs_rssi > 127)
253 ds->ds_rxstat.rs_rssi = 127; 221 ds->ds_rxstat.rs_rssi = 127;
254 222
223 /* Update Beacon RSSI, this is used by ANI. */
224 if (ieee80211_is_beacon(fc))
225 sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi;
226
255 rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); 227 rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
256 rx_status->band = hw->conf.channel->band; 228 rx_status->band = hw->conf.channel->band;
257 rx_status->freq = hw->conf.channel->center_freq; 229 rx_status->freq = hw->conf.channel->center_freq;
@@ -332,10 +304,10 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
332 spin_lock_init(&sc->rx.rxbuflock); 304 spin_lock_init(&sc->rx.rxbuflock);
333 305
334 sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, 306 sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
335 min(sc->cachelsz, (u16)64)); 307 min(sc->common.cachelsz, (u16)64));
336 308
337 DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", 309 DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
338 sc->cachelsz, sc->rx.bufsize); 310 sc->common.cachelsz, sc->rx.bufsize);
339 311
340 /* Initialize rx descriptors */ 312 /* Initialize rx descriptors */
341 313
@@ -348,7 +320,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
348 } 320 }
349 321
350 list_for_each_entry(bf, &sc->rx.rxbuf, list) { 322 list_for_each_entry(bf, &sc->rx.rxbuf, list) {
351 skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL); 323 skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL);
352 if (skb == NULL) { 324 if (skb == NULL) {
353 error = -ENOMEM; 325 error = -ENOMEM;
354 goto err; 326 goto err;
@@ -448,8 +420,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
448 else 420 else
449 rfilt |= ATH9K_RX_FILTER_BEACON; 421 rfilt |= ATH9K_RX_FILTER_BEACON;
450 422
451 /* If in HOSTAP mode, want to enable reception of PSPOLL frames */ 423 if (sc->rx.rxfilter & FIF_PSPOLL)
452 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP)
453 rfilt |= ATH9K_RX_FILTER_PSPOLL; 424 rfilt |= ATH9K_RX_FILTER_PSPOLL;
454 425
455 if (sc->sec_wiphy) { 426 if (sc->sec_wiphy) {
@@ -774,7 +745,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
774 745
775 /* Ensure we always have an skb to requeue once we are done 746 /* Ensure we always have an skb to requeue once we are done
776 * processing the current buffer's skb */ 747 * processing the current buffer's skb */
777 requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_ATOMIC); 748 requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC);
778 749
779 /* If there is no memory we ignore the current RX'd frame, 750 /* If there is no memory we ignore the current RX'd frame,
780 * tell hardware it can give us a new frame using the old 751 * tell hardware it can give us a new frame using the old
@@ -789,7 +760,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
789 DMA_FROM_DEVICE); 760 DMA_FROM_DEVICE);
790 761
791 skb_put(skb, ds->ds_rxstat.rs_datalen); 762 skb_put(skb, ds->ds_rxstat.rs_datalen);
792 skb->protocol = cpu_to_be16(ETH_P_CONTROL);
793 763
794 /* see if any padding is done by the hw and remove it */ 764 /* see if any padding is done by the hw and remove it */
795 hdr = (struct ieee80211_hdr *)skb->data; 765 hdr = (struct ieee80211_hdr *)skb->data;
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c
index 9949b11cb151..487193f1de1a 100644
--- a/drivers/net/wireless/ath/main.c
+++ b/drivers/net/wireless/ath/main.c
@@ -17,6 +17,42 @@
17#include <linux/kernel.h> 17#include <linux/kernel.h>
18#include <linux/module.h> 18#include <linux/module.h>
19 19
20#include "ath.h"
21
20MODULE_AUTHOR("Atheros Communications"); 22MODULE_AUTHOR("Atheros Communications");
21MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); 23MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
22MODULE_LICENSE("Dual BSD/GPL"); 24MODULE_LICENSE("Dual BSD/GPL");
25
26struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
27 u32 len,
28 gfp_t gfp_mask)
29{
30 struct sk_buff *skb;
31 u32 off;
32
33 /*
34 * Cache-line-align. This is important (for the
35 * 5210 at least) as not doing so causes bogus data
36 * in rx'd frames.
37 */
38
39 /* Note: the kernel can allocate a value greater than
40 * what we ask it to give us. We really only need 4 KB as that
41 * is this hardware supports and in fact we need at least 3849
42 * as that is the MAX AMSDU size this hardware supports.
43 * Unfortunately this means we may get 8 KB here from the
44 * kernel... and that is actually what is observed on some
45 * systems :( */
46 skb = __dev_alloc_skb(len + common->cachelsz - 1, gfp_mask);
47 if (skb != NULL) {
48 off = ((unsigned long) skb->data) % common->cachelsz;
49 if (off != 0)
50 skb_reserve(skb, common->cachelsz - off);
51 } else {
52 printk(KERN_ERR "skbuff alloc of size %u failed\n", len);
53 return NULL;
54 }
55
56 return skb;
57}
58EXPORT_SYMBOL(ath_rxbuf_alloc);
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index b6811cff18ba..a1b3b731935b 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -493,6 +493,10 @@ enum {
493 493
494/* Max size of a security key */ 494/* Max size of a security key */
495#define B43_SEC_KEYSIZE 16 495#define B43_SEC_KEYSIZE 16
496/* Max number of group keys */
497#define B43_NR_GROUP_KEYS 4
498/* Max number of pairwise keys */
499#define B43_NR_PAIRWISE_KEYS 50
496/* Security algorithms. */ 500/* Security algorithms. */
497enum { 501enum {
498 B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ 502 B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */
@@ -639,7 +643,7 @@ struct b43_wl {
639 u8 mac_addr[ETH_ALEN]; 643 u8 mac_addr[ETH_ALEN];
640 /* Current BSSID */ 644 /* Current BSSID */
641 u8 bssid[ETH_ALEN]; 645 u8 bssid[ETH_ALEN];
642 /* Interface type. (IEEE80211_IF_TYPE_XXX) */ 646 /* Interface type. (NL80211_IFTYPE_XXX) */
643 int if_type; 647 int if_type;
644 /* Is the card operating in AP, STA or IBSS mode? */ 648 /* Is the card operating in AP, STA or IBSS mode? */
645 bool operating; 649 bool operating;
@@ -819,8 +823,7 @@ struct b43_wldev {
819 823
820 /* encryption/decryption */ 824 /* encryption/decryption */
821 u16 ktp; /* Key table pointer */ 825 u16 ktp; /* Key table pointer */
822 u8 max_nr_keys; 826 struct b43_key key[B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS];
823 struct b43_key key[58];
824 827
825 /* Firmware data */ 828 /* Firmware data */
826 struct b43_firmware fw; 829 struct b43_firmware fw;
@@ -845,7 +848,7 @@ static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev)
845 return ssb_get_drvdata(ssb_dev); 848 return ssb_get_drvdata(ssb_dev);
846} 849}
847 850
848/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */ 851/* Is the device operating in a specified mode (NL80211_IFTYPE_XXX). */
849static inline int b43_is_mode(struct b43_wl *wl, int type) 852static inline int b43_is_mode(struct b43_wl *wl, int type)
850{ 853{
851 return (wl->operating && wl->if_type == type); 854 return (wl->operating && wl->if_type == type);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 925f346ea361..950beefbeaeb 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -796,18 +796,19 @@ static void key_write(struct b43_wldev *dev,
796static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) 796static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
797{ 797{
798 u32 addrtmp[2] = { 0, 0, }; 798 u32 addrtmp[2] = { 0, 0, };
799 u8 per_sta_keys_start = 8; 799 u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
800 800
801 if (b43_new_kidx_api(dev)) 801 if (b43_new_kidx_api(dev))
802 per_sta_keys_start = 4; 802 pairwise_keys_start = B43_NR_GROUP_KEYS;
803 803
804 B43_WARN_ON(index < per_sta_keys_start); 804 B43_WARN_ON(index < pairwise_keys_start);
805 /* We have two default TX keys and possibly two default RX keys. 805 /* We have four default TX keys and possibly four default RX keys.
806 * Physical mac 0 is mapped to physical key 4 or 8, depending 806 * Physical mac 0 is mapped to physical key 4 or 8, depending
807 * on the firmware version. 807 * on the firmware version.
808 * So we must adjust the index here. 808 * So we must adjust the index here.
809 */ 809 */
810 index -= per_sta_keys_start; 810 index -= pairwise_keys_start;
811 B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS);
811 812
812 if (addr) { 813 if (addr) {
813 addrtmp[0] = addr[0]; 814 addrtmp[0] = addr[0];
@@ -818,27 +819,11 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr)
818 addrtmp[1] |= ((u32) (addr[5]) << 8); 819 addrtmp[1] |= ((u32) (addr[5]) << 8);
819 } 820 }
820 821
821 if (dev->dev->id.revision >= 5) { 822 /* Receive match transmitter address (RCMTA) mechanism */
822 /* Receive match transmitter address mechanism */ 823 b43_shm_write32(dev, B43_SHM_RCMTA,
823 b43_shm_write32(dev, B43_SHM_RCMTA, 824 (index * 2) + 0, addrtmp[0]);
824 (index * 2) + 0, addrtmp[0]); 825 b43_shm_write16(dev, B43_SHM_RCMTA,
825 b43_shm_write16(dev, B43_SHM_RCMTA, 826 (index * 2) + 1, addrtmp[1]);
826 (index * 2) + 1, addrtmp[1]);
827 } else {
828 /* RXE (Receive Engine) and
829 * PSM (Programmable State Machine) mechanism
830 */
831 if (index < 8) {
832 /* TODO write to RCM 16, 19, 22 and 25 */
833 } else {
834 b43_shm_write32(dev, B43_SHM_SHARED,
835 B43_SHM_SH_PSM + (index * 6) + 0,
836 addrtmp[0]);
837 b43_shm_write16(dev, B43_SHM_SHARED,
838 B43_SHM_SH_PSM + (index * 6) + 4,
839 addrtmp[1]);
840 }
841 }
842} 827}
843 828
844static void do_key_write(struct b43_wldev *dev, 829static void do_key_write(struct b43_wldev *dev,
@@ -846,20 +831,20 @@ static void do_key_write(struct b43_wldev *dev,
846 const u8 *key, size_t key_len, const u8 *mac_addr) 831 const u8 *key, size_t key_len, const u8 *mac_addr)
847{ 832{
848 u8 buf[B43_SEC_KEYSIZE] = { 0, }; 833 u8 buf[B43_SEC_KEYSIZE] = { 0, };
849 u8 per_sta_keys_start = 8; 834 u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
850 835
851 if (b43_new_kidx_api(dev)) 836 if (b43_new_kidx_api(dev))
852 per_sta_keys_start = 4; 837 pairwise_keys_start = B43_NR_GROUP_KEYS;
853 838
854 B43_WARN_ON(index >= dev->max_nr_keys); 839 B43_WARN_ON(index >= ARRAY_SIZE(dev->key));
855 B43_WARN_ON(key_len > B43_SEC_KEYSIZE); 840 B43_WARN_ON(key_len > B43_SEC_KEYSIZE);
856 841
857 if (index >= per_sta_keys_start) 842 if (index >= pairwise_keys_start)
858 keymac_write(dev, index, NULL); /* First zero out mac. */ 843 keymac_write(dev, index, NULL); /* First zero out mac. */
859 if (key) 844 if (key)
860 memcpy(buf, key, key_len); 845 memcpy(buf, key, key_len);
861 key_write(dev, index, algorithm, buf); 846 key_write(dev, index, algorithm, buf);
862 if (index >= per_sta_keys_start) 847 if (index >= pairwise_keys_start)
863 keymac_write(dev, index, mac_addr); 848 keymac_write(dev, index, mac_addr);
864 849
865 dev->key[index].algorithm = algorithm; 850 dev->key[index].algorithm = algorithm;
@@ -872,21 +857,24 @@ static int b43_key_write(struct b43_wldev *dev,
872 struct ieee80211_key_conf *keyconf) 857 struct ieee80211_key_conf *keyconf)
873{ 858{
874 int i; 859 int i;
875 int sta_keys_start; 860 int pairwise_keys_start;
876 861
877 if (key_len > B43_SEC_KEYSIZE) 862 if (key_len > B43_SEC_KEYSIZE)
878 return -EINVAL; 863 return -EINVAL;
879 for (i = 0; i < dev->max_nr_keys; i++) { 864 for (i = 0; i < ARRAY_SIZE(dev->key); i++) {
880 /* Check that we don't already have this key. */ 865 /* Check that we don't already have this key. */
881 B43_WARN_ON(dev->key[i].keyconf == keyconf); 866 B43_WARN_ON(dev->key[i].keyconf == keyconf);
882 } 867 }
883 if (index < 0) { 868 if (index < 0) {
884 /* Pairwise key. Get an empty slot for the key. */ 869 /* Pairwise key. Get an empty slot for the key. */
885 if (b43_new_kidx_api(dev)) 870 if (b43_new_kidx_api(dev))
886 sta_keys_start = 4; 871 pairwise_keys_start = B43_NR_GROUP_KEYS;
887 else 872 else
888 sta_keys_start = 8; 873 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
889 for (i = sta_keys_start; i < dev->max_nr_keys; i++) { 874 for (i = pairwise_keys_start;
875 i < pairwise_keys_start + B43_NR_PAIRWISE_KEYS;
876 i++) {
877 B43_WARN_ON(i >= ARRAY_SIZE(dev->key));
890 if (!dev->key[i].keyconf) { 878 if (!dev->key[i].keyconf) {
891 /* found empty */ 879 /* found empty */
892 index = i; 880 index = i;
@@ -914,7 +902,7 @@ static int b43_key_write(struct b43_wldev *dev,
914 902
915static int b43_key_clear(struct b43_wldev *dev, int index) 903static int b43_key_clear(struct b43_wldev *dev, int index)
916{ 904{
917 if (B43_WARN_ON((index < 0) || (index >= dev->max_nr_keys))) 905 if (B43_WARN_ON((index < 0) || (index >= ARRAY_SIZE(dev->key))))
918 return -EINVAL; 906 return -EINVAL;
919 do_key_write(dev, index, B43_SEC_ALGO_NONE, 907 do_key_write(dev, index, B43_SEC_ALGO_NONE,
920 NULL, B43_SEC_KEYSIZE, NULL); 908 NULL, B43_SEC_KEYSIZE, NULL);
@@ -929,15 +917,19 @@ static int b43_key_clear(struct b43_wldev *dev, int index)
929 917
930static void b43_clear_keys(struct b43_wldev *dev) 918static void b43_clear_keys(struct b43_wldev *dev)
931{ 919{
932 int i; 920 int i, count;
933 921
934 for (i = 0; i < dev->max_nr_keys; i++) 922 if (b43_new_kidx_api(dev))
923 count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
924 else
925 count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
926 for (i = 0; i < count; i++)
935 b43_key_clear(dev, i); 927 b43_key_clear(dev, i);
936} 928}
937 929
938static void b43_dump_keymemory(struct b43_wldev *dev) 930static void b43_dump_keymemory(struct b43_wldev *dev)
939{ 931{
940 unsigned int i, index, offset; 932 unsigned int i, index, count, offset, pairwise_keys_start;
941 u8 mac[ETH_ALEN]; 933 u8 mac[ETH_ALEN];
942 u16 algo; 934 u16 algo;
943 u32 rcmta0; 935 u32 rcmta0;
@@ -951,7 +943,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
951 hf = b43_hf_read(dev); 943 hf = b43_hf_read(dev);
952 b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", 944 b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n",
953 !!(hf & B43_HF_USEDEFKEYS)); 945 !!(hf & B43_HF_USEDEFKEYS));
954 for (index = 0; index < dev->max_nr_keys; index++) { 946 if (b43_new_kidx_api(dev)) {
947 pairwise_keys_start = B43_NR_GROUP_KEYS;
948 count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS;
949 } else {
950 pairwise_keys_start = B43_NR_GROUP_KEYS * 2;
951 count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS;
952 }
953 for (index = 0; index < count; index++) {
955 key = &(dev->key[index]); 954 key = &(dev->key[index]);
956 printk(KERN_DEBUG "Key slot %02u: %s", 955 printk(KERN_DEBUG "Key slot %02u: %s",
957 index, (key->keyconf == NULL) ? " " : "*"); 956 index, (key->keyconf == NULL) ? " " : "*");
@@ -965,11 +964,11 @@ static void b43_dump_keymemory(struct b43_wldev *dev)
965 B43_SHM_SH_KEYIDXBLOCK + (index * 2)); 964 B43_SHM_SH_KEYIDXBLOCK + (index * 2));
966 printk(" Algo: %04X/%02X", algo, key->algorithm); 965 printk(" Algo: %04X/%02X", algo, key->algorithm);
967 966
968 if (index >= 4) { 967 if (index >= pairwise_keys_start) {
969 rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, 968 rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
970 ((index - 4) * 2) + 0); 969 ((index - pairwise_keys_start) * 2) + 0);
971 rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, 970 rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
972 ((index - 4) * 2) + 1); 971 ((index - pairwise_keys_start) * 2) + 1);
973 *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); 972 *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0);
974 *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); 973 *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1);
975 printk(" MAC: %pM", mac); 974 printk(" MAC: %pM", mac);
@@ -1429,116 +1428,6 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
1429 b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); 1428 b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset);
1430} 1429}
1431 1430
1432static void b43_write_probe_resp_plcp(struct b43_wldev *dev,
1433 u16 shm_offset, u16 size,
1434 struct ieee80211_rate *rate)
1435{
1436 struct b43_plcp_hdr4 plcp;
1437 u32 tmp;
1438 __le16 dur;
1439
1440 plcp.data = 0;
1441 b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
1442 dur = ieee80211_generic_frame_duration(dev->wl->hw,
1443 dev->wl->vif, size,
1444 rate);
1445 /* Write PLCP in two parts and timing for packet transfer */
1446 tmp = le32_to_cpu(plcp.data);
1447 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset, tmp & 0xFFFF);
1448 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 2, tmp >> 16);
1449 b43_shm_write16(dev, B43_SHM_SHARED, shm_offset + 6, le16_to_cpu(dur));
1450}
1451
1452/* Instead of using custom probe response template, this function
1453 * just patches custom beacon template by:
1454 * 1) Changing packet type
1455 * 2) Patching duration field
1456 * 3) Stripping TIM
1457 */
1458static const u8 *b43_generate_probe_resp(struct b43_wldev *dev,
1459 u16 *dest_size,
1460 struct ieee80211_rate *rate)
1461{
1462 const u8 *src_data;
1463 u8 *dest_data;
1464 u16 src_size, elem_size, src_pos, dest_pos;
1465 __le16 dur;
1466 struct ieee80211_hdr *hdr;
1467 size_t ie_start;
1468
1469 src_size = dev->wl->current_beacon->len;
1470 src_data = (const u8 *)dev->wl->current_beacon->data;
1471
1472 /* Get the start offset of the variable IEs in the packet. */
1473 ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
1474 B43_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, u.beacon.variable));
1475
1476 if (B43_WARN_ON(src_size < ie_start))
1477 return NULL;
1478
1479 dest_data = kmalloc(src_size, GFP_ATOMIC);
1480 if (unlikely(!dest_data))
1481 return NULL;
1482
1483 /* Copy the static data and all Information Elements, except the TIM. */
1484 memcpy(dest_data, src_data, ie_start);
1485 src_pos = ie_start;
1486 dest_pos = ie_start;
1487 for ( ; src_pos < src_size - 2; src_pos += elem_size) {
1488 elem_size = src_data[src_pos + 1] + 2;
1489 if (src_data[src_pos] == 5) {
1490 /* This is the TIM. */
1491 continue;
1492 }
1493 memcpy(dest_data + dest_pos, src_data + src_pos,
1494 elem_size);
1495 dest_pos += elem_size;
1496 }
1497 *dest_size = dest_pos;
1498 hdr = (struct ieee80211_hdr *)dest_data;
1499
1500 /* Set the frame control. */
1501 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
1502 IEEE80211_STYPE_PROBE_RESP);
1503 dur = ieee80211_generic_frame_duration(dev->wl->hw,
1504 dev->wl->vif, *dest_size,
1505 rate);
1506 hdr->duration_id = dur;
1507
1508 return dest_data;
1509}
1510
1511static void b43_write_probe_resp_template(struct b43_wldev *dev,
1512 u16 ram_offset,
1513 u16 shm_size_offset,
1514 struct ieee80211_rate *rate)
1515{
1516 const u8 *probe_resp_data;
1517 u16 size;
1518
1519 size = dev->wl->current_beacon->len;
1520 probe_resp_data = b43_generate_probe_resp(dev, &size, rate);
1521 if (unlikely(!probe_resp_data))
1522 return;
1523
1524 /* Looks like PLCP headers plus packet timings are stored for
1525 * all possible basic rates
1526 */
1527 /* FIXME this is the wrong offset : it goes in tkip rx phase1 shm */
1528#if 0
1529 b43_write_probe_resp_plcp(dev, 0x31A, size, &b43_b_ratetable[0]);
1530 b43_write_probe_resp_plcp(dev, 0x32C, size, &b43_b_ratetable[1]);
1531 b43_write_probe_resp_plcp(dev, 0x33E, size, &b43_b_ratetable[2]);
1532 b43_write_probe_resp_plcp(dev, 0x350, size, &b43_b_ratetable[3]);
1533#endif
1534
1535 size = min((size_t) size, 0x200 - sizeof(struct b43_plcp_hdr6));
1536 b43_write_template_common(dev, probe_resp_data,
1537 size, ram_offset, shm_size_offset,
1538 rate->hw_value);
1539 kfree(probe_resp_data);
1540}
1541
1542static void b43_upload_beacon0(struct b43_wldev *dev) 1431static void b43_upload_beacon0(struct b43_wldev *dev)
1543{ 1432{
1544 struct b43_wl *wl = dev->wl; 1433 struct b43_wl *wl = dev->wl;
@@ -1546,10 +1435,6 @@ static void b43_upload_beacon0(struct b43_wldev *dev)
1546 if (wl->beacon0_uploaded) 1435 if (wl->beacon0_uploaded)
1547 return; 1436 return;
1548 b43_write_beacon_template(dev, 0x68, 0x18); 1437 b43_write_beacon_template(dev, 0x68, 0x18);
1549 /* FIXME: Probe resp upload doesn't really belong here,
1550 * but we don't use that feature anyway. */
1551 b43_write_probe_resp_template(dev, 0x268, 0x4A,
1552 &__b43_ratetable[3]);
1553 wl->beacon0_uploaded = 1; 1438 wl->beacon0_uploaded = 1;
1554} 1439}
1555 1440
@@ -2990,17 +2875,14 @@ error:
2990 2875
2991static void b43_security_init(struct b43_wldev *dev) 2876static void b43_security_init(struct b43_wldev *dev)
2992{ 2877{
2993 dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20;
2994 B43_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key));
2995 dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP); 2878 dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP);
2996 /* KTP is a word address, but we address SHM bytewise. 2879 /* KTP is a word address, but we address SHM bytewise.
2997 * So multiply by two. 2880 * So multiply by two.
2998 */ 2881 */
2999 dev->ktp *= 2; 2882 dev->ktp *= 2;
3000 if (dev->dev->id.revision >= 5) { 2883 /* Number of RCMTA address slots */
3001 /* Number of RCMTA address slots */ 2884 b43_write16(dev, B43_MMIO_RCMTA_COUNT, B43_NR_PAIRWISE_KEYS);
3002 b43_write16(dev, B43_MMIO_RCMTA_COUNT, dev->max_nr_keys - 8); 2885 /* Clear the key memory. */
3003 }
3004 b43_clear_keys(dev); 2886 b43_clear_keys(dev);
3005} 2887}
3006 2888
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c
index aa1486a1354b..cfb8337d3859 100644
--- a/drivers/net/wireless/b43/phy_lp.c
+++ b/drivers/net/wireless/b43/phy_lp.c
@@ -59,9 +59,126 @@ static void b43_lpphy_op_free(struct b43_wldev *dev)
59 dev->phy.lp = NULL; 59 dev->phy.lp = NULL;
60} 60}
61 61
62static void lpphy_read_band_sprom(struct b43_wldev *dev)
63{
64 struct b43_phy_lp *lpphy = dev->phy.lp;
65 struct ssb_bus *bus = dev->dev->bus;
66 u16 cckpo, maxpwr;
67 u32 ofdmpo;
68 int i;
69
70 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
71 lpphy->tx_isolation_med_band = bus->sprom.tri2g;
72 lpphy->bx_arch = bus->sprom.bxa2g;
73 lpphy->rx_pwr_offset = bus->sprom.rxpo2g;
74 lpphy->rssi_vf = bus->sprom.rssismf2g;
75 lpphy->rssi_vc = bus->sprom.rssismc2g;
76 lpphy->rssi_gs = bus->sprom.rssisav2g;
77 lpphy->txpa[0] = bus->sprom.pa0b0;
78 lpphy->txpa[1] = bus->sprom.pa0b1;
79 lpphy->txpa[2] = bus->sprom.pa0b2;
80 maxpwr = bus->sprom.maxpwr_bg;
81 lpphy->max_tx_pwr_med_band = maxpwr;
82 cckpo = bus->sprom.cck2gpo;
83 ofdmpo = bus->sprom.ofdm2gpo;
84 if (cckpo) {
85 for (i = 0; i < 4; i++) {
86 lpphy->tx_max_rate[i] =
87 maxpwr - (ofdmpo & 0xF) * 2;
88 ofdmpo >>= 4;
89 }
90 ofdmpo = bus->sprom.ofdm2gpo;
91 for (i = 4; i < 15; i++) {
92 lpphy->tx_max_rate[i] =
93 maxpwr - (ofdmpo & 0xF) * 2;
94 ofdmpo >>= 4;
95 }
96 } else {
97 ofdmpo &= 0xFF;
98 for (i = 0; i < 4; i++)
99 lpphy->tx_max_rate[i] = maxpwr;
100 for (i = 4; i < 15; i++)
101 lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
102 }
103 } else { /* 5GHz */
104 lpphy->tx_isolation_low_band = bus->sprom.tri5gl;
105 lpphy->tx_isolation_med_band = bus->sprom.tri5g;
106 lpphy->tx_isolation_hi_band = bus->sprom.tri5gh;
107 lpphy->bx_arch = bus->sprom.bxa5g;
108 lpphy->rx_pwr_offset = bus->sprom.rxpo5g;
109 lpphy->rssi_vf = bus->sprom.rssismf5g;
110 lpphy->rssi_vc = bus->sprom.rssismc5g;
111 lpphy->rssi_gs = bus->sprom.rssisav5g;
112 lpphy->txpa[0] = bus->sprom.pa1b0;
113 lpphy->txpa[1] = bus->sprom.pa1b1;
114 lpphy->txpa[2] = bus->sprom.pa1b2;
115 lpphy->txpal[0] = bus->sprom.pa1lob0;
116 lpphy->txpal[1] = bus->sprom.pa1lob1;
117 lpphy->txpal[2] = bus->sprom.pa1lob2;
118 lpphy->txpah[0] = bus->sprom.pa1hib0;
119 lpphy->txpah[1] = bus->sprom.pa1hib1;
120 lpphy->txpah[2] = bus->sprom.pa1hib2;
121 maxpwr = bus->sprom.maxpwr_al;
122 ofdmpo = bus->sprom.ofdm5glpo;
123 lpphy->max_tx_pwr_low_band = maxpwr;
124 for (i = 4; i < 12; i++) {
125 lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
126 ofdmpo >>= 4;
127 }
128 maxpwr = bus->sprom.maxpwr_a;
129 ofdmpo = bus->sprom.ofdm5gpo;
130 lpphy->max_tx_pwr_med_band = maxpwr;
131 for (i = 4; i < 12; i++) {
132 lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
133 ofdmpo >>= 4;
134 }
135 maxpwr = bus->sprom.maxpwr_ah;
136 ofdmpo = bus->sprom.ofdm5ghpo;
137 lpphy->max_tx_pwr_hi_band = maxpwr;
138 for (i = 4; i < 12; i++) {
139 lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
140 ofdmpo >>= 4;
141 }
142 }
143}
144
145static void lpphy_adjust_gain_table(struct b43_wldev *dev)
146{
147 struct b43_phy_lp *lpphy = dev->phy.lp;
148 u32 freq = dev->wl->hw->conf.channel->center_freq;
149 u16 temp[3];
150 u16 isolation;
151
152 B43_WARN_ON(dev->phy.rev >= 2);
153
154 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
155 isolation = lpphy->tx_isolation_med_band;
156 else if (freq <= 5320)
157 isolation = lpphy->tx_isolation_low_band;
158 else if (freq <= 5700)
159 isolation = lpphy->tx_isolation_med_band;
160 else
161 isolation = lpphy->tx_isolation_hi_band;
162
163 temp[0] = ((isolation - 26) / 12) << 12;
164 temp[1] = temp[0] + 0x1000;
165 temp[2] = temp[0] + 0x2000;
166
167 b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
168 b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
169}
170
62static void lpphy_table_init(struct b43_wldev *dev) 171static void lpphy_table_init(struct b43_wldev *dev)
63{ 172{
64 //TODO 173 if (dev->phy.rev < 2)
174 lpphy_rev0_1_table_init(dev);
175 else
176 lpphy_rev2plus_table_init(dev);
177
178 lpphy_init_tx_gain_table(dev);
179
180 if (dev->phy.rev < 2)
181 lpphy_adjust_gain_table(dev);
65} 182}
66 183
67static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) 184static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
@@ -130,7 +247,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
130 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); 247 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
131 b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); 248 b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
132 b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); 249 b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
133 b43_hf_write(dev, b43_hf_read(dev) | 0x0800ULL << 32); 250 b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W);
134 } 251 }
135 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 252 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
136 b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); 253 b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
@@ -161,6 +278,56 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
161 } 278 }
162} 279}
163 280
281static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
282{
283 static const u16 addr[] = {
284 B43_PHY_OFDM(0xC1),
285 B43_PHY_OFDM(0xC2),
286 B43_PHY_OFDM(0xC3),
287 B43_PHY_OFDM(0xC4),
288 B43_PHY_OFDM(0xC5),
289 B43_PHY_OFDM(0xC6),
290 B43_PHY_OFDM(0xC7),
291 B43_PHY_OFDM(0xC8),
292 B43_PHY_OFDM(0xCF),
293 };
294
295 static const u16 coefs[] = {
296 0xDE5E, 0xE832, 0xE331, 0x4D26,
297 0x0026, 0x1420, 0x0020, 0xFE08,
298 0x0008,
299 };
300
301 struct b43_phy_lp *lpphy = dev->phy.lp;
302 int i;
303
304 for (i = 0; i < ARRAY_SIZE(addr); i++) {
305 lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]);
306 b43_phy_write(dev, addr[i], coefs[i]);
307 }
308}
309
310static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
311{
312 static const u16 addr[] = {
313 B43_PHY_OFDM(0xC1),
314 B43_PHY_OFDM(0xC2),
315 B43_PHY_OFDM(0xC3),
316 B43_PHY_OFDM(0xC4),
317 B43_PHY_OFDM(0xC5),
318 B43_PHY_OFDM(0xC6),
319 B43_PHY_OFDM(0xC7),
320 B43_PHY_OFDM(0xC8),
321 B43_PHY_OFDM(0xCF),
322 };
323
324 struct b43_phy_lp *lpphy = dev->phy.lp;
325 int i;
326
327 for (i = 0; i < ARRAY_SIZE(addr); i++)
328 b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
329}
330
164static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) 331static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
165{ 332{
166 struct ssb_bus *bus = dev->dev->bus; 333 struct ssb_bus *bus = dev->dev->bus;
@@ -175,7 +342,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
175 b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0); 342 b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0);
176 b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0); 343 b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0);
177 b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10); 344 b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10);
178 b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x78); 345 b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4);
179 b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200); 346 b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200);
180 b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F); 347 b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F);
181 b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40); 348 b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40);
@@ -183,7 +350,12 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
183 b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); 350 b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
184 b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); 351 b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
185 b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); 352 b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
186 b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10); 353 if (bus->boardinfo.rev >= 0x18) {
354 b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
355 b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
356 } else {
357 b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
358 }
187 b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); 359 b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4);
188 b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); 360 b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);
189 b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); 361 b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48);
@@ -213,8 +385,10 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
213 b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); 385 b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
214 b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); 386 b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
215 387
216 b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); 388 if ((bus->chip_id == 0x4325) && (bus->chip_rev == 1)) {
217 b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); 389 b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
390 b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
391 }
218 392
219 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 393 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
220 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); 394 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40);
@@ -234,6 +408,14 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
234 b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1, 408 b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1,
235 0x2000 | ((u16)lpphy->rssi_gs << 10) | 409 0x2000 | ((u16)lpphy->rssi_gs << 10) |
236 ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); 410 ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
411
412 if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
413 b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
414 b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
415 b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
416 }
417
418 lpphy_save_dig_flt_state(dev);
237} 419}
238 420
239static void lpphy_baseband_init(struct b43_wldev *dev) 421static void lpphy_baseband_init(struct b43_wldev *dev)
@@ -333,12 +515,73 @@ static void lpphy_2062_init(struct b43_wldev *dev)
333/* Initialize the 2063 radio. */ 515/* Initialize the 2063 radio. */
334static void lpphy_2063_init(struct b43_wldev *dev) 516static void lpphy_2063_init(struct b43_wldev *dev)
335{ 517{
336 //TODO 518 b2063_upload_init_table(dev);
519 b43_radio_write(dev, B2063_LOGEN_SP5, 0);
520 b43_radio_set(dev, B2063_COMM8, 0x38);
521 b43_radio_write(dev, B2063_REG_SP1, 0x56);
522 b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2);
523 b43_radio_write(dev, B2063_PA_SP7, 0);
524 b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
525 b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
526 b43_radio_write(dev, B2063_PA_SP3, 0xa0);
527 b43_radio_write(dev, B2063_PA_SP4, 0xa0);
528 b43_radio_write(dev, B2063_PA_SP2, 0x18);
337} 529}
338 530
531struct lpphy_stx_table_entry {
532 u16 phy_offset;
533 u16 phy_shift;
534 u16 rf_addr;
535 u16 rf_shift;
536 u16 mask;
537};
538
539static const struct lpphy_stx_table_entry lpphy_stx_table[] = {
540 { .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, },
541 { .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, },
542 { .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, },
543 { .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, },
544 { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, },
545 { .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, },
546 { .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, },
547 { .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, },
548 { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, },
549 { .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, },
550 { .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, },
551 { .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, },
552 { .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, },
553 { .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, },
554 { .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, },
555 { .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, },
556 { .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, },
557 { .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, },
558 { .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, },
559 { .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, },
560 { .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, },
561 { .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, },
562 { .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, },
563 { .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, },
564 { .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, },
565 { .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, },
566 { .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, },
567 { .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, },
568 { .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, },
569};
570
339static void lpphy_sync_stx(struct b43_wldev *dev) 571static void lpphy_sync_stx(struct b43_wldev *dev)
340{ 572{
341 //TODO 573 const struct lpphy_stx_table_entry *e;
574 unsigned int i;
575 u16 tmp;
576
577 for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) {
578 e = &lpphy_stx_table[i];
579 tmp = b43_radio_read(dev, e->rf_addr);
580 tmp >>= e->rf_shift;
581 tmp <<= e->phy_shift;
582 b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset),
583 ~(e->mask << e->phy_shift), tmp);
584 }
342} 585}
343 586
344static void lpphy_radio_init(struct b43_wldev *dev) 587static void lpphy_radio_init(struct b43_wldev *dev)
@@ -356,8 +599,343 @@ static void lpphy_radio_init(struct b43_wldev *dev)
356 lpphy_sync_stx(dev); 599 lpphy_sync_stx(dev);
357 b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); 600 b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
358 b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); 601 b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
359 //TODO Do something on the backplane 602 if (dev->dev->bus->chip_id == 0x4325) {
603 // TODO SSB PMU recalibration
604 }
605 }
606}
607
608struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
609
610static void lpphy_set_rc_cap(struct b43_wldev *dev)
611{
612 u8 rc_cap = dev->phy.lp->rc_cap;
613
614 b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80));
615 b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80);
616 b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80);
617}
618
619static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
620{
621 return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
622}
623
624static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
625{
626 b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
627}
628
629static void lpphy_disable_crs(struct b43_wldev *dev)
630{
631 b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
632 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1);
633 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
634 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
635 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
636 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
637 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
638 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
639 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
640 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
641 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
642 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
643 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
644 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
645 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
646 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
647 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
648 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
649 b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
650 b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
651 b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
652 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
653 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
654 b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
655 b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
656 b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
657}
658
659static void lpphy_restore_crs(struct b43_wldev *dev)
660{
661 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
662 b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60);
663 else
664 b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20);
665 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
666 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
667}
668
669struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
670
671static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
672{
673 struct lpphy_tx_gains gains;
674 u16 tmp;
675
676 gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
677 if (dev->phy.rev < 2) {
678 tmp = b43_phy_read(dev,
679 B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
680 gains.gm = tmp & 0x0007;
681 gains.pga = (tmp & 0x0078) >> 3;
682 gains.pad = (tmp & 0x780) >> 7;
683 } else {
684 tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
685 gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
686 gains.gm = tmp & 0xFF;
687 gains.pga = (tmp >> 8) & 0xFF;
688 }
689
690 return gains;
691}
692
693static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
694{
695 u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
696 ctl |= dac << 7;
697 b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
698}
699
700static void lpphy_set_tx_gains(struct b43_wldev *dev,
701 struct lpphy_tx_gains gains)
702{
703 u16 rf_gain, pa_gain;
704
705 if (dev->phy.rev < 2) {
706 rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
707 b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
708 0xF800, rf_gain);
709 } else {
710 pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00;
711 b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
712 (gains.pga << 8) | gains.gm);
713 b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
714 0x8000, gains.pad | pa_gain);
715 b43_phy_write(dev, B43_PHY_OFDM(0xFC),
716 (gains.pga << 8) | gains.gm);
717 b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
718 0x8000, gains.pad | pa_gain);
719 }
720 lpphy_set_dac_gain(dev, gains.dac);
721 if (dev->phy.rev < 2) {
722 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8);
723 } else {
724 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7);
725 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14);
726 }
727 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4);
728}
729
730static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
731{
732 u16 trsw = gain & 0x1;
733 u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
734 u16 ext_lna = (gain & 2) >> 1;
735
736 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
737 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
738 0xFBFF, ext_lna << 10);
739 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
740 0xF7FF, ext_lna << 11);
741 b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
742}
743
744static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
745{
746 u16 low_gain = gain & 0xFFFF;
747 u16 high_gain = (gain >> 16) & 0xF;
748 u16 ext_lna = (gain >> 21) & 0x1;
749 u16 trsw = ~(gain >> 20) & 0x1;
750 u16 tmp;
751
752 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
753 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
754 0xFDFF, ext_lna << 9);
755 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
756 0xFBFF, ext_lna << 10);
757 b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
758 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
759 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
760 tmp = (gain >> 2) & 0x3;
761 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
762 0xE7FF, tmp<<11);
763 b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
764 }
765}
766
767static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
768{
769 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
770 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
771 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
772 if (dev->phy.rev >= 2) {
773 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
774 if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
775 return;
776 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
777 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7);
778 } else {
779 b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
780 }
781}
782
783static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
784{
785 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
786 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
787 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
788 if (dev->phy.rev >= 2) {
789 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
790 if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ)
791 return;
792 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
793 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8);
794 } else {
795 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
796 }
797}
798
799static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
800{
801 if (dev->phy.rev < 2)
802 lpphy_rev0_1_set_rx_gain(dev, gain);
803 else
804 lpphy_rev2plus_set_rx_gain(dev, gain);
805 lpphy_enable_rx_gain_override(dev);
806}
807
808static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
809{
810 u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
811 lpphy_set_rx_gain(dev, gain);
812}
813
814static void lpphy_stop_ddfs(struct b43_wldev *dev)
815{
816 b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
817 b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
818}
819
820static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
821 int incr1, int incr2, int scale_idx)
822{
823 lpphy_stop_ddfs(dev);
824 b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
825 b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
826 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
827 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
828 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
829 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
830 b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
831 b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
832 b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
833 b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x20);
834}
835
836static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
837 struct lpphy_iq_est *iq_est)
838{
839 int i;
840
841 b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
842 b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
843 b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
844 b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
845 b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFDFF);
846
847 for (i = 0; i < 500; i++) {
848 if (!(b43_phy_read(dev,
849 B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
850 break;
851 msleep(1);
852 }
853
854 if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
855 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
856 return false;
857 }
858
859 iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
860 iq_est->iq_prod <<= 16;
861 iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
862
863 iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
864 iq_est->i_pwr <<= 16;
865 iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
866
867 iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
868 iq_est->q_pwr <<= 16;
869 iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
870
871 b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
872 return true;
873}
874
875static int lpphy_loopback(struct b43_wldev *dev)
876{
877 struct lpphy_iq_est iq_est;
878 int i, index = -1;
879 u32 tmp;
880
881 memset(&iq_est, 0, sizeof(iq_est));
882
883 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3);
884 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
885 b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
886 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
887 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
888 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
889 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
890 b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
891 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
892 b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
893 for (i = 0; i < 32; i++) {
894 lpphy_set_rx_gain_by_index(dev, i);
895 lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
896 if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
897 continue;
898 tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
899 if ((tmp > 4000) && (tmp < 10000)) {
900 index = i;
901 break;
902 }
360 } 903 }
904 lpphy_stop_ddfs(dev);
905 return index;
906}
907
908static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
909{
910 u32 quotient, remainder, rbit, roundup, tmp;
911
912 if (divisor == 0) {
913 quotient = 0;
914 remainder = 0;
915 } else {
916 quotient = dividend / divisor;
917 remainder = dividend % divisor;
918 }
919
920 rbit = divisor & 0x1;
921 roundup = (divisor >> 1) + rbit;
922 precision--;
923
924 while (precision != 0xFF) {
925 tmp = remainder - roundup;
926 quotient <<= 1;
927 remainder <<= 1;
928 if (remainder >= roundup) {
929 remainder = (tmp << 1) + rbit;
930 quotient--;
931 }
932 precision--;
933 }
934
935 if (remainder >= roundup)
936 quotient++;
937
938 return quotient;
361} 939}
362 940
363/* Read the TX power control mode from hardware. */ 941/* Read the TX power control mode from hardware. */
@@ -444,6 +1022,170 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev,
444 lpphy_write_tx_pctl_mode_to_hardware(dev); 1022 lpphy_write_tx_pctl_mode_to_hardware(dev);
445} 1023}
446 1024
1025static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
1026{
1027 struct b43_phy_lp *lpphy = dev->phy.lp;
1028 struct lpphy_iq_est iq_est;
1029 struct lpphy_tx_gains tx_gains;
1030 static const u32 ideal_pwr_table[22] = {
1031 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
1032 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
1033 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
1034 0x0004c, 0x0002c, 0x0001a, 0xc0006,
1035 };
1036 bool old_txg_ovr;
1037 u8 old_bbmult;
1038 u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
1039 old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl;
1040 u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
1041 int loopback, i, j, inner_sum;
1042
1043 memset(&iq_est, 0, sizeof(iq_est));
1044
1045 b43_switch_channel(dev, 7);
1046 old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1;
1047 old_bbmult = lpphy_get_bb_mult(dev);
1048 if (old_txg_ovr)
1049 tx_gains = lpphy_get_tx_gains(dev);
1050 old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
1051 old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
1052 old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
1053 old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
1054 old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
1055 old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
1056 old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
1057 old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) &
1058 B43_LPPHY_TX_PWR_CTL_CMD_MODE;
1059
1060 lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
1061 lpphy_disable_crs(dev);
1062 loopback = lpphy_loopback(dev);
1063 if (loopback == -1)
1064 goto finish;
1065 lpphy_set_rx_gain_by_index(dev, loopback);
1066 b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
1067 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
1068 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
1069 b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
1070 for (i = 128; i <= 159; i++) {
1071 b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
1072 inner_sum = 0;
1073 for (j = 5; j <= 25; j++) {
1074 lpphy_run_ddfs(dev, 1, 1, j, j, 0);
1075 if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
1076 goto finish;
1077 mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
1078 if (j == 5)
1079 tmp = mean_sq_pwr;
1080 ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
1081 normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
1082 mean_sq_pwr = ideal_pwr - normal_pwr;
1083 mean_sq_pwr *= mean_sq_pwr;
1084 inner_sum += mean_sq_pwr;
1085 if ((i = 128) || (inner_sum < mean_sq_pwr_min)) {
1086 lpphy->rc_cap = i;
1087 mean_sq_pwr_min = inner_sum;
1088 }
1089 }
1090 }
1091 lpphy_stop_ddfs(dev);
1092
1093finish:
1094 lpphy_restore_crs(dev);
1095 b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
1096 b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
1097 b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
1098 b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
1099 b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
1100 b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
1101 b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
1102
1103 lpphy_set_bb_mult(dev, old_bbmult);
1104 if (old_txg_ovr) {
1105 /*
1106 * SPEC FIXME: The specs say "get_tx_gains" here, which is
1107 * illogical. According to lwfinger, vendor driver v4.150.10.5
1108 * has a Set here, while v4.174.64.19 has a Get - regression in
1109 * the vendor driver? This should be tested this once the code
1110 * is testable.
1111 */
1112 lpphy_set_tx_gains(dev, tx_gains);
1113 }
1114 lpphy_set_tx_power_control(dev, old_txpctl);
1115 if (lpphy->rc_cap)
1116 lpphy_set_rc_cap(dev);
1117}
1118
1119static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
1120{
1121 struct ssb_bus *bus = dev->dev->bus;
1122 u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
1123 u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
1124 int i;
1125
1126 b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
1127 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1128 b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
1129 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
1130 b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
1131 b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
1132 b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
1133 b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
1134 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
1135
1136 for (i = 0; i < 10000; i++) {
1137 if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
1138 break;
1139 msleep(1);
1140 }
1141
1142 if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
1143 b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
1144
1145 tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
1146
1147 b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
1148 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1149 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
1150 b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
1151 b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
1152
1153 if (crystal_freq == 24000000) {
1154 b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
1155 b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
1156 } else {
1157 b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
1158 b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
1159 }
1160
1161 b43_radio_write(dev, B2063_PA_SP7, 0x7D);
1162
1163 for (i = 0; i < 10000; i++) {
1164 if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
1165 break;
1166 msleep(1);
1167 }
1168
1169 if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
1170 b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
1171
1172 b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1173}
1174
1175static void lpphy_calibrate_rc(struct b43_wldev *dev)
1176{
1177 struct b43_phy_lp *lpphy = dev->phy.lp;
1178
1179 if (dev->phy.rev >= 2) {
1180 lpphy_rev2plus_rc_calib(dev);
1181 } else if (!lpphy->rc_cap) {
1182 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1183 lpphy_rev0_1_rc_calib(dev);
1184 } else {
1185 lpphy_set_rc_cap(dev);
1186 }
1187}
1188
447static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) 1189static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
448{ 1190{
449 struct b43_phy_lp *lpphy = dev->phy.lp; 1191 struct b43_phy_lp *lpphy = dev->phy.lp;
@@ -532,13 +1274,14 @@ static void lpphy_tx_pctl_init(struct b43_wldev *dev)
532 1274
533static int b43_lpphy_op_init(struct b43_wldev *dev) 1275static int b43_lpphy_op_init(struct b43_wldev *dev)
534{ 1276{
535 /* TODO: band SPROM */ 1277 lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
536 lpphy_baseband_init(dev); 1278 lpphy_baseband_init(dev);
537 lpphy_radio_init(dev); 1279 lpphy_radio_init(dev);
538 //TODO calibrate RC 1280 lpphy_calibrate_rc(dev);
539 //TODO set channel 1281 //TODO set channel
540 lpphy_tx_pctl_init(dev); 1282 lpphy_tx_pctl_init(dev);
541 //TODO full calib 1283 lpphy_calibration(dev);
1284 //TODO ACI init
542 1285
543 return 0; 1286 return 0;
544} 1287}
@@ -616,7 +1359,6 @@ static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
616 return B43_TXPWR_RES_DONE; 1359 return B43_TXPWR_RES_DONE;
617} 1360}
618 1361
619
620const struct b43_phy_operations b43_phyops_lp = { 1362const struct b43_phy_operations b43_phyops_lp = {
621 .allocate = b43_lpphy_op_allocate, 1363 .allocate = b43_lpphy_op_allocate,
622 .free = b43_lpphy_op_free, 1364 .free = b43_lpphy_op_free,
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h
index 829b2bba3ee1..0461d5b3144f 100644
--- a/drivers/net/wireless/b43/phy_lp.h
+++ b/drivers/net/wireless/b43/phy_lp.h
@@ -831,6 +831,22 @@ struct b43_phy_lp {
831 /* Transmit isolation high band */ 831 /* Transmit isolation high band */
832 u8 tx_isolation_hi_band; /* FIXME initial value? */ 832 u8 tx_isolation_hi_band; /* FIXME initial value? */
833 833
834 /* Max transmit power medium band */
835 u16 max_tx_pwr_med_band;
836 /* Max transmit power low band */
837 u16 max_tx_pwr_low_band;
838 /* Max transmit power high band */
839 u16 max_tx_pwr_hi_band;
840
841 /* FIXME What are these used for? */
842 /* FIXME Is 15 the correct array size? */
843 u16 tx_max_rate[15];
844 u16 tx_max_ratel[15];
845 u16 tx_max_rateh[15];
846
847 /* Transmit power arrays */
848 s16 txpa[3], txpal[3], txpah[3];
849
834 /* Receive power offset */ 850 /* Receive power offset */
835 u8 rx_pwr_offset; /* FIXME initial value? */ 851 u8 rx_pwr_offset; /* FIXME initial value? */
836 852
@@ -865,6 +881,9 @@ struct b43_phy_lp {
865 /* Transmit iqlocal best coeffs */ 881 /* Transmit iqlocal best coeffs */
866 bool tx_iqloc_best_coeffs_valid; 882 bool tx_iqloc_best_coeffs_valid;
867 u8 tx_iqloc_best_coeffs[11]; 883 u8 tx_iqloc_best_coeffs[11];
884
885 /* Used for "Save/Restore Dig Filt State" */
886 u16 dig_flt_state[9];
868}; 887};
869 888
870 889
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c
index 4ea734dce218..2721310acb2a 100644
--- a/drivers/net/wireless/b43/tables_lpphy.c
+++ b/drivers/net/wireless/b43/tables_lpphy.c
@@ -28,22 +28,22 @@
28#include "phy_lp.h" 28#include "phy_lp.h"
29 29
30 30
31/* Entry of the 2062 radio init table */ 31/* Entry of the 2062/2063 radio init table */
32struct b2062_init_tab_entry { 32struct b206x_init_tab_entry {
33 u16 offset; 33 u16 offset;
34 u16 value_a; 34 u16 value_a;
35 u16 value_g; 35 u16 value_g;
36 u8 flags; 36 u8 flags;
37}; 37};
38#define B2062_FLAG_A 0x01 /* Flag: Init in A mode */ 38#define B206X_FLAG_A 0x01 /* Flag: Init in A mode */
39#define B2062_FLAG_G 0x02 /* Flag: Init in G mode */ 39#define B206X_FLAG_G 0x02 /* Flag: Init in G mode */
40 40
41static const struct b2062_init_tab_entry b2062_init_tab[] = { 41static const struct b206x_init_tab_entry b2062_init_tab[] = {
42 /* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 42 /* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
43 /* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 43 /* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
44 /* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 44 /* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
45 /* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 45 /* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
46 { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 46 { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
47 /* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 47 /* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
48 /* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 48 /* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
49 /* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 49 /* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -56,42 +56,42 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
56 /* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 56 /* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
57 /* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 57 /* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
58 /* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 58 /* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
59 { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B2062_FLAG_G, }, 59 { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B206X_FLAG_G, },
60 /* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ 60 /* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
61 { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 61 { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
62 { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 62 { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
63 /* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 63 /* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
64 /* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ 64 /* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
65 { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B2062_FLAG_A, }, 65 { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B206X_FLAG_A, },
66 /* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ 66 /* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
67 /* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ 67 /* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
68 /* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ 68 /* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
69 /* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ 69 /* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
70 /* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 70 /* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
71 /* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 71 /* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
72 { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 72 { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
73 /* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 73 /* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
74 { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 74 { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
75 { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 75 { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B206X_FLAG_A | B206X_FLAG_G, },
76 { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 76 { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
77 /* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */ 77 /* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */
78 /* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ 78 /* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
79 /* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ 79 /* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */
80 { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 80 { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
81 /* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */ 81 /* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
82 { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_G, }, 82 { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
83 /* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ 83 /* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */
84 /* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */ 84 /* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */
85 /* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */ 85 /* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
86 /* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ 86 /* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
87 /* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 87 /* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
88 /* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */ 88 /* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */
89 { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 89 { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
90 /* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 90 /* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
91 /* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 91 /* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
92 /* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 92 /* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
93 { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 93 { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
94 { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 94 { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
95 /* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ 95 /* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
96 /* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */ 96 /* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */
97 /* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ 97 /* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
@@ -112,8 +112,8 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
112 /* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 112 /* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
113 /* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */ 113 /* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */
114 /* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 114 /* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
115 { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 115 { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
116 { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 116 { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
117 /* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 117 /* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
118 /* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ 118 /* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
119 /* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */ 119 /* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */
@@ -121,7 +121,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
121 /* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 121 /* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
122 /* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ 122 /* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
123 /* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ 123 /* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */
124 { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 124 { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B206X_FLAG_A | B206X_FLAG_G, },
125 /* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ 125 /* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
126 /* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ 126 /* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
127 /* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ 127 /* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
@@ -150,7 +150,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
150 /* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 150 /* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
151 /* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 151 /* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
152 /* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 152 /* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
153 { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 153 { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, },
154 /* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 154 /* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
155 /* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 155 /* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
156 /* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 156 /* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -162,24 +162,24 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
162 /* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 162 /* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
163 /* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 163 /* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
164 /* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 164 /* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
165 { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 165 { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, },
166 /* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 166 /* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
167 /* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */ 167 /* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */
168 /* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 168 /* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
169 /* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ 169 /* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
170 /* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 170 /* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
171 /* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ 171 /* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
172 { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 172 { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B206X_FLAG_A | B206X_FLAG_G, },
173 { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 173 { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B206X_FLAG_A | B206X_FLAG_G, },
174 /* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 174 /* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
175 /* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ 175 /* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */
176 /* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ 176 /* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
177 /* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ 177 /* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
178 /* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ 178 /* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
179 /* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 179 /* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
180 { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 180 { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
181 /* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ 181 /* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
182 { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 182 { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, },
183 /* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 183 /* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
184 /* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 184 /* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
185 /* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ 185 /* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
@@ -198,41 +198,41 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
198 /* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */ 198 /* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */
199 /* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */ 199 /* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */
200 /* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 200 /* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
201 { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 201 { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B206X_FLAG_A | B206X_FLAG_G, },
202 { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 202 { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B206X_FLAG_A | B206X_FLAG_G, },
203 /* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 203 /* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
204 /* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 204 /* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
205 /* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 205 /* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
206 { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 206 { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B206X_FLAG_A | B206X_FLAG_G, },
207 { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 207 { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B206X_FLAG_A | B206X_FLAG_G, },
208 { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 208 { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
209 { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 209 { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
210 { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 210 { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, },
211 { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 211 { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
212 { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 212 { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
213 { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 213 { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, },
214 { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 214 { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B206X_FLAG_A | B206X_FLAG_G, },
215 { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 215 { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B206X_FLAG_A | B206X_FLAG_G, },
216 /* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 216 /* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
217 /* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 217 /* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
218 /* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 218 /* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
219 { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 219 { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B206X_FLAG_A | B206X_FLAG_G, },
220 { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 220 { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B206X_FLAG_A | B206X_FLAG_G, },
221 /* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 221 /* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
222 { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 222 { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B206X_FLAG_A | B206X_FLAG_G, },
223 { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 223 { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
224 { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 224 { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B206X_FLAG_A | B206X_FLAG_G, },
225 { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 225 { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B206X_FLAG_A | B206X_FLAG_G, },
226 { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 226 { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B206X_FLAG_A | B206X_FLAG_G, },
227 /* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 227 /* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
228 /* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 228 /* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
229 /* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 229 /* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
230 /* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 230 /* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
231 { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 231 { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B206X_FLAG_A | B206X_FLAG_G, },
232 { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 232 { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
233 /* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 233 /* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
234 { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 234 { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B206X_FLAG_A | B206X_FLAG_G, },
235 { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B2062_FLAG_A | B2062_FLAG_G, }, 235 { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, },
236 /* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ 236 /* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
237 /* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 237 /* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
238 /* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 238 /* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
@@ -241,7 +241,7 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
241 /* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ 241 /* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
242 /* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ 242 /* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
243 /* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ 243 /* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
244 { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B2062_FLAG_A, }, 244 { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B206X_FLAG_A, },
245 /* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ 245 /* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
246 /* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ 246 /* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
247 /* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ 247 /* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
@@ -253,19 +253,337 @@ static const struct b2062_init_tab_entry b2062_init_tab[] = {
253 /* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ 253 /* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
254}; 254};
255 255
256static const struct b206x_init_tab_entry b2063_init_tab[] = {
257 { .offset = B2063_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
258 /* { .offset = B2063_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
259 /* { .offset = B2063_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
260 /* { .offset = B2063_COMM4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
261 /* { .offset = B2063_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
262 /* { .offset = B2063_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
263 /* { .offset = B2063_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
264 /* { .offset = B2063_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
265 /* { .offset = B2063_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
266 { .offset = B2063_COMM10, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A, },
267 /* { .offset = B2063_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
268 /* { .offset = B2063_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
269 /* { .offset = B2063_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
270 /* { .offset = B2063_COMM14, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
271 /* { .offset = B2063_COMM15, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
272 { .offset = B2063_COMM16, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
273 { .offset = B2063_COMM17, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
274 { .offset = B2063_COMM18, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
275 { .offset = B2063_COMM19, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
276 { .offset = B2063_COMM20, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
277 { .offset = B2063_COMM21, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
278 { .offset = B2063_COMM22, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
279 { .offset = B2063_COMM23, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
280 { .offset = B2063_COMM24, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, },
281 /* { .offset = B2063_PWR_SWITCH_CTL, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
282 /* { .offset = B2063_PLL_SP1, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
283 /* { .offset = B2063_PLL_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
284 { .offset = B2063_LOGEN_SP1, .value_a = 0x00e8, .value_g = 0x00d4, .flags = B206X_FLAG_A | B206X_FLAG_G, },
285 { .offset = B2063_LOGEN_SP2, .value_a = 0x00a7, .value_g = 0x0053, .flags = B206X_FLAG_A | B206X_FLAG_G, },
286 /* { .offset = B2063_LOGEN_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
287 { .offset = B2063_LOGEN_SP4, .value_a = 0x00f0, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
288 /* { .offset = B2063_LOGEN_SP5, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
289 { .offset = B2063_G_RX_SP1, .value_a = 0x001f, .value_g = 0x005e, .flags = B206X_FLAG_G, },
290 { .offset = B2063_G_RX_SP2, .value_a = 0x007f, .value_g = 0x007e, .flags = B206X_FLAG_G, },
291 { .offset = B2063_G_RX_SP3, .value_a = 0x0030, .value_g = 0x00f0, .flags = B206X_FLAG_G, },
292 /* { .offset = B2063_G_RX_SP4, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
293 /* { .offset = B2063_G_RX_SP5, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */
294 /* { .offset = B2063_G_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
295 { .offset = B2063_G_RX_SP7, .value_a = 0x007f, .value_g = 0x007f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
296 /* { .offset = B2063_G_RX_SP8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
297 /* { .offset = B2063_G_RX_SP9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
298 { .offset = B2063_G_RX_SP10, .value_a = 0x000c, .value_g = 0x000c, .flags = B206X_FLAG_A | B206X_FLAG_G, },
299 /* { .offset = B2063_G_RX_SP11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
300 { .offset = B2063_A_RX_SP1, .value_a = 0x003c, .value_g = 0x003f, .flags = B206X_FLAG_A, },
301 { .offset = B2063_A_RX_SP2, .value_a = 0x00fc, .value_g = 0x00fe, .flags = B206X_FLAG_A, },
302 /* { .offset = B2063_A_RX_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
303 /* { .offset = B2063_A_RX_SP4, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
304 /* { .offset = B2063_A_RX_SP5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
305 /* { .offset = B2063_A_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
306 { .offset = B2063_A_RX_SP7, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, },
307 /* { .offset = B2063_RX_BB_SP1, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
308 /* { .offset = B2063_RX_BB_SP2, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */
309 /* { .offset = B2063_RX_BB_SP3, .value_a = 0x00a8, .value_g = 0x00a8, .flags = 0, }, */
310 { .offset = B2063_RX_BB_SP4, .value_a = 0x0060, .value_g = 0x0060, .flags = B206X_FLAG_A | B206X_FLAG_G, },
311 /* { .offset = B2063_RX_BB_SP5, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */
312 /* { .offset = B2063_RX_BB_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
313 /* { .offset = B2063_RX_BB_SP7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
314 { .offset = B2063_RX_BB_SP8, .value_a = 0x0030, .value_g = 0x0030, .flags = B206X_FLAG_A | B206X_FLAG_G, },
315 /* { .offset = B2063_TX_RF_SP1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
316 /* { .offset = B2063_TX_RF_SP2, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
317 { .offset = B2063_TX_RF_SP3, .value_a = 0x000c, .value_g = 0x000b, .flags = B206X_FLAG_A | B206X_FLAG_G, },
318 { .offset = B2063_TX_RF_SP4, .value_a = 0x0010, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
319 /* { .offset = B2063_TX_RF_SP5, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
320 /* { .offset = B2063_TX_RF_SP6, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
321 /* { .offset = B2063_TX_RF_SP7, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
322 /* { .offset = B2063_TX_RF_SP8, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */
323 /* { .offset = B2063_TX_RF_SP9, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
324 /* { .offset = B2063_TX_RF_SP10, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
325 /* { .offset = B2063_TX_RF_SP11, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
326 /* { .offset = B2063_TX_RF_SP12, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
327 /* { .offset = B2063_TX_RF_SP13, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
328 /* { .offset = B2063_TX_RF_SP14, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
329 /* { .offset = B2063_TX_RF_SP15, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
330 /* { .offset = B2063_TX_RF_SP16, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
331 /* { .offset = B2063_TX_RF_SP17, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
332 { .offset = B2063_PA_SP1, .value_a = 0x003d, .value_g = 0x00fd, .flags = B206X_FLAG_A | B206X_FLAG_G, },
333 /* { .offset = B2063_PA_SP2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
334 /* { .offset = B2063_PA_SP3, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
335 /* { .offset = B2063_PA_SP4, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
336 /* { .offset = B2063_PA_SP5, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
337 /* { .offset = B2063_PA_SP6, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */
338 /* { .offset = B2063_PA_SP7, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
339 { .offset = B2063_TX_BB_SP1, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, },
340 /* { .offset = B2063_TX_BB_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
341 /* { .offset = B2063_TX_BB_SP3, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
342 /* { .offset = B2063_REG_SP1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
343 { .offset = B2063_BANDGAP_CTL1, .value_a = 0x0056, .value_g = 0x0056, .flags = B206X_FLAG_A | B206X_FLAG_G, },
344 /* { .offset = B2063_BANDGAP_CTL2, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
345 /* { .offset = B2063_LPO_CTL1, .value_a = 0x000e, .value_g = 0x000e, .flags = 0, }, */
346 /* { .offset = B2063_RC_CALIB_CTL1, .value_a = 0x007e, .value_g = 0x007e, .flags = 0, }, */
347 /* { .offset = B2063_RC_CALIB_CTL2, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */
348 /* { .offset = B2063_RC_CALIB_CTL3, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */
349 /* { .offset = B2063_RC_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
350 /* { .offset = B2063_RC_CALIB_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
351 /* { .offset = B2063_RC_CALIB_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
352 /* { .offset = B2063_RC_CALIB_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
353 /* { .offset = B2063_RC_CALIB_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
354 /* { .offset = B2063_RC_CALIB_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
355 /* { .offset = B2063_RC_CALIB_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
356 /* { .offset = B2063_PLL_JTAG_CALNRST, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
357 /* { .offset = B2063_PLL_JTAG_IN_PLL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
358 /* { .offset = B2063_PLL_JTAG_IN_PLL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
359 /* { .offset = B2063_PLL_JTAG_PLL_CP1, .value_a = 0x00cf, .value_g = 0x00cf, .flags = 0, }, */
360 /* { .offset = B2063_PLL_JTAG_PLL_CP2, .value_a = 0x0059, .value_g = 0x0059, .flags = 0, }, */
361 /* { .offset = B2063_PLL_JTAG_PLL_CP3, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
362 /* { .offset = B2063_PLL_JTAG_PLL_CP4, .value_a = 0x0042, .value_g = 0x0042, .flags = 0, }, */
363 /* { .offset = B2063_PLL_JTAG_PLL_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
364 /* { .offset = B2063_PLL_JTAG_PLL_LF1, .value_a = 0x00db, .value_g = 0x00db, .flags = 0, }, */
365 /* { .offset = B2063_PLL_JTAG_PLL_LF2, .value_a = 0x0094, .value_g = 0x0094, .flags = 0, }, */
366 /* { .offset = B2063_PLL_JTAG_PLL_LF3, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
367 /* { .offset = B2063_PLL_JTAG_PLL_LF4, .value_a = 0x0063, .value_g = 0x0063, .flags = 0, }, */
368 /* { .offset = B2063_PLL_JTAG_PLL_SG1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */
369 /* { .offset = B2063_PLL_JTAG_PLL_SG2, .value_a = 0x00d3, .value_g = 0x00d3, .flags = 0, }, */
370 /* { .offset = B2063_PLL_JTAG_PLL_SG3, .value_a = 0x00b1, .value_g = 0x00b1, .flags = 0, }, */
371 /* { .offset = B2063_PLL_JTAG_PLL_SG4, .value_a = 0x003b, .value_g = 0x003b, .flags = 0, }, */
372 /* { .offset = B2063_PLL_JTAG_PLL_SG5, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */
373 /* { .offset = B2063_PLL_JTAG_PLL_VCO1, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
374 { .offset = B2063_PLL_JTAG_PLL_VCO2, .value_a = 0x00f7, .value_g = 0x00f7, .flags = B206X_FLAG_A | B206X_FLAG_G, },
375 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
376 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
377 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB3, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
378 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
379 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB5, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */
380 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB6, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
381 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB7, .value_a = 0x0016, .value_g = 0x0016, .flags = 0, }, */
382 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB8, .value_a = 0x006b, .value_g = 0x006b, .flags = 0, }, */
383 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
384 /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB10, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
385 /* { .offset = B2063_PLL_JTAG_PLL_XTAL_12, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */
386 /* { .offset = B2063_PLL_JTAG_PLL_XTAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
387 /* { .offset = B2063_LOGEN_ACL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
388 /* { .offset = B2063_LOGEN_ACL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
389 /* { .offset = B2063_LOGEN_ACL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
390 /* { .offset = B2063_LOGEN_ACL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
391 /* { .offset = B2063_LOGEN_ACL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
392 /* { .offset = B2063_LO_CALIB_INPUTS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
393 /* { .offset = B2063_LO_CALIB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
394 /* { .offset = B2063_LO_CALIB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
395 /* { .offset = B2063_LO_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
396 /* { .offset = B2063_LO_CALIB_WAITCNT, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
397 /* { .offset = B2063_LO_CALIB_OVR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
398 /* { .offset = B2063_LO_CALIB_OVR2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
399 /* { .offset = B2063_LO_CALIB_OVAL1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
400 /* { .offset = B2063_LO_CALIB_OVAL2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
401 /* { .offset = B2063_LO_CALIB_OVAL3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
402 /* { .offset = B2063_LO_CALIB_OVAL4, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
403 /* { .offset = B2063_LO_CALIB_OVAL5, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
404 /* { .offset = B2063_LO_CALIB_OVAL6, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
405 /* { .offset = B2063_LO_CALIB_OVAL7, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
406 /* { .offset = B2063_LO_CALIB_CALVLD1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
407 /* { .offset = B2063_LO_CALIB_CALVLD2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
408 /* { .offset = B2063_LO_CALIB_CVAL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
409 /* { .offset = B2063_LO_CALIB_CVAL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
410 /* { .offset = B2063_LO_CALIB_CVAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
411 /* { .offset = B2063_LO_CALIB_CVAL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
412 /* { .offset = B2063_LO_CALIB_CVAL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
413 /* { .offset = B2063_LO_CALIB_CVAL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
414 /* { .offset = B2063_LO_CALIB_CVAL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
415 /* { .offset = B2063_LOGEN_CALIB_EN, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
416 /* { .offset = B2063_LOGEN_PEAKDET1, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */
417 /* { .offset = B2063_LOGEN_RCCR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
418 /* { .offset = B2063_LOGEN_VCOBUF1, .value_a = 0x0060, .value_g = 0x0060, .flags = 0, }, */
419 /* { .offset = B2063_LOGEN_MIXER1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
420 /* { .offset = B2063_LOGEN_MIXER2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
421 /* { .offset = B2063_LOGEN_BUF1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
422 /* { .offset = B2063_LOGEN_BUF2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
423 /* { .offset = B2063_LOGEN_DIV1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
424 /* { .offset = B2063_LOGEN_DIV2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
425 /* { .offset = B2063_LOGEN_DIV3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
426 /* { .offset = B2063_LOGEN_CBUFRX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
427 /* { .offset = B2063_LOGEN_CBUFRX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
428 /* { .offset = B2063_LOGEN_CBUFTX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
429 /* { .offset = B2063_LOGEN_CBUFTX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */
430 /* { .offset = B2063_LOGEN_IDAC1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
431 /* { .offset = B2063_LOGEN_SPARE1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
432 /* { .offset = B2063_LOGEN_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
433 /* { .offset = B2063_LOGEN_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
434 /* { .offset = B2063_G_RX_1ST1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
435 /* { .offset = B2063_G_RX_1ST2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
436 /* { .offset = B2063_G_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
437 /* { .offset = B2063_G_RX_2ND1, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
438 /* { .offset = B2063_G_RX_2ND2, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
439 /* { .offset = B2063_G_RX_2ND3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
440 /* { .offset = B2063_G_RX_2ND4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
441 /* { .offset = B2063_G_RX_2ND5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
442 /* { .offset = B2063_G_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
443 /* { .offset = B2063_G_RX_2ND7, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */
444 /* { .offset = B2063_G_RX_2ND8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
445 /* { .offset = B2063_G_RX_PS1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
446 /* { .offset = B2063_G_RX_PS2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
447 /* { .offset = B2063_G_RX_PS3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
448 /* { .offset = B2063_G_RX_PS4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
449 /* { .offset = B2063_G_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
450 /* { .offset = B2063_G_RX_MIX1, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
451 /* { .offset = B2063_G_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
452 { .offset = B2063_G_RX_MIX3, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
453 { .offset = B2063_G_RX_MIX4, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, },
454 /* { .offset = B2063_G_RX_MIX5, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
455 /* { .offset = B2063_G_RX_MIX6, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
456 /* { .offset = B2063_G_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
457 /* { .offset = B2063_G_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
458 /* { .offset = B2063_G_RX_PDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
459 /* { .offset = B2063_G_RX_SPARES1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
460 /* { .offset = B2063_G_RX_SPARES2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
461 /* { .offset = B2063_G_RX_SPARES3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
462 /* { .offset = B2063_A_RX_1ST1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
463 { .offset = B2063_A_RX_1ST2, .value_a = 0x00f0, .value_g = 0x0030, .flags = B206X_FLAG_A, },
464 /* { .offset = B2063_A_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
465 /* { .offset = B2063_A_RX_1ST4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
466 /* { .offset = B2063_A_RX_1ST5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
467 /* { .offset = B2063_A_RX_2ND1, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
468 /* { .offset = B2063_A_RX_2ND2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
469 /* { .offset = B2063_A_RX_2ND3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
470 /* { .offset = B2063_A_RX_2ND4, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
471 /* { .offset = B2063_A_RX_2ND5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
472 /* { .offset = B2063_A_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
473 /* { .offset = B2063_A_RX_2ND7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */
474 /* { .offset = B2063_A_RX_PS1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
475 /* { .offset = B2063_A_RX_PS2, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
476 /* { .offset = B2063_A_RX_PS3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
477 /* { .offset = B2063_A_RX_PS4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */
478 /* { .offset = B2063_A_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
479 { .offset = B2063_A_RX_PS6, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
480 /* { .offset = B2063_A_RX_MIX1, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
481 /* { .offset = B2063_A_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
482 /* { .offset = B2063_A_RX_MIX3, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
483 { .offset = B2063_A_RX_MIX4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
484 { .offset = B2063_A_RX_MIX5, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
485 { .offset = B2063_A_RX_MIX6, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, },
486 /* { .offset = B2063_A_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */
487 /* { .offset = B2063_A_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */
488 /* { .offset = B2063_A_RX_PWRDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
489 /* { .offset = B2063_A_RX_SPARE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
490 /* { .offset = B2063_A_RX_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
491 /* { .offset = B2063_A_RX_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
492 { .offset = B2063_RX_TIA_CTL1, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
493 /* { .offset = B2063_RX_TIA_CTL2, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
494 { .offset = B2063_RX_TIA_CTL3, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, },
495 /* { .offset = B2063_RX_TIA_CTL4, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */
496 /* { .offset = B2063_RX_TIA_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
497 /* { .offset = B2063_RX_TIA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
498 /* { .offset = B2063_RX_BB_CTL1, .value_a = 0x0074, .value_g = 0x0074, .flags = 0, }, */
499 { .offset = B2063_RX_BB_CTL2, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, },
500 /* { .offset = B2063_RX_BB_CTL3, .value_a = 0x00a2, .value_g = 0x00a2, .flags = 0, }, */
501 /* { .offset = B2063_RX_BB_CTL4, .value_a = 0x00aa, .value_g = 0x00aa, .flags = 0, }, */
502 /* { .offset = B2063_RX_BB_CTL5, .value_a = 0x0024, .value_g = 0x0024, .flags = 0, }, */
503 /* { .offset = B2063_RX_BB_CTL6, .value_a = 0x00a9, .value_g = 0x00a9, .flags = 0, }, */
504 /* { .offset = B2063_RX_BB_CTL7, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */
505 /* { .offset = B2063_RX_BB_CTL8, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */
506 /* { .offset = B2063_RX_BB_CTL9, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
507 /* { .offset = B2063_TX_RF_CTL1, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
508 /* { .offset = B2063_TX_RF_IDAC_LO_RF_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
509 /* { .offset = B2063_TX_RF_IDAC_LO_RF_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
510 /* { .offset = B2063_TX_RF_IDAC_LO_BB_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
511 /* { .offset = B2063_TX_RF_IDAC_LO_BB_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */
512 /* { .offset = B2063_TX_RF_CTL2, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
513 /* { .offset = B2063_TX_RF_CTL3, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
514 /* { .offset = B2063_TX_RF_CTL4, .value_a = 0x00b8, .value_g = 0x00b8, .flags = 0, }, */
515 /* { .offset = B2063_TX_RF_CTL5, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */
516 /* { .offset = B2063_TX_RF_CTL6, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */
517 /* { .offset = B2063_TX_RF_CTL7, .value_a = 0x0078, .value_g = 0x0078, .flags = 0, }, */
518 /* { .offset = B2063_TX_RF_CTL8, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */
519 /* { .offset = B2063_TX_RF_CTL9, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */
520 /* { .offset = B2063_TX_RF_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
521 /* { .offset = B2063_TX_RF_CTL14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
522 /* { .offset = B2063_TX_RF_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
523 { .offset = B2063_PA_CTL1, .value_a = 0x0000, .value_g = 0x0004, .flags = B206X_FLAG_A, },
524 /* { .offset = B2063_PA_CTL2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */
525 /* { .offset = B2063_PA_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
526 /* { .offset = B2063_PA_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
527 /* { .offset = B2063_PA_CTL5, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */
528 /* { .offset = B2063_PA_CTL6, .value_a = 0x0077, .value_g = 0x0077, .flags = 0, }, */
529 /* { .offset = B2063_PA_CTL7, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */
530 /* { .offset = B2063_PA_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
531 /* { .offset = B2063_PA_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
532 /* { .offset = B2063_PA_CTL10, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
533 /* { .offset = B2063_PA_CTL11, .value_a = 0x0070, .value_g = 0x0070, .flags = 0, }, */
534 /* { .offset = B2063_PA_CTL12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
535 /* { .offset = B2063_PA_CTL13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
536 /* { .offset = B2063_TX_BB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
537 /* { .offset = B2063_TX_BB_CTL2, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
538 /* { .offset = B2063_TX_BB_CTL3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
539 /* { .offset = B2063_TX_BB_CTL4, .value_a = 0x000b, .value_g = 0x000b, .flags = 0, }, */
540 /* { .offset = B2063_GPIO_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
541 { .offset = B2063_VREG_CTL1, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, },
542 /* { .offset = B2063_AMUX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
543 /* { .offset = B2063_IQ_CALIB_GVAR, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */
544 /* { .offset = B2063_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */
545 /* { .offset = B2063_IQ_CALIB_CTL2, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */
546 /* { .offset = B2063_TEMPSENSE_CTL1, .value_a = 0x0046, .value_g = 0x0046, .flags = 0, }, */
547 /* { .offset = B2063_TEMPSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
548 /* { .offset = B2063_TX_RX_LOOPBACK1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
549 /* { .offset = B2063_TX_RX_LOOPBACK2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */
550 /* { .offset = B2063_EXT_TSSI_CTL1, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */
551 /* { .offset = B2063_EXT_TSSI_CTL2, .value_a = 0x0023, .value_g = 0x0023, .flags = 0, }, */
552 /* { .offset = B2063_AFE_CTL , .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */
553};
554
256void b2062_upload_init_table(struct b43_wldev *dev) 555void b2062_upload_init_table(struct b43_wldev *dev)
257{ 556{
258 const struct b2062_init_tab_entry *e; 557 const struct b206x_init_tab_entry *e;
259 unsigned int i; 558 unsigned int i;
260 559
261 for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) { 560 for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) {
262 e = &b2062_init_tab[i]; 561 e = &b2062_init_tab[i];
263 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { 562 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
264 if (!(e->flags & B2062_FLAG_G)) 563 if (!(e->flags & B206X_FLAG_G))
564 continue;
565 b43_radio_write(dev, e->offset, e->value_g);
566 } else {
567 if (!(e->flags & B206X_FLAG_A))
568 continue;
569 b43_radio_write(dev, e->offset, e->value_a);
570 }
571 }
572}
573
574void b2063_upload_init_table(struct b43_wldev *dev)
575{
576 const struct b206x_init_tab_entry *e;
577 unsigned int i;
578
579 for (i = 0; i < ARRAY_SIZE(b2063_init_tab); i++) {
580 e = &b2063_init_tab[i];
581 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
582 if (!(e->flags & B206X_FLAG_G))
265 continue; 583 continue;
266 b43_radio_write(dev, e->offset, e->value_g); 584 b43_radio_write(dev, e->offset, e->value_g);
267 } else { 585 } else {
268 if (!(e->flags & B2062_FLAG_A)) 586 if (!(e->flags & B206X_FLAG_A))
269 continue; 587 continue;
270 b43_radio_write(dev, e->offset, e->value_a); 588 b43_radio_write(dev, e->offset, e->value_a);
271 } 589 }
@@ -392,3 +710,1726 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
392 offset++; 710 offset++;
393 } 711 }
394} 712}
713
714static const u8 lpphy_min_sig_sq_table[] = {
715 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd,
716 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
717 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00,
718 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
719 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd,
720 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
721};
722
723static const u16 lpphy_rev01_noise_scale_table[] = {
724 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
725 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4,
726 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0x00a4,
727 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c00, 0x2d36,
728 0x0000, 0x0000, 0x4c00, 0x2d36,
729};
730
731static const u16 lpphy_rev2plus_noise_scale_table[] = {
732 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
733 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
734 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x0000,
735 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
736 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
737 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4,
738 0x00a4,
739};
740
741static const u16 lpphy_crs_gain_nft_table[] = {
742 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f, 0x036f,
743 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381, 0x0374, 0x0381,
744 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f, 0x0040, 0x005e, 0x007f,
745 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d, 0x013d,
746};
747
748static const u16 lpphy_rev01_filter_control_table[] = {
749 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077, 0xff53,
750 0x0127,
751};
752
753static const u32 lpphy_rev2plus_filter_control_table[] = {
754 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27, 0x0000217f,
755 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f,
756};
757
758static const u32 lpphy_rev01_ps_control_table[] = {
759 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101, 0x00000080,
760 0x08080101, 0x00000040, 0x08080101, 0x000000c0, 0x08a81501, 0x000000c0,
761 0x0fe8fd01, 0x000000c0, 0x08300105, 0x000000c0, 0x08080201, 0x000000c0,
762 0x08280205, 0x000000c0, 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0,
763 0x08080202, 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0,
764 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106, 0x000000c0,
765 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0,
766};
767
768static const u32 lpphy_rev2plus_ps_control_table[] = {
769 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000, 0x00002080,
770 0x00006180, 0x00003002, 0x00000040, 0x00002042, 0x00180047, 0x00080043,
771 0x00000041, 0x000020c1, 0x00046006, 0x00042002, 0x00040000, 0x00002003,
772 0x00180006, 0x00080002,
773};
774
775static const u8 lpphy_pll_fraction_table[] = {
776 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80,
777 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
778};
779
780static const u16 lpphy_iq_local_table[] = {
781 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002,
782 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007,
783 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
784 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600,
785 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006,
786 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000,
787 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
788 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
789 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
790 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000,
791 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
792 0x0000, 0x0000,
793};
794
795static const u16 lpphy_ofdm_cck_gain_table[] = {
796 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001,
797 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075,
798 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d,
799 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d,
800};
801
802static const u16 lpphy_gain_delta_table[] = {
803 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
804};
805
806static const u32 lpphy_tx_power_control_table[] = {
807 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c, 0x0000004b,
808 0x0000004a, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045,
809 0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003f,
810 0x0000003e, 0x0000003d, 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039,
811 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033,
812 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e, 0x0000002d,
813 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029, 0x00000028, 0x00000027,
814 0x00000026, 0x00000025, 0x00000024, 0x00000023, 0x00000022, 0x00000021,
815 0x00000020, 0x0000001f, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b,
816 0x0000001a, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015,
817 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000, 0x00000000,
818 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
819 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
820 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
821 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
822 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
823 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
824 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
825 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
826 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
827 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
828 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
829 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
830 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
831 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
832 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
833 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
834 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
835 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
836 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
837 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
838 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
839 0x000075a0, 0x000075a0, 0x000075a1, 0x000075a1, 0x000075a2, 0x000075a2,
840 0x000075a3, 0x000075a3, 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1,
841 0x000074b2, 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20,
842 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23, 0x00006d23,
843 0x00004660, 0x00004660, 0x00004661, 0x00004661, 0x00004662, 0x00004662,
844 0x00004663, 0x00004663, 0x00003e60, 0x00003e60, 0x00003e61, 0x00003e61,
845 0x00003e62, 0x00003e62, 0x00003e63, 0x00003e63, 0x00003660, 0x00003660,
846 0x00003661, 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663,
847 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62, 0x00002e62,
848 0x00002e63, 0x00002e63, 0x00002660, 0x00002660, 0x00002661, 0x00002661,
849 0x00002662, 0x00002662, 0x00002663, 0x00002663, 0x000025e0, 0x000025e0,
850 0x000025e1, 0x000025e1, 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3,
851 0x00001de0, 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2,
852 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61, 0x00001d61,
853 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63, 0x00001560, 0x00001560,
854 0x00001561, 0x00001561, 0x00001562, 0x00001562, 0x00001563, 0x00001563,
855 0x00000d60, 0x00000d60, 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62,
856 0x00000d63, 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1,
857 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10, 0x00000e10,
858 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12, 0x00000e13, 0x00000e13,
859 0x00000bf0, 0x00000bf0, 0x00000bf1, 0x00000bf1, 0x00000bf2, 0x00000bf2,
860 0x00000bf3, 0x00000bf3, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
861 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
862 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
863 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
864 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
865 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
866 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
867 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
868 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
869 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
870 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
871 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
872 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
873 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
874 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
875 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
876 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
877 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
878 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
879 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
880 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000,
881 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc,
882 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04, 0x0000fcff,
883 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006, 0x0000ff03, 0x000007fc,
884 0x0000fc08, 0x00000203, 0x0000fffb, 0x00000600, 0x0000fa01, 0x0000fc03,
885 0x0000fe06, 0x0000fe00, 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff,
886 0x000004fd, 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500,
887 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa, 0x00000700,
888 0x00000305, 0x000004ff, 0x00000801, 0x00000503, 0x000005f9, 0x00000404,
889 0x0000fb08, 0x000005fd, 0x00000501, 0x00000405, 0x0000fb03, 0x000007fc,
890 0x00000403, 0x00000303, 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd,
891 0x0000fe01, 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe,
892 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa, 0x000003fe,
893 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06, 0x000008fc, 0x00000701,
894 0x00000504, 0x0000fdfe, 0x0000fdfc, 0x000003fe, 0x00000704, 0x000002fc,
895 0x000004f9, 0x0000fdfd, 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb,
896 0x000004f9, 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05,
897 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa, 0x00000305,
898 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc, 0x0000fe03, 0x00000701,
899 0x000001fb, 0x000001f9, 0x00000206, 0x000006fd, 0x00000508, 0x00000700,
900 0x00000304, 0x000005fe, 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb,
901 0x000007f9, 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08,
902 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb, 0x00000702,
903};
904
905static const u32 lpphy_gain_idx_table[] = {
906 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
907 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
908 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
909 0x10000001, 0x00000000, 0x20000082, 0x00000000, 0x40000104, 0x00000000,
910 0x60004207, 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001,
911 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000,
912 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711, 0x00000001,
913 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010, 0x11630915, 0x00000011,
914 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018,
915 0x22468e21, 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019,
916 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a,
917 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c, 0x0000001a,
918 0x64ca55ad, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
919 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
920 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
921 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082, 0x00000000,
922 0x40000104, 0x00000000, 0x60004207, 0x00000001, 0x7000838a, 0x00000001,
923 0xd021050d, 0x00000001, 0xe041c683, 0x00000001, 0x50828805, 0x00000000,
924 0x80e34288, 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000,
925 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010,
926 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018,
927 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019, 0x4286d023, 0x00000019,
928 0xa347d0a4, 0x00000019, 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019,
929 0x0408d329, 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a,
930 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a,
931};
932
933static const u16 lpphy_aux_gain_idx_table[] = {
934 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
935 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
936 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0016,
937};
938
939static const u32 lpphy_gain_value_table[] = {
940 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
941 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
942 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
943 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
944 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
945 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
946 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
947 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
948 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
949 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
950 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x000000f1,
951 0x00000000, 0x00000000,
952};
953
954static const u16 lpphy_gain_table[] = {
955 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808, 0x080a,
956 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813, 0x0814, 0x0816,
957 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824, 0x0830, 0x0834, 0x0837,
958 0x083b, 0x083f, 0x0840, 0x0844, 0x0857, 0x085b, 0x085f, 0x08d7, 0x08db,
959 0x08df, 0x0957, 0x095b, 0x095f, 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f,
960 0x175f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
961 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
962 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
963 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
964 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
965 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
966};
967
968static const u32 lpphy_a0_gain_idx_table[] = {
969 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
970 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
971 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
972 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
973 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
974 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
975 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
976 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
977 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
978 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
979 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
980};
981
982static const u16 lpphy_a0_aux_gain_idx_table[] = {
983 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
984 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
985 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0014,
986};
987
988static const u32 lpphy_a0_gain_value_table[] = {
989 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004,
990 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a,
991 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006,
992 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000,
993 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000,
994 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
995 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
996 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
997 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f,
998 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000,
999 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x000000f7,
1000 0x00000000, 0x00000000,
1001};
1002
1003static const u16 lpphy_a0_gain_table[] = {
1004 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c,
1005 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016, 0x0017, 0x001a,
1006 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034, 0x0037, 0x003b, 0x003f,
1007 0x0040, 0x0044, 0x0057, 0x005b, 0x005f, 0x00d7, 0x00db, 0x00df, 0x0157,
1008 0x015b, 0x015f, 0x0357, 0x035b, 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000,
1009 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1010 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1011 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1012 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1013 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1014 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1015};
1016
1017static const u16 lpphy_sw_control_table[] = {
1018 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0128,
1019 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0009, 0x0009,
1020 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0018, 0x0018, 0x0018,
1021 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0128, 0x0128, 0x0009, 0x0009,
1022 0x0028, 0x0028, 0x0028, 0x0028, 0x0128, 0x0128, 0x0009, 0x0009, 0x0028,
1023 0x0028, 0x0028, 0x0028, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009,
1024 0x0009, 0x0009, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018,
1025 0x0018,
1026};
1027
1028static const u8 lpphy_hf_table[] = {
1029 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48,
1030 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17,
1031};
1032
1033static const u32 lpphy_papd_eps_table[] = {
1034 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9, 0x00021fdf,
1035 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7, 0x0004efc2, 0x00055fb5,
1036 0x0005cfb0, 0x00063fa8, 0x00068fa3, 0x00071f98, 0x0007ef92, 0x00084f8b,
1037 0x0008df82, 0x00097f77, 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c,
1038 0x000bff41, 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16,
1039 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15, 0x00143f1c,
1040 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f, 0x001e6f7e, 0x0021cfa4,
1041 0x0025bfd2, 0x002a2008, 0x002fb047, 0x00360090, 0x003d40e0, 0x0045c135,
1042 0x004fb189, 0x005ae1d7, 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf,
1043 0x007ff2e3, 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356,
1044 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506,
1045};
1046
1047static const u32 lpphy_papd_mult_table[] = {
1048 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065,
1049 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f,
1050 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca,
1051 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e,
1052 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193,
1053 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a,
1054 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325,
1055 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471,
1056 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646,
1057 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd,
1058 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28,
1059};
1060
1061static struct lpphy_tx_gain_table_entry lpphy_rev0_nopa_tx_gain_table[] = {
1062 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
1063 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
1064 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
1065 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
1066 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
1067 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
1068 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
1069 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
1070 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
1071 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
1072 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
1073 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
1074 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
1075 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
1076 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
1077 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
1078 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
1079 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
1080 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
1081 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
1082 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
1083 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
1084 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
1085 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
1086 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
1087 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
1088 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
1089 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
1090 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
1091 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
1092 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
1093 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
1094 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
1095 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
1096 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
1097 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
1098 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
1099 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
1100 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
1101 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
1102 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
1103 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
1104 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
1105 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
1106 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
1107 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
1108 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
1109 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
1110 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
1111 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
1112 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
1113 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
1114 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
1115 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
1116 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
1117 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
1118 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
1119 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
1120 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
1121 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
1122 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
1123 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
1124 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
1125 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
1126 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
1127 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
1128 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
1129 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
1130 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
1131 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
1132 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
1133 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
1134 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
1135 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1136 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1137 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
1138 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1139 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
1140 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
1141 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1142 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1143 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
1144 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
1145 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
1146 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1147 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
1148 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1149 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1150 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1151 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1152 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1153 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1154 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1155 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1156 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
1157 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1158 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1159 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1160 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1161 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1162 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1163 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1164 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
1165 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1166 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1167 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1168 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1169 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1170 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1171 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1172 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
1173 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
1174 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
1175 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
1176 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
1177 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
1178 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1179 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1180 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
1181 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1182 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1183 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1184 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
1185 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
1186 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1187 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1188 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
1189 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
1190};
1191
1192static struct lpphy_tx_gain_table_entry lpphy_rev0_2ghz_tx_gain_table[] = {
1193 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1194 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1195 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
1196 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1197 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
1198 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
1199 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1200 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1201 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
1202 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
1203 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
1204 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1205 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
1206 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1207 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1208 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1209 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1210 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1211 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1212 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1213 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1214 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
1215 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1216 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1217 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1218 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1219 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1220 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1221 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1222 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
1223 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1224 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1225 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1226 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1227 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1228 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1229 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1230 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
1231 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
1232 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
1233 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
1234 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
1235 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
1236 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1237 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1238 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
1239 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1240 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1241 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1242 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
1243 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
1244 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1245 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1246 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
1247 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
1248 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
1249 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
1250 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
1251 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
1252 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
1253 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
1254 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
1255 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
1256 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
1257 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
1258 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
1259 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
1260 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
1261 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
1262 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
1263 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
1264 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
1265 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
1266 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
1267 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
1268 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
1269 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
1270 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
1271 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
1272 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
1273 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
1274 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
1275 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
1276 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
1277 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
1278 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
1279 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
1280 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
1281 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
1282 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
1283 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
1284 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
1285 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
1286 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
1287 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
1288 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
1289 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
1290 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
1291 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
1292 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
1293 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
1294 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
1295 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
1296 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
1297 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
1298 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
1299 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
1300 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
1301 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
1302 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
1303 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
1304 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
1305 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
1306 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
1307 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
1308 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
1309 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
1310 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
1311 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
1312 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 60, },
1313 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 59, },
1314 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 57, },
1315 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 83, },
1316 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 81, },
1317 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 78, },
1318 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 76, },
1319 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 74, },
1320 { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 72, },
1321};
1322
1323static struct lpphy_tx_gain_table_entry lpphy_rev0_5ghz_tx_gain_table[] = {
1324 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
1325 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
1326 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
1327 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
1328 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
1329 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
1330 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
1331 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
1332 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
1333 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
1334 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
1335 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
1336 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
1337 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
1338 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
1339 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
1340 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
1341 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
1342 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
1343 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
1344 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
1345 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
1346 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
1347 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
1348 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
1349 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
1350 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
1351 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
1352 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
1353 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
1354 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
1355 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
1356 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
1357 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
1358 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
1359 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
1360 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
1361 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
1362 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
1363 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
1364 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
1365 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
1366 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
1367 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
1368 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
1369 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
1370 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
1371 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
1372 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
1373 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
1374 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
1375 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
1376 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
1377 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
1378 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
1379 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
1380 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
1381 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
1382 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
1383 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
1384 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
1385 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
1386 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
1387 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
1388 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
1389 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
1390 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
1391 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
1392 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
1393 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1394 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1395 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
1396 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1397 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
1398 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
1399 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1400 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1401 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
1402 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
1403 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
1404 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1405 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
1406 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1407 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1408 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1409 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1410 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1411 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1412 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1413 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1414 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1415 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1416 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1417 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1418 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1419 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1420 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1421 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
1422 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1423 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1424 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1425 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1426 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1427 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1428 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1429 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
1430 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
1431 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
1432 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
1433 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
1434 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
1435 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1436 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1437 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
1438 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1439 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1440 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1441 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
1442 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
1443 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1444 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1445 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
1446 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
1447 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
1448 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
1449 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
1450 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
1451 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
1452};
1453
1454static struct lpphy_tx_gain_table_entry lpphy_rev1_nopa_tx_gain_table[] = {
1455 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, },
1456 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, },
1457 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, },
1458 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, },
1459 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, },
1460 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, },
1461 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, },
1462 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, },
1463 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, },
1464 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, },
1465 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, },
1466 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, },
1467 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, },
1468 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, },
1469 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, },
1470 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, },
1471 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, },
1472 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, },
1473 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, },
1474 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, },
1475 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, },
1476 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, },
1477 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, },
1478 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, },
1479 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, },
1480 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, },
1481 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
1482 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
1483 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
1484 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
1485 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
1486 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
1487 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
1488 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
1489 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
1490 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
1491 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
1492 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
1493 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
1494 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
1495 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
1496 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
1497 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, },
1498 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, },
1499 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, },
1500 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, },
1501 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, },
1502 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, },
1503 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, },
1504 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
1505 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
1506 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, },
1507 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, },
1508 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, },
1509 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, },
1510 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, },
1511 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, },
1512 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, },
1513 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
1514 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
1515 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, },
1516 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
1517 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, },
1518 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, },
1519 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, },
1520 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
1521 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
1522 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
1523 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, },
1524 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
1525 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
1526 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
1527 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
1528 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
1529 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
1530 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
1531 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
1532 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
1533 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, },
1534 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
1535 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
1536 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
1537 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1538 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1539 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
1540 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1541 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
1542 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
1543 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1544 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1545 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
1546 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
1547 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
1548 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1549 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
1550 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1551 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1552 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1553 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1554 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1555 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1556 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1557 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1558 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
1559 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1560 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1561 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1562 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1563 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1564 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1565 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1566 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
1567 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1568 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1569 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1570 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1571 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1572 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1573 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1574 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
1575 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
1576 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
1577 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
1578 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
1579 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
1580 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1581 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1582 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
1583 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1584 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1585 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1586 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
1587 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
1588 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1589 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1590 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
1591 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
1592};
1593
1594static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = {
1595 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 85, },
1596 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 81, },
1597 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 78, },
1598 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 76, },
1599 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 74, },
1600 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 72, },
1601 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
1602 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
1603 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
1604 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1605 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1606 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, },
1607 { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1608 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, },
1609 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, },
1610 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1611 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1612 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, },
1613 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, },
1614 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, },
1615 { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1616 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, },
1617 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1618 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1619 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1620 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1621 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1622 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1623 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1624 { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1625 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, },
1626 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1627 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1628 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1629 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1630 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1631 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1632 { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1633 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, },
1634 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1635 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1636 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1637 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1638 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1639 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1640 { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1641 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, },
1642 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, },
1643 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, },
1644 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, },
1645 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, },
1646 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, },
1647 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1648 { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1649 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, },
1650 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1651 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1652 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1653 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, },
1654 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, },
1655 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1656 { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1657 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, },
1658 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, },
1659 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
1660 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
1661 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
1662 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
1663 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, },
1664 { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
1665 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, },
1666 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, },
1667 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, },
1668 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, },
1669 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, },
1670 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, },
1671 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, },
1672 { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, },
1673 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, },
1674 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, },
1675 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, },
1676 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, },
1677 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, },
1678 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, },
1679 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, },
1680 { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, },
1681 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, },
1682 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, },
1683 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, },
1684 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, },
1685 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, },
1686 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, },
1687 { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, },
1688 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, },
1689 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, },
1690 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, },
1691 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, },
1692 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, },
1693 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, },
1694 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, },
1695 { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, },
1696 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, },
1697 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, },
1698 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, },
1699 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, },
1700 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, },
1701 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, },
1702 { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, },
1703 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, },
1704 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, },
1705 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, },
1706 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, },
1707 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, },
1708 { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, },
1709 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, },
1710 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, },
1711 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, },
1712 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, },
1713 { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, },
1714 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, },
1715 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, },
1716 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, },
1717 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, },
1718 { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, },
1719 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, },
1720 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, },
1721 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, },
1722 { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, },
1723};
1724
1725static struct lpphy_tx_gain_table_entry lpphy_rev1_5ghz_tx_gain_table[] = {
1726 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, },
1727 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, },
1728 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, },
1729 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, },
1730 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, },
1731 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, },
1732 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, },
1733 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, },
1734 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, },
1735 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, },
1736 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, },
1737 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, },
1738 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, },
1739 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, },
1740 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, },
1741 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, },
1742 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, },
1743 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, },
1744 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, },
1745 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, },
1746 { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, },
1747 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, },
1748 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, },
1749 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, },
1750 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, },
1751 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, },
1752 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, },
1753 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, },
1754 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, },
1755 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, },
1756 { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, },
1757 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, },
1758 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, },
1759 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, },
1760 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, },
1761 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, },
1762 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, },
1763 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, },
1764 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, },
1765 { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, },
1766 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, },
1767 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, },
1768 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, },
1769 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, },
1770 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, },
1771 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, },
1772 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, },
1773 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, },
1774 { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, },
1775 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, },
1776 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, },
1777 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, },
1778 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, },
1779 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, },
1780 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, },
1781 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, },
1782 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, },
1783 { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, },
1784 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, },
1785 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, },
1786 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, },
1787 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, },
1788 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, },
1789 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, },
1790 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, },
1791 { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, },
1792 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, },
1793 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, },
1794 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, },
1795 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, },
1796 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, },
1797 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, },
1798 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, },
1799 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, },
1800 { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, },
1801 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, },
1802 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, },
1803 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, },
1804 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, },
1805 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, },
1806 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, },
1807 { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, },
1808 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, },
1809 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, },
1810 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, },
1811 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, },
1812 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, },
1813 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, },
1814 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, },
1815 { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, },
1816 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, },
1817 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, },
1818 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, },
1819 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, },
1820 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, },
1821 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, },
1822 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, },
1823 { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, },
1824 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, },
1825 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, },
1826 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, },
1827 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, },
1828 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, },
1829 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, },
1830 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, },
1831 { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, },
1832 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, },
1833 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, },
1834 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, },
1835 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, },
1836 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, },
1837 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, },
1838 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, },
1839 { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, },
1840 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, },
1841 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, },
1842 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, },
1843 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, },
1844 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, },
1845 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, },
1846 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, },
1847 { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, },
1848 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, },
1849 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, },
1850 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, },
1851 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, },
1852 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, },
1853 { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, },
1854};
1855
1856static struct lpphy_tx_gain_table_entry lpphy_rev2_nopa_tx_gain_table[] = {
1857 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 152, },
1858 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 147, },
1859 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 143, },
1860 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 139, },
1861 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 135, },
1862 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 131, },
1863 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 128, },
1864 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 124, },
1865 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 121, },
1866 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 117, },
1867 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 114, },
1868 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 111, },
1869 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 107, },
1870 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 104, },
1871 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 101, },
1872 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 99, },
1873 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 96, },
1874 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 93, },
1875 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 90, },
1876 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 88, },
1877 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 85, },
1878 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 83, },
1879 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 81, },
1880 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 78, },
1881 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 76, },
1882 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 74, },
1883 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 72, },
1884 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 70, },
1885 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 68, },
1886 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 66, },
1887 { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, },
1888 { .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, },
1889 { .gm = 255, .pga = 255, .pad = 192, .dac = 0, .bb_mult = 64, },
1890 { .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, },
1891 { .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, },
1892 { .gm = 255, .pga = 255, .pad = 176, .dac = 0, .bb_mult = 64, },
1893 { .gm = 255, .pga = 255, .pad = 171, .dac = 0, .bb_mult = 64, },
1894 { .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, },
1895 { .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, },
1896 { .gm = 255, .pga = 255, .pad = 157, .dac = 0, .bb_mult = 64, },
1897 { .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, },
1898 { .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, },
1899 { .gm = 255, .pga = 255, .pad = 144, .dac = 0, .bb_mult = 64, },
1900 { .gm = 255, .pga = 255, .pad = 140, .dac = 0, .bb_mult = 64, },
1901 { .gm = 255, .pga = 255, .pad = 136, .dac = 0, .bb_mult = 64, },
1902 { .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, },
1903 { .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, },
1904 { .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, },
1905 { .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, },
1906 { .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, },
1907 { .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, },
1908 { .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, },
1909 { .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, },
1910 { .gm = 255, .pga = 255, .pad = 105, .dac = 0, .bb_mult = 64, },
1911 { .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, },
1912 { .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, },
1913 { .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, },
1914 { .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, },
1915 { .gm = 255, .pga = 255, .pad = 91, .dac = 0, .bb_mult = 64, },
1916 { .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, },
1917 { .gm = 255, .pga = 255, .pad = 86, .dac = 0, .bb_mult = 64, },
1918 { .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, },
1919 { .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, },
1920 { .gm = 255, .pga = 255, .pad = 79, .dac = 0, .bb_mult = 64, },
1921 { .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, },
1922 { .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, },
1923 { .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, },
1924 { .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, },
1925 { .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, },
1926 { .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, },
1927 { .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, },
1928 { .gm = 255, .pga = 248, .pad = 64, .dac = 0, .bb_mult = 64, },
1929 { .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, },
1930 { .gm = 255, .pga = 241, .pad = 62, .dac = 0, .bb_mult = 64, },
1931 { .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, },
1932 { .gm = 255, .pga = 234, .pad = 60, .dac = 0, .bb_mult = 64, },
1933 { .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, },
1934 { .gm = 255, .pga = 227, .pad = 59, .dac = 0, .bb_mult = 64, },
1935 { .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, },
1936 { .gm = 255, .pga = 221, .pad = 57, .dac = 0, .bb_mult = 64, },
1937 { .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, },
1938 { .gm = 255, .pga = 215, .pad = 55, .dac = 0, .bb_mult = 64, },
1939 { .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, },
1940 { .gm = 255, .pga = 208, .pad = 54, .dac = 0, .bb_mult = 64, },
1941 { .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, },
1942 { .gm = 255, .pga = 203, .pad = 52, .dac = 0, .bb_mult = 64, },
1943 { .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, },
1944 { .gm = 255, .pga = 197, .pad = 51, .dac = 0, .bb_mult = 64, },
1945 { .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, },
1946 { .gm = 255, .pga = 191, .pad = 49, .dac = 0, .bb_mult = 64, },
1947 { .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, },
1948 { .gm = 255, .pga = 186, .pad = 48, .dac = 0, .bb_mult = 64, },
1949 { .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, },
1950 { .gm = 255, .pga = 181, .pad = 47, .dac = 0, .bb_mult = 64, },
1951 { .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, },
1952 { .gm = 255, .pga = 175, .pad = 45, .dac = 0, .bb_mult = 64, },
1953 { .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, },
1954 { .gm = 255, .pga = 170, .pad = 44, .dac = 0, .bb_mult = 64, },
1955 { .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, },
1956 { .gm = 255, .pga = 166, .pad = 43, .dac = 0, .bb_mult = 64, },
1957 { .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, },
1958 { .gm = 255, .pga = 161, .pad = 42, .dac = 0, .bb_mult = 64, },
1959 { .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, },
1960 { .gm = 255, .pga = 156, .pad = 40, .dac = 0, .bb_mult = 64, },
1961 { .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, },
1962 { .gm = 255, .pga = 152, .pad = 39, .dac = 0, .bb_mult = 64, },
1963 { .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, },
1964 { .gm = 255, .pga = 148, .pad = 38, .dac = 0, .bb_mult = 64, },
1965 { .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, },
1966 { .gm = 255, .pga = 143, .pad = 37, .dac = 0, .bb_mult = 64, },
1967 { .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, },
1968 { .gm = 255, .pga = 139, .pad = 36, .dac = 0, .bb_mult = 64, },
1969 { .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, },
1970 { .gm = 255, .pga = 135, .pad = 35, .dac = 0, .bb_mult = 64, },
1971 { .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, },
1972 { .gm = 255, .pga = 132, .pad = 34, .dac = 0, .bb_mult = 64, },
1973 { .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, },
1974 { .gm = 255, .pga = 128, .pad = 33, .dac = 0, .bb_mult = 64, },
1975 { .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, },
1976 { .gm = 255, .pga = 124, .pad = 32, .dac = 0, .bb_mult = 64, },
1977 { .gm = 255, .pga = 124, .pad = 31, .dac = 0, .bb_mult = 64, },
1978 { .gm = 255, .pga = 121, .pad = 31, .dac = 0, .bb_mult = 64, },
1979 { .gm = 255, .pga = 121, .pad = 30, .dac = 0, .bb_mult = 64, },
1980 { .gm = 255, .pga = 117, .pad = 30, .dac = 0, .bb_mult = 64, },
1981 { .gm = 255, .pga = 117, .pad = 29, .dac = 0, .bb_mult = 64, },
1982 { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
1983 { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, },
1984 { .gm = 255, .pga = 111, .pad = 29, .dac = 0, .bb_mult = 64, },
1985};
1986
1987static struct lpphy_tx_gain_table_entry lpphy_rev2_2ghz_tx_gain_table[] = {
1988 { .gm = 7, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
1989 { .gm = 7, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
1990 { .gm = 7, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
1991 { .gm = 7, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
1992 { .gm = 7, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
1993 { .gm = 7, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
1994 { .gm = 7, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
1995 { .gm = 7, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
1996 { .gm = 7, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
1997 { .gm = 7, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
1998 { .gm = 7, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
1999 { .gm = 7, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
2000 { .gm = 7, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
2001 { .gm = 7, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
2002 { .gm = 7, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
2003 { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
2004 { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
2005 { .gm = 7, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
2006 { .gm = 7, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
2007 { .gm = 7, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
2008 { .gm = 7, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
2009 { .gm = 7, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
2010 { .gm = 7, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
2011 { .gm = 7, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
2012 { .gm = 7, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
2013 { .gm = 7, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
2014 { .gm = 7, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
2015 { .gm = 7, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
2016 { .gm = 7, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
2017 { .gm = 7, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
2018 { .gm = 7, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
2019 { .gm = 7, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
2020 { .gm = 7, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
2021 { .gm = 7, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
2022 { .gm = 7, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
2023 { .gm = 7, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
2024 { .gm = 7, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
2025 { .gm = 7, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
2026 { .gm = 7, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
2027 { .gm = 7, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
2028 { .gm = 7, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
2029 { .gm = 7, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
2030 { .gm = 7, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
2031 { .gm = 7, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
2032 { .gm = 7, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
2033 { .gm = 7, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
2034 { .gm = 7, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
2035 { .gm = 7, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
2036 { .gm = 7, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
2037 { .gm = 7, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
2038 { .gm = 7, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
2039 { .gm = 7, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
2040 { .gm = 7, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
2041 { .gm = 7, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
2042 { .gm = 7, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
2043 { .gm = 7, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
2044 { .gm = 7, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
2045 { .gm = 7, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
2046 { .gm = 7, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
2047 { .gm = 7, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
2048 { .gm = 7, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
2049 { .gm = 7, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
2050 { .gm = 7, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
2051 { .gm = 7, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
2052 { .gm = 7, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
2053 { .gm = 7, .pga = 31, .pad = 128, .dac = 0, .bb_mult = 64, },
2054 { .gm = 7, .pga = 31, .pad = 124, .dac = 0, .bb_mult = 64, },
2055 { .gm = 7, .pga = 30, .pad = 124, .dac = 0, .bb_mult = 64, },
2056 { .gm = 7, .pga = 30, .pad = 121, .dac = 0, .bb_mult = 64, },
2057 { .gm = 7, .pga = 29, .pad = 121, .dac = 0, .bb_mult = 64, },
2058 { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
2059 { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, },
2060 { .gm = 7, .pga = 29, .pad = 114, .dac = 0, .bb_mult = 64, },
2061 { .gm = 7, .pga = 28, .pad = 114, .dac = 0, .bb_mult = 64, },
2062 { .gm = 7, .pga = 28, .pad = 111, .dac = 0, .bb_mult = 64, },
2063 { .gm = 7, .pga = 27, .pad = 111, .dac = 0, .bb_mult = 64, },
2064 { .gm = 7, .pga = 27, .pad = 108, .dac = 0, .bb_mult = 64, },
2065 { .gm = 7, .pga = 26, .pad = 108, .dac = 0, .bb_mult = 64, },
2066 { .gm = 7, .pga = 26, .pad = 104, .dac = 0, .bb_mult = 64, },
2067 { .gm = 7, .pga = 25, .pad = 104, .dac = 0, .bb_mult = 64, },
2068 { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
2069 { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, },
2070 { .gm = 7, .pga = 25, .pad = 99, .dac = 0, .bb_mult = 64, },
2071 { .gm = 7, .pga = 24, .pad = 99, .dac = 0, .bb_mult = 64, },
2072 { .gm = 7, .pga = 24, .pad = 96, .dac = 0, .bb_mult = 64, },
2073 { .gm = 7, .pga = 23, .pad = 96, .dac = 0, .bb_mult = 64, },
2074 { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
2075 { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, },
2076 { .gm = 7, .pga = 23, .pad = 90, .dac = 0, .bb_mult = 64, },
2077 { .gm = 7, .pga = 22, .pad = 90, .dac = 0, .bb_mult = 64, },
2078 { .gm = 7, .pga = 22, .pad = 88, .dac = 0, .bb_mult = 64, },
2079 { .gm = 7, .pga = 21, .pad = 88, .dac = 0, .bb_mult = 64, },
2080 { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
2081 { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, },
2082 { .gm = 7, .pga = 21, .pad = 83, .dac = 0, .bb_mult = 64, },
2083 { .gm = 7, .pga = 20, .pad = 83, .dac = 0, .bb_mult = 64, },
2084 { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
2085 { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, },
2086 { .gm = 7, .pga = 20, .pad = 78, .dac = 0, .bb_mult = 64, },
2087 { .gm = 7, .pga = 19, .pad = 78, .dac = 0, .bb_mult = 64, },
2088 { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
2089 { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, },
2090 { .gm = 7, .pga = 19, .pad = 74, .dac = 0, .bb_mult = 64, },
2091 { .gm = 7, .pga = 18, .pad = 74, .dac = 0, .bb_mult = 64, },
2092 { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
2093 { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, },
2094 { .gm = 7, .pga = 18, .pad = 70, .dac = 0, .bb_mult = 64, },
2095 { .gm = 7, .pga = 17, .pad = 70, .dac = 0, .bb_mult = 64, },
2096 { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
2097 { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, },
2098 { .gm = 7, .pga = 17, .pad = 66, .dac = 0, .bb_mult = 64, },
2099 { .gm = 7, .pga = 16, .pad = 66, .dac = 0, .bb_mult = 64, },
2100 { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
2101 { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, },
2102 { .gm = 7, .pga = 16, .pad = 62, .dac = 0, .bb_mult = 64, },
2103 { .gm = 7, .pga = 15, .pad = 62, .dac = 0, .bb_mult = 64, },
2104 { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
2105 { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, },
2106 { .gm = 7, .pga = 15, .pad = 59, .dac = 0, .bb_mult = 64, },
2107 { .gm = 7, .pga = 14, .pad = 59, .dac = 0, .bb_mult = 64, },
2108 { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
2109 { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, },
2110 { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
2111 { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, },
2112 { .gm = 7, .pga = 14, .pad = 54, .dac = 0, .bb_mult = 64, },
2113 { .gm = 7, .pga = 13, .pad = 54, .dac = 0, .bb_mult = 64, },
2114 { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
2115 { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, },
2116};
2117
2118static struct lpphy_tx_gain_table_entry lpphy_rev2_5ghz_tx_gain_table[] = {
2119 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 152, },
2120 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 147, },
2121 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 143, },
2122 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 139, },
2123 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 135, },
2124 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 131, },
2125 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 128, },
2126 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 124, },
2127 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 121, },
2128 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 117, },
2129 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 114, },
2130 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 111, },
2131 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 107, },
2132 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 104, },
2133 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 101, },
2134 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 99, },
2135 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 96, },
2136 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 93, },
2137 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 90, },
2138 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 88, },
2139 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 85, },
2140 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 83, },
2141 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 81, },
2142 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 78, },
2143 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 76, },
2144 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 74, },
2145 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 72, },
2146 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 70, },
2147 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 68, },
2148 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 66, },
2149 { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 64, },
2150 { .gm = 255, .pga = 248, .pad = 255, .dac = 0, .bb_mult = 64, },
2151 { .gm = 255, .pga = 241, .pad = 255, .dac = 0, .bb_mult = 64, },
2152 { .gm = 255, .pga = 234, .pad = 255, .dac = 0, .bb_mult = 64, },
2153 { .gm = 255, .pga = 227, .pad = 255, .dac = 0, .bb_mult = 64, },
2154 { .gm = 255, .pga = 221, .pad = 255, .dac = 0, .bb_mult = 64, },
2155 { .gm = 255, .pga = 215, .pad = 255, .dac = 0, .bb_mult = 64, },
2156 { .gm = 255, .pga = 208, .pad = 255, .dac = 0, .bb_mult = 64, },
2157 { .gm = 255, .pga = 203, .pad = 255, .dac = 0, .bb_mult = 64, },
2158 { .gm = 255, .pga = 197, .pad = 255, .dac = 0, .bb_mult = 64, },
2159 { .gm = 255, .pga = 191, .pad = 255, .dac = 0, .bb_mult = 64, },
2160 { .gm = 255, .pga = 186, .pad = 255, .dac = 0, .bb_mult = 64, },
2161 { .gm = 255, .pga = 181, .pad = 255, .dac = 0, .bb_mult = 64, },
2162 { .gm = 255, .pga = 175, .pad = 255, .dac = 0, .bb_mult = 64, },
2163 { .gm = 255, .pga = 170, .pad = 255, .dac = 0, .bb_mult = 64, },
2164 { .gm = 255, .pga = 166, .pad = 255, .dac = 0, .bb_mult = 64, },
2165 { .gm = 255, .pga = 161, .pad = 255, .dac = 0, .bb_mult = 64, },
2166 { .gm = 255, .pga = 156, .pad = 255, .dac = 0, .bb_mult = 64, },
2167 { .gm = 255, .pga = 152, .pad = 255, .dac = 0, .bb_mult = 64, },
2168 { .gm = 255, .pga = 148, .pad = 255, .dac = 0, .bb_mult = 64, },
2169 { .gm = 255, .pga = 143, .pad = 255, .dac = 0, .bb_mult = 64, },
2170 { .gm = 255, .pga = 139, .pad = 255, .dac = 0, .bb_mult = 64, },
2171 { .gm = 255, .pga = 135, .pad = 255, .dac = 0, .bb_mult = 64, },
2172 { .gm = 255, .pga = 132, .pad = 255, .dac = 0, .bb_mult = 64, },
2173 { .gm = 255, .pga = 128, .pad = 255, .dac = 0, .bb_mult = 64, },
2174 { .gm = 255, .pga = 124, .pad = 255, .dac = 0, .bb_mult = 64, },
2175 { .gm = 255, .pga = 121, .pad = 255, .dac = 0, .bb_mult = 64, },
2176 { .gm = 255, .pga = 117, .pad = 255, .dac = 0, .bb_mult = 64, },
2177 { .gm = 255, .pga = 114, .pad = 255, .dac = 0, .bb_mult = 64, },
2178 { .gm = 255, .pga = 111, .pad = 255, .dac = 0, .bb_mult = 64, },
2179 { .gm = 255, .pga = 108, .pad = 255, .dac = 0, .bb_mult = 64, },
2180 { .gm = 255, .pga = 104, .pad = 255, .dac = 0, .bb_mult = 64, },
2181 { .gm = 255, .pga = 102, .pad = 255, .dac = 0, .bb_mult = 64, },
2182 { .gm = 255, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, },
2183 { .gm = 255, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, },
2184 { .gm = 255, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, },
2185 { .gm = 255, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, },
2186 { .gm = 255, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, },
2187 { .gm = 255, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, },
2188 { .gm = 255, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, },
2189 { .gm = 255, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, },
2190 { .gm = 255, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, },
2191 { .gm = 255, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, },
2192 { .gm = 255, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, },
2193 { .gm = 255, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, },
2194 { .gm = 255, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, },
2195 { .gm = 255, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, },
2196 { .gm = 255, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, },
2197 { .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
2198 { .gm = 255, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, },
2199 { .gm = 255, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, },
2200 { .gm = 255, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, },
2201 { .gm = 255, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, },
2202 { .gm = 255, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, },
2203 { .gm = 255, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, },
2204 { .gm = 255, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, },
2205 { .gm = 255, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, },
2206 { .gm = 255, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, },
2207 { .gm = 255, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, },
2208 { .gm = 255, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, },
2209 { .gm = 255, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, },
2210 { .gm = 255, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, },
2211 { .gm = 255, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, },
2212 { .gm = 255, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, },
2213 { .gm = 255, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, },
2214 { .gm = 255, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, },
2215 { .gm = 255, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, },
2216 { .gm = 255, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, },
2217 { .gm = 255, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, },
2218 { .gm = 255, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, },
2219 { .gm = 255, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, },
2220 { .gm = 255, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, },
2221 { .gm = 255, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, },
2222 { .gm = 255, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, },
2223 { .gm = 255, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, },
2224 { .gm = 255, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, },
2225 { .gm = 255, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, },
2226 { .gm = 255, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, },
2227 { .gm = 255, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, },
2228 { .gm = 255, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, },
2229 { .gm = 255, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, },
2230 { .gm = 255, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, },
2231 { .gm = 255, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, },
2232 { .gm = 255, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, },
2233 { .gm = 255, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, },
2234 { .gm = 255, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, },
2235 { .gm = 255, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, },
2236 { .gm = 255, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, },
2237 { .gm = 255, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, },
2238 { .gm = 255, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, },
2239 { .gm = 255, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, },
2240 { .gm = 255, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, },
2241 { .gm = 255, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, },
2242 { .gm = 255, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, },
2243 { .gm = 255, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, },
2244 { .gm = 255, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, },
2245 { .gm = 255, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, },
2246 { .gm = 255, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, },
2247};
2248
2249void lpphy_rev0_1_table_init(struct b43_wldev *dev)
2250{
2251 B43_WARN_ON(dev->phy.rev >= 2);
2252
2253 b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
2254 ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
2255 b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
2256 ARRAY_SIZE(lpphy_rev01_noise_scale_table), lpphy_rev01_noise_scale_table);
2257 b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
2258 ARRAY_SIZE(lpphy_crs_gain_nft_table), lpphy_crs_gain_nft_table);
2259 b43_lptab_write_bulk(dev, B43_LPTAB16(8, 0),
2260 ARRAY_SIZE(lpphy_rev01_filter_control_table), lpphy_rev01_filter_control_table);
2261 b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
2262 ARRAY_SIZE(lpphy_rev01_ps_control_table), lpphy_rev01_ps_control_table);
2263 b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
2264 ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
2265 b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
2266 ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
2267 b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0),
2268 ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
2269 b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0),
2270 ARRAY_SIZE(lpphy_ofdm_cck_gain_table), lpphy_ofdm_cck_gain_table);
2271 b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
2272 ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table);
2273 b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
2274 ARRAY_SIZE(lpphy_tx_power_control_table), lpphy_tx_power_control_table);
2275}
2276
2277void lpphy_rev2plus_table_init(struct b43_wldev *dev)
2278{
2279 struct ssb_bus *bus = dev->dev->bus;
2280 int i;
2281
2282 B43_WARN_ON(dev->phy.rev < 2);
2283
2284 /*
2285 * FIXME This code follows the specs, but it looks wrong:
2286 * In each pass, it writes 4 bytes to an offset in table ID 7,
2287 * then increments the offset by 1 for the next pass. This results
2288 * in the first 3 bytes of each pass except the first one getting
2289 * written to a location that has already been zeroed in the previous
2290 * pass.
2291 * This is what the vendor driver does, but it still looks suspicious.
2292 *
2293 * This should probably suffice:
2294 *
2295 * for (i = 0; i < 704; i+=4)
2296 * b43_lptab_write(dev, B43_LPTAB32(7, i), 0)
2297 *
2298 * This should be tested once the code is functional.
2299 */
2300 for (i = 0; i < 704; i++)
2301 b43_lptab_write(dev, B43_LPTAB32(7, i), 0);
2302
2303 b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0),
2304 ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table);
2305 b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0),
2306 ARRAY_SIZE(lpphy_rev2plus_noise_scale_table), lpphy_rev2plus_noise_scale_table);
2307 b43_lptab_write_bulk(dev, B43_LPTAB32(11, 0),
2308 ARRAY_SIZE(lpphy_rev2plus_filter_control_table), lpphy_rev2plus_filter_control_table);
2309 b43_lptab_write_bulk(dev, B43_LPTAB32(12, 0),
2310 ARRAY_SIZE(lpphy_rev2plus_ps_control_table), lpphy_rev2plus_ps_control_table);
2311 b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
2312 ARRAY_SIZE(lpphy_gain_idx_table), lpphy_gain_idx_table);
2313 b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
2314 ARRAY_SIZE(lpphy_aux_gain_idx_table), lpphy_aux_gain_idx_table);
2315 b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0),
2316 ARRAY_SIZE(lpphy_sw_control_table), lpphy_sw_control_table);
2317 b43_lptab_write_bulk(dev, B43_LPTAB8(16, 0),
2318 ARRAY_SIZE(lpphy_hf_table), lpphy_hf_table);
2319 b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
2320 ARRAY_SIZE(lpphy_gain_value_table), lpphy_gain_value_table);
2321 b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
2322 ARRAY_SIZE(lpphy_gain_table), lpphy_gain_table);
2323 b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0),
2324 ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table);
2325 b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0),
2326 ARRAY_SIZE(lpphy_iq_local_table), lpphy_iq_local_table);
2327 b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0),
2328 ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table);
2329 b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0),
2330 ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table);
2331
2332 if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) {
2333 b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0),
2334 ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table);
2335 b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0),
2336 ARRAY_SIZE(lpphy_a0_aux_gain_idx_table), lpphy_a0_aux_gain_idx_table);
2337 b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0),
2338 ARRAY_SIZE(lpphy_a0_gain_value_table), lpphy_a0_gain_value_table);
2339 b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0),
2340 ARRAY_SIZE(lpphy_a0_gain_table), lpphy_a0_gain_table);
2341 }
2342}
2343
2344static void lpphy_rev0_1_write_gain_table(struct b43_wldev *dev, int offset,
2345 struct lpphy_tx_gain_table_entry data)
2346{
2347 u32 tmp;
2348
2349 B43_WARN_ON(dev->phy.rev >= 2);
2350
2351 tmp = data.pad << 11;
2352 tmp |= data.pga << 7;
2353 tmp |= data.gm << 4;
2354 tmp |= data.dac;
2355 b43_lptab_write(dev, B43_LPTAB32(10, 0xC0 + offset), tmp);
2356 tmp = data.bb_mult << 20;
2357 b43_lptab_write(dev, B43_LPTAB32(10, 0x140 + offset), tmp);
2358}
2359
2360static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset,
2361 struct lpphy_tx_gain_table_entry data)
2362{
2363 u32 tmp;
2364
2365 B43_WARN_ON(dev->phy.rev < 2);
2366
2367 tmp = data.pad << 16;
2368 tmp |= data.pga << 8;
2369 tmp |= data.gm;
2370 tmp |= 0x7f000000;
2371 b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp);
2372 tmp = data.bb_mult << 20;
2373 tmp |= data.dac << 28;
2374 b43_lptab_write(dev, B43_LPTAB32(7, 0x140 + offset), tmp);
2375}
2376
2377void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
2378 struct lpphy_tx_gain_table_entry data)
2379{
2380 if (dev->phy.rev >= 2)
2381 lpphy_rev2plus_write_gain_table(dev, offset, data);
2382 else
2383 lpphy_rev0_1_write_gain_table(dev, offset, data);
2384}
2385
2386void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
2387 struct lpphy_tx_gain_table_entry *table)
2388{
2389 int i;
2390
2391 for (i = offset; i < count; i++)
2392 lpphy_write_gain_table(dev, i, table[i]);
2393}
2394
2395void lpphy_init_tx_gain_table(struct b43_wldev *dev)
2396{
2397 struct ssb_bus *bus = dev->dev->bus;
2398
2399 switch (dev->phy.rev) {
2400 case 0:
2401 if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
2402 (bus->sprom.boardflags_lo & B43_BFL_HGPA))
2403 lpphy_write_gain_table_bulk(dev, 0, 128,
2404 lpphy_rev0_nopa_tx_gain_table);
2405 else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2406 lpphy_write_gain_table_bulk(dev, 0, 128,
2407 lpphy_rev0_2ghz_tx_gain_table);
2408 else
2409 lpphy_write_gain_table_bulk(dev, 0, 128,
2410 lpphy_rev0_5ghz_tx_gain_table);
2411 break;
2412 case 1:
2413 if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) ||
2414 (bus->sprom.boardflags_lo & B43_BFL_HGPA))
2415 lpphy_write_gain_table_bulk(dev, 0, 128,
2416 lpphy_rev1_nopa_tx_gain_table);
2417 else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2418 lpphy_write_gain_table_bulk(dev, 0, 128,
2419 lpphy_rev1_2ghz_tx_gain_table);
2420 else
2421 lpphy_write_gain_table_bulk(dev, 0, 128,
2422 lpphy_rev1_5ghz_tx_gain_table);
2423 break;
2424 default:
2425 if (bus->sprom.boardflags_hi & B43_BFH_NOPA)
2426 lpphy_write_gain_table_bulk(dev, 0, 128,
2427 lpphy_rev2_nopa_tx_gain_table);
2428 else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2429 lpphy_write_gain_table_bulk(dev, 0, 128,
2430 lpphy_rev2_2ghz_tx_gain_table);
2431 else
2432 lpphy_write_gain_table_bulk(dev, 0, 128,
2433 lpphy_rev2_5ghz_tx_gain_table);
2434 }
2435}
diff --git a/drivers/net/wireless/b43/tables_lpphy.h b/drivers/net/wireless/b43/tables_lpphy.h
index 0b8d02895a5d..84f1d265f657 100644
--- a/drivers/net/wireless/b43/tables_lpphy.h
+++ b/drivers/net/wireless/b43/tables_lpphy.h
@@ -26,6 +26,19 @@ void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset,
26 unsigned int nr_elements, const void *data); 26 unsigned int nr_elements, const void *data);
27 27
28void b2062_upload_init_table(struct b43_wldev *dev); 28void b2062_upload_init_table(struct b43_wldev *dev);
29void b2063_upload_init_table(struct b43_wldev *dev);
29 30
31struct lpphy_tx_gain_table_entry {
32 u8 gm, pga, pad, dac, bb_mult;
33};
34
35void lpphy_write_gain_table(struct b43_wldev *dev, int offset,
36 struct lpphy_tx_gain_table_entry data);
37void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count,
38 struct lpphy_tx_gain_table_entry *table);
39
40void lpphy_rev0_1_table_init(struct b43_wldev *dev);
41void lpphy_rev2plus_table_init(struct b43_wldev *dev);
42void lpphy_init_tx_gain_table(struct b43_wldev *dev);
30 43
31#endif /* B43_TABLES_LPPHY_H_ */ 44#endif /* B43_TABLES_LPPHY_H_ */
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 5b85e7d73592..5280ebc8c6e9 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -237,7 +237,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
237 int wlhdr_len; 237 int wlhdr_len;
238 size_t iv_len; 238 size_t iv_len;
239 239
240 B43_WARN_ON(key_idx >= dev->max_nr_keys); 240 B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key));
241 key = &(dev->key[key_idx]); 241 key = &(dev->key[key_idx]);
242 242
243 if (unlikely(!key->keyconf)) { 243 if (unlikely(!key->keyconf)) {
@@ -578,7 +578,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
578 * key index, but the ucode passed it slightly different. 578 * key index, but the ucode passed it slightly different.
579 */ 579 */
580 keyidx = b43_kidx_to_raw(dev, keyidx); 580 keyidx = b43_kidx_to_raw(dev, keyidx);
581 B43_WARN_ON(keyidx >= dev->max_nr_keys); 581 B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
582 582
583 if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { 583 if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
584 wlhdr_len = ieee80211_hdrlen(fctl); 584 wlhdr_len = ieee80211_hdrlen(fctl);
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index cf3fbc6b98ef..191718a0c545 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -117,8 +117,8 @@ static struct iwl_lib_ops iwl1000_lib = {
117 EEPROM_5000_REG_BAND_3_CHANNELS, 117 EEPROM_5000_REG_BAND_3_CHANNELS,
118 EEPROM_5000_REG_BAND_4_CHANNELS, 118 EEPROM_5000_REG_BAND_4_CHANNELS,
119 EEPROM_5000_REG_BAND_5_CHANNELS, 119 EEPROM_5000_REG_BAND_5_CHANNELS,
120 EEPROM_5000_REG_BAND_24_FAT_CHANNELS, 120 EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
121 EEPROM_5000_REG_BAND_52_FAT_CHANNELS 121 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
122 }, 122 },
123 .verify_signature = iwlcore_eeprom_verify_signature, 123 .verify_signature = iwlcore_eeprom_verify_signature,
124 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 124 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index b569c6f38e5c..16772780c5b0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -176,7 +176,7 @@ struct iwl3945_eeprom {
176 * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory 176 * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
177 * txpower (MSB). 177 * txpower (MSB).
178 * 178 *
179 * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) 179 * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz)
180 * channels (only for 4965, not supported by 3945) appear later in the EEPROM. 180 * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
181 * 181 *
182 * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 182 * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index e1b0ef3c56a3..ba5ef832d770 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -502,14 +502,14 @@ static void _iwl3945_dbg_report_frame(struct iwl_priv *priv,
502 } 502 }
503 } 503 }
504 if (print_dump) 504 if (print_dump)
505 iwl_print_hex_dump(IWL_DL_RX, data, length); 505 iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
506} 506}
507 507
508static void iwl3945_dbg_report_frame(struct iwl_priv *priv, 508static void iwl3945_dbg_report_frame(struct iwl_priv *priv,
509 struct iwl_rx_packet *pkt, 509 struct iwl_rx_packet *pkt,
510 struct ieee80211_hdr *header, int group100) 510 struct ieee80211_hdr *header, int group100)
511{ 511{
512 if (iwl_debug_level & IWL_DL_RX) 512 if (iwl_get_debug_level(priv) & IWL_DL_RX)
513 _iwl3945_dbg_report_frame(priv, pkt, header, group100); 513 _iwl3945_dbg_report_frame(priv, pkt, header, group100);
514} 514}
515 515
@@ -544,9 +544,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
544 struct ieee80211_rx_status *stats) 544 struct ieee80211_rx_status *stats)
545{ 545{
546 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 546 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
547#ifdef CONFIG_IWLWIFI_LEDS
548 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); 547 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
549#endif
550 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); 548 struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
551 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); 549 struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
552 short len = le16_to_cpu(rx_hdr->len); 550 short len = le16_to_cpu(rx_hdr->len);
@@ -577,6 +575,8 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
577 if (ieee80211_is_data(hdr->frame_control)) 575 if (ieee80211_is_data(hdr->frame_control))
578 priv->rxtxpackets += len; 576 priv->rxtxpackets += len;
579#endif 577#endif
578 iwl_update_stats(priv, false, hdr->frame_control, len);
579
580 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); 580 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
581 ieee80211_rx_irqsafe(priv->hw, rxb->skb); 581 ieee80211_rx_irqsafe(priv->hw, rxb->skb);
582 rxb->skb = NULL; 582 rxb->skb = NULL;
@@ -679,6 +679,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
679 679
680 /* Set "1" to report good data frames in groups of 100 */ 680 /* Set "1" to report good data frames in groups of 100 */
681 iwl3945_dbg_report_frame(priv, pkt, header, 1); 681 iwl3945_dbg_report_frame(priv, pkt, header, 1);
682 iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
682 683
683 if (network_packet) { 684 if (network_packet) {
684 priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); 685 priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp);
@@ -2851,8 +2852,8 @@ static struct iwl_lib_ops iwl3945_lib = {
2851 EEPROM_REGULATORY_BAND_3_CHANNELS, 2852 EEPROM_REGULATORY_BAND_3_CHANNELS,
2852 EEPROM_REGULATORY_BAND_4_CHANNELS, 2853 EEPROM_REGULATORY_BAND_4_CHANNELS,
2853 EEPROM_REGULATORY_BAND_5_CHANNELS, 2854 EEPROM_REGULATORY_BAND_5_CHANNELS,
2854 EEPROM_REGULATORY_BAND_NO_FAT, 2855 EEPROM_REGULATORY_BAND_NO_HT40,
2855 EEPROM_REGULATORY_BAND_NO_FAT, 2856 EEPROM_REGULATORY_BAND_NO_HT40,
2856 }, 2857 },
2857 .verify_signature = iwlcore_eeprom_verify_signature, 2858 .verify_signature = iwlcore_eeprom_verify_signature,
2858 .acquire_semaphore = iwl3945_eeprom_acquire_semaphore, 2859 .acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index a71a489096ff..b34322a32458 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -188,7 +188,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
188 * 188 *
189 * 1) Regulatory information (max txpower and channel usage flags) is provided 189 * 1) Regulatory information (max txpower and channel usage flags) is provided
190 * separately for each channel that can possibly supported by 4965. 190 * separately for each channel that can possibly supported by 4965.
191 * 40 MHz wide (.11n fat) channels are listed separately from 20 MHz 191 * 40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
192 * (legacy) channels. 192 * (legacy) channels.
193 * 193 *
194 * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom 194 * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
@@ -251,8 +251,8 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
251 * no reduction (such as with regulatory txpower limits) is required. 251 * no reduction (such as with regulatory txpower limits) is required.
252 * 252 *
253 * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel 253 * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
254 * widths and 40 Mhz (.11n fat) channel widths; there is no separate 254 * widths and 40 Mhz (.11n HT40) channel widths; there is no separate
255 * factory measurement for fat channels. 255 * factory measurement for ht40 channels.
256 * 256 *
257 * The result of this step is the final target txpower. The rest of 257 * The result of this step is the final target txpower. The rest of
258 * the steps figure out the proper settings for the device to achieve 258 * the steps figure out the proper settings for the device to achieve
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 670214823cb9..e427a8937ed8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -46,7 +46,7 @@
46#include "iwl-sta.h" 46#include "iwl-sta.h"
47 47
48static int iwl4965_send_tx_power(struct iwl_priv *priv); 48static int iwl4965_send_tx_power(struct iwl_priv *priv);
49static int iwl4965_hw_get_temperature(const struct iwl_priv *priv); 49static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
50 50
51/* Highest firmware API version supported */ 51/* Highest firmware API version supported */
52#define IWL4965_UCODE_API_MAX 2 52#define IWL4965_UCODE_API_MAX 2
@@ -146,7 +146,7 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
146 146
147 IWL_DEBUG_INFO(priv, "Begin load bsm\n"); 147 IWL_DEBUG_INFO(priv, "Begin load bsm\n");
148 148
149 priv->ucode_type = UCODE_INIT; 149 priv->ucode_type = UCODE_RT;
150 150
151 /* make sure bootstrap program is no larger than BSM's SRAM size */ 151 /* make sure bootstrap program is no larger than BSM's SRAM size */
152 if (len > IWL49_MAX_BSM_SIZE) 152 if (len > IWL49_MAX_BSM_SIZE)
@@ -256,8 +256,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
256*/ 256*/
257static void iwl4965_init_alive_start(struct iwl_priv *priv) 257static void iwl4965_init_alive_start(struct iwl_priv *priv)
258{ 258{
259 int ret;
260
261 /* Check alive response for "valid" sign from uCode */ 259 /* Check alive response for "valid" sign from uCode */
262 if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { 260 if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
263 /* We had an error bringing up the hardware, so take it 261 /* We had an error bringing up the hardware, so take it
@@ -289,35 +287,13 @@ static void iwl4965_init_alive_start(struct iwl_priv *priv)
289 IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); 287 IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
290 goto restart; 288 goto restart;
291 } 289 }
292 priv->ucode_type = UCODE_RT;
293 if (test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
294 IWL_WARN(priv, "Runtime uCode already alive? "
295 "Waiting for alive anyway\n");
296 clear_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
297 }
298 ret = wait_event_interruptible_timeout(
299 priv->wait_command_queue,
300 test_bit(STATUS_RT_UCODE_ALIVE, &priv->status),
301 UCODE_ALIVE_TIMEOUT);
302 if (!ret) {
303 /* FIXME: if STATUS_RT_UCODE_ALIVE timeout
304 * go back to restart the download Init uCode again
305 * this might cause to trap in the restart loop
306 */
307 priv->ucode_type = UCODE_NONE;
308 if (!test_bit(STATUS_RT_UCODE_ALIVE, &priv->status)) {
309 IWL_ERR(priv, "Runtime timeout after %dms\n",
310 jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
311 goto restart;
312 }
313 }
314 return; 290 return;
315 291
316restart: 292restart:
317 queue_work(priv->workqueue, &priv->restart); 293 queue_work(priv->workqueue, &priv->restart);
318} 294}
319 295
320static bool is_fat_channel(__le32 rxon_flags) 296static bool is_ht40_channel(__le32 rxon_flags)
321{ 297{
322 int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK) 298 int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
323 >> RXON_FLG_CHANNEL_MODE_POS; 299 >> RXON_FLG_CHANNEL_MODE_POS;
@@ -806,7 +782,7 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
806 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; 782 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
807 priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; 783 priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
808 priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; 784 priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
809 priv->hw_params.fat_channel = BIT(IEEE80211_BAND_5GHZ); 785 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
810 786
811 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; 787 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
812 788
@@ -1266,7 +1242,7 @@ static const struct gain_entry gain_table[2][108] = {
1266}; 1242};
1267 1243
1268static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, 1244static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
1269 u8 is_fat, u8 ctrl_chan_high, 1245 u8 is_ht40, u8 ctrl_chan_high,
1270 struct iwl4965_tx_power_db *tx_power_tbl) 1246 struct iwl4965_tx_power_db *tx_power_tbl)
1271{ 1247{
1272 u8 saturation_power; 1248 u8 saturation_power;
@@ -1298,8 +1274,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
1298 user_target_power = 2 * priv->tx_power_user_lmt; 1274 user_target_power = 2 * priv->tx_power_user_lmt;
1299 1275
1300 /* Get current (RXON) channel, band, width */ 1276 /* Get current (RXON) channel, band, width */
1301 IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_fat %d\n", channel, band, 1277 IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
1302 is_fat); 1278 is_ht40);
1303 1279
1304 ch_info = iwl_get_channel_info(priv, priv->band, channel); 1280 ch_info = iwl_get_channel_info(priv, priv->band, channel);
1305 1281
@@ -1318,7 +1294,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
1318 IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n", 1294 IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
1319 channel, txatten_grp); 1295 channel, txatten_grp);
1320 1296
1321 if (is_fat) { 1297 if (is_ht40) {
1322 if (ctrl_chan_high) 1298 if (ctrl_chan_high)
1323 channel -= 2; 1299 channel -= 2;
1324 else 1300 else
@@ -1342,8 +1318,8 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
1342 1318
1343 /* regulatory txpower limits ... reg_limit values are in half-dBm, 1319 /* regulatory txpower limits ... reg_limit values are in half-dBm,
1344 * max_power_avg values are in dBm, convert * 2 */ 1320 * max_power_avg values are in dBm, convert * 2 */
1345 if (is_fat) 1321 if (is_ht40)
1346 reg_limit = ch_info->fat_max_power_avg * 2; 1322 reg_limit = ch_info->ht40_max_power_avg * 2;
1347 else 1323 else
1348 reg_limit = ch_info->max_power_avg * 2; 1324 reg_limit = ch_info->max_power_avg * 2;
1349 1325
@@ -1509,7 +1485,7 @@ static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
1509/** 1485/**
1510 * iwl4965_send_tx_power - Configure the TXPOWER level user limit 1486 * iwl4965_send_tx_power - Configure the TXPOWER level user limit
1511 * 1487 *
1512 * Uses the active RXON for channel, band, and characteristics (fat, high) 1488 * Uses the active RXON for channel, band, and characteristics (ht40, high)
1513 * The power limit is taken from priv->tx_power_user_lmt. 1489 * The power limit is taken from priv->tx_power_user_lmt.
1514 */ 1490 */
1515static int iwl4965_send_tx_power(struct iwl_priv *priv) 1491static int iwl4965_send_tx_power(struct iwl_priv *priv)
@@ -1517,7 +1493,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
1517 struct iwl4965_txpowertable_cmd cmd = { 0 }; 1493 struct iwl4965_txpowertable_cmd cmd = { 0 };
1518 int ret; 1494 int ret;
1519 u8 band = 0; 1495 u8 band = 0;
1520 bool is_fat = false; 1496 bool is_ht40 = false;
1521 u8 ctrl_chan_high = 0; 1497 u8 ctrl_chan_high = 0;
1522 1498
1523 if (test_bit(STATUS_SCANNING, &priv->status)) { 1499 if (test_bit(STATUS_SCANNING, &priv->status)) {
@@ -1530,9 +1506,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
1530 1506
1531 band = priv->band == IEEE80211_BAND_2GHZ; 1507 band = priv->band == IEEE80211_BAND_2GHZ;
1532 1508
1533 is_fat = is_fat_channel(priv->active_rxon.flags); 1509 is_ht40 = is_ht40_channel(priv->active_rxon.flags);
1534 1510
1535 if (is_fat && 1511 if (is_ht40 &&
1536 (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) 1512 (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
1537 ctrl_chan_high = 1; 1513 ctrl_chan_high = 1;
1538 1514
@@ -1541,7 +1517,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
1541 1517
1542 ret = iwl4965_fill_txpower_tbl(priv, band, 1518 ret = iwl4965_fill_txpower_tbl(priv, band,
1543 le16_to_cpu(priv->active_rxon.channel), 1519 le16_to_cpu(priv->active_rxon.channel),
1544 is_fat, ctrl_chan_high, &cmd.tx_power); 1520 is_ht40, ctrl_chan_high, &cmd.tx_power);
1545 if (ret) 1521 if (ret)
1546 goto out; 1522 goto out;
1547 1523
@@ -1595,7 +1571,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1595{ 1571{
1596 int rc; 1572 int rc;
1597 u8 band = 0; 1573 u8 band = 0;
1598 bool is_fat = false; 1574 bool is_ht40 = false;
1599 u8 ctrl_chan_high = 0; 1575 u8 ctrl_chan_high = 0;
1600 struct iwl4965_channel_switch_cmd cmd = { 0 }; 1576 struct iwl4965_channel_switch_cmd cmd = { 0 };
1601 const struct iwl_channel_info *ch_info; 1577 const struct iwl_channel_info *ch_info;
@@ -1604,9 +1580,9 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1604 1580
1605 ch_info = iwl_get_channel_info(priv, priv->band, channel); 1581 ch_info = iwl_get_channel_info(priv, priv->band, channel);
1606 1582
1607 is_fat = is_fat_channel(priv->staging_rxon.flags); 1583 is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
1608 1584
1609 if (is_fat && 1585 if (is_ht40 &&
1610 (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) 1586 (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
1611 ctrl_chan_high = 1; 1587 ctrl_chan_high = 1;
1612 1588
@@ -1621,7 +1597,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1621 else 1597 else
1622 cmd.expect_beacon = 1; 1598 cmd.expect_beacon = 1;
1623 1599
1624 rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_fat, 1600 rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40,
1625 ctrl_chan_high, &cmd.tx_power); 1601 ctrl_chan_high, &cmd.tx_power);
1626 if (rc) { 1602 if (rc) {
1627 IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); 1603 IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc);
@@ -1680,7 +1656,7 @@ static s32 sign_extend(u32 oper, int index)
1680 * 1656 *
1681 * A return of <0 indicates bogus data in the statistics 1657 * A return of <0 indicates bogus data in the statistics
1682 */ 1658 */
1683static int iwl4965_hw_get_temperature(const struct iwl_priv *priv) 1659static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
1684{ 1660{
1685 s32 temperature; 1661 s32 temperature;
1686 s32 vt; 1662 s32 vt;
@@ -1688,8 +1664,8 @@ static int iwl4965_hw_get_temperature(const struct iwl_priv *priv)
1688 u32 R4; 1664 u32 R4;
1689 1665
1690 if (test_bit(STATUS_TEMPERATURE, &priv->status) && 1666 if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
1691 (priv->statistics.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK)) { 1667 (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
1692 IWL_DEBUG_TEMP(priv, "Running FAT temperature calibration\n"); 1668 IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
1693 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); 1669 R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
1694 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); 1670 R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
1695 R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]); 1671 R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
@@ -2330,8 +2306,8 @@ static struct iwl_lib_ops iwl4965_lib = {
2330 EEPROM_REGULATORY_BAND_3_CHANNELS, 2306 EEPROM_REGULATORY_BAND_3_CHANNELS,
2331 EEPROM_REGULATORY_BAND_4_CHANNELS, 2307 EEPROM_REGULATORY_BAND_4_CHANNELS,
2332 EEPROM_REGULATORY_BAND_5_CHANNELS, 2308 EEPROM_REGULATORY_BAND_5_CHANNELS,
2333 EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS, 2309 EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
2334 EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS 2310 EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
2335 }, 2311 },
2336 .verify_signature = iwlcore_eeprom_verify_signature, 2312 .verify_signature = iwlcore_eeprom_verify_signature,
2337 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 2313 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 87957c052839..755c184b3ecb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -845,7 +845,7 @@ int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
845 } 845 }
846 846
847 priv->hw_params.max_bsm_size = 0; 847 priv->hw_params.max_bsm_size = 0;
848 priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | 848 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) |
849 BIT(IEEE80211_BAND_5GHZ); 849 BIT(IEEE80211_BAND_5GHZ);
850 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; 850 priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
851 851
@@ -1547,8 +1547,8 @@ struct iwl_lib_ops iwl5000_lib = {
1547 EEPROM_5000_REG_BAND_3_CHANNELS, 1547 EEPROM_5000_REG_BAND_3_CHANNELS,
1548 EEPROM_5000_REG_BAND_4_CHANNELS, 1548 EEPROM_5000_REG_BAND_4_CHANNELS,
1549 EEPROM_5000_REG_BAND_5_CHANNELS, 1549 EEPROM_5000_REG_BAND_5_CHANNELS,
1550 EEPROM_5000_REG_BAND_24_FAT_CHANNELS, 1550 EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
1551 EEPROM_5000_REG_BAND_52_FAT_CHANNELS 1551 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
1552 }, 1552 },
1553 .verify_signature = iwlcore_eeprom_verify_signature, 1553 .verify_signature = iwlcore_eeprom_verify_signature,
1554 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 1554 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
@@ -1597,8 +1597,8 @@ static struct iwl_lib_ops iwl5150_lib = {
1597 EEPROM_5000_REG_BAND_3_CHANNELS, 1597 EEPROM_5000_REG_BAND_3_CHANNELS,
1598 EEPROM_5000_REG_BAND_4_CHANNELS, 1598 EEPROM_5000_REG_BAND_4_CHANNELS,
1599 EEPROM_5000_REG_BAND_5_CHANNELS, 1599 EEPROM_5000_REG_BAND_5_CHANNELS,
1600 EEPROM_5000_REG_BAND_24_FAT_CHANNELS, 1600 EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
1601 EEPROM_5000_REG_BAND_52_FAT_CHANNELS 1601 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
1602 }, 1602 },
1603 .verify_signature = iwlcore_eeprom_verify_signature, 1603 .verify_signature = iwlcore_eeprom_verify_signature,
1604 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 1604 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 4450943d3dac..c3ec6c20cc94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -118,8 +118,8 @@ static struct iwl_lib_ops iwl6000_lib = {
118 EEPROM_5000_REG_BAND_3_CHANNELS, 118 EEPROM_5000_REG_BAND_3_CHANNELS,
119 EEPROM_5000_REG_BAND_4_CHANNELS, 119 EEPROM_5000_REG_BAND_4_CHANNELS,
120 EEPROM_5000_REG_BAND_5_CHANNELS, 120 EEPROM_5000_REG_BAND_5_CHANNELS,
121 EEPROM_5000_REG_BAND_24_FAT_CHANNELS, 121 EEPROM_5000_REG_BAND_24_HT40_CHANNELS,
122 EEPROM_5000_REG_BAND_52_FAT_CHANNELS 122 EEPROM_5000_REG_BAND_52_HT40_CHANNELS
123 }, 123 },
124 .verify_signature = iwlcore_eeprom_verify_signature, 124 .verify_signature = iwlcore_eeprom_verify_signature,
125 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, 125 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 52a4810274e9..21331552ff2c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -97,7 +97,7 @@ struct iwl_scale_tbl_info {
97 enum iwl_table_type lq_type; 97 enum iwl_table_type lq_type;
98 u8 ant_type; 98 u8 ant_type;
99 u8 is_SGI; /* 1 = short guard interval */ 99 u8 is_SGI; /* 1 = short guard interval */
100 u8 is_fat; /* 1 = 40 MHz channel width */ 100 u8 is_ht40; /* 1 = 40 MHz channel width */
101 u8 is_dup; /* 1 = duplicated data streams */ 101 u8 is_dup; /* 1 = duplicated data streams */
102 u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ 102 u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */
103 u8 max_search; /* maximun number of tables we can search */ 103 u8 max_search; /* maximun number of tables we can search */
@@ -539,11 +539,11 @@ static u32 rate_n_flags_from_tbl(struct iwl_priv *priv,
539 RATE_MCS_ANT_ABC_MSK); 539 RATE_MCS_ANT_ABC_MSK);
540 540
541 if (is_Ht(tbl->lq_type)) { 541 if (is_Ht(tbl->lq_type)) {
542 if (tbl->is_fat) { 542 if (tbl->is_ht40) {
543 if (tbl->is_dup) 543 if (tbl->is_dup)
544 rate_n_flags |= RATE_MCS_DUP_MSK; 544 rate_n_flags |= RATE_MCS_DUP_MSK;
545 else 545 else
546 rate_n_flags |= RATE_MCS_FAT_MSK; 546 rate_n_flags |= RATE_MCS_HT40_MSK;
547 } 547 }
548 if (tbl->is_SGI) 548 if (tbl->is_SGI)
549 rate_n_flags |= RATE_MCS_SGI_MSK; 549 rate_n_flags |= RATE_MCS_SGI_MSK;
@@ -579,7 +579,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
579 return -EINVAL; 579 return -EINVAL;
580 } 580 }
581 tbl->is_SGI = 0; /* default legacy setup */ 581 tbl->is_SGI = 0; /* default legacy setup */
582 tbl->is_fat = 0; 582 tbl->is_ht40 = 0;
583 tbl->is_dup = 0; 583 tbl->is_dup = 0;
584 tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); 584 tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS);
585 tbl->lq_type = LQ_NONE; 585 tbl->lq_type = LQ_NONE;
@@ -598,9 +598,9 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
598 if (rate_n_flags & RATE_MCS_SGI_MSK) 598 if (rate_n_flags & RATE_MCS_SGI_MSK)
599 tbl->is_SGI = 1; 599 tbl->is_SGI = 1;
600 600
601 if ((rate_n_flags & RATE_MCS_FAT_MSK) || 601 if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
602 (rate_n_flags & RATE_MCS_DUP_MSK)) 602 (rate_n_flags & RATE_MCS_DUP_MSK))
603 tbl->is_fat = 1; 603 tbl->is_ht40 = 1;
604 604
605 if (rate_n_flags & RATE_MCS_DUP_MSK) 605 if (rate_n_flags & RATE_MCS_DUP_MSK)
606 tbl->is_dup = 1; 606 tbl->is_dup = 1;
@@ -776,7 +776,7 @@ static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
776 if (num_of_ant(tbl->ant_type) > 1) 776 if (num_of_ant(tbl->ant_type) > 1)
777 tbl->ant_type = ANT_A;/*FIXME:RS*/ 777 tbl->ant_type = ANT_A;/*FIXME:RS*/
778 778
779 tbl->is_fat = 0; 779 tbl->is_ht40 = 0;
780 tbl->is_SGI = 0; 780 tbl->is_SGI = 0;
781 tbl->max_search = IWL_MAX_SEARCH; 781 tbl->max_search = IWL_MAX_SEARCH;
782 } 782 }
@@ -880,7 +880,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
880 880
881 if ((info->status.rates[0].idx < 0) || 881 if ((info->status.rates[0].idx < 0) ||
882 (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) || 882 (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
883 (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || 883 (tbl_type.is_ht40 != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
884 (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) || 884 (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
885 (tbl_type.ant_type != info->antenna_sel_tx) || 885 (tbl_type.ant_type != info->antenna_sel_tx) ||
886 (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) || 886 (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
@@ -1049,7 +1049,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1049 else 1049 else
1050 tbl->expected_tpt = expected_tpt_A; 1050 tbl->expected_tpt = expected_tpt_A;
1051 } else if (is_siso(tbl->lq_type)) { 1051 } else if (is_siso(tbl->lq_type)) {
1052 if (tbl->is_fat && !lq_sta->is_dup) 1052 if (tbl->is_ht40 && !lq_sta->is_dup)
1053 if (tbl->is_SGI) 1053 if (tbl->is_SGI)
1054 tbl->expected_tpt = expected_tpt_siso40MHzSGI; 1054 tbl->expected_tpt = expected_tpt_siso40MHzSGI;
1055 else 1055 else
@@ -1059,7 +1059,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1059 else 1059 else
1060 tbl->expected_tpt = expected_tpt_siso20MHz; 1060 tbl->expected_tpt = expected_tpt_siso20MHz;
1061 } else if (is_mimo2(tbl->lq_type)) { 1061 } else if (is_mimo2(tbl->lq_type)) {
1062 if (tbl->is_fat && !lq_sta->is_dup) 1062 if (tbl->is_ht40 && !lq_sta->is_dup)
1063 if (tbl->is_SGI) 1063 if (tbl->is_SGI)
1064 tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; 1064 tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
1065 else 1065 else
@@ -1069,7 +1069,7 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
1069 else 1069 else
1070 tbl->expected_tpt = expected_tpt_mimo2_20MHz; 1070 tbl->expected_tpt = expected_tpt_mimo2_20MHz;
1071 } else if (is_mimo3(tbl->lq_type)) { 1071 } else if (is_mimo3(tbl->lq_type)) {
1072 if (tbl->is_fat && !lq_sta->is_dup) 1072 if (tbl->is_ht40 && !lq_sta->is_dup)
1073 if (tbl->is_SGI) 1073 if (tbl->is_SGI)
1074 tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; 1074 tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
1075 else 1075 else
@@ -1217,13 +1217,13 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1217 tbl->max_search = IWL_MAX_SEARCH; 1217 tbl->max_search = IWL_MAX_SEARCH;
1218 rate_mask = lq_sta->active_mimo2_rate; 1218 rate_mask = lq_sta->active_mimo2_rate;
1219 1219
1220 if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) 1220 if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
1221 tbl->is_fat = 1; 1221 tbl->is_ht40 = 1;
1222 else 1222 else
1223 tbl->is_fat = 0; 1223 tbl->is_ht40 = 0;
1224 1224
1225 /* FIXME: - don't toggle SGI here 1225 /* FIXME: - don't toggle SGI here
1226 if (tbl->is_fat) { 1226 if (tbl->is_ht40) {
1227 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) 1227 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1228 tbl->is_SGI = 1; 1228 tbl->is_SGI = 1;
1229 else 1229 else
@@ -1283,13 +1283,13 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv,
1283 tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; 1283 tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH;
1284 rate_mask = lq_sta->active_mimo3_rate; 1284 rate_mask = lq_sta->active_mimo3_rate;
1285 1285
1286 if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) 1286 if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
1287 tbl->is_fat = 1; 1287 tbl->is_ht40 = 1;
1288 else 1288 else
1289 tbl->is_fat = 0; 1289 tbl->is_ht40 = 0;
1290 1290
1291 /* FIXME: - don't toggle SGI here 1291 /* FIXME: - don't toggle SGI here
1292 if (tbl->is_fat) { 1292 if (tbl->is_ht40) {
1293 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) 1293 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1294 tbl->is_SGI = 1; 1294 tbl->is_SGI = 1;
1295 else 1295 else
@@ -1342,13 +1342,13 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
1342 tbl->max_search = IWL_MAX_SEARCH; 1342 tbl->max_search = IWL_MAX_SEARCH;
1343 rate_mask = lq_sta->active_siso_rate; 1343 rate_mask = lq_sta->active_siso_rate;
1344 1344
1345 if (iwl_is_fat_tx_allowed(priv, &sta->ht_cap)) 1345 if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap))
1346 tbl->is_fat = 1; 1346 tbl->is_ht40 = 1;
1347 else 1347 else
1348 tbl->is_fat = 0; 1348 tbl->is_ht40 = 0;
1349 1349
1350 /* FIXME: - don't toggle SGI here 1350 /* FIXME: - don't toggle SGI here
1351 if (tbl->is_fat) { 1351 if (tbl->is_ht40) {
1352 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) 1352 if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
1353 tbl->is_SGI = 1; 1353 tbl->is_SGI = 1;
1354 else 1354 else
@@ -1401,7 +1401,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
1401 if (!iwl_ht_enabled(priv)) 1401 if (!iwl_ht_enabled(priv))
1402 /* stay in Legacy */ 1402 /* stay in Legacy */
1403 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; 1403 tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
1404 else if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE && 1404 else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
1405 tbl->action > IWL_LEGACY_SWITCH_SISO) 1405 tbl->action > IWL_LEGACY_SWITCH_SISO)
1406 tbl->action = IWL_LEGACY_SWITCH_SISO; 1406 tbl->action = IWL_LEGACY_SWITCH_SISO;
1407 for (; ;) { 1407 for (; ;) {
@@ -1535,7 +1535,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1535 u8 update_search_tbl_counter = 0; 1535 u8 update_search_tbl_counter = 0;
1536 int ret; 1536 int ret;
1537 1537
1538 if (iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE && 1538 if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE &&
1539 tbl->action > IWL_SISO_SWITCH_ANTENNA2) { 1539 tbl->action > IWL_SISO_SWITCH_ANTENNA2) {
1540 /* stay in SISO */ 1540 /* stay in SISO */
1541 tbl->action = IWL_SISO_SWITCH_ANTENNA1; 1541 tbl->action = IWL_SISO_SWITCH_ANTENNA1;
@@ -1586,11 +1586,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
1586 goto out; 1586 goto out;
1587 break; 1587 break;
1588 case IWL_SISO_SWITCH_GI: 1588 case IWL_SISO_SWITCH_GI:
1589 if (!tbl->is_fat && 1589 if (!tbl->is_ht40 &&
1590 !(priv->current_ht_config.sgf & 1590 !(priv->current_ht_config.sgf &
1591 HT_SHORT_GI_20MHZ)) 1591 HT_SHORT_GI_20MHZ))
1592 break; 1592 break;
1593 if (tbl->is_fat && 1593 if (tbl->is_ht40 &&
1594 !(priv->current_ht_config.sgf & 1594 !(priv->current_ht_config.sgf &
1595 HT_SHORT_GI_40MHZ)) 1595 HT_SHORT_GI_40MHZ))
1596 break; 1596 break;
@@ -1674,7 +1674,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
1674 u8 update_search_tbl_counter = 0; 1674 u8 update_search_tbl_counter = 0;
1675 int ret; 1675 int ret;
1676 1676
1677 if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) && 1677 if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
1678 (tbl->action < IWL_MIMO2_SWITCH_SISO_A || 1678 (tbl->action < IWL_MIMO2_SWITCH_SISO_A ||
1679 tbl->action > IWL_MIMO2_SWITCH_SISO_C)) { 1679 tbl->action > IWL_MIMO2_SWITCH_SISO_C)) {
1680 /* switch in SISO */ 1680 /* switch in SISO */
@@ -1726,11 +1726,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
1726 break; 1726 break;
1727 1727
1728 case IWL_MIMO2_SWITCH_GI: 1728 case IWL_MIMO2_SWITCH_GI:
1729 if (!tbl->is_fat && 1729 if (!tbl->is_ht40 &&
1730 !(priv->current_ht_config.sgf & 1730 !(priv->current_ht_config.sgf &
1731 HT_SHORT_GI_20MHZ)) 1731 HT_SHORT_GI_20MHZ))
1732 break; 1732 break;
1733 if (tbl->is_fat && 1733 if (tbl->is_ht40 &&
1734 !(priv->current_ht_config.sgf & 1734 !(priv->current_ht_config.sgf &
1735 HT_SHORT_GI_40MHZ)) 1735 HT_SHORT_GI_40MHZ))
1736 break; 1736 break;
@@ -1816,7 +1816,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
1816 int ret; 1816 int ret;
1817 u8 update_search_tbl_counter = 0; 1817 u8 update_search_tbl_counter = 0;
1818 1818
1819 if ((iwl_tx_ant_restriction(priv) == IWL_TX_SINGLE) && 1819 if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) &&
1820 (tbl->action < IWL_MIMO3_SWITCH_SISO_A || 1820 (tbl->action < IWL_MIMO3_SWITCH_SISO_A ||
1821 tbl->action > IWL_MIMO3_SWITCH_SISO_C)) { 1821 tbl->action > IWL_MIMO3_SWITCH_SISO_C)) {
1822 /* switch in SISO */ 1822 /* switch in SISO */
@@ -1890,11 +1890,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
1890 break; 1890 break;
1891 1891
1892 case IWL_MIMO3_SWITCH_GI: 1892 case IWL_MIMO3_SWITCH_GI:
1893 if (!tbl->is_fat && 1893 if (!tbl->is_ht40 &&
1894 !(priv->current_ht_config.sgf & 1894 !(priv->current_ht_config.sgf &
1895 HT_SHORT_GI_20MHZ)) 1895 HT_SHORT_GI_20MHZ))
1896 break; 1896 break;
1897 if (tbl->is_fat && 1897 if (tbl->is_ht40 &&
1898 !(priv->current_ht_config.sgf & 1898 !(priv->current_ht_config.sgf &
1899 HT_SHORT_GI_40MHZ)) 1899 HT_SHORT_GI_40MHZ))
1900 break; 1900 break;
@@ -2202,7 +2202,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2202 2202
2203 /* If we are searching for better modulation mode, check success. */ 2203 /* If we are searching for better modulation mode, check success. */
2204 if (lq_sta->search_better_tbl && 2204 if (lq_sta->search_better_tbl &&
2205 (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI)) { 2205 (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI)) {
2206 /* If good success, continue using the "search" mode; 2206 /* If good success, continue using the "search" mode;
2207 * no need to send new link quality command, since we're 2207 * no need to send new link quality command, since we're
2208 * continuing to use the setup that we've been trying. */ 2208 * continuing to use the setup that we've been trying. */
@@ -2332,7 +2332,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2332 scale_action = 0; 2332 scale_action = 0;
2333 if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type)) 2333 if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type))
2334 scale_action = -1; 2334 scale_action = -1;
2335 if (iwl_tx_ant_restriction(priv) != IWL_TX_MULTI && 2335 if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI &&
2336 (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) 2336 (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type)))
2337 scale_action = -1; 2337 scale_action = -1;
2338 switch (scale_action) { 2338 switch (scale_action) {
@@ -2368,7 +2368,7 @@ lq_update:
2368 rate = rs_update_rate_tbl(priv, lq_sta, 2368 rate = rs_update_rate_tbl(priv, lq_sta,
2369 tbl, index, is_green); 2369 tbl, index, is_green);
2370 2370
2371 if (iwl_tx_ant_restriction(priv) == IWL_TX_MULTI) { 2371 if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) {
2372 /* Should we stay with this modulation mode, 2372 /* Should we stay with this modulation mode,
2373 * or search for a new one? */ 2373 * or search for a new one? */
2374 rs_stay_in_table(lq_sta); 2374 rs_stay_in_table(lq_sta);
@@ -2576,7 +2576,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
2576 info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI; 2576 info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
2577 if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK) 2577 if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
2578 info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA; 2578 info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA;
2579 if (lq_sta->last_rate_n_flags & RATE_MCS_FAT_MSK) 2579 if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK)
2580 info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 2580 info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2581 if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK) 2581 if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
2582 info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD; 2582 info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
@@ -2963,7 +2963,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
2963 (is_siso(tbl->lq_type)) ? "SISO" : 2963 (is_siso(tbl->lq_type)) ? "SISO" :
2964 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); 2964 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
2965 desc += sprintf(buff+desc, " %s", 2965 desc += sprintf(buff+desc, " %s",
2966 (tbl->is_fat) ? "40MHz" : "20MHz"); 2966 (tbl->is_ht40) ? "40MHz" : "20MHz");
2967 desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", 2967 desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
2968 (lq_sta->is_green) ? "GF enabled" : ""); 2968 (lq_sta->is_green) ? "GF enabled" : "");
2969 } 2969 }
@@ -3028,12 +3028,13 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
3028 return -ENOMEM; 3028 return -ENOMEM;
3029 3029
3030 for (i = 0; i < LQ_SIZE; i++) { 3030 for (i = 0; i < LQ_SIZE; i++) {
3031 desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d GF=%d\n" 3031 desc += sprintf(buff+desc,
3032 "%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n"
3032 "rate=0x%X\n", 3033 "rate=0x%X\n",
3033 lq_sta->active_tbl == i ? "*" : "x", 3034 lq_sta->active_tbl == i ? "*" : "x",
3034 lq_sta->lq_info[i].lq_type, 3035 lq_sta->lq_info[i].lq_type,
3035 lq_sta->lq_info[i].is_SGI, 3036 lq_sta->lq_info[i].is_SGI,
3036 lq_sta->lq_info[i].is_fat, 3037 lq_sta->lq_info[i].is_ht40,
3037 lq_sta->lq_info[i].is_dup, 3038 lq_sta->lq_info[i].is_dup,
3038 lq_sta->is_green, 3039 lq_sta->is_green,
3039 lq_sta->lq_info[i].current_rate); 3040 lq_sta->lq_info[i].current_rate);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index db580cbf5982..2232b1794e76 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -533,16 +533,12 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
533 533
534 if (palive->ver_subtype == INITIALIZE_SUBTYPE) { 534 if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
535 IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); 535 IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
536 set_bit(STATUS_INIT_UCODE_ALIVE, &priv->status);
537 wake_up_interruptible(&priv->wait_command_queue);
538 memcpy(&priv->card_alive_init, 536 memcpy(&priv->card_alive_init,
539 &pkt->u.alive_frame, 537 &pkt->u.alive_frame,
540 sizeof(struct iwl_init_alive_resp)); 538 sizeof(struct iwl_init_alive_resp));
541 pwork = &priv->init_alive_start; 539 pwork = &priv->init_alive_start;
542 } else { 540 } else {
543 IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); 541 IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
544 set_bit(STATUS_RT_UCODE_ALIVE, &priv->status);
545 wake_up_interruptible(&priv->wait_command_queue);
546 memcpy(&priv->card_alive, &pkt->u.alive_frame, 542 memcpy(&priv->card_alive, &pkt->u.alive_frame,
547 sizeof(struct iwl_alive_resp)); 543 sizeof(struct iwl_alive_resp));
548 pwork = &priv->alive_start; 544 pwork = &priv->alive_start;
@@ -896,7 +892,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
896 iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); 892 iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
897 893
898#ifdef CONFIG_IWLWIFI_DEBUG 894#ifdef CONFIG_IWLWIFI_DEBUG
899 if (iwl_debug_level & IWL_DL_ISR) { 895 if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
900 /* just for debug */ 896 /* just for debug */
901 inta_mask = iwl_read32(priv, CSR_INT_MASK); 897 inta_mask = iwl_read32(priv, CSR_INT_MASK);
902 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", 898 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -931,7 +927,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
931 } 927 }
932 928
933#ifdef CONFIG_IWLWIFI_DEBUG 929#ifdef CONFIG_IWLWIFI_DEBUG
934 if (iwl_debug_level & (IWL_DL_ISR)) { 930 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
935 /* NIC fires this, but we don't use it, redundant with WAKEUP */ 931 /* NIC fires this, but we don't use it, redundant with WAKEUP */
936 if (inta & CSR_INT_BIT_SCD) { 932 if (inta & CSR_INT_BIT_SCD) {
937 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " 933 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1045,7 +1041,7 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
1045 iwl_enable_interrupts(priv); 1041 iwl_enable_interrupts(priv);
1046 1042
1047#ifdef CONFIG_IWLWIFI_DEBUG 1043#ifdef CONFIG_IWLWIFI_DEBUG
1048 if (iwl_debug_level & (IWL_DL_ISR)) { 1044 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
1049 inta = iwl_read32(priv, CSR_INT); 1045 inta = iwl_read32(priv, CSR_INT);
1050 inta_mask = iwl_read32(priv, CSR_INT_MASK); 1046 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1051 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); 1047 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -1076,7 +1072,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1076 inta = priv->inta; 1072 inta = priv->inta;
1077 1073
1078#ifdef CONFIG_IWLWIFI_DEBUG 1074#ifdef CONFIG_IWLWIFI_DEBUG
1079 if (iwl_debug_level & IWL_DL_ISR) { 1075 if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
1080 /* just for debug */ 1076 /* just for debug */
1081 inta_mask = iwl_read32(priv, CSR_INT_MASK); 1077 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1082 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", 1078 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
@@ -1104,7 +1100,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1104 } 1100 }
1105 1101
1106#ifdef CONFIG_IWLWIFI_DEBUG 1102#ifdef CONFIG_IWLWIFI_DEBUG
1107 if (iwl_debug_level & (IWL_DL_ISR)) { 1103 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
1108 /* NIC fires this, but we don't use it, redundant with WAKEUP */ 1104 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1109 if (inta & CSR_INT_BIT_SCD) { 1105 if (inta & CSR_INT_BIT_SCD) {
1110 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " 1106 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1610,7 +1606,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
1610 set_bit(STATUS_READY, &priv->status); 1606 set_bit(STATUS_READY, &priv->status);
1611 wake_up_interruptible(&priv->wait_command_queue); 1607 wake_up_interruptible(&priv->wait_command_queue);
1612 1608
1613 iwl_power_update_mode(priv, 1); 1609 iwl_power_update_mode(priv, true);
1614 1610
1615 /* reassociate for ADHOC mode */ 1611 /* reassociate for ADHOC mode */
1616 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { 1612 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
@@ -1784,7 +1780,6 @@ static int __iwl_up(struct iwl_priv *priv)
1784{ 1780{
1785 int i; 1781 int i;
1786 int ret; 1782 int ret;
1787 unsigned long status;
1788 1783
1789 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { 1784 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
1790 IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); 1785 IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
@@ -1862,51 +1857,6 @@ static int __iwl_up(struct iwl_priv *priv)
1862 /* start card; "initialize" will load runtime ucode */ 1857 /* start card; "initialize" will load runtime ucode */
1863 iwl_nic_start(priv); 1858 iwl_nic_start(priv);
1864 1859
1865 /* Just finish download Init or Runtime uCode image to device
1866 * now we wait here for uCode send REPLY_ALIVE notification
1867 * to indicate uCode is ready.
1868 * 1) For Init uCode image, all iwlagn devices should wait here
1869 * on STATUS_INIT_UCODE_ALIVE status bit; if timeout before
1870 * receive the REPLY_ALIVE notification, go back and try to
1871 * download the Init uCode image again.
1872 * 2) For Runtime uCode image, all iwlagn devices except 4965
1873 * wait here on STATUS_RT_UCODE_ALIVE status bit; if
1874 * timeout before receive the REPLY_ALIVE notification, go back
1875 * and download the Runtime uCode image again.
1876 * 3) For 4965 Runtime uCode, it will not go through this path,
1877 * need to wait for STATUS_RT_UCODE_ALIVE status bit in
1878 * iwl4965_init_alive_start() function; if timeout, need to
1879 * restart and download Init uCode image.
1880 */
1881 if (priv->ucode_type == UCODE_INIT)
1882 status = STATUS_INIT_UCODE_ALIVE;
1883 else
1884 status = STATUS_RT_UCODE_ALIVE;
1885 if (test_bit(status, &priv->status)) {
1886 IWL_WARN(priv,
1887 "%s uCode already alive? "
1888 "Waiting for alive anyway\n",
1889 (status == STATUS_INIT_UCODE_ALIVE)
1890 ? "INIT" : "Runtime");
1891 clear_bit(status, &priv->status);
1892 }
1893 ret = wait_event_interruptible_timeout(
1894 priv->wait_command_queue,
1895 test_bit(status, &priv->status),
1896 UCODE_ALIVE_TIMEOUT);
1897 if (!ret) {
1898 if (!test_bit(status, &priv->status)) {
1899 priv->ucode_type =
1900 (status == STATUS_INIT_UCODE_ALIVE)
1901 ? UCODE_NONE : UCODE_INIT;
1902 IWL_ERR(priv,
1903 "%s timeout after %dms\n",
1904 (status == STATUS_INIT_UCODE_ALIVE)
1905 ? "INIT" : "Runtime",
1906 jiffies_to_msecs(UCODE_ALIVE_TIMEOUT));
1907 continue;
1908 }
1909 }
1910 IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); 1860 IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
1911 1861
1912 return 0; 1862 return 0;
@@ -2125,7 +2075,7 @@ void iwl_post_associate(struct iwl_priv *priv)
2125 * If chain noise has already been run, then we need to enable 2075 * If chain noise has already been run, then we need to enable
2126 * power management here */ 2076 * power management here */
2127 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) 2077 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
2128 iwl_power_update_mode(priv, 0); 2078 iwl_power_update_mode(priv, false);
2129 2079
2130 /* Enable Rx differential gain and sensitivity calibrations */ 2080 /* Enable Rx differential gain and sensitivity calibrations */
2131 iwl_chain_noise_reset(priv); 2081 iwl_chain_noise_reset(priv);
@@ -2455,15 +2405,15 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw,
2455 * 2405 *
2456 * See the level definitions in iwl for details. 2406 * See the level definitions in iwl for details.
2457 * 2407 *
2458 * FIXME This file can be deprecated as the module parameter is 2408 * The debug_level being managed using sysfs below is a per device debug
2459 * writable and users can thus also change the debug level 2409 * level that is used instead of the global debug level if it (the per
2460 * using the /sys/module/iwl3945/parameters/debug file. 2410 * device debug level) is set.
2461 */ 2411 */
2462
2463static ssize_t show_debug_level(struct device *d, 2412static ssize_t show_debug_level(struct device *d,
2464 struct device_attribute *attr, char *buf) 2413 struct device_attribute *attr, char *buf)
2465{ 2414{
2466 return sprintf(buf, "0x%08X\n", iwl_debug_level); 2415 struct iwl_priv *priv = dev_get_drvdata(d);
2416 return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
2467} 2417}
2468static ssize_t store_debug_level(struct device *d, 2418static ssize_t store_debug_level(struct device *d,
2469 struct device_attribute *attr, 2419 struct device_attribute *attr,
@@ -2476,9 +2426,12 @@ static ssize_t store_debug_level(struct device *d,
2476 ret = strict_strtoul(buf, 0, &val); 2426 ret = strict_strtoul(buf, 0, &val);
2477 if (ret) 2427 if (ret)
2478 IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); 2428 IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
2479 else 2429 else {
2480 iwl_debug_level = val; 2430 priv->debug_level = val;
2481 2431 if (iwl_alloc_traffic_mem(priv))
2432 IWL_ERR(priv,
2433 "Not enough memory to generate traffic log\n");
2434 }
2482 return strnlen(buf, count); 2435 return strnlen(buf, count);
2483} 2436}
2484 2437
@@ -2612,47 +2565,6 @@ static ssize_t store_filter_flags(struct device *d,
2612static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, 2565static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
2613 store_filter_flags); 2566 store_filter_flags);
2614 2567
2615static ssize_t store_power_level(struct device *d,
2616 struct device_attribute *attr,
2617 const char *buf, size_t count)
2618{
2619 struct iwl_priv *priv = dev_get_drvdata(d);
2620 int ret;
2621 unsigned long mode;
2622
2623
2624 mutex_lock(&priv->mutex);
2625
2626 ret = strict_strtoul(buf, 10, &mode);
2627 if (ret)
2628 goto out;
2629
2630 ret = iwl_power_set_user_mode(priv, mode);
2631 if (ret) {
2632 IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
2633 goto out;
2634 }
2635 ret = count;
2636
2637 out:
2638 mutex_unlock(&priv->mutex);
2639 return ret;
2640}
2641
2642static ssize_t show_power_level(struct device *d,
2643 struct device_attribute *attr, char *buf)
2644{
2645 struct iwl_priv *priv = dev_get_drvdata(d);
2646 int level = priv->power_data.power_mode;
2647 char *p = buf;
2648
2649 p += sprintf(p, "%d\n", level);
2650 return p - buf + 1;
2651}
2652
2653static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
2654 store_power_level);
2655
2656 2568
2657static ssize_t show_statistics(struct device *d, 2569static ssize_t show_statistics(struct device *d,
2658 struct device_attribute *attr, char *buf) 2570 struct device_attribute *attr, char *buf)
@@ -2745,7 +2657,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
2745static struct attribute *iwl_sysfs_entries[] = { 2657static struct attribute *iwl_sysfs_entries[] = {
2746 &dev_attr_flags.attr, 2658 &dev_attr_flags.attr,
2747 &dev_attr_filter_flags.attr, 2659 &dev_attr_filter_flags.attr,
2748 &dev_attr_power_level.attr,
2749 &dev_attr_statistics.attr, 2660 &dev_attr_statistics.attr,
2750 &dev_attr_temperature.attr, 2661 &dev_attr_temperature.attr,
2751 &dev_attr_tx_power.attr, 2662 &dev_attr_tx_power.attr,
@@ -2819,6 +2730,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2819#ifdef CONFIG_IWLWIFI_DEBUG 2730#ifdef CONFIG_IWLWIFI_DEBUG
2820 atomic_set(&priv->restrict_refcnt, 0); 2731 atomic_set(&priv->restrict_refcnt, 0);
2821#endif 2732#endif
2733 if (iwl_alloc_traffic_mem(priv))
2734 IWL_ERR(priv, "Not enough memory to generate traffic log\n");
2822 2735
2823 /************************** 2736 /**************************
2824 * 2. Initializing PCI bus 2737 * 2. Initializing PCI bus
@@ -3003,6 +2916,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
3003 pci_disable_device(pdev); 2916 pci_disable_device(pdev);
3004 out_ieee80211_free_hw: 2917 out_ieee80211_free_hw:
3005 ieee80211_free_hw(priv->hw); 2918 ieee80211_free_hw(priv->hw);
2919 iwl_free_traffic_mem(priv);
3006 out: 2920 out:
3007 return err; 2921 return err;
3008} 2922}
@@ -3061,6 +2975,7 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
3061 * until now... */ 2975 * until now... */
3062 destroy_workqueue(priv->workqueue); 2976 destroy_workqueue(priv->workqueue);
3063 priv->workqueue = NULL; 2977 priv->workqueue = NULL;
2978 iwl_free_traffic_mem(priv);
3064 2979
3065 free_irq(priv->pci_dev->irq, priv); 2980 free_irq(priv->pci_dev->irq, priv);
3066 pci_disable_msi(priv->pci_dev); 2981 pci_disable_msi(priv->pci_dev);
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 13180d6ee2f7..c4b565a2de94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -852,7 +852,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
852 priv->cfg->ops->lib->update_chain_flags(priv); 852 priv->cfg->ops->lib->update_chain_flags(priv);
853 853
854 data->state = IWL_CHAIN_NOISE_DONE; 854 data->state = IWL_CHAIN_NOISE_DONE;
855 iwl_power_update_mode(priv, 0); 855 iwl_power_update_mode(priv, false);
856} 856}
857EXPORT_SYMBOL(iwl_chain_noise_calibration); 857EXPORT_SYMBOL(iwl_chain_noise_calibration);
858 858
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 39ede5727fe4..68d7719071f7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -283,7 +283,7 @@ struct iwl3945_power_per_rate {
283 * 1) Dual stream (MIMO) 283 * 1) Dual stream (MIMO)
284 * 2) Triple stream (MIMO) 284 * 2) Triple stream (MIMO)
285 * 285 *
286 * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data 286 * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
287 * 287 *
288 * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"): 288 * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
289 * 3-0: 0xD) 6 Mbps 289 * 3-0: 0xD) 6 Mbps
@@ -320,11 +320,11 @@ struct iwl3945_power_per_rate {
320#define RATE_MCS_GF_POS 10 320#define RATE_MCS_GF_POS 10
321#define RATE_MCS_GF_MSK 0x400 321#define RATE_MCS_GF_MSK 0x400
322 322
323/* Bit 11: (1) Use 40Mhz FAT chnl width, (0) use 20 MHz legacy chnl width */ 323/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */
324#define RATE_MCS_FAT_POS 11 324#define RATE_MCS_HT40_POS 11
325#define RATE_MCS_FAT_MSK 0x800 325#define RATE_MCS_HT40_MSK 0x800
326 326
327/* Bit 12: (1) Duplicate data on both 20MHz chnls. FAT (bit 11) must be set. */ 327/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */
328#define RATE_MCS_DUP_POS 12 328#define RATE_MCS_DUP_POS 12
329#define RATE_MCS_DUP_MSK 0x1000 329#define RATE_MCS_DUP_MSK 0x1000
330 330
@@ -459,7 +459,7 @@ struct iwl_init_alive_resp {
459 459
460 /* calibration values from "initialize" uCode */ 460 /* calibration values from "initialize" uCode */
461 __le32 voltage; /* signed, higher value is lower voltage */ 461 __le32 voltage; /* signed, higher value is lower voltage */
462 __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for FAT channel*/ 462 __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */
463 __le32 therm_r2[2]; /* signed */ 463 __le32 therm_r2[2]; /* signed */
464 __le32 therm_r3[2]; /* signed */ 464 __le32 therm_r3[2]; /* signed */
465 __le32 therm_r4[2]; /* signed */ 465 __le32 therm_r4[2]; /* signed */
@@ -610,7 +610,7 @@ enum {
610#define RXON_FLG_HT_OPERATING_MODE_POS (23) 610#define RXON_FLG_HT_OPERATING_MODE_POS (23)
611 611
612#define RXON_FLG_HT_PROT_MSK cpu_to_le32(0x1 << 23) 612#define RXON_FLG_HT_PROT_MSK cpu_to_le32(0x1 << 23)
613#define RXON_FLG_FAT_PROT_MSK cpu_to_le32(0x2 << 23) 613#define RXON_FLG_HT40_PROT_MSK cpu_to_le32(0x2 << 23)
614 614
615#define RXON_FLG_CHANNEL_MODE_POS (25) 615#define RXON_FLG_CHANNEL_MODE_POS (25)
616#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25) 616#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25)
@@ -891,7 +891,7 @@ struct iwl_qosparam_cmd {
891#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) 891#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
892#define STA_FLG_MAX_AGG_SIZE_POS (19) 892#define STA_FLG_MAX_AGG_SIZE_POS (19)
893#define STA_FLG_MAX_AGG_SIZE_MSK cpu_to_le32(3 << 19) 893#define STA_FLG_MAX_AGG_SIZE_MSK cpu_to_le32(3 << 19)
894#define STA_FLG_FAT_EN_MSK cpu_to_le32(1 << 21) 894#define STA_FLG_HT40_EN_MSK cpu_to_le32(1 << 21)
895#define STA_FLG_MIMO_DIS_MSK cpu_to_le32(1 << 22) 895#define STA_FLG_MIMO_DIS_MSK cpu_to_le32(1 << 22)
896#define STA_FLG_AGG_MPDU_DENSITY_POS (23) 896#define STA_FLG_AGG_MPDU_DENSITY_POS (23)
897#define STA_FLG_AGG_MPDU_DENSITY_MSK cpu_to_le32(7 << 23) 897#define STA_FLG_AGG_MPDU_DENSITY_MSK cpu_to_le32(7 << 23)
@@ -1984,10 +1984,10 @@ struct iwl_link_qual_agg_params {
1984 * a) Use this same initial rate for first 3 entries. 1984 * a) Use this same initial rate for first 3 entries.
1985 * b) Find next lower available rate using same mode (SISO or MIMO), 1985 * b) Find next lower available rate using same mode (SISO or MIMO),
1986 * use for next 3 entries. If no lower rate available, switch to 1986 * use for next 3 entries. If no lower rate available, switch to
1987 * legacy mode (no FAT channel, no MIMO, no short guard interval). 1987 * legacy mode (no HT40 channel, no MIMO, no short guard interval).
1988 * c) If using MIMO, set command's mimo_delimiter to number of entries 1988 * c) If using MIMO, set command's mimo_delimiter to number of entries
1989 * using MIMO (3 or 6). 1989 * using MIMO (3 or 6).
1990 * d) After trying 2 HT rates, switch to legacy mode (no FAT channel, 1990 * d) After trying 2 HT rates, switch to legacy mode (no HT40 channel,
1991 * no MIMO, no short guard interval), at the next lower bit rate 1991 * no MIMO, no short guard interval), at the next lower bit rate
1992 * (e.g. if second HT bit rate was 54, try 48 legacy), and follow 1992 * (e.g. if second HT bit rate was 54, try 48 legacy), and follow
1993 * legacy procedure for remaining table entries. 1993 * legacy procedure for remaining table entries.
@@ -2313,15 +2313,22 @@ struct iwl_spectrum_notification {
2313 * PM allow: 2313 * PM allow:
2314 * bit 0 - '0' Driver not allow power management 2314 * bit 0 - '0' Driver not allow power management
2315 * '1' Driver allow PM (use rest of parameters) 2315 * '1' Driver allow PM (use rest of parameters)
2316 *
2316 * uCode send sleep notifications: 2317 * uCode send sleep notifications:
2317 * bit 1 - '0' Don't send sleep notification 2318 * bit 1 - '0' Don't send sleep notification
2318 * '1' send sleep notification (SEND_PM_NOTIFICATION) 2319 * '1' send sleep notification (SEND_PM_NOTIFICATION)
2320 *
2319 * Sleep over DTIM 2321 * Sleep over DTIM
2320 * bit 2 - '0' PM have to walk up every DTIM 2322 * bit 2 - '0' PM have to walk up every DTIM
2321 * '1' PM could sleep over DTIM till listen Interval. 2323 * '1' PM could sleep over DTIM till listen Interval.
2324 *
2322 * PCI power managed 2325 * PCI power managed
2323 * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1) 2326 * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
2324 * '1' !(PCI_CFG_LINK_CTRL & 0x1) 2327 * '1' !(PCI_CFG_LINK_CTRL & 0x1)
2328 *
2329 * Fast PD
2330 * bit 4 - '1' Put radio to sleep when receiving frame for others
2331 *
2325 * Force sleep Modes 2332 * Force sleep Modes
2326 * bit 31/30- '00' use both mac/xtal sleeps 2333 * bit 31/30- '00' use both mac/xtal sleeps
2327 * '01' force Mac sleep 2334 * '01' force Mac sleep
@@ -3017,7 +3024,7 @@ struct iwl_statistics_cmd {
3017 * one channel that has just been scanned. 3024 * one channel that has just been scanned.
3018 */ 3025 */
3019#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) 3026#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2)
3020#define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8) 3027#define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8)
3021 3028
3022struct iwl3945_notif_statistics { 3029struct iwl3945_notif_statistics {
3023 __le32 flag; 3030 __le32 flag;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 2ffbd27d01d2..af735128333a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -105,7 +105,7 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
105 r->flags |= IEEE80211_TX_RC_MCS; 105 r->flags |= IEEE80211_TX_RC_MCS;
106 if (rate_n_flags & RATE_MCS_GF_MSK) 106 if (rate_n_flags & RATE_MCS_GF_MSK)
107 r->flags |= IEEE80211_TX_RC_GREEN_FIELD; 107 r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
108 if (rate_n_flags & RATE_MCS_FAT_MSK) 108 if (rate_n_flags & RATE_MCS_HT40_MSK)
109 r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 109 r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
110 if (rate_n_flags & RATE_MCS_DUP_MSK) 110 if (rate_n_flags & RATE_MCS_DUP_MSK)
111 r->flags |= IEEE80211_TX_RC_DUP_DATA; 111 r->flags |= IEEE80211_TX_RC_DUP_DATA;
@@ -400,7 +400,7 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
400 (WLAN_HT_CAP_SM_PS_DISABLED << 2)); 400 (WLAN_HT_CAP_SM_PS_DISABLED << 2));
401 401
402 max_bit_rate = MAX_BIT_RATE_20_MHZ; 402 max_bit_rate = MAX_BIT_RATE_20_MHZ;
403 if (priv->hw_params.fat_channel & BIT(band)) { 403 if (priv->hw_params.ht40_channel & BIT(band)) {
404 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; 404 ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
405 ht_info->cap |= IEEE80211_HT_CAP_SGI_40; 405 ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
406 ht_info->mcs.rx_mask[4] = 0x01; 406 ht_info->mcs.rx_mask[4] = 0x01;
@@ -540,7 +540,7 @@ int iwlcore_init_geos(struct iwl_priv *priv)
540 if (ch->flags & EEPROM_CHANNEL_RADAR) 540 if (ch->flags & EEPROM_CHANNEL_RADAR)
541 geo_ch->flags |= IEEE80211_CHAN_RADAR; 541 geo_ch->flags |= IEEE80211_CHAN_RADAR;
542 542
543 geo_ch->flags |= ch->fat_extension_channel; 543 geo_ch->flags |= ch->ht40_extension_channel;
544 544
545 if (ch->max_power_avg > priv->tx_power_channel_lmt) 545 if (ch->max_power_avg > priv->tx_power_channel_lmt)
546 priv->tx_power_channel_lmt = ch->max_power_avg; 546 priv->tx_power_channel_lmt = ch->max_power_avg;
@@ -604,16 +604,16 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
604 return 0; 604 return 0;
605 605
606 if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 606 if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
607 return !(ch_info->fat_extension_channel & 607 return !(ch_info->ht40_extension_channel &
608 IEEE80211_CHAN_NO_HT40PLUS); 608 IEEE80211_CHAN_NO_HT40PLUS);
609 else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) 609 else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
610 return !(ch_info->fat_extension_channel & 610 return !(ch_info->ht40_extension_channel &
611 IEEE80211_CHAN_NO_HT40MINUS); 611 IEEE80211_CHAN_NO_HT40MINUS);
612 612
613 return 0; 613 return 0;
614} 614}
615 615
616u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, 616u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
617 struct ieee80211_sta_ht_cap *sta_ht_inf) 617 struct ieee80211_sta_ht_cap *sta_ht_inf)
618{ 618{
619 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; 619 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
@@ -637,7 +637,7 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
637 le16_to_cpu(priv->staging_rxon.channel), 637 le16_to_cpu(priv->staging_rxon.channel),
638 iwl_ht_conf->extension_chan_offset); 638 iwl_ht_conf->extension_chan_offset);
639} 639}
640EXPORT_SYMBOL(iwl_is_fat_tx_allowed); 640EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
641 641
642static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) 642static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
643{ 643{
@@ -866,7 +866,7 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
866 if (!ht_info->is_ht) { 866 if (!ht_info->is_ht) {
867 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 867 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
868 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 868 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
869 RXON_FLG_FAT_PROT_MSK | 869 RXON_FLG_HT40_PROT_MSK |
870 RXON_FLG_HT_PROT_MSK); 870 RXON_FLG_HT_PROT_MSK);
871 return; 871 return;
872 } 872 }
@@ -877,12 +877,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
877 rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); 877 rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
878 878
879 /* Set up channel bandwidth: 879 /* Set up channel bandwidth:
880 * 20 MHz only, 20/40 mixed or pure 40 if fat ok */ 880 * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */
881 /* clear the HT channel mode before set the mode */ 881 /* clear the HT channel mode before set the mode */
882 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 882 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
883 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); 883 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
884 if (iwl_is_fat_tx_allowed(priv, NULL)) { 884 if (iwl_is_ht40_tx_allowed(priv, NULL)) {
885 /* pure 40 fat */ 885 /* pure ht40 */
886 if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { 886 if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) {
887 rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; 887 rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
888 /* Note: control channel is opposite of extension channel */ 888 /* Note: control channel is opposite of extension channel */
@@ -1278,7 +1278,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
1278 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 1278 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
1279 1279
1280 IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); 1280 IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
1281 iwl_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); 1281 iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
1282 IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); 1282 IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
1283 IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); 1283 IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
1284 IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", 1284 IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
@@ -1343,17 +1343,10 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
1343 u32 desc, time, count, base, data1; 1343 u32 desc, time, count, base, data1;
1344 u32 blink1, blink2, ilink1, ilink2; 1344 u32 blink1, blink2, ilink1, ilink2;
1345 1345
1346 switch (priv->ucode_type) { 1346 if (priv->ucode_type == UCODE_INIT)
1347 case UCODE_RT:
1348 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1349 break;
1350 case UCODE_INIT:
1351 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); 1347 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
1352 break; 1348 else
1353 default: 1349 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1354 IWL_ERR(priv, "uCode image not available\n");
1355 return;
1356 }
1357 1350
1358 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1351 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1359 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); 1352 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
@@ -1405,17 +1398,10 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1405 1398
1406 if (num_events == 0) 1399 if (num_events == 0)
1407 return; 1400 return;
1408 switch (priv->ucode_type) { 1401 if (priv->ucode_type == UCODE_INIT)
1409 case UCODE_RT:
1410 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1411 break;
1412 case UCODE_INIT:
1413 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); 1402 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1414 break; 1403 else
1415 default: 1404 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1416 IWL_ERR(priv, "uCode image not available\n");
1417 return;
1418 }
1419 1405
1420 if (mode == 0) 1406 if (mode == 0)
1421 event_size = 2 * sizeof(u32); 1407 event_size = 2 * sizeof(u32);
@@ -1452,17 +1438,10 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
1452 u32 next_entry; /* index of next entry to be written by uCode */ 1438 u32 next_entry; /* index of next entry to be written by uCode */
1453 u32 size; /* # entries that we'll print */ 1439 u32 size; /* # entries that we'll print */
1454 1440
1455 switch (priv->ucode_type) { 1441 if (priv->ucode_type == UCODE_INIT)
1456 case UCODE_RT:
1457 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1458 break;
1459 case UCODE_INIT:
1460 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); 1442 base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
1461 break; 1443 else
1462 default: 1444 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1463 IWL_ERR(priv, "uCode image not available\n");
1464 return;
1465 }
1466 1445
1467 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1446 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1468 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); 1447 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
@@ -1508,7 +1487,7 @@ void iwl_irq_handle_error(struct iwl_priv *priv)
1508 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 1487 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
1509 1488
1510#ifdef CONFIG_IWLWIFI_DEBUG 1489#ifdef CONFIG_IWLWIFI_DEBUG
1511 if (iwl_debug_level & IWL_DL_FW_ERRORS) { 1490 if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) {
1512 iwl_dump_nic_error_log(priv); 1491 iwl_dump_nic_error_log(priv);
1513 iwl_dump_nic_event_log(priv); 1492 iwl_dump_nic_event_log(priv);
1514 iwl_print_rx_config_cmd(priv); 1493 iwl_print_rx_config_cmd(priv);
@@ -1589,7 +1568,8 @@ int iwl_setup_mac(struct iwl_priv *priv)
1589 IEEE80211_HW_NOISE_DBM | 1568 IEEE80211_HW_NOISE_DBM |
1590 IEEE80211_HW_AMPDU_AGGREGATION | 1569 IEEE80211_HW_AMPDU_AGGREGATION |
1591 IEEE80211_HW_SPECTRUM_MGMT | 1570 IEEE80211_HW_SPECTRUM_MGMT |
1592 IEEE80211_HW_SUPPORTS_PS; 1571 IEEE80211_HW_SUPPORTS_PS |
1572 IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
1593 hw->wiphy->interface_modes = 1573 hw->wiphy->interface_modes =
1594 BIT(NL80211_IFTYPE_STATION) | 1574 BIT(NL80211_IFTYPE_STATION) |
1595 BIT(NL80211_IFTYPE_ADHOC); 1575 BIT(NL80211_IFTYPE_ADHOC);
@@ -1684,8 +1664,6 @@ int iwl_init_drv(struct iwl_priv *priv)
1684 priv->qos_data.qos_cap.val = 0; 1664 priv->qos_data.qos_cap.val = 0;
1685 1665
1686 priv->rates_mask = IWL_RATES_MASK; 1666 priv->rates_mask = IWL_RATES_MASK;
1687 /* If power management is turned on, default to CAM mode */
1688 priv->power_mode = IWL_POWER_MODE_CAM;
1689 priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX; 1667 priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
1690 1668
1691 ret = iwl_init_channel_map(priv); 1669 ret = iwl_init_channel_map(priv);
@@ -1985,7 +1963,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
1985 } 1963 }
1986 1964
1987#ifdef CONFIG_IWLWIFI_DEBUG 1965#ifdef CONFIG_IWLWIFI_DEBUG
1988 if (iwl_debug_level & (IWL_DL_ISR)) { 1966 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
1989 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); 1967 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
1990 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " 1968 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
1991 "fh 0x%08x\n", inta, inta_mask, inta_fh); 1969 "fh 0x%08x\n", inta, inta_mask, inta_fh);
@@ -2235,7 +2213,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
2235 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 2213 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
2236 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 2214 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
2237 spin_unlock_irqrestore(&priv->lock, flags); 2215 spin_unlock_irqrestore(&priv->lock, flags);
2238 priv->power_data.ct_kill_toggle = false; 2216 priv->thermal_throttle.ct_kill_toggle = false;
2239 2217
2240 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 2218 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
2241 case CSR_HW_REV_TYPE_1000: 2219 case CSR_HW_REV_TYPE_1000:
@@ -2248,6 +2226,15 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
2248 2226
2249 ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 2227 ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
2250 sizeof(adv_cmd), &adv_cmd); 2228 sizeof(adv_cmd), &adv_cmd);
2229 if (ret)
2230 IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
2231 else
2232 IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
2233 "succeeded, "
2234 "critical temperature enter is %d,"
2235 "exit is %d\n",
2236 priv->hw_params.ct_kill_threshold,
2237 priv->hw_params.ct_kill_exit_threshold);
2251 break; 2238 break;
2252 default: 2239 default:
2253 cmd.critical_temperature_R = 2240 cmd.critical_temperature_R =
@@ -2255,16 +2242,15 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
2255 2242
2256 ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, 2243 ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
2257 sizeof(cmd), &cmd); 2244 sizeof(cmd), &cmd);
2245 if (ret)
2246 IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
2247 else
2248 IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
2249 "succeeded, "
2250 "critical temperature is %d\n",
2251 priv->hw_params.ct_kill_threshold);
2258 break; 2252 break;
2259 } 2253 }
2260 ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
2261 sizeof(cmd), &cmd);
2262 if (ret)
2263 IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
2264 else
2265 IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD succeeded, "
2266 "critical temperature is %d\n",
2267 cmd.critical_temperature_R);
2268} 2254}
2269EXPORT_SYMBOL(iwl_rf_kill_ct_config); 2255EXPORT_SYMBOL(iwl_rf_kill_ct_config);
2270 2256
@@ -2310,7 +2296,7 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
2310 IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " 2296 IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
2311 "notification for %s:\n", 2297 "notification for %s:\n",
2312 le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); 2298 le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd));
2313 iwl_print_hex_dump(IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); 2299 iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
2314} 2300}
2315EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); 2301EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
2316 2302
@@ -2428,7 +2414,7 @@ static void iwl_ht_conf(struct iwl_priv *priv,
2428 else if (conf_is_ht40_plus(&priv->hw->conf)) 2414 else if (conf_is_ht40_plus(&priv->hw->conf))
2429 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; 2415 iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
2430 2416
2431 /* If no above or below channel supplied disable FAT channel */ 2417 /* If no above or below channel supplied disable HT40 channel */
2432 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && 2418 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
2433 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) 2419 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
2434 iwl_conf->supported_chan_width = 0; 2420 iwl_conf->supported_chan_width = 0;
@@ -2564,7 +2550,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
2564 if (bss_conf->assoc) { 2550 if (bss_conf->assoc) {
2565 priv->assoc_id = bss_conf->aid; 2551 priv->assoc_id = bss_conf->aid;
2566 priv->beacon_int = bss_conf->beacon_int; 2552 priv->beacon_int = bss_conf->beacon_int;
2567 priv->power_data.dtim_period = bss_conf->dtim_period;
2568 priv->timestamp = bss_conf->timestamp; 2553 priv->timestamp = bss_conf->timestamp;
2569 priv->assoc_capability = bss_conf->assoc_capability; 2554 priv->assoc_capability = bss_conf->assoc_capability;
2570 2555
@@ -2814,13 +2799,10 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2814 iwl_set_rate(priv); 2799 iwl_set_rate(priv);
2815 } 2800 }
2816 2801
2817 if (changed & IEEE80211_CONF_CHANGE_PS && 2802 if (changed & IEEE80211_CONF_CHANGE_PS) {
2818 priv->iw_mode == NL80211_IFTYPE_STATION) { 2803 ret = iwl_power_update_mode(priv, false);
2819 priv->power_data.power_disabled =
2820 !(conf->flags & IEEE80211_CONF_PS);
2821 ret = iwl_power_update_mode(priv, 0);
2822 if (ret) 2804 if (ret)
2823 IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); 2805 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
2824 } 2806 }
2825 2807
2826 if (changed & IEEE80211_CONF_CHANGE_POWER) { 2808 if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -2953,6 +2935,248 @@ void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
2953} 2935}
2954EXPORT_SYMBOL(iwl_mac_reset_tsf); 2936EXPORT_SYMBOL(iwl_mac_reset_tsf);
2955 2937
2938#ifdef CONFIG_IWLWIFI_DEBUGFS
2939
2940#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
2941
2942void iwl_reset_traffic_log(struct iwl_priv *priv)
2943{
2944 priv->tx_traffic_idx = 0;
2945 priv->rx_traffic_idx = 0;
2946 if (priv->tx_traffic)
2947 memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
2948 if (priv->rx_traffic)
2949 memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
2950}
2951
2952int iwl_alloc_traffic_mem(struct iwl_priv *priv)
2953{
2954 u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
2955
2956 if (iwl_debug_level & IWL_DL_TX) {
2957 if (!priv->tx_traffic) {
2958 priv->tx_traffic =
2959 kzalloc(traffic_size, GFP_KERNEL);
2960 if (!priv->tx_traffic)
2961 return -ENOMEM;
2962 }
2963 }
2964 if (iwl_debug_level & IWL_DL_RX) {
2965 if (!priv->rx_traffic) {
2966 priv->rx_traffic =
2967 kzalloc(traffic_size, GFP_KERNEL);
2968 if (!priv->rx_traffic)
2969 return -ENOMEM;
2970 }
2971 }
2972 iwl_reset_traffic_log(priv);
2973 return 0;
2974}
2975EXPORT_SYMBOL(iwl_alloc_traffic_mem);
2976
2977void iwl_free_traffic_mem(struct iwl_priv *priv)
2978{
2979 kfree(priv->tx_traffic);
2980 priv->tx_traffic = NULL;
2981
2982 kfree(priv->rx_traffic);
2983 priv->rx_traffic = NULL;
2984}
2985EXPORT_SYMBOL(iwl_free_traffic_mem);
2986
2987void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
2988 u16 length, struct ieee80211_hdr *header)
2989{
2990 __le16 fc;
2991 u16 len;
2992
2993 if (likely(!(iwl_debug_level & IWL_DL_TX)))
2994 return;
2995
2996 if (!priv->tx_traffic)
2997 return;
2998
2999 fc = header->frame_control;
3000 if (ieee80211_is_data(fc)) {
3001 len = (length > IWL_TRAFFIC_ENTRY_SIZE)
3002 ? IWL_TRAFFIC_ENTRY_SIZE : length;
3003 memcpy((priv->tx_traffic +
3004 (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
3005 header, len);
3006 priv->tx_traffic_idx =
3007 (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
3008 }
3009}
3010EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
3011
3012void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
3013 u16 length, struct ieee80211_hdr *header)
3014{
3015 __le16 fc;
3016 u16 len;
3017
3018 if (likely(!(iwl_debug_level & IWL_DL_RX)))
3019 return;
3020
3021 if (!priv->rx_traffic)
3022 return;
3023
3024 fc = header->frame_control;
3025 if (ieee80211_is_data(fc)) {
3026 len = (length > IWL_TRAFFIC_ENTRY_SIZE)
3027 ? IWL_TRAFFIC_ENTRY_SIZE : length;
3028 memcpy((priv->rx_traffic +
3029 (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
3030 header, len);
3031 priv->rx_traffic_idx =
3032 (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
3033 }
3034}
3035EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
3036
3037const char *get_mgmt_string(int cmd)
3038{
3039 switch (cmd) {
3040 IWL_CMD(MANAGEMENT_ASSOC_REQ);
3041 IWL_CMD(MANAGEMENT_ASSOC_RESP);
3042 IWL_CMD(MANAGEMENT_REASSOC_REQ);
3043 IWL_CMD(MANAGEMENT_REASSOC_RESP);
3044 IWL_CMD(MANAGEMENT_PROBE_REQ);
3045 IWL_CMD(MANAGEMENT_PROBE_RESP);
3046 IWL_CMD(MANAGEMENT_BEACON);
3047 IWL_CMD(MANAGEMENT_ATIM);
3048 IWL_CMD(MANAGEMENT_DISASSOC);
3049 IWL_CMD(MANAGEMENT_AUTH);
3050 IWL_CMD(MANAGEMENT_DEAUTH);
3051 IWL_CMD(MANAGEMENT_ACTION);
3052 default:
3053 return "UNKNOWN";
3054
3055 }
3056}
3057
3058const char *get_ctrl_string(int cmd)
3059{
3060 switch (cmd) {
3061 IWL_CMD(CONTROL_BACK_REQ);
3062 IWL_CMD(CONTROL_BACK);
3063 IWL_CMD(CONTROL_PSPOLL);
3064 IWL_CMD(CONTROL_RTS);
3065 IWL_CMD(CONTROL_CTS);
3066 IWL_CMD(CONTROL_ACK);
3067 IWL_CMD(CONTROL_CFEND);
3068 IWL_CMD(CONTROL_CFENDACK);
3069 default:
3070 return "UNKNOWN";
3071
3072 }
3073}
3074
3075void iwl_clear_tx_stats(struct iwl_priv *priv)
3076{
3077 memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
3078
3079}
3080
3081void iwl_clear_rx_stats(struct iwl_priv *priv)
3082{
3083 memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
3084}
3085
3086/*
3087 * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will
3088 * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass.
3089 * Use debugFs to display the rx/rx_statistics
3090 * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL
3091 * information will be recorded, but DATA pkt still will be recorded
3092 * for the reason of iwl_led.c need to control the led blinking based on
3093 * number of tx and rx data.
3094 *
3095 */
3096void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
3097{
3098 struct traffic_stats *stats;
3099
3100 if (is_tx)
3101 stats = &priv->tx_stats;
3102 else
3103 stats = &priv->rx_stats;
3104
3105 if (ieee80211_is_mgmt(fc)) {
3106 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
3107 case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
3108 stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
3109 break;
3110 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
3111 stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
3112 break;
3113 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
3114 stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
3115 break;
3116 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
3117 stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
3118 break;
3119 case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
3120 stats->mgmt[MANAGEMENT_PROBE_REQ]++;
3121 break;
3122 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
3123 stats->mgmt[MANAGEMENT_PROBE_RESP]++;
3124 break;
3125 case cpu_to_le16(IEEE80211_STYPE_BEACON):
3126 stats->mgmt[MANAGEMENT_BEACON]++;
3127 break;
3128 case cpu_to_le16(IEEE80211_STYPE_ATIM):
3129 stats->mgmt[MANAGEMENT_ATIM]++;
3130 break;
3131 case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
3132 stats->mgmt[MANAGEMENT_DISASSOC]++;
3133 break;
3134 case cpu_to_le16(IEEE80211_STYPE_AUTH):
3135 stats->mgmt[MANAGEMENT_AUTH]++;
3136 break;
3137 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
3138 stats->mgmt[MANAGEMENT_DEAUTH]++;
3139 break;
3140 case cpu_to_le16(IEEE80211_STYPE_ACTION):
3141 stats->mgmt[MANAGEMENT_ACTION]++;
3142 break;
3143 }
3144 } else if (ieee80211_is_ctl(fc)) {
3145 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
3146 case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
3147 stats->ctrl[CONTROL_BACK_REQ]++;
3148 break;
3149 case cpu_to_le16(IEEE80211_STYPE_BACK):
3150 stats->ctrl[CONTROL_BACK]++;
3151 break;
3152 case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
3153 stats->ctrl[CONTROL_PSPOLL]++;
3154 break;
3155 case cpu_to_le16(IEEE80211_STYPE_RTS):
3156 stats->ctrl[CONTROL_RTS]++;
3157 break;
3158 case cpu_to_le16(IEEE80211_STYPE_CTS):
3159 stats->ctrl[CONTROL_CTS]++;
3160 break;
3161 case cpu_to_le16(IEEE80211_STYPE_ACK):
3162 stats->ctrl[CONTROL_ACK]++;
3163 break;
3164 case cpu_to_le16(IEEE80211_STYPE_CFEND):
3165 stats->ctrl[CONTROL_CFEND]++;
3166 break;
3167 case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
3168 stats->ctrl[CONTROL_CFENDACK]++;
3169 break;
3170 }
3171 } else {
3172 /* data */
3173 stats->data_cnt++;
3174 stats->data_bytes += len;
3175 }
3176}
3177EXPORT_SYMBOL(iwl_update_stats);
3178#endif
3179
2956#ifdef CONFIG_PM 3180#ifdef CONFIG_PM
2957 3181
2958int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) 3182int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 10ddcdda1041..32750f4f1ce1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -83,6 +83,8 @@ struct iwl_cmd;
83#define IWL_SKU_A 0x2 83#define IWL_SKU_A 0x2
84#define IWL_SKU_N 0x8 84#define IWL_SKU_N 0x8
85 85
86#define IWL_CMD(x) case x: return #x
87
86struct iwl_hcmd_ops { 88struct iwl_hcmd_ops {
87 int (*rxon_assoc)(struct iwl_priv *priv); 89 int (*rxon_assoc)(struct iwl_priv *priv);
88 int (*commit_rxon)(struct iwl_priv *priv); 90 int (*commit_rxon)(struct iwl_priv *priv);
@@ -264,7 +266,7 @@ int iwl_full_rxon_required(struct iwl_priv *priv);
264void iwl_set_rxon_chain(struct iwl_priv *priv); 266void iwl_set_rxon_chain(struct iwl_priv *priv);
265int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); 267int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
266void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); 268void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
267u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv, 269u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv,
268 struct ieee80211_sta_ht_cap *sta_ht_inf); 270 struct ieee80211_sta_ht_cap *sta_ht_inf);
269void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); 271void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band);
270void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode); 272void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode);
@@ -300,7 +302,55 @@ void iwl_config_ap(struct iwl_priv *priv);
300int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, 302int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
301 struct ieee80211_tx_queue_stats *stats); 303 struct ieee80211_tx_queue_stats *stats);
302void iwl_mac_reset_tsf(struct ieee80211_hw *hw); 304void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
305#ifdef CONFIG_IWLWIFI_DEBUGFS
306int iwl_alloc_traffic_mem(struct iwl_priv *priv);
307void iwl_free_traffic_mem(struct iwl_priv *priv);
308void iwl_reset_traffic_log(struct iwl_priv *priv);
309void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
310 u16 length, struct ieee80211_hdr *header);
311void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
312 u16 length, struct ieee80211_hdr *header);
313const char *get_mgmt_string(int cmd);
314const char *get_ctrl_string(int cmd);
315void iwl_clear_tx_stats(struct iwl_priv *priv);
316void iwl_clear_rx_stats(struct iwl_priv *priv);
317void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
318 u16 len);
319#else
320static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv)
321{
322 return 0;
323}
324static inline void iwl_free_traffic_mem(struct iwl_priv *priv)
325{
326}
327static inline void iwl_reset_traffic_log(struct iwl_priv *priv)
328{
329}
330static inline void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
331 u16 length, struct ieee80211_hdr *header)
332{
333}
334static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
335 u16 length, struct ieee80211_hdr *header)
336{
337}
338static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
339 __le16 fc, u16 len)
340{
341 struct traffic_stats *stats;
342
343 if (is_tx)
344 stats = &priv->tx_stats;
345 else
346 stats = &priv->rx_stats;
303 347
348 if (ieee80211_is_data(fc)) {
349 /* data */
350 stats->data_bytes += len;
351 }
352}
353#endif
304/***************************************************** 354/*****************************************************
305 * RX handlers. 355 * RX handlers.
306 * **************************************************/ 356 * **************************************************/
@@ -512,8 +562,6 @@ void iwlcore_free_geos(struct iwl_priv *priv);
512#define STATUS_POWER_PMI 16 562#define STATUS_POWER_PMI 16
513#define STATUS_FW_ERROR 17 563#define STATUS_FW_ERROR 17
514#define STATUS_MODE_PENDING 18 564#define STATUS_MODE_PENDING 18
515#define STATUS_INIT_UCODE_ALIVE 19
516#define STATUS_RT_UCODE_ALIVE 20
517 565
518 566
519static inline int iwl_is_ready(struct iwl_priv *priv) 567static inline int iwl_is_ready(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index fbe177608bc7..723f38a023ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -46,7 +46,7 @@ do { \
46#ifdef CONFIG_IWLWIFI_DEBUG 46#ifdef CONFIG_IWLWIFI_DEBUG
47#define IWL_DEBUG(__priv, level, fmt, args...) \ 47#define IWL_DEBUG(__priv, level, fmt, args...) \
48do { \ 48do { \
49 if (iwl_debug_level & (level)) \ 49 if (iwl_get_debug_level(__priv) & (level)) \
50 dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ 50 dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
51 "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ 51 "%c %s " fmt, in_interrupt() ? 'I' : 'U', \
52 __func__ , ## args); \ 52 __func__ , ## args); \
@@ -54,15 +54,15 @@ do { \
54 54
55#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ 55#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \
56do { \ 56do { \
57 if ((iwl_debug_level & (level)) && net_ratelimit()) \ 57 if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \
58 dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ 58 dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \
59 "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ 59 "%c %s " fmt, in_interrupt() ? 'I' : 'U', \
60 __func__ , ## args); \ 60 __func__ , ## args); \
61} while (0) 61} while (0)
62 62
63#define iwl_print_hex_dump(level, p, len) \ 63#define iwl_print_hex_dump(priv, level, p, len) \
64do { \ 64do { \
65 if (iwl_debug_level & level) \ 65 if (iwl_get_debug_level(priv) & level) \
66 print_hex_dump(KERN_DEBUG, "iwl data: ", \ 66 print_hex_dump(KERN_DEBUG, "iwl data: ", \
67 DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ 67 DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
68} while (0) 68} while (0)
@@ -72,13 +72,12 @@ struct iwl_debugfs {
72 const char *name; 72 const char *name;
73 struct dentry *dir_drv; 73 struct dentry *dir_drv;
74 struct dentry *dir_data; 74 struct dentry *dir_data;
75 struct dentry *dir_debug;
75 struct dentry *dir_rf; 76 struct dentry *dir_rf;
76 struct dir_data_files { 77 struct dir_data_files {
77 struct dentry *file_sram; 78 struct dentry *file_sram;
78 struct dentry *file_nvm; 79 struct dentry *file_nvm;
79 struct dentry *file_stations; 80 struct dentry *file_stations;
80 struct dentry *file_rx_statistics;
81 struct dentry *file_tx_statistics;
82 struct dentry *file_log_event; 81 struct dentry *file_log_event;
83 struct dentry *file_channels; 82 struct dentry *file_channels;
84 struct dentry *file_status; 83 struct dentry *file_status;
@@ -89,12 +88,26 @@ struct iwl_debugfs {
89 struct dentry *file_led; 88 struct dentry *file_led;
90#endif 89#endif
91 struct dentry *file_disable_ht40; 90 struct dentry *file_disable_ht40;
91 struct dentry *file_sleep_level_override;
92 struct dentry *file_current_sleep_command;
92 } dbgfs_data_files; 93 } dbgfs_data_files;
93 struct dir_rf_files { 94 struct dir_rf_files {
94 struct dentry *file_disable_sensitivity; 95 struct dentry *file_disable_sensitivity;
95 struct dentry *file_disable_chain_noise; 96 struct dentry *file_disable_chain_noise;
96 struct dentry *file_disable_tx_power; 97 struct dentry *file_disable_tx_power;
97 } dbgfs_rf_files; 98 } dbgfs_rf_files;
99 struct dir_debug_files {
100 struct dentry *file_rx_statistics;
101 struct dentry *file_tx_statistics;
102 struct dentry *file_traffic_log;
103 struct dentry *file_rx_queue;
104 struct dentry *file_tx_queue;
105 struct dentry *file_ucode_rx_stats;
106 struct dentry *file_ucode_tx_stats;
107 struct dentry *file_ucode_general_stats;
108 struct dentry *file_sensitivity;
109 struct dentry *file_chain_noise;
110 } dbgfs_debug_files;
98 u32 sram_offset; 111 u32 sram_offset;
99 u32 sram_len; 112 u32 sram_len;
100}; 113};
@@ -106,7 +119,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv);
106#else 119#else
107#define IWL_DEBUG(__priv, level, fmt, args...) 120#define IWL_DEBUG(__priv, level, fmt, args...)
108#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) 121#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
109static inline void iwl_print_hex_dump(int level, void *p, u32 len) 122static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
123 void *p, u32 len)
110{} 124{}
111#endif /* CONFIG_IWLWIFI_DEBUG */ 125#endif /* CONFIG_IWLWIFI_DEBUG */
112 126
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 6748a3fb9669..f68fb4711da2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -38,7 +38,7 @@
38#include "iwl-debug.h" 38#include "iwl-debug.h"
39#include "iwl-core.h" 39#include "iwl-core.h"
40#include "iwl-io.h" 40#include "iwl-io.h"
41 41#include "iwl-calib.h"
42 42
43/* create and remove of files */ 43/* create and remove of files */
44#define DEBUGFS_ADD_DIR(name, parent) do { \ 44#define DEBUGFS_ADD_DIR(name, parent) do { \
@@ -126,18 +126,58 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file,
126 size_t count, loff_t *ppos) { 126 size_t count, loff_t *ppos) {
127 127
128 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 128 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
129 char buf[256]; 129 char *buf;
130 int pos = 0; 130 int pos = 0;
131 const size_t bufsz = sizeof(buf);
132 131
133 pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", 132 int cnt;
134 priv->tx_stats[0].cnt); 133 ssize_t ret;
135 pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", 134 const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
136 priv->tx_stats[1].cnt); 135 buf = kzalloc(bufsz, GFP_KERNEL);
137 pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", 136 if (!buf)
138 priv->tx_stats[2].cnt); 137 return -ENOMEM;
138 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
139 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
140 pos += scnprintf(buf + pos, bufsz - pos,
141 "\t%s\t\t: %u\n",
142 get_mgmt_string(cnt),
143 priv->tx_stats.mgmt[cnt]);
144 }
145 pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
146 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
147 pos += scnprintf(buf + pos, bufsz - pos,
148 "\t%s\t\t: %u\n",
149 get_ctrl_string(cnt),
150 priv->tx_stats.ctrl[cnt]);
151 }
152 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
153 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
154 priv->tx_stats.data_cnt);
155 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
156 priv->tx_stats.data_bytes);
157 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
158 kfree(buf);
159 return ret;
160}
139 161
140 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 162static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file,
163 const char __user *user_buf,
164 size_t count, loff_t *ppos)
165{
166 struct iwl_priv *priv = file->private_data;
167 u32 clear_flag;
168 char buf[8];
169 int buf_size;
170
171 memset(buf, 0, sizeof(buf));
172 buf_size = min(count, sizeof(buf) - 1);
173 if (copy_from_user(buf, user_buf, buf_size))
174 return -EFAULT;
175 if (sscanf(buf, "%x", &clear_flag) != 1)
176 return -EFAULT;
177 if (clear_flag == 1)
178 iwl_clear_tx_stats(priv);
179
180 return count;
141} 181}
142 182
143static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, 183static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
@@ -145,18 +185,59 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file,
145 size_t count, loff_t *ppos) { 185 size_t count, loff_t *ppos) {
146 186
147 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 187 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
148 char buf[256]; 188 char *buf;
149 int pos = 0; 189 int pos = 0;
150 const size_t bufsz = sizeof(buf); 190 int cnt;
191 ssize_t ret;
192 const size_t bufsz = 100 +
193 sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX);
194 buf = kzalloc(bufsz, GFP_KERNEL);
195 if (!buf)
196 return -ENOMEM;
151 197
152 pos += scnprintf(buf + pos, bufsz - pos, "mgmt: %u\n", 198 pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
153 priv->rx_stats[0].cnt); 199 for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
154 pos += scnprintf(buf + pos, bufsz - pos, "ctrl: %u\n", 200 pos += scnprintf(buf + pos, bufsz - pos,
155 priv->rx_stats[1].cnt); 201 "\t%s\t\t: %u\n",
156 pos += scnprintf(buf + pos, bufsz - pos, "data: %u\n", 202 get_mgmt_string(cnt),
157 priv->rx_stats[2].cnt); 203 priv->rx_stats.mgmt[cnt]);
204 }
205 pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
206 for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
207 pos += scnprintf(buf + pos, bufsz - pos,
208 "\t%s\t\t: %u\n",
209 get_ctrl_string(cnt),
210 priv->rx_stats.ctrl[cnt]);
211 }
212 pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
213 pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
214 priv->rx_stats.data_cnt);
215 pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
216 priv->rx_stats.data_bytes);
158 217
159 return simple_read_from_buffer(user_buf, count, ppos, buf, pos); 218 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
219 kfree(buf);
220 return ret;
221}
222
223static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file,
224 const char __user *user_buf,
225 size_t count, loff_t *ppos)
226{
227 struct iwl_priv *priv = file->private_data;
228 u32 clear_flag;
229 char buf[8];
230 int buf_size;
231
232 memset(buf, 0, sizeof(buf));
233 buf_size = min(count, sizeof(buf) - 1);
234 if (copy_from_user(buf, user_buf, buf_size))
235 return -EFAULT;
236 if (sscanf(buf, "%x", &clear_flag) != 1)
237 return -EFAULT;
238 if (clear_flag == 1)
239 iwl_clear_rx_stats(priv);
240 return count;
160} 241}
161 242
162#define BYTE1_MASK 0x000000ff; 243#define BYTE1_MASK 0x000000ff;
@@ -623,7 +704,7 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
623 size_t count, loff_t *ppos) 704 size_t count, loff_t *ppos)
624{ 705{
625 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 706 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
626 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 707 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
627 struct iwl_tt_restriction *restriction; 708 struct iwl_tt_restriction *restriction;
628 char buf[100]; 709 char buf[100];
629 int pos = 0; 710 int pos = 0;
@@ -632,12 +713,11 @@ static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
632 713
633 pos += scnprintf(buf + pos, bufsz - pos, 714 pos += scnprintf(buf + pos, bufsz - pos,
634 "Thermal Throttling Mode: %s\n", 715 "Thermal Throttling Mode: %s\n",
635 (priv->power_data.adv_tt) 716 tt->advanced_tt ? "Advance" : "Legacy");
636 ? "Advance" : "Legacy");
637 pos += scnprintf(buf + pos, bufsz - pos, 717 pos += scnprintf(buf + pos, bufsz - pos,
638 "Thermal Throttling State: %d\n", 718 "Thermal Throttling State: %d\n",
639 tt->state); 719 tt->state);
640 if (priv->power_data.adv_tt) { 720 if (tt->advanced_tt) {
641 restriction = tt->restriction + tt->state; 721 restriction = tt->restriction + tt->state;
642 pos += scnprintf(buf + pos, bufsz - pos, 722 pos += scnprintf(buf + pos, bufsz - pos,
643 "Tx mode: %d\n", 723 "Tx mode: %d\n",
@@ -696,12 +776,87 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
696 return ret; 776 return ret;
697} 777}
698 778
779static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
780 const char __user *user_buf,
781 size_t count, loff_t *ppos)
782{
783 struct iwl_priv *priv = file->private_data;
784 char buf[8];
785 int buf_size;
786 int value;
787
788 memset(buf, 0, sizeof(buf));
789 buf_size = min(count, sizeof(buf) - 1);
790 if (copy_from_user(buf, user_buf, buf_size))
791 return -EFAULT;
792
793 if (sscanf(buf, "%d", &value) != 1)
794 return -EINVAL;
795
796 /*
797 * Our users expect 0 to be "CAM", but 0 isn't actually
798 * valid here. However, let's not confuse them and present
799 * IWL_POWER_INDEX_1 as "1", not "0".
800 */
801 if (value > 0)
802 value -= 1;
803
804 if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
805 return -EINVAL;
806
807 priv->power_data.debug_sleep_level_override = value;
808
809 iwl_power_update_mode(priv, false);
810
811 return count;
812}
813
814static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
815 char __user *user_buf,
816 size_t count, loff_t *ppos)
817{
818 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
819 char buf[10];
820 int pos, value;
821 const size_t bufsz = sizeof(buf);
822
823 /* see the write function */
824 value = priv->power_data.debug_sleep_level_override;
825 if (value >= 0)
826 value += 1;
827
828 pos = scnprintf(buf, bufsz, "%d\n", value);
829 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
830}
831
832static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
833 char __user *user_buf,
834 size_t count, loff_t *ppos)
835{
836 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
837 char buf[200];
838 int pos = 0, i;
839 const size_t bufsz = sizeof(buf);
840 struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
841
842 pos += scnprintf(buf + pos, bufsz - pos,
843 "flags: %#.2x\n", le16_to_cpu(cmd->flags));
844 pos += scnprintf(buf + pos, bufsz - pos,
845 "RX/TX timeout: %d/%d usec\n",
846 le32_to_cpu(cmd->rx_data_timeout),
847 le32_to_cpu(cmd->tx_data_timeout));
848 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
849 pos += scnprintf(buf + pos, bufsz - pos,
850 "sleep_interval[%d]: %d\n", i,
851 le32_to_cpu(cmd->sleep_interval[i]));
852
853 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
854}
855
699DEBUGFS_READ_WRITE_FILE_OPS(sram); 856DEBUGFS_READ_WRITE_FILE_OPS(sram);
700DEBUGFS_WRITE_FILE_OPS(log_event); 857DEBUGFS_WRITE_FILE_OPS(log_event);
701DEBUGFS_READ_FILE_OPS(nvm); 858DEBUGFS_READ_FILE_OPS(nvm);
702DEBUGFS_READ_FILE_OPS(stations); 859DEBUGFS_READ_FILE_OPS(stations);
703DEBUGFS_READ_FILE_OPS(rx_statistics);
704DEBUGFS_READ_FILE_OPS(tx_statistics);
705DEBUGFS_READ_FILE_OPS(channels); 860DEBUGFS_READ_FILE_OPS(channels);
706DEBUGFS_READ_FILE_OPS(status); 861DEBUGFS_READ_FILE_OPS(status);
707DEBUGFS_READ_WRITE_FILE_OPS(interrupt); 862DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
@@ -711,6 +866,713 @@ DEBUGFS_READ_FILE_OPS(led);
711#endif 866#endif
712DEBUGFS_READ_FILE_OPS(thermal_throttling); 867DEBUGFS_READ_FILE_OPS(thermal_throttling);
713DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 868DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
869DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
870DEBUGFS_READ_FILE_OPS(current_sleep_command);
871
872static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
873 char __user *user_buf,
874 size_t count, loff_t *ppos)
875{
876 struct iwl_priv *priv = file->private_data;
877 int pos = 0, ofs = 0;
878 int cnt = 0, entry;
879 struct iwl_tx_queue *txq;
880 struct iwl_queue *q;
881 struct iwl_rx_queue *rxq = &priv->rxq;
882 char *buf;
883 int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
884 (IWL_MAX_NUM_QUEUES * 32 * 8) + 400;
885 const u8 *ptr;
886 ssize_t ret;
887
888 buf = kzalloc(bufsz, GFP_KERNEL);
889 if (!buf) {
890 IWL_ERR(priv, "Can not allocate buffer\n");
891 return -ENOMEM;
892 }
893 pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
894 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
895 txq = &priv->txq[cnt];
896 q = &txq->q;
897 pos += scnprintf(buf + pos, bufsz - pos,
898 "q[%d]: read_ptr: %u, write_ptr: %u\n",
899 cnt, q->read_ptr, q->write_ptr);
900 }
901 if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) {
902 ptr = priv->tx_traffic;
903 pos += scnprintf(buf + pos, bufsz - pos,
904 "Tx Traffic idx: %u\n", priv->tx_traffic_idx);
905 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
906 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
907 entry++, ofs += 16) {
908 pos += scnprintf(buf + pos, bufsz - pos,
909 "0x%.4x ", ofs);
910 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
911 buf + pos, bufsz - pos, 0);
912 pos += strlen(buf);
913 if (bufsz - pos > 0)
914 buf[pos++] = '\n';
915 }
916 }
917 }
918
919 pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
920 pos += scnprintf(buf + pos, bufsz - pos,
921 "read: %u, write: %u\n",
922 rxq->read, rxq->write);
923
924 if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) {
925 ptr = priv->rx_traffic;
926 pos += scnprintf(buf + pos, bufsz - pos,
927 "Rx Traffic idx: %u\n", priv->rx_traffic_idx);
928 for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
929 for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
930 entry++, ofs += 16) {
931 pos += scnprintf(buf + pos, bufsz - pos,
932 "0x%.4x ", ofs);
933 hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
934 buf + pos, bufsz - pos, 0);
935 pos += strlen(buf);
936 if (bufsz - pos > 0)
937 buf[pos++] = '\n';
938 }
939 }
940 }
941
942 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
943 kfree(buf);
944 return ret;
945}
946
947static ssize_t iwl_dbgfs_traffic_log_write(struct file *file,
948 const char __user *user_buf,
949 size_t count, loff_t *ppos)
950{
951 struct iwl_priv *priv = file->private_data;
952 char buf[8];
953 int buf_size;
954 int traffic_log;
955
956 memset(buf, 0, sizeof(buf));
957 buf_size = min(count, sizeof(buf) - 1);
958 if (copy_from_user(buf, user_buf, buf_size))
959 return -EFAULT;
960 if (sscanf(buf, "%d", &traffic_log) != 1)
961 return -EFAULT;
962 if (traffic_log == 0)
963 iwl_reset_traffic_log(priv);
964
965 return count;
966}
967
968static ssize_t iwl_dbgfs_tx_queue_read(struct file *file,
969 char __user *user_buf,
970 size_t count, loff_t *ppos) {
971
972 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
973 struct iwl_tx_queue *txq;
974 struct iwl_queue *q;
975 char *buf;
976 int pos = 0;
977 int cnt;
978 int ret;
979 const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES;
980
981 buf = kzalloc(bufsz, GFP_KERNEL);
982 if (!buf)
983 return -ENOMEM;
984
985 for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
986 txq = &priv->txq[cnt];
987 q = &txq->q;
988 pos += scnprintf(buf + pos, bufsz - pos,
989 "hwq %.2d: read=%u write=%u stop=%d"
990 " swq_id=%#.2x (ac %d/hwq %d)\n",
991 cnt, q->read_ptr, q->write_ptr,
992 !!test_bit(cnt, priv->queue_stopped),
993 txq->swq_id,
994 txq->swq_id & 0x80 ? txq->swq_id & 3 :
995 txq->swq_id,
996 txq->swq_id & 0x80 ? (txq->swq_id >> 2) &
997 0x1f : txq->swq_id);
998 if (cnt >= 4)
999 continue;
1000 /* for the ACs, display the stop count too */
1001 pos += scnprintf(buf + pos, bufsz - pos,
1002 " stop-count: %d\n",
1003 atomic_read(&priv->queue_stop_count[cnt]));
1004 }
1005 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1006 kfree(buf);
1007 return ret;
1008}
1009
1010static ssize_t iwl_dbgfs_rx_queue_read(struct file *file,
1011 char __user *user_buf,
1012 size_t count, loff_t *ppos) {
1013
1014 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1015 struct iwl_rx_queue *rxq = &priv->rxq;
1016 char buf[256];
1017 int pos = 0;
1018 const size_t bufsz = sizeof(buf);
1019
1020 pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
1021 rxq->read);
1022 pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
1023 rxq->write);
1024 pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
1025 rxq->free_count);
1026 pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
1027 le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF);
1028 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1029}
1030
1031#define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0)
1032#define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1)
1033#define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2)
1034
1035static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf,
1036 int bufsz)
1037{
1038 int p = 0;
1039
1040 p += scnprintf(buf + p, bufsz - p,
1041 "Statistics Flag(0x%X):\n",
1042 le32_to_cpu(priv->statistics.flag));
1043 if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK)
1044 p += scnprintf(buf + p, bufsz - p,
1045 "\tStatistics have been cleared\n");
1046 p += scnprintf(buf + p, bufsz - p,
1047 "\tOperational Frequency: %s\n",
1048 (le32_to_cpu(priv->statistics.flag) &
1049 UCODE_STATISTICS_FREQUENCY_MSK)
1050 ? "2.4 GHz" : "5.2 GHz");
1051 p += scnprintf(buf + p, bufsz - p,
1052 "\tTGj Narrow Band: %s\n",
1053 (le32_to_cpu(priv->statistics.flag) &
1054 UCODE_STATISTICS_NARROW_BAND_MSK)
1055 ? "enabled" : "disabled");
1056 return p;
1057}
1058
1059
1060static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
1061 char __user *user_buf,
1062 size_t count, loff_t *ppos)
1063{
1064 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1065 int pos = 0;
1066 char *buf;
1067 int bufsz = sizeof(struct statistics_rx_phy) * 20 +
1068 sizeof(struct statistics_rx_non_phy) * 20 +
1069 sizeof(struct statistics_rx_ht_phy) * 20 + 400;
1070 ssize_t ret;
1071 struct statistics_rx_phy *ofdm;
1072 struct statistics_rx_phy *cck;
1073 struct statistics_rx_non_phy *general;
1074 struct statistics_rx_ht_phy *ht;
1075
1076 if (!iwl_is_alive(priv))
1077 return -EAGAIN;
1078
1079 /* make request to uCode to retrieve statistics information */
1080 mutex_lock(&priv->mutex);
1081 ret = iwl_send_statistics_request(priv, 0);
1082 mutex_unlock(&priv->mutex);
1083
1084 if (ret) {
1085 IWL_ERR(priv,
1086 "Error sending statistics request: %zd\n", ret);
1087 return -EAGAIN;
1088 }
1089 buf = kzalloc(bufsz, GFP_KERNEL);
1090 if (!buf) {
1091 IWL_ERR(priv, "Can not allocate Buffer\n");
1092 return -ENOMEM;
1093 }
1094
1095 /* the statistic information display here is based on
1096 * the last statistics notification from uCode
1097 * might not reflect the current uCode activity
1098 */
1099 ofdm = &priv->statistics.rx.ofdm;
1100 cck = &priv->statistics.rx.cck;
1101 general = &priv->statistics.rx.general;
1102 ht = &priv->statistics.rx.ofdm_ht;
1103 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1104 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n");
1105 pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1106 le32_to_cpu(ofdm->ina_cnt));
1107 pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1108 le32_to_cpu(ofdm->fina_cnt));
1109 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1110 le32_to_cpu(ofdm->plcp_err));
1111 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1112 le32_to_cpu(ofdm->crc32_err));
1113 pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1114 le32_to_cpu(ofdm->overrun_err));
1115 pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1116 le32_to_cpu(ofdm->early_overrun_err));
1117 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1118 le32_to_cpu(ofdm->crc32_good));
1119 pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1120 le32_to_cpu(ofdm->false_alarm_cnt));
1121 pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1122 le32_to_cpu(ofdm->fina_sync_err_cnt));
1123 pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1124 le32_to_cpu(ofdm->sfd_timeout));
1125 pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1126 le32_to_cpu(ofdm->fina_timeout));
1127 pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1128 le32_to_cpu(ofdm->unresponded_rts));
1129 pos += scnprintf(buf + pos, bufsz - pos,
1130 "rxe_frame_limit_overrun: %u\n",
1131 le32_to_cpu(ofdm->rxe_frame_limit_overrun));
1132 pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1133 le32_to_cpu(ofdm->sent_ack_cnt));
1134 pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1135 le32_to_cpu(ofdm->sent_cts_cnt));
1136 pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1137 le32_to_cpu(ofdm->sent_ba_rsp_cnt));
1138 pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1139 le32_to_cpu(ofdm->dsp_self_kill));
1140 pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1141 le32_to_cpu(ofdm->mh_format_err));
1142 pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1143 le32_to_cpu(ofdm->re_acq_main_rssi_sum));
1144
1145 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n");
1146 pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n",
1147 le32_to_cpu(cck->ina_cnt));
1148 pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n",
1149 le32_to_cpu(cck->fina_cnt));
1150 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1151 le32_to_cpu(cck->plcp_err));
1152 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1153 le32_to_cpu(cck->crc32_err));
1154 pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1155 le32_to_cpu(cck->overrun_err));
1156 pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1157 le32_to_cpu(cck->early_overrun_err));
1158 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1159 le32_to_cpu(cck->crc32_good));
1160 pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n",
1161 le32_to_cpu(cck->false_alarm_cnt));
1162 pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n",
1163 le32_to_cpu(cck->fina_sync_err_cnt));
1164 pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n",
1165 le32_to_cpu(cck->sfd_timeout));
1166 pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n",
1167 le32_to_cpu(cck->fina_timeout));
1168 pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n",
1169 le32_to_cpu(cck->unresponded_rts));
1170 pos += scnprintf(buf + pos, bufsz - pos,
1171 "rxe_frame_limit_overrun: %u\n",
1172 le32_to_cpu(cck->rxe_frame_limit_overrun));
1173 pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n",
1174 le32_to_cpu(cck->sent_ack_cnt));
1175 pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n",
1176 le32_to_cpu(cck->sent_cts_cnt));
1177 pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n",
1178 le32_to_cpu(cck->sent_ba_rsp_cnt));
1179 pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n",
1180 le32_to_cpu(cck->dsp_self_kill));
1181 pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1182 le32_to_cpu(cck->mh_format_err));
1183 pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n",
1184 le32_to_cpu(cck->re_acq_main_rssi_sum));
1185
1186 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n");
1187 pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n",
1188 le32_to_cpu(general->bogus_cts));
1189 pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n",
1190 le32_to_cpu(general->bogus_ack));
1191 pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n",
1192 le32_to_cpu(general->non_bssid_frames));
1193 pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n",
1194 le32_to_cpu(general->filtered_frames));
1195 pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n",
1196 le32_to_cpu(general->non_channel_beacons));
1197 pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n",
1198 le32_to_cpu(general->channel_beacons));
1199 pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n",
1200 le32_to_cpu(general->num_missed_bcon));
1201 pos += scnprintf(buf + pos, bufsz - pos,
1202 "adc_rx_saturation_time: %u\n",
1203 le32_to_cpu(general->adc_rx_saturation_time));
1204 pos += scnprintf(buf + pos, bufsz - pos,
1205 "ina_detection_search_time: %u\n",
1206 le32_to_cpu(general->ina_detection_search_time));
1207 pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n",
1208 le32_to_cpu(general->beacon_silence_rssi_a));
1209 pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n",
1210 le32_to_cpu(general->beacon_silence_rssi_b));
1211 pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n",
1212 le32_to_cpu(general->beacon_silence_rssi_c));
1213 pos += scnprintf(buf + pos, bufsz - pos,
1214 "interference_data_flag: %u\n",
1215 le32_to_cpu(general->interference_data_flag));
1216 pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n",
1217 le32_to_cpu(general->channel_load));
1218 pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n",
1219 le32_to_cpu(general->dsp_false_alarms));
1220 pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n",
1221 le32_to_cpu(general->beacon_rssi_a));
1222 pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n",
1223 le32_to_cpu(general->beacon_rssi_b));
1224 pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n",
1225 le32_to_cpu(general->beacon_rssi_c));
1226 pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n",
1227 le32_to_cpu(general->beacon_energy_a));
1228 pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n",
1229 le32_to_cpu(general->beacon_energy_b));
1230 pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n",
1231 le32_to_cpu(general->beacon_energy_c));
1232
1233 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n");
1234 pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n",
1235 le32_to_cpu(ht->plcp_err));
1236 pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n",
1237 le32_to_cpu(ht->overrun_err));
1238 pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n",
1239 le32_to_cpu(ht->early_overrun_err));
1240 pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n",
1241 le32_to_cpu(ht->crc32_good));
1242 pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n",
1243 le32_to_cpu(ht->crc32_err));
1244 pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n",
1245 le32_to_cpu(ht->mh_format_err));
1246 pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n",
1247 le32_to_cpu(ht->agg_crc32_good));
1248 pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n",
1249 le32_to_cpu(ht->agg_mpdu_cnt));
1250 pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n",
1251 le32_to_cpu(ht->agg_cnt));
1252
1253 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1254 kfree(buf);
1255 return ret;
1256}
1257
1258static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
1259 char __user *user_buf,
1260 size_t count, loff_t *ppos)
1261{
1262 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1263 int pos = 0;
1264 char *buf;
1265 int bufsz = (sizeof(struct statistics_tx) * 24) + 250;
1266 ssize_t ret;
1267 struct statistics_tx *tx;
1268
1269 if (!iwl_is_alive(priv))
1270 return -EAGAIN;
1271
1272 /* make request to uCode to retrieve statistics information */
1273 mutex_lock(&priv->mutex);
1274 ret = iwl_send_statistics_request(priv, 0);
1275 mutex_unlock(&priv->mutex);
1276
1277 if (ret) {
1278 IWL_ERR(priv,
1279 "Error sending statistics request: %zd\n", ret);
1280 return -EAGAIN;
1281 }
1282 buf = kzalloc(bufsz, GFP_KERNEL);
1283 if (!buf) {
1284 IWL_ERR(priv, "Can not allocate Buffer\n");
1285 return -ENOMEM;
1286 }
1287
1288 /* the statistic information display here is based on
1289 * the last statistics notification from uCode
1290 * might not reflect the current uCode activity
1291 */
1292 tx = &priv->statistics.tx;
1293 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1294 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n");
1295 pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n",
1296 le32_to_cpu(tx->preamble_cnt));
1297 pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n",
1298 le32_to_cpu(tx->rx_detected_cnt));
1299 pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n",
1300 le32_to_cpu(tx->bt_prio_defer_cnt));
1301 pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n",
1302 le32_to_cpu(tx->bt_prio_kill_cnt));
1303 pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n",
1304 le32_to_cpu(tx->few_bytes_cnt));
1305 pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n",
1306 le32_to_cpu(tx->cts_timeout));
1307 pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n",
1308 le32_to_cpu(tx->ack_timeout));
1309 pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n",
1310 le32_to_cpu(tx->expected_ack_cnt));
1311 pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n",
1312 le32_to_cpu(tx->actual_ack_cnt));
1313 pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n",
1314 le32_to_cpu(tx->dump_msdu_cnt));
1315 pos += scnprintf(buf + pos, bufsz - pos,
1316 "burst_abort_next_frame_mismatch_cnt: %u\n",
1317 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt));
1318 pos += scnprintf(buf + pos, bufsz - pos,
1319 "burst_abort_missing_next_frame_cnt: %u\n",
1320 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt));
1321 pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n",
1322 le32_to_cpu(tx->cts_timeout_collision));
1323 pos += scnprintf(buf + pos, bufsz - pos,
1324 "ack_or_ba_timeout_collision: %u\n",
1325 le32_to_cpu(tx->ack_or_ba_timeout_collision));
1326 pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n",
1327 le32_to_cpu(tx->agg.ba_timeout));
1328 pos += scnprintf(buf + pos, bufsz - pos,
1329 "agg ba_reschedule_frames: %u\n",
1330 le32_to_cpu(tx->agg.ba_reschedule_frames));
1331 pos += scnprintf(buf + pos, bufsz - pos,
1332 "agg scd_query_agg_frame_cnt: %u\n",
1333 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt));
1334 pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n",
1335 le32_to_cpu(tx->agg.scd_query_no_agg));
1336 pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n",
1337 le32_to_cpu(tx->agg.scd_query_agg));
1338 pos += scnprintf(buf + pos, bufsz - pos,
1339 "agg scd_query_mismatch: %u\n",
1340 le32_to_cpu(tx->agg.scd_query_mismatch));
1341 pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n",
1342 le32_to_cpu(tx->agg.frame_not_ready));
1343 pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n",
1344 le32_to_cpu(tx->agg.underrun));
1345 pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n",
1346 le32_to_cpu(tx->agg.bt_prio_kill));
1347 pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n",
1348 le32_to_cpu(tx->agg.rx_ba_rsp_cnt));
1349
1350 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1351 kfree(buf);
1352 return ret;
1353}
1354
1355static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
1356 char __user *user_buf,
1357 size_t count, loff_t *ppos)
1358{
1359 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1360 int pos = 0;
1361 char *buf;
1362 int bufsz = sizeof(struct statistics_general) * 4 + 250;
1363 ssize_t ret;
1364 struct statistics_general *general;
1365 struct statistics_dbg *dbg;
1366 struct statistics_div *div;
1367
1368 if (!iwl_is_alive(priv))
1369 return -EAGAIN;
1370
1371 /* make request to uCode to retrieve statistics information */
1372 mutex_lock(&priv->mutex);
1373 ret = iwl_send_statistics_request(priv, 0);
1374 mutex_unlock(&priv->mutex);
1375
1376 if (ret) {
1377 IWL_ERR(priv,
1378 "Error sending statistics request: %zd\n", ret);
1379 return -EAGAIN;
1380 }
1381 buf = kzalloc(bufsz, GFP_KERNEL);
1382 if (!buf) {
1383 IWL_ERR(priv, "Can not allocate Buffer\n");
1384 return -ENOMEM;
1385 }
1386
1387 /* the statistic information display here is based on
1388 * the last statistics notification from uCode
1389 * might not reflect the current uCode activity
1390 */
1391 general = &priv->statistics.general;
1392 dbg = &priv->statistics.general.dbg;
1393 div = &priv->statistics.general.div;
1394 pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
1395 pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n");
1396 pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n",
1397 le32_to_cpu(general->temperature));
1398 pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n",
1399 le32_to_cpu(general->temperature_m));
1400 pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n",
1401 le32_to_cpu(dbg->burst_check));
1402 pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n",
1403 le32_to_cpu(dbg->burst_count));
1404 pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n",
1405 le32_to_cpu(general->sleep_time));
1406 pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n",
1407 le32_to_cpu(general->slots_out));
1408 pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n",
1409 le32_to_cpu(general->slots_idle));
1410 pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n",
1411 le32_to_cpu(general->ttl_timestamp));
1412 pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n",
1413 le32_to_cpu(div->tx_on_a));
1414 pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n",
1415 le32_to_cpu(div->tx_on_b));
1416 pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n",
1417 le32_to_cpu(div->exec_time));
1418 pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n",
1419 le32_to_cpu(div->probe_time));
1420 pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n",
1421 le32_to_cpu(general->rx_enable_counter));
1422 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1423 kfree(buf);
1424 return ret;
1425}
1426
1427static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
1428 char __user *user_buf,
1429 size_t count, loff_t *ppos) {
1430
1431 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1432 int pos = 0;
1433 int cnt = 0;
1434 char *buf;
1435 int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
1436 ssize_t ret;
1437 struct iwl_sensitivity_data *data;
1438
1439 data = &priv->sensitivity_data;
1440 buf = kzalloc(bufsz, GFP_KERNEL);
1441 if (!buf) {
1442 IWL_ERR(priv, "Can not allocate Buffer\n");
1443 return -ENOMEM;
1444 }
1445
1446 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
1447 data->auto_corr_ofdm);
1448 pos += scnprintf(buf + pos, bufsz - pos,
1449 "auto_corr_ofdm_mrc:\t\t %u\n",
1450 data->auto_corr_ofdm_mrc);
1451 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
1452 data->auto_corr_ofdm_x1);
1453 pos += scnprintf(buf + pos, bufsz - pos,
1454 "auto_corr_ofdm_mrc_x1:\t\t %u\n",
1455 data->auto_corr_ofdm_mrc_x1);
1456 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
1457 data->auto_corr_cck);
1458 pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
1459 data->auto_corr_cck_mrc);
1460 pos += scnprintf(buf + pos, bufsz - pos,
1461 "last_bad_plcp_cnt_ofdm:\t\t %u\n",
1462 data->last_bad_plcp_cnt_ofdm);
1463 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
1464 data->last_fa_cnt_ofdm);
1465 pos += scnprintf(buf + pos, bufsz - pos,
1466 "last_bad_plcp_cnt_cck:\t\t %u\n",
1467 data->last_bad_plcp_cnt_cck);
1468 pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
1469 data->last_fa_cnt_cck);
1470 pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
1471 data->nrg_curr_state);
1472 pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
1473 data->nrg_prev_state);
1474 pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
1475 for (cnt = 0; cnt < 10; cnt++) {
1476 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1477 data->nrg_value[cnt]);
1478 }
1479 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1480 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
1481 for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
1482 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1483 data->nrg_silence_rssi[cnt]);
1484 }
1485 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1486 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
1487 data->nrg_silence_ref);
1488 pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
1489 data->nrg_energy_idx);
1490 pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
1491 data->nrg_silence_idx);
1492 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
1493 data->nrg_th_cck);
1494 pos += scnprintf(buf + pos, bufsz - pos,
1495 "nrg_auto_corr_silence_diff:\t %u\n",
1496 data->nrg_auto_corr_silence_diff);
1497 pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
1498 data->num_in_cck_no_fa);
1499 pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
1500 data->nrg_th_ofdm);
1501
1502 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1503 kfree(buf);
1504 return ret;
1505}
1506
1507
1508static ssize_t iwl_dbgfs_chain_noise_read(struct file *file,
1509 char __user *user_buf,
1510 size_t count, loff_t *ppos) {
1511
1512 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
1513 int pos = 0;
1514 int cnt = 0;
1515 char *buf;
1516 int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
1517 ssize_t ret;
1518 struct iwl_chain_noise_data *data;
1519
1520 data = &priv->chain_noise_data;
1521 buf = kzalloc(bufsz, GFP_KERNEL);
1522 if (!buf) {
1523 IWL_ERR(priv, "Can not allocate Buffer\n");
1524 return -ENOMEM;
1525 }
1526
1527 pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
1528 data->active_chains);
1529 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
1530 data->chain_noise_a);
1531 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
1532 data->chain_noise_b);
1533 pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
1534 data->chain_noise_c);
1535 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
1536 data->chain_signal_a);
1537 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
1538 data->chain_signal_b);
1539 pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
1540 data->chain_signal_c);
1541 pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
1542 data->beacon_count);
1543
1544 pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
1545 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1546 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1547 data->disconn_array[cnt]);
1548 }
1549 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1550 pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
1551 for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
1552 pos += scnprintf(buf + pos, bufsz - pos, " %u",
1553 data->delta_gain_code[cnt]);
1554 }
1555 pos += scnprintf(buf + pos, bufsz - pos, "\n");
1556 pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
1557 data->radio_write);
1558 pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
1559 data->state);
1560
1561 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
1562 kfree(buf);
1563 return ret;
1564}
1565
1566DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics);
1567DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics);
1568DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
1569DEBUGFS_READ_FILE_OPS(rx_queue);
1570DEBUGFS_READ_FILE_OPS(tx_queue);
1571DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
1572DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
1573DEBUGFS_READ_FILE_OPS(ucode_general_stats);
1574DEBUGFS_READ_FILE_OPS(sensitivity);
1575DEBUGFS_READ_FILE_OPS(chain_noise);
714 1576
715/* 1577/*
716 * Create the debugfs files and directories 1578 * Create the debugfs files and directories
@@ -738,12 +1600,11 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
738 1600
739 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); 1601 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
740 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); 1602 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
1603 DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv);
741 DEBUGFS_ADD_FILE(nvm, data); 1604 DEBUGFS_ADD_FILE(nvm, data);
742 DEBUGFS_ADD_FILE(sram, data); 1605 DEBUGFS_ADD_FILE(sram, data);
743 DEBUGFS_ADD_FILE(log_event, data); 1606 DEBUGFS_ADD_FILE(log_event, data);
744 DEBUGFS_ADD_FILE(stations, data); 1607 DEBUGFS_ADD_FILE(stations, data);
745 DEBUGFS_ADD_FILE(rx_statistics, data);
746 DEBUGFS_ADD_FILE(tx_statistics, data);
747 DEBUGFS_ADD_FILE(channels, data); 1608 DEBUGFS_ADD_FILE(channels, data);
748 DEBUGFS_ADD_FILE(status, data); 1609 DEBUGFS_ADD_FILE(status, data);
749 DEBUGFS_ADD_FILE(interrupt, data); 1610 DEBUGFS_ADD_FILE(interrupt, data);
@@ -751,8 +1612,22 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
751#ifdef CONFIG_IWLWIFI_LEDS 1612#ifdef CONFIG_IWLWIFI_LEDS
752 DEBUGFS_ADD_FILE(led, data); 1613 DEBUGFS_ADD_FILE(led, data);
753#endif 1614#endif
1615 DEBUGFS_ADD_FILE(sleep_level_override, data);
1616 DEBUGFS_ADD_FILE(current_sleep_command, data);
754 DEBUGFS_ADD_FILE(thermal_throttling, data); 1617 DEBUGFS_ADD_FILE(thermal_throttling, data);
755 DEBUGFS_ADD_FILE(disable_ht40, data); 1618 DEBUGFS_ADD_FILE(disable_ht40, data);
1619 DEBUGFS_ADD_FILE(rx_statistics, debug);
1620 DEBUGFS_ADD_FILE(tx_statistics, debug);
1621 DEBUGFS_ADD_FILE(traffic_log, debug);
1622 DEBUGFS_ADD_FILE(rx_queue, debug);
1623 DEBUGFS_ADD_FILE(tx_queue, debug);
1624 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1625 DEBUGFS_ADD_FILE(ucode_rx_stats, debug);
1626 DEBUGFS_ADD_FILE(ucode_tx_stats, debug);
1627 DEBUGFS_ADD_FILE(ucode_general_stats, debug);
1628 DEBUGFS_ADD_FILE(sensitivity, debug);
1629 DEBUGFS_ADD_FILE(chain_noise, debug);
1630 }
756 DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); 1631 DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
757 DEBUGFS_ADD_BOOL(disable_chain_noise, rf, 1632 DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
758 &priv->disable_chain_noise_cal); 1633 &priv->disable_chain_noise_cal);
@@ -778,9 +1653,9 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
778 if (!priv->dbgfs) 1653 if (!priv->dbgfs)
779 return; 1654 return;
780 1655
1656 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
1657 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
781 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); 1658 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
782 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
783 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
784 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); 1659 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
785 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); 1660 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
786 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); 1661 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
@@ -794,6 +1669,24 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
794 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); 1669 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling);
795 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); 1670 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40);
796 DEBUGFS_REMOVE(priv->dbgfs->dir_data); 1671 DEBUGFS_REMOVE(priv->dbgfs->dir_data);
1672 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics);
1673 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics);
1674 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log);
1675 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue);
1676 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue);
1677 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) {
1678 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1679 file_ucode_rx_stats);
1680 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1681 file_ucode_tx_stats);
1682 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1683 file_ucode_general_stats);
1684 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1685 file_sensitivity);
1686 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.
1687 file_chain_noise);
1688 }
1689 DEBUGFS_REMOVE(priv->dbgfs->dir_debug);
797 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); 1690 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
798 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); 1691 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
799 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || 1692 if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index cab6255210d5..b96c3c9e92a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -277,8 +277,8 @@ struct iwl_channel_info {
277 struct iwl4965_channel_tgd_info tgd; 277 struct iwl4965_channel_tgd_info tgd;
278 struct iwl4965_channel_tgh_info tgh; 278 struct iwl4965_channel_tgh_info tgh;
279 struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ 279 struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */
280 struct iwl_eeprom_channel fat_eeprom; /* EEPROM regulatory limit for 280 struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for
281 * FAT channel */ 281 * HT40 channel */
282 282
283 u8 channel; /* channel number */ 283 u8 channel; /* channel number */
284 u8 flags; /* flags copied from EEPROM */ 284 u8 flags; /* flags copied from EEPROM */
@@ -291,13 +291,13 @@ struct iwl_channel_info {
291 u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ 291 u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */
292 enum ieee80211_band band; 292 enum ieee80211_band band;
293 293
294 /* FAT channel info */ 294 /* HT40 channel info */
295 s8 fat_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ 295 s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
296 s8 fat_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ 296 s8 ht40_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */
297 s8 fat_min_power; /* always 0 */ 297 s8 ht40_min_power; /* always 0 */
298 s8 fat_scan_power; /* (dBm) eeprom, direct scans, any rate */ 298 s8 ht40_scan_power; /* (dBm) eeprom, direct scans, any rate */
299 u8 fat_flags; /* flags copied from EEPROM */ 299 u8 ht40_flags; /* flags copied from EEPROM */
300 u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */ 300 u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
301 301
302 /* Radio/DSP gain settings for each "normal" data Tx rate. 302 /* Radio/DSP gain settings for each "normal" data Tx rate.
303 * These include, in addition to RF and DSP gain, a few fields for 303 * These include, in addition to RF and DSP gain, a few fields for
@@ -649,7 +649,7 @@ struct iwl_sensitivity_ranges {
649 * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR 649 * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
650 * @max_stations: 650 * @max_stations:
651 * @bcast_sta_id: 651 * @bcast_sta_id:
652 * @fat_channel: is 40MHz width possible in band 2.4 652 * @ht40_channel: is 40MHz width possible in band 2.4
653 * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) 653 * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
654 * @sw_crypto: 0 for hw, 1 for sw 654 * @sw_crypto: 0 for hw, 1 for sw
655 * @max_xxx_size: for ucode uses 655 * @max_xxx_size: for ucode uses
@@ -673,7 +673,7 @@ struct iwl_hw_params {
673 u32 max_pkt_size; 673 u32 max_pkt_size;
674 u8 max_stations; 674 u8 max_stations;
675 u8 bcast_sta_id; 675 u8 bcast_sta_id;
676 u8 fat_channel; 676 u8 ht40_channel;
677 u8 max_beacon_itrvl; /* in 1024 ms */ 677 u8 max_beacon_itrvl; /* in 1024 ms */
678 u32 max_inst_size; 678 u32 max_inst_size;
679 u32 max_data_size; 679 u32 max_data_size;
@@ -823,8 +823,6 @@ struct iwl_calib_result {
823 size_t buf_len; 823 size_t buf_len;
824}; 824};
825 825
826#define UCODE_ALIVE_TIMEOUT (5 * HZ)
827
828enum ucode_type { 826enum ucode_type {
829 UCODE_NONE = 0, 827 UCODE_NONE = 0,
830 UCODE_INIT, 828 UCODE_INIT,
@@ -877,6 +875,8 @@ struct iwl_chain_noise_data {
877#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ 875#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */
878#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ 876#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
879 877
878#define IWL_TRAFFIC_ENTRIES (256)
879#define IWL_TRAFFIC_ENTRY_SIZE (64)
880 880
881enum { 881enum {
882 MEASUREMENT_READY = (1 << 0), 882 MEASUREMENT_READY = (1 << 0),
@@ -917,6 +917,48 @@ struct isr_statistics {
917 u32 unhandled; 917 u32 unhandled;
918}; 918};
919 919
920#ifdef CONFIG_IWLWIFI_DEBUGFS
921/* management statistics */
922enum iwl_mgmt_stats {
923 MANAGEMENT_ASSOC_REQ = 0,
924 MANAGEMENT_ASSOC_RESP,
925 MANAGEMENT_REASSOC_REQ,
926 MANAGEMENT_REASSOC_RESP,
927 MANAGEMENT_PROBE_REQ,
928 MANAGEMENT_PROBE_RESP,
929 MANAGEMENT_BEACON,
930 MANAGEMENT_ATIM,
931 MANAGEMENT_DISASSOC,
932 MANAGEMENT_AUTH,
933 MANAGEMENT_DEAUTH,
934 MANAGEMENT_ACTION,
935 MANAGEMENT_MAX,
936};
937/* control statistics */
938enum iwl_ctrl_stats {
939 CONTROL_BACK_REQ = 0,
940 CONTROL_BACK,
941 CONTROL_PSPOLL,
942 CONTROL_RTS,
943 CONTROL_CTS,
944 CONTROL_ACK,
945 CONTROL_CFEND,
946 CONTROL_CFENDACK,
947 CONTROL_MAX,
948};
949
950struct traffic_stats {
951 u32 mgmt[MANAGEMENT_MAX];
952 u32 ctrl[CONTROL_MAX];
953 u32 data_cnt;
954 u64 data_bytes;
955};
956#else
957struct traffic_stats {
958 u64 data_bytes;
959};
960#endif
961
920#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ 962#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
921 963
922struct iwl_priv { 964struct iwl_priv {
@@ -1062,15 +1104,14 @@ struct iwl_priv {
1062 int last_rx_noise; /* From beacon statistics */ 1104 int last_rx_noise; /* From beacon statistics */
1063 1105
1064 /* counts mgmt, ctl, and data packets */ 1106 /* counts mgmt, ctl, and data packets */
1065 struct traffic_stats { 1107 struct traffic_stats tx_stats;
1066 u32 cnt; 1108 struct traffic_stats rx_stats;
1067 u64 bytes;
1068 } tx_stats[3], rx_stats[3];
1069 1109
1070 /* counts interrupts */ 1110 /* counts interrupts */
1071 struct isr_statistics isr_stats; 1111 struct isr_statistics isr_stats;
1072 1112
1073 struct iwl_power_mgr power_data; 1113 struct iwl_power_mgr power_data;
1114 struct iwl_tt_mgmt thermal_throttle;
1074 1115
1075 struct iwl_notif_statistics statistics; 1116 struct iwl_notif_statistics statistics;
1076 unsigned long last_statistics_time; 1117 unsigned long last_statistics_time;
@@ -1078,7 +1119,6 @@ struct iwl_priv {
1078 /* context information */ 1119 /* context information */
1079 u16 rates_mask; 1120 u16 rates_mask;
1080 1121
1081 u32 power_mode;
1082 u8 bssid[ETH_ALEN]; 1122 u8 bssid[ETH_ALEN];
1083 u16 rts_threshold; 1123 u16 rts_threshold;
1084 u8 mac_addr[ETH_ALEN]; 1124 u8 mac_addr[ETH_ALEN];
@@ -1157,6 +1197,9 @@ struct iwl_priv {
1157 struct work_struct report_work; 1197 struct work_struct report_work;
1158 struct work_struct request_scan; 1198 struct work_struct request_scan;
1159 struct work_struct beacon_update; 1199 struct work_struct beacon_update;
1200 struct work_struct tt_work;
1201 struct work_struct ct_enter;
1202 struct work_struct ct_exit;
1160 1203
1161 struct tasklet_struct irq_tasklet; 1204 struct tasklet_struct irq_tasklet;
1162 1205
@@ -1175,11 +1218,17 @@ struct iwl_priv {
1175 1218
1176#ifdef CONFIG_IWLWIFI_DEBUG 1219#ifdef CONFIG_IWLWIFI_DEBUG
1177 /* debugging info */ 1220 /* debugging info */
1221 u32 debug_level; /* per device debugging will override global
1222 iwl_debug_level if set */
1178 u32 framecnt_to_us; 1223 u32 framecnt_to_us;
1179 atomic_t restrict_refcnt; 1224 atomic_t restrict_refcnt;
1180 bool disable_ht40; 1225 bool disable_ht40;
1181#ifdef CONFIG_IWLWIFI_DEBUGFS 1226#ifdef CONFIG_IWLWIFI_DEBUGFS
1182 /* debugfs */ 1227 /* debugfs */
1228 u16 tx_traffic_idx;
1229 u16 rx_traffic_idx;
1230 u8 *tx_traffic;
1231 u8 *rx_traffic;
1183 struct iwl_debugfs *dbgfs; 1232 struct iwl_debugfs *dbgfs;
1184#endif /* CONFIG_IWLWIFI_DEBUGFS */ 1233#endif /* CONFIG_IWLWIFI_DEBUGFS */
1185#endif /* CONFIG_IWLWIFI_DEBUG */ 1234#endif /* CONFIG_IWLWIFI_DEBUG */
@@ -1211,8 +1260,27 @@ static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
1211 1260
1212#ifdef CONFIG_IWLWIFI_DEBUG 1261#ifdef CONFIG_IWLWIFI_DEBUG
1213const char *iwl_get_tx_fail_reason(u32 status); 1262const char *iwl_get_tx_fail_reason(u32 status);
1263/*
1264 * iwl_get_debug_level: Return active debug level for device
1265 *
1266 * Using sysfs it is possible to set per device debug level. This debug
1267 * level will be used if set, otherwise the global debug level which can be
1268 * set via module parameter is used.
1269 */
1270static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
1271{
1272 if (priv->debug_level)
1273 return priv->debug_level;
1274 else
1275 return iwl_debug_level;
1276}
1214#else 1277#else
1215static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } 1278static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; }
1279
1280static inline u32 iwl_get_debug_level(struct iwl_priv *priv)
1281{
1282 return iwl_debug_level;
1283}
1216#endif 1284#endif
1217 1285
1218 1286
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 51eed7226669..78c4a324a3b5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -127,11 +127,11 @@ static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */
127 145, 149, 153, 157, 161, 165 127 145, 149, 153, 157, 161, 165
128}; 128};
129 129
130static const u8 iwl_eeprom_band_6[] = { /* 2.4 FAT channel */ 130static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */
131 1, 2, 3, 4, 5, 6, 7 131 1, 2, 3, 4, 5, 6, 7
132}; 132};
133 133
134static const u8 iwl_eeprom_band_7[] = { /* 5.2 FAT channel */ 134static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */
135 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 135 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
136}; 136};
137 137
@@ -462,13 +462,13 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
462 iwl_eeprom_query_addr(priv, offset); 462 iwl_eeprom_query_addr(priv, offset);
463 *eeprom_ch_index = iwl_eeprom_band_5; 463 *eeprom_ch_index = iwl_eeprom_band_5;
464 break; 464 break;
465 case 6: /* 2.4GHz FAT channels */ 465 case 6: /* 2.4GHz ht40 channels */
466 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); 466 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6);
467 *eeprom_ch_info = (struct iwl_eeprom_channel *) 467 *eeprom_ch_info = (struct iwl_eeprom_channel *)
468 iwl_eeprom_query_addr(priv, offset); 468 iwl_eeprom_query_addr(priv, offset);
469 *eeprom_ch_index = iwl_eeprom_band_6; 469 *eeprom_ch_index = iwl_eeprom_band_6;
470 break; 470 break;
471 case 7: /* 5 GHz FAT channels */ 471 case 7: /* 5 GHz ht40 channels */
472 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); 472 *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7);
473 *eeprom_ch_info = (struct iwl_eeprom_channel *) 473 *eeprom_ch_info = (struct iwl_eeprom_channel *)
474 iwl_eeprom_query_addr(priv, offset); 474 iwl_eeprom_query_addr(priv, offset);
@@ -484,14 +484,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv,
484 ? # x " " : "") 484 ? # x " " : "")
485 485
486/** 486/**
487 * iwl_set_fat_chan_info - Copy fat channel info into driver's priv. 487 * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv.
488 * 488 *
489 * Does not set up a command, or touch hardware. 489 * Does not set up a command, or touch hardware.
490 */ 490 */
491static int iwl_set_fat_chan_info(struct iwl_priv *priv, 491static int iwl_set_ht40_chan_info(struct iwl_priv *priv,
492 enum ieee80211_band band, u16 channel, 492 enum ieee80211_band band, u16 channel,
493 const struct iwl_eeprom_channel *eeprom_ch, 493 const struct iwl_eeprom_channel *eeprom_ch,
494 u8 fat_extension_channel) 494 u8 ht40_extension_channel)
495{ 495{
496 struct iwl_channel_info *ch_info; 496 struct iwl_channel_info *ch_info;
497 497
@@ -501,7 +501,7 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
501 if (!is_channel_valid(ch_info)) 501 if (!is_channel_valid(ch_info))
502 return -1; 502 return -1;
503 503
504 IWL_DEBUG_INFO(priv, "FAT Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" 504 IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
505 " Ad-Hoc %ssupported\n", 505 " Ad-Hoc %ssupported\n",
506 ch_info->channel, 506 ch_info->channel,
507 is_channel_a_band(ch_info) ? 507 is_channel_a_band(ch_info) ?
@@ -517,13 +517,13 @@ static int iwl_set_fat_chan_info(struct iwl_priv *priv,
517 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? 517 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
518 "" : "not "); 518 "" : "not ");
519 519
520 ch_info->fat_eeprom = *eeprom_ch; 520 ch_info->ht40_eeprom = *eeprom_ch;
521 ch_info->fat_max_power_avg = eeprom_ch->max_power_avg; 521 ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
522 ch_info->fat_curr_txpow = eeprom_ch->max_power_avg; 522 ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg;
523 ch_info->fat_min_power = 0; 523 ch_info->ht40_min_power = 0;
524 ch_info->fat_scan_power = eeprom_ch->max_power_avg; 524 ch_info->ht40_scan_power = eeprom_ch->max_power_avg;
525 ch_info->fat_flags = eeprom_ch->flags; 525 ch_info->ht40_flags = eeprom_ch->flags;
526 ch_info->fat_extension_channel = fat_extension_channel; 526 ch_info->ht40_extension_channel = ht40_extension_channel;
527 527
528 return 0; 528 return 0;
529} 529}
@@ -589,9 +589,9 @@ int iwl_init_channel_map(struct iwl_priv *priv)
589 /* Copy the run-time flags so they are there even on 589 /* Copy the run-time flags so they are there even on
590 * invalid channels */ 590 * invalid channels */
591 ch_info->flags = eeprom_ch_info[ch].flags; 591 ch_info->flags = eeprom_ch_info[ch].flags;
592 /* First write that fat is not enabled, and then enable 592 /* First write that ht40 is not enabled, and then enable
593 * one by one */ 593 * one by one */
594 ch_info->fat_extension_channel = 594 ch_info->ht40_extension_channel =
595 (IEEE80211_CHAN_NO_HT40PLUS | 595 (IEEE80211_CHAN_NO_HT40PLUS |
596 IEEE80211_CHAN_NO_HT40MINUS); 596 IEEE80211_CHAN_NO_HT40MINUS);
597 597
@@ -642,17 +642,17 @@ int iwl_init_channel_map(struct iwl_priv *priv)
642 } 642 }
643 } 643 }
644 644
645 /* Check if we do have FAT channels */ 645 /* Check if we do have HT40 channels */
646 if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] == 646 if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
647 EEPROM_REGULATORY_BAND_NO_FAT && 647 EEPROM_REGULATORY_BAND_NO_HT40 &&
648 priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] == 648 priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
649 EEPROM_REGULATORY_BAND_NO_FAT) 649 EEPROM_REGULATORY_BAND_NO_HT40)
650 return 0; 650 return 0;
651 651
652 /* Two additional EEPROM bands for 2.4 and 5 GHz FAT channels */ 652 /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
653 for (band = 6; band <= 7; band++) { 653 for (band = 6; band <= 7; band++) {
654 enum ieee80211_band ieeeband; 654 enum ieee80211_band ieeeband;
655 u8 fat_extension_chan; 655 u8 ht40_extension_chan;
656 656
657 iwl_init_band_reference(priv, band, &eeprom_ch_count, 657 iwl_init_band_reference(priv, band, &eeprom_ch_count,
658 &eeprom_ch_info, &eeprom_ch_index); 658 &eeprom_ch_info, &eeprom_ch_index);
@@ -669,19 +669,19 @@ int iwl_init_channel_map(struct iwl_priv *priv)
669 (eeprom_ch_index[ch] == 6) || 669 (eeprom_ch_index[ch] == 6) ||
670 (eeprom_ch_index[ch] == 7))) 670 (eeprom_ch_index[ch] == 7)))
671 /* both are allowed: above and below */ 671 /* both are allowed: above and below */
672 fat_extension_chan = 0; 672 ht40_extension_chan = 0;
673 else 673 else
674 fat_extension_chan = 674 ht40_extension_chan =
675 IEEE80211_CHAN_NO_HT40MINUS; 675 IEEE80211_CHAN_NO_HT40MINUS;
676 676
677 /* Set up driver's info for lower half */ 677 /* Set up driver's info for lower half */
678 iwl_set_fat_chan_info(priv, ieeeband, 678 iwl_set_ht40_chan_info(priv, ieeeband,
679 eeprom_ch_index[ch], 679 eeprom_ch_index[ch],
680 &(eeprom_ch_info[ch]), 680 &(eeprom_ch_info[ch]),
681 fat_extension_chan); 681 ht40_extension_chan);
682 682
683 /* Set up driver's info for upper half */ 683 /* Set up driver's info for upper half */
684 iwl_set_fat_chan_info(priv, ieeeband, 684 iwl_set_ht40_chan_info(priv, ieeeband,
685 (eeprom_ch_index[ch] + 4), 685 (eeprom_ch_index[ch] + 4),
686 &(eeprom_ch_info[ch]), 686 &(eeprom_ch_info[ch]),
687 IEEE80211_CHAN_NO_HT40PLUS); 687 IEEE80211_CHAN_NO_HT40PLUS);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 195b4ef12c27..05d4fc4451dc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -88,10 +88,10 @@ struct iwl_priv;
88 * requirement for establishing a new network for legal operation on channels 88 * requirement for establishing a new network for legal operation on channels
89 * requiring RADAR detection or restricting ACTIVE scanning. 89 * requiring RADAR detection or restricting ACTIVE scanning.
90 * 90 *
91 * NOTE: "WIDE" flag does not indicate anything about "FAT" 40 MHz channels. 91 * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
92 * It only indicates that 20 MHz channel use is supported; FAT channel 92 * It only indicates that 20 MHz channel use is supported; HT40 channel
93 * usage is indicated by a separate set of regulatory flags for each 93 * usage is indicated by a separate set of regulatory flags for each
94 * FAT channel pair. 94 * HT40 channel pair.
95 * 95 *
96 * NOTE: Using a channel inappropriately will result in a uCode error! 96 * NOTE: Using a channel inappropriately will result in a uCode error!
97 */ 97 */
@@ -112,7 +112,7 @@ enum {
112#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) 112#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1)
113 113
114/* *regulatory* channel data format in eeprom, one for each channel. 114/* *regulatory* channel data format in eeprom, one for each channel.
115 * There are separate entries for FAT (40 MHz) vs. normal (20 MHz) channels. */ 115 * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
116struct iwl_eeprom_channel { 116struct iwl_eeprom_channel {
117 u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ 117 u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */
118 s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ 118 s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */
@@ -170,9 +170,9 @@ struct iwl_eeprom_channel {
170 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ 170 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
171#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ 171#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\
172 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ 172 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */
173#define EEPROM_5000_REG_BAND_24_FAT_CHANNELS ((0x82)\ 173#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\
174 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ 174 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */
175#define EEPROM_5000_REG_BAND_52_FAT_CHANNELS ((0x92)\ 175#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\
176 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ 176 | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
177 177
178/* 5050 Specific */ 178/* 5050 Specific */
@@ -313,7 +313,7 @@ struct iwl_eeprom_calib_info {
313 * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory 313 * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
314 * txpower (MSB). 314 * txpower (MSB).
315 * 315 *
316 * Entries immediately below are for 20 MHz channel width. FAT (40 MHz) 316 * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz)
317 * channels (only for 4965, not supported by 3945) appear later in the EEPROM. 317 * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
318 * 318 *
319 * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 319 * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
@@ -352,29 +352,29 @@ struct iwl_eeprom_calib_info {
352#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ 352#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */
353 353
354/* 354/*
355 * 2.4 GHz FAT channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) 355 * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
356 * 356 *
357 * The channel listed is the center of the lower 20 MHz half of the channel. 357 * The channel listed is the center of the lower 20 MHz half of the channel.
358 * The overall center frequency is actually 2 channels (10 MHz) above that, 358 * The overall center frequency is actually 2 channels (10 MHz) above that,
359 * and the upper half of each FAT channel is centered 4 channels (20 MHz) away 359 * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
360 * from the lower half; e.g. the upper half of FAT channel 1 is channel 5, 360 * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
361 * and the overall FAT channel width centers on channel 3. 361 * and the overall HT40 channel width centers on channel 3.
362 * 362 *
363 * NOTE: The RXON command uses 20 MHz channel numbers to specify the 363 * NOTE: The RXON command uses 20 MHz channel numbers to specify the
364 * control channel to which to tune. RXON also specifies whether the 364 * control channel to which to tune. RXON also specifies whether the
365 * control channel is the upper or lower half of a FAT channel. 365 * control channel is the upper or lower half of a HT40 channel.
366 * 366 *
367 * NOTE: 4965 does not support FAT channels on 2.4 GHz. 367 * NOTE: 4965 does not support HT40 channels on 2.4 GHz.
368 */ 368 */
369#define EEPROM_4965_REGULATORY_BAND_24_FAT_CHANNELS (2*0xA0) /* 14 bytes */ 369#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */
370 370
371/* 371/*
372 * 5.2 GHz FAT channels 36 (40), 44 (48), 52 (56), 60 (64), 372 * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
373 * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) 373 * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
374 */ 374 */
375#define EEPROM_4965_REGULATORY_BAND_52_FAT_CHANNELS (2*0xA8) /* 22 bytes */ 375#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */
376 376
377#define EEPROM_REGULATORY_BAND_NO_FAT (0) 377#define EEPROM_REGULATORY_BAND_NO_HT40 (0)
378 378
379struct iwl_eeprom_ops { 379struct iwl_eeprom_ops {
380 const u32 regulatory_bands[7]; 380 const u32 regulatory_bands[7];
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index b82ad15d5189..532c8d6cd8da 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -36,8 +36,6 @@
36#include "iwl-core.h" 36#include "iwl-core.h"
37 37
38 38
39#define IWL_CMD(x) case x: return #x
40
41const char *get_cmd_string(u8 cmd) 39const char *get_cmd_string(u8 cmd)
42{ 40{
43 switch (cmd) { 41 switch (cmd) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 3d61cb43151c..f420c99e7240 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -272,7 +272,8 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
272 /* count both tx and rx traffic to be able to 272 /* count both tx and rx traffic to be able to
273 * handle traffic in either direction 273 * handle traffic in either direction
274 */ 274 */
275 u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes; 275 u64 current_tpt = priv->tx_stats.data_bytes +
276 priv->rx_stats.data_bytes;
276 s64 tpt = current_tpt - priv->led_tpt; 277 s64 tpt = current_tpt - priv->led_tpt;
277 278
278 if (tpt < 0) /* wraparound */ 279 if (tpt < 0) /* wraparound */
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 00937b3ee8ec..0b16841f45f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -42,20 +42,35 @@
42#include "iwl-power.h" 42#include "iwl-power.h"
43 43
44/* 44/*
45 * Setting power level allow the card to go to sleep when not busy. 45 * Setting power level allows the card to go to sleep when not busy.
46 * 46 *
47 * The power level is set to INDEX_1 (the least deep state) by 47 * We calculate a sleep command based on the required latency, which
48 * default, and will, in the future, be the deepest state unless 48 * we get from mac80211. In order to handle thermal throttling, we can
49 * otherwise required by pm_qos network latency requirements. 49 * also use pre-defined power levels.
50 *
51 * Using INDEX_1 without pm_qos is ok because mac80211 will disable
52 * PS when even checking every beacon for the TIM bit would exceed
53 * the required latency.
54 */ 50 */
55 51
56#define IWL_POWER_RANGE_0_MAX (2) 52/*
57#define IWL_POWER_RANGE_1_MAX (10) 53 * For now, keep using power level 1 instead of automatically
54 * adjusting ...
55 */
56bool no_sleep_autoadjust = true;
57module_param(no_sleep_autoadjust, bool, S_IRUGO);
58MODULE_PARM_DESC(no_sleep_autoadjust,
59 "don't automatically adjust sleep level "
60 "according to maximum network latency");
58 61
62/*
63 * This defines the old power levels. They are still used by default
64 * (level 1) and for thermal throttle (levels 3 through 5)
65 */
66
67struct iwl_power_vec_entry {
68 struct iwl_powertable_cmd cmd;
69 u8 no_dtim;
70};
71
72#define IWL_DTIM_RANGE_0_MAX 2
73#define IWL_DTIM_RANGE_1_MAX 10
59 74
60#define NOSLP cpu_to_le16(0), 0, 0 75#define NOSLP cpu_to_le16(0), 0, 0
61#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 76#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
@@ -67,9 +82,8 @@
67 cpu_to_le32(X3), \ 82 cpu_to_le32(X3), \
68 cpu_to_le32(X4)} 83 cpu_to_le32(X4)}
69/* default power management (not Tx power) table values */ 84/* default power management (not Tx power) table values */
70/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */ 85/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
71static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { 86static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
72 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
73 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 87 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
74 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 88 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
75 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 89 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
@@ -78,9 +92,8 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
78}; 92};
79 93
80 94
81/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */ 95/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
82static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { 96static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
83 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
84 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 97 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
85 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 98 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
86 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 99 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
@@ -88,9 +101,8 @@ static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
88 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 101 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
89}; 102};
90 103
91/* for DTIM period > IWL_POWER_RANGE_1_MAX */ 104/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
92static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { 105static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
93 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
94 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 106 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
95 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 107 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
96 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 108 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
@@ -98,6 +110,56 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
98 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 110 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
99}; 111};
100 112
113static void iwl_static_sleep_cmd(struct iwl_priv *priv,
114 struct iwl_powertable_cmd *cmd,
115 enum iwl_power_level lvl, int period)
116{
117 const struct iwl_power_vec_entry *table;
118 int max_sleep, i;
119 bool skip;
120
121 table = range_2;
122 if (period < IWL_DTIM_RANGE_1_MAX)
123 table = range_1;
124 if (period < IWL_DTIM_RANGE_0_MAX)
125 table = range_0;
126
127 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
128
129 *cmd = table[lvl].cmd;
130
131 if (period == 0) {
132 skip = false;
133 period = 1;
134 } else {
135 skip = !!table[lvl].no_dtim;
136 }
137
138 if (skip) {
139 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
140 max_sleep = le32_to_cpu(slp_itrvl);
141 if (max_sleep == 0xFF)
142 max_sleep = period * (skip + 1);
143 else if (max_sleep > period)
144 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
145 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
146 } else {
147 max_sleep = period;
148 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
149 }
150
151 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
152 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
153 cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
154
155 if (priv->power_data.pci_pm)
156 cmd->flags |= IWL_POWER_PCI_PM_MSK;
157 else
158 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
159
160 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
161}
162
101/* default Thermal Throttling transaction table 163/* default Thermal Throttling transaction table
102 * Current state | Throttling Down | Throttling Up 164 * Current state | Throttling Down | Throttling Up
103 *============================================================================= 165 *=============================================================================
@@ -132,104 +194,50 @@ static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = {
132 194
133/* Advance Thermal Throttling default restriction table */ 195/* Advance Thermal Throttling default restriction table */
134static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { 196static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
135 {IWL_TX_MULTI, true, IWL_RX_MULTI}, 197 {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true },
136 {IWL_TX_SINGLE, true, IWL_RX_MULTI}, 198 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true },
137 {IWL_TX_SINGLE, false, IWL_RX_SINGLE}, 199 {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false },
138 {IWL_TX_NONE, false, IWL_RX_NONE} 200 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
139}; 201};
140 202
141/* set card power command */
142static int iwl_set_power(struct iwl_priv *priv, void *cmd)
143{
144 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
145 sizeof(struct iwl_powertable_cmd), cmd);
146}
147 203
148/* initialize to default */ 204static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
149static void iwl_power_init_handle(struct iwl_priv *priv) 205 struct iwl_powertable_cmd *cmd)
150{ 206{
151 struct iwl_power_mgr *pow_data; 207 memset(cmd, 0, sizeof(*cmd));
152 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
153 struct iwl_powertable_cmd *cmd;
154 int i;
155 u16 lctl;
156
157 IWL_DEBUG_POWER(priv, "Initialize power \n");
158
159 pow_data = &priv->power_data;
160
161 memset(pow_data, 0, sizeof(*pow_data));
162 208
163 memcpy(&pow_data->pwr_range_0[0], &range_0[0], size); 209 if (priv->power_data.pci_pm)
164 memcpy(&pow_data->pwr_range_1[0], &range_1[0], size); 210 cmd->flags |= IWL_POWER_PCI_PM_MSK;
165 memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
166 211
167 lctl = iwl_pcie_link_ctl(priv); 212 IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
168
169 IWL_DEBUG_POWER(priv, "adjust power command flags\n");
170
171 for (i = 0; i < IWL_POWER_NUM; i++) {
172 cmd = &pow_data->pwr_range_0[i].cmd;
173
174 if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
175 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
176 else
177 cmd->flags |= IWL_POWER_PCI_PM_MSK;
178 }
179} 213}
180 214
181/* adjust power command according to DTIM period and power level*/ 215static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
182static int iwl_update_power_cmd(struct iwl_priv *priv, 216 struct iwl_powertable_cmd *cmd,
183 struct iwl_powertable_cmd *cmd, u16 mode) 217 int dynps_ms, int wakeup_period)
184{ 218{
185 struct iwl_power_vec_entry *range;
186 struct iwl_power_mgr *pow_data;
187 int i; 219 int i;
188 u32 max_sleep = 0;
189 u8 period;
190 bool skip;
191 220
192 if (mode > IWL_POWER_INDEX_5) { 221 memset(cmd, 0, sizeof(*cmd));
193 IWL_DEBUG_POWER(priv, "Error invalid power mode \n");
194 return -EINVAL;
195 }
196 222
197 pow_data = &priv->power_data; 223 cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
198 224 IWL_POWER_FAST_PD; /* no use seeing frames for others */
199 if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX)
200 range = &pow_data->pwr_range_0[0];
201 else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
202 range = &pow_data->pwr_range_1[0];
203 else
204 range = &pow_data->pwr_range_2[0];
205 225
206 period = pow_data->dtim_period; 226 if (priv->power_data.pci_pm)
207 memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); 227 cmd->flags |= IWL_POWER_PCI_PM_MSK;
208 228
209 if (period == 0) { 229 cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
210 period = 1; 230 cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
211 skip = false;
212 } else {
213 skip = !!range[mode].no_dtim;
214 }
215
216 if (skip) {
217 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
218 max_sleep = le32_to_cpu(slp_itrvl);
219 if (max_sleep == 0xFF)
220 max_sleep = period * (skip + 1);
221 else if (max_sleep > period)
222 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
223 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
224 } else {
225 max_sleep = period;
226 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
227 }
228 231
229 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 232 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
230 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 233 cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
231 cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 234
235 IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
236}
232 237
238static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
239{
240 IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
233 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); 241 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
234 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 242 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
235 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 243 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
@@ -240,113 +248,107 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
240 le32_to_cpu(cmd->sleep_interval[3]), 248 le32_to_cpu(cmd->sleep_interval[3]),
241 le32_to_cpu(cmd->sleep_interval[4])); 249 le32_to_cpu(cmd->sleep_interval[4]));
242 250
243 return 0; 251 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
252 sizeof(struct iwl_powertable_cmd), cmd);
244} 253}
245 254
246 255
247/*
248 * compute the final power mode index
249 */
250int iwl_power_update_mode(struct iwl_priv *priv, bool force) 256int iwl_power_update_mode(struct iwl_priv *priv, bool force)
251{ 257{
252 struct iwl_power_mgr *setting = &(priv->power_data);
253 int ret = 0; 258 int ret = 0;
254 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 259 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
255 u16 uninitialized_var(final_mode); 260 bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
261 (priv->hw->conf.flags & IEEE80211_CONF_PS);
256 bool update_chains; 262 bool update_chains;
263 struct iwl_powertable_cmd cmd;
264 int dtimper;
257 265
258 /* Don't update the RX chain when chain noise calibration is running */ 266 /* Don't update the RX chain when chain noise calibration is running */
259 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || 267 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
260 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 268 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
261 269
262 final_mode = priv->power_data.user_power_setting; 270 if (priv->vif)
263 271 dtimper = priv->vif->bss_conf.dtim_period;
264 if (setting->power_disabled) 272 else
265 final_mode = IWL_POWER_MODE_CAM; 273 dtimper = 1;
274
275 /* TT power setting overwrites everything */
276 if (tt->state >= IWL_TI_1)
277 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
278 else if (!enabled)
279 iwl_power_sleep_cam_cmd(priv, &cmd);
280 else if (priv->power_data.debug_sleep_level_override >= 0)
281 iwl_static_sleep_cmd(priv, &cmd,
282 priv->power_data.debug_sleep_level_override,
283 dtimper);
284 else if (no_sleep_autoadjust)
285 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
286 else
287 iwl_power_fill_sleep_cmd(priv, &cmd,
288 priv->hw->conf.dynamic_ps_timeout,
289 priv->hw->conf.max_sleep_period);
266 290
267 if (tt->state >= IWL_TI_1) {
268 /* TT power setting overwrite user & system power setting */
269 final_mode = tt->tt_power_mode;
270 }
271 if (iwl_is_ready_rf(priv) && 291 if (iwl_is_ready_rf(priv) &&
272 ((setting->power_mode != final_mode) || force)) { 292 (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
273 struct iwl_powertable_cmd cmd; 293 if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
274
275 if (final_mode != IWL_POWER_MODE_CAM)
276 set_bit(STATUS_POWER_PMI, &priv->status); 294 set_bit(STATUS_POWER_PMI, &priv->status);
277 295
278 iwl_update_power_cmd(priv, &cmd, final_mode);
279 cmd.keep_alive_beacons = 0;
280
281 if (final_mode == IWL_POWER_INDEX_5)
282 cmd.flags |= IWL_POWER_FAST_PD;
283
284 ret = iwl_set_power(priv, &cmd); 296 ret = iwl_set_power(priv, &cmd);
285 297 if (!ret) {
286 if (final_mode == IWL_POWER_MODE_CAM) 298 if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
287 clear_bit(STATUS_POWER_PMI, &priv->status); 299 clear_bit(STATUS_POWER_PMI, &priv->status);
288 300
289 if (priv->cfg->ops->lib->update_chain_flags && update_chains) 301 if (priv->cfg->ops->lib->update_chain_flags &&
290 priv->cfg->ops->lib->update_chain_flags(priv); 302 update_chains)
291 else 303 priv->cfg->ops->lib->update_chain_flags(priv);
292 IWL_DEBUG_POWER(priv, "Cannot update the power, chain noise " 304 else
305 IWL_DEBUG_POWER(priv,
306 "Cannot update the power, chain noise "
293 "calibration running: %d\n", 307 "calibration running: %d\n",
294 priv->chain_noise_data.state); 308 priv->chain_noise_data.state);
295 if (!ret) 309 memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
296 setting->power_mode = final_mode; 310 } else
311 IWL_ERR(priv, "set power fail, ret = %d", ret);
297 } 312 }
298 313
299 return ret; 314 return ret;
300} 315}
301EXPORT_SYMBOL(iwl_power_update_mode); 316EXPORT_SYMBOL(iwl_power_update_mode);
302 317
303/* set user_power_setting */
304int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
305{
306 if (mode >= IWL_POWER_NUM)
307 return -EINVAL;
308
309 priv->power_data.user_power_setting = mode;
310
311 return iwl_power_update_mode(priv, 0);
312}
313EXPORT_SYMBOL(iwl_power_set_user_mode);
314
315bool iwl_ht_enabled(struct iwl_priv *priv) 318bool iwl_ht_enabled(struct iwl_priv *priv)
316{ 319{
317 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 320 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
318 struct iwl_tt_restriction *restriction; 321 struct iwl_tt_restriction *restriction;
319 322
320 if (!priv->power_data.adv_tt) 323 if (!priv->thermal_throttle.advanced_tt)
321 return true; 324 return true;
322 restriction = tt->restriction + tt->state; 325 restriction = tt->restriction + tt->state;
323 return restriction->is_ht; 326 return restriction->is_ht;
324} 327}
325EXPORT_SYMBOL(iwl_ht_enabled); 328EXPORT_SYMBOL(iwl_ht_enabled);
326 329
327u8 iwl_tx_ant_restriction(struct iwl_priv *priv) 330enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv)
328{ 331{
329 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 332 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
330 struct iwl_tt_restriction *restriction; 333 struct iwl_tt_restriction *restriction;
331 334
332 if (!priv->power_data.adv_tt) 335 if (!priv->thermal_throttle.advanced_tt)
333 return IWL_TX_MULTI; 336 return IWL_ANT_OK_MULTI;
334 restriction = tt->restriction + tt->state; 337 restriction = tt->restriction + tt->state;
335 return restriction->tx_stream; 338 return restriction->tx_stream;
336} 339}
337EXPORT_SYMBOL(iwl_tx_ant_restriction); 340EXPORT_SYMBOL(iwl_tx_ant_restriction);
338 341
339u8 iwl_rx_ant_restriction(struct iwl_priv *priv) 342enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
340{ 343{
341 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 344 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
342 struct iwl_tt_restriction *restriction; 345 struct iwl_tt_restriction *restriction;
343 346
344 if (!priv->power_data.adv_tt) 347 if (!priv->thermal_throttle.advanced_tt)
345 return IWL_RX_MULTI; 348 return IWL_ANT_OK_MULTI;
346 restriction = tt->restriction + tt->state; 349 restriction = tt->restriction + tt->state;
347 return restriction->rx_stream; 350 return restriction->rx_stream;
348} 351}
349EXPORT_SYMBOL(iwl_rx_ant_restriction);
350 352
351#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 353#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
352 354
@@ -361,21 +363,21 @@ EXPORT_SYMBOL(iwl_rx_ant_restriction);
361static void iwl_tt_check_exit_ct_kill(unsigned long data) 363static void iwl_tt_check_exit_ct_kill(unsigned long data)
362{ 364{
363 struct iwl_priv *priv = (struct iwl_priv *)data; 365 struct iwl_priv *priv = (struct iwl_priv *)data;
364 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 366 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
365 unsigned long flags; 367 unsigned long flags;
366 368
367 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 369 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
368 return; 370 return;
369 371
370 if (tt->state == IWL_TI_CT_KILL) { 372 if (tt->state == IWL_TI_CT_KILL) {
371 if (priv->power_data.ct_kill_toggle) { 373 if (priv->thermal_throttle.ct_kill_toggle) {
372 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 374 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
373 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 375 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
374 priv->power_data.ct_kill_toggle = false; 376 priv->thermal_throttle.ct_kill_toggle = false;
375 } else { 377 } else {
376 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 378 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
377 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 379 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
378 priv->power_data.ct_kill_toggle = true; 380 priv->thermal_throttle.ct_kill_toggle = true;
379 } 381 }
380 iwl_read32(priv, CSR_UCODE_DRV_GP1); 382 iwl_read32(priv, CSR_UCODE_DRV_GP1);
381 spin_lock_irqsave(&priv->reg_lock, flags); 383 spin_lock_irqsave(&priv->reg_lock, flags);
@@ -386,7 +388,7 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
386 /* Reschedule the ct_kill timer to occur in 388 /* Reschedule the ct_kill timer to occur in
387 * CT_KILL_EXIT_DURATION seconds to ensure we get a 389 * CT_KILL_EXIT_DURATION seconds to ensure we get a
388 * thermal update */ 390 * thermal update */
389 mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies + 391 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
390 CT_KILL_EXIT_DURATION * HZ); 392 CT_KILL_EXIT_DURATION * HZ);
391 } 393 }
392} 394}
@@ -400,7 +402,7 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
400 ieee80211_stop_queues(priv->hw); 402 ieee80211_stop_queues(priv->hw);
401 IWL_DEBUG_POWER(priv, 403 IWL_DEBUG_POWER(priv,
402 "Schedule 5 seconds CT_KILL Timer\n"); 404 "Schedule 5 seconds CT_KILL Timer\n");
403 mod_timer(&priv->power_data.ct_kill_exit_tm, jiffies + 405 mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies +
404 CT_KILL_EXIT_DURATION * HZ); 406 CT_KILL_EXIT_DURATION * HZ);
405 } else { 407 } else {
406 IWL_DEBUG_POWER(priv, "Wake all queues\n"); 408 IWL_DEBUG_POWER(priv, "Wake all queues\n");
@@ -424,9 +426,8 @@ static void iwl_perform_ct_kill_task(struct iwl_priv *priv,
424 */ 426 */
425static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) 427static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
426{ 428{
427 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 429 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
428 enum iwl_tt_state new_state; 430 enum iwl_tt_state old_state;
429 struct iwl_power_mgr *setting = &priv->power_data;
430 431
431#ifdef CONFIG_IWLWIFI_DEBUG 432#ifdef CONFIG_IWLWIFI_DEBUG
432 if ((tt->tt_previous_temp) && 433 if ((tt->tt_previous_temp) &&
@@ -438,38 +439,28 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
438 (temp - tt->tt_previous_temp)); 439 (temp - tt->tt_previous_temp));
439 } 440 }
440#endif 441#endif
442 old_state = tt->state;
441 /* in Celsius */ 443 /* in Celsius */
442 if (temp >= IWL_MINIMAL_POWER_THRESHOLD) 444 if (temp >= IWL_MINIMAL_POWER_THRESHOLD)
443 new_state = IWL_TI_CT_KILL; 445 tt->state = IWL_TI_CT_KILL;
444 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) 446 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2)
445 new_state = IWL_TI_2; 447 tt->state = IWL_TI_2;
446 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) 448 else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1)
447 new_state = IWL_TI_1; 449 tt->state = IWL_TI_1;
448 else 450 else
449 new_state = IWL_TI_0; 451 tt->state = IWL_TI_0;
450 452
451#ifdef CONFIG_IWLWIFI_DEBUG 453#ifdef CONFIG_IWLWIFI_DEBUG
452 tt->tt_previous_temp = temp; 454 tt->tt_previous_temp = temp;
453#endif 455#endif
454 if (tt->state != new_state) { 456 if (tt->state != old_state) {
455 if (tt->state == IWL_TI_0) { 457 switch (tt->state) {
456 tt->sys_power_mode = setting->power_mode;
457 IWL_DEBUG_POWER(priv, "current power mode: %u\n",
458 setting->power_mode);
459 }
460 switch (new_state) {
461 case IWL_TI_0: 458 case IWL_TI_0:
462 /* when system ready to go back to IWL_TI_0 state 459 /*
463 * using system power mode instead of TT power mode 460 * When the system is ready to go back to IWL_TI_0
464 * revert back to the orginal power mode which was saved 461 * we only have to call iwl_power_update_mode() to
465 * before enter Thermal Throttling state 462 * do so.
466 * update priv->power_data.user_power_setting to the
467 * required power mode to make sure
468 * iwl_power_update_mode() will update power correctly.
469 */ 463 */
470 priv->power_data.user_power_setting =
471 tt->sys_power_mode;
472 tt->tt_power_mode = tt->sys_power_mode;
473 break; 464 break;
474 case IWL_TI_1: 465 case IWL_TI_1:
475 tt->tt_power_mode = IWL_POWER_INDEX_3; 466 tt->tt_power_mode = IWL_POWER_INDEX_3;
@@ -481,24 +472,26 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
481 tt->tt_power_mode = IWL_POWER_INDEX_5; 472 tt->tt_power_mode = IWL_POWER_INDEX_5;
482 break; 473 break;
483 } 474 }
475 mutex_lock(&priv->mutex);
484 if (iwl_power_update_mode(priv, true)) { 476 if (iwl_power_update_mode(priv, true)) {
485 /* TT state not updated 477 /* TT state not updated
486 * try again during next temperature read 478 * try again during next temperature read
487 */ 479 */
480 tt->state = old_state;
488 IWL_ERR(priv, "Cannot update power mode, " 481 IWL_ERR(priv, "Cannot update power mode, "
489 "TT state not updated\n"); 482 "TT state not updated\n");
490 } else { 483 } else {
491 if (new_state == IWL_TI_CT_KILL) 484 if (tt->state == IWL_TI_CT_KILL)
492 iwl_perform_ct_kill_task(priv, true); 485 iwl_perform_ct_kill_task(priv, true);
493 else if (tt->state == IWL_TI_CT_KILL && 486 else if (old_state == IWL_TI_CT_KILL &&
494 new_state != IWL_TI_CT_KILL) 487 tt->state != IWL_TI_CT_KILL)
495 iwl_perform_ct_kill_task(priv, false); 488 iwl_perform_ct_kill_task(priv, false);
496 tt->state = new_state;
497 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", 489 IWL_DEBUG_POWER(priv, "Temperature state changed %u\n",
498 tt->state); 490 tt->state);
499 IWL_DEBUG_POWER(priv, "Power Index change to %u\n", 491 IWL_DEBUG_POWER(priv, "Power Index change to %u\n",
500 tt->tt_power_mode); 492 tt->tt_power_mode);
501 } 493 }
494 mutex_unlock(&priv->mutex);
502 } 495 }
503} 496}
504 497
@@ -525,7 +518,7 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
525 */ 518 */
526static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) 519static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
527{ 520{
528 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 521 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
529 int i; 522 int i;
530 bool changed = false; 523 bool changed = false;
531 enum iwl_tt_state old_state; 524 enum iwl_tt_state old_state;
@@ -570,20 +563,15 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
570 } 563 }
571 if (changed) { 564 if (changed) {
572 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 565 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
573 struct iwl_power_mgr *setting = &priv->power_data;
574 566
575 if (tt->state >= IWL_TI_1) { 567 if (tt->state >= IWL_TI_1) {
576 /* if switching from IWL_TI_0 to other TT state
577 * save previous power setting in tt->sys_power_mode */
578 if (old_state == IWL_TI_0)
579 tt->sys_power_mode = setting->power_mode;
580 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 568 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
581 tt->tt_power_mode = IWL_POWER_INDEX_5; 569 tt->tt_power_mode = IWL_POWER_INDEX_5;
582 if (!iwl_ht_enabled(priv)) 570 if (!iwl_ht_enabled(priv))
583 /* disable HT */ 571 /* disable HT */
584 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | 572 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
585 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 573 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
586 RXON_FLG_FAT_PROT_MSK | 574 RXON_FLG_HT40_PROT_MSK |
587 RXON_FLG_HT_PROT_MSK); 575 RXON_FLG_HT_PROT_MSK);
588 else { 576 else {
589 /* check HT capability and set 577 /* check HT capability and set
@@ -593,22 +581,17 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
593 } 581 }
594 582
595 } else { 583 } else {
596 /* restore system power setting */ 584 /*
597 /* the previous power mode was saved in 585 * restore system power setting -- it will be
598 * tt->sys_power_mode when system move into 586 * recalculated automatically.
599 * Thermal Throttling state
600 * set power_data.user_power_setting to the previous
601 * system power mode to make sure power will get
602 * updated correctly
603 */ 587 */
604 priv->power_data.user_power_setting = 588
605 tt->sys_power_mode;
606 tt->tt_power_mode = tt->sys_power_mode;
607 /* check HT capability and set 589 /* check HT capability and set
608 * according to the system HT capability 590 * according to the system HT capability
609 * in case get disabled before */ 591 * in case get disabled before */
610 iwl_set_rxon_ht(priv, &priv->current_ht_config); 592 iwl_set_rxon_ht(priv, &priv->current_ht_config);
611 } 593 }
594 mutex_lock(&priv->mutex);
612 if (iwl_power_update_mode(priv, true)) { 595 if (iwl_power_update_mode(priv, true)) {
613 /* TT state not updated 596 /* TT state not updated
614 * try again during next temperature read 597 * try again during next temperature read
@@ -631,6 +614,7 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
631 iwl_perform_ct_kill_task(priv, false); 614 iwl_perform_ct_kill_task(priv, false);
632 } 615 }
633 } 616 }
617 mutex_unlock(&priv->mutex);
634 } 618 }
635} 619}
636 620
@@ -644,17 +628,21 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
644 * for advance mode 628 * for advance mode
645 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state 629 * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state
646 */ 630 */
647void iwl_tt_enter_ct_kill(struct iwl_priv *priv) 631static void iwl_bg_ct_enter(struct work_struct *work)
648{ 632{
649 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 633 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter);
634 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
650 635
651 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 636 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
652 return; 637 return;
653 638
639 if (!iwl_is_ready(priv))
640 return;
641
654 if (tt->state != IWL_TI_CT_KILL) { 642 if (tt->state != IWL_TI_CT_KILL) {
655 IWL_ERR(priv, "Device reached critical temperature " 643 IWL_ERR(priv, "Device reached critical temperature "
656 "- ucode going to sleep!\n"); 644 "- ucode going to sleep!\n");
657 if (!priv->power_data.adv_tt) 645 if (!priv->thermal_throttle.advanced_tt)
658 iwl_legacy_tt_handler(priv, 646 iwl_legacy_tt_handler(priv,
659 IWL_MINIMAL_POWER_THRESHOLD); 647 IWL_MINIMAL_POWER_THRESHOLD);
660 else 648 else
@@ -662,38 +650,61 @@ void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
662 CT_KILL_THRESHOLD + 1); 650 CT_KILL_THRESHOLD + 1);
663 } 651 }
664} 652}
665EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
666 653
667/* Card State Notification indicated out of critical temperature 654/* Card State Notification indicated out of critical temperature
668 * since Card State Notification will not provide any temperature reading 655 * since Card State Notification will not provide any temperature reading
669 * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature 656 * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature
670 * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state 657 * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state
671 */ 658 */
672void iwl_tt_exit_ct_kill(struct iwl_priv *priv) 659static void iwl_bg_ct_exit(struct work_struct *work)
673{ 660{
674 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 661 struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit);
662 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
675 663
676 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 664 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
677 return; 665 return;
678 666
667 if (!iwl_is_ready(priv))
668 return;
669
679 /* stop ct_kill_exit_tm timer */ 670 /* stop ct_kill_exit_tm timer */
680 del_timer_sync(&priv->power_data.ct_kill_exit_tm); 671 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
681 672
682 if (tt->state == IWL_TI_CT_KILL) { 673 if (tt->state == IWL_TI_CT_KILL) {
683 IWL_ERR(priv, 674 IWL_ERR(priv,
684 "Device temperature below critical" 675 "Device temperature below critical"
685 "- ucode awake!\n"); 676 "- ucode awake!\n");
686 if (!priv->power_data.adv_tt) 677 if (!priv->thermal_throttle.advanced_tt)
687 iwl_legacy_tt_handler(priv, 678 iwl_legacy_tt_handler(priv,
688 IWL_REDUCED_PERFORMANCE_THRESHOLD_2); 679 IWL_REDUCED_PERFORMANCE_THRESHOLD_2);
689 else 680 else
690 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); 681 iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD);
691 } 682 }
692} 683}
684
685void iwl_tt_enter_ct_kill(struct iwl_priv *priv)
686{
687 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
688 return;
689
690 IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n");
691 queue_work(priv->workqueue, &priv->ct_enter);
692}
693EXPORT_SYMBOL(iwl_tt_enter_ct_kill);
694
695void iwl_tt_exit_ct_kill(struct iwl_priv *priv)
696{
697 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
698 return;
699
700 IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n");
701 queue_work(priv->workqueue, &priv->ct_exit);
702}
693EXPORT_SYMBOL(iwl_tt_exit_ct_kill); 703EXPORT_SYMBOL(iwl_tt_exit_ct_kill);
694 704
695void iwl_tt_handler(struct iwl_priv *priv) 705static void iwl_bg_tt_work(struct work_struct *work)
696{ 706{
707 struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work);
697 s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ 708 s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */
698 709
699 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 710 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -702,11 +713,20 @@ void iwl_tt_handler(struct iwl_priv *priv)
702 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) 713 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
703 temp = KELVIN_TO_CELSIUS(priv->temperature); 714 temp = KELVIN_TO_CELSIUS(priv->temperature);
704 715
705 if (!priv->power_data.adv_tt) 716 if (!priv->thermal_throttle.advanced_tt)
706 iwl_legacy_tt_handler(priv, temp); 717 iwl_legacy_tt_handler(priv, temp);
707 else 718 else
708 iwl_advance_tt_handler(priv, temp); 719 iwl_advance_tt_handler(priv, temp);
709} 720}
721
722void iwl_tt_handler(struct iwl_priv *priv)
723{
724 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
725 return;
726
727 IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n");
728 queue_work(priv->workqueue, &priv->tt_work);
729}
710EXPORT_SYMBOL(iwl_tt_handler); 730EXPORT_SYMBOL(iwl_tt_handler);
711 731
712/* Thermal throttling initialization 732/* Thermal throttling initialization
@@ -716,8 +736,7 @@ EXPORT_SYMBOL(iwl_tt_handler);
716 */ 736 */
717void iwl_tt_initialize(struct iwl_priv *priv) 737void iwl_tt_initialize(struct iwl_priv *priv)
718{ 738{
719 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 739 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
720 struct iwl_power_mgr *setting = &priv->power_data;
721 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 740 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
722 struct iwl_tt_trans *transaction; 741 struct iwl_tt_trans *transaction;
723 742
@@ -726,11 +745,15 @@ void iwl_tt_initialize(struct iwl_priv *priv)
726 memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 745 memset(tt, 0, sizeof(struct iwl_tt_mgmt));
727 746
728 tt->state = IWL_TI_0; 747 tt->state = IWL_TI_0;
729 tt->sys_power_mode = setting->power_mode; 748 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
730 tt->tt_power_mode = tt->sys_power_mode; 749 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
731 init_timer(&priv->power_data.ct_kill_exit_tm); 750 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
732 priv->power_data.ct_kill_exit_tm.data = (unsigned long)priv; 751
733 priv->power_data.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 752 /* setup deferred ct kill work */
753 INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
754 INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);
755 INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit);
756
734 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 757 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
735 case CSR_HW_REV_TYPE_6x00: 758 case CSR_HW_REV_TYPE_6x00:
736 case CSR_HW_REV_TYPE_6x50: 759 case CSR_HW_REV_TYPE_6x50:
@@ -742,7 +765,7 @@ void iwl_tt_initialize(struct iwl_priv *priv)
742 GFP_KERNEL); 765 GFP_KERNEL);
743 if (!tt->restriction || !tt->transaction) { 766 if (!tt->restriction || !tt->transaction) {
744 IWL_ERR(priv, "Fallback to Legacy Throttling\n"); 767 IWL_ERR(priv, "Fallback to Legacy Throttling\n");
745 priv->power_data.adv_tt = false; 768 priv->thermal_throttle.advanced_tt = false;
746 kfree(tt->restriction); 769 kfree(tt->restriction);
747 tt->restriction = NULL; 770 tt->restriction = NULL;
748 kfree(tt->transaction); 771 kfree(tt->transaction);
@@ -764,12 +787,12 @@ void iwl_tt_initialize(struct iwl_priv *priv)
764 IWL_TI_STATE_MAX; 787 IWL_TI_STATE_MAX;
765 memcpy(tt->restriction, 788 memcpy(tt->restriction,
766 &restriction_range[0], size); 789 &restriction_range[0], size);
767 priv->power_data.adv_tt = true; 790 priv->thermal_throttle.advanced_tt = true;
768 } 791 }
769 break; 792 break;
770 default: 793 default:
771 IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); 794 IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n");
772 priv->power_data.adv_tt = false; 795 priv->thermal_throttle.advanced_tt = false;
773 break; 796 break;
774 } 797 }
775} 798}
@@ -778,12 +801,15 @@ EXPORT_SYMBOL(iwl_tt_initialize);
778/* cleanup thermal throttling management related memory and timer */ 801/* cleanup thermal throttling management related memory and timer */
779void iwl_tt_exit(struct iwl_priv *priv) 802void iwl_tt_exit(struct iwl_priv *priv)
780{ 803{
781 struct iwl_tt_mgmt *tt = &priv->power_data.tt; 804 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
782 805
783 /* stop ct_kill_exit_tm timer if activated */ 806 /* stop ct_kill_exit_tm timer if activated */
784 del_timer_sync(&priv->power_data.ct_kill_exit_tm); 807 del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm);
808 cancel_work_sync(&priv->tt_work);
809 cancel_work_sync(&priv->ct_enter);
810 cancel_work_sync(&priv->ct_exit);
785 811
786 if (priv->power_data.adv_tt) { 812 if (priv->thermal_throttle.advanced_tt) {
787 /* free advance thermal throttling memory */ 813 /* free advance thermal throttling memory */
788 kfree(tt->restriction); 814 kfree(tt->restriction);
789 tt->restriction = NULL; 815 tt->restriction = NULL;
@@ -796,9 +822,13 @@ EXPORT_SYMBOL(iwl_tt_exit);
796/* initialize to default */ 822/* initialize to default */
797void iwl_power_initialize(struct iwl_priv *priv) 823void iwl_power_initialize(struct iwl_priv *priv)
798{ 824{
799 iwl_power_init_handle(priv); 825 u16 lctl = iwl_pcie_link_ctl(priv);
800 priv->power_data.user_power_setting = IWL_POWER_INDEX_1; 826
801 /* default to disabled until mac80211 says otherwise */ 827 priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
802 priv->power_data.power_disabled = 1; 828
829 priv->power_data.debug_sleep_level_override = -1;
830
831 memset(&priv->power_data.sleep_cmd, 0,
832 sizeof(priv->power_data.sleep_cmd));
803} 833}
804EXPORT_SYMBOL(iwl_power_initialize); 834EXPORT_SYMBOL(iwl_power_initialize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 3d49b7a45b74..df6f6a49712b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -28,22 +28,17 @@
28#ifndef __iwl_power_setting_h__ 28#ifndef __iwl_power_setting_h__
29#define __iwl_power_setting_h__ 29#define __iwl_power_setting_h__
30 30
31#include <net/mac80211.h>
32#include "iwl-commands.h" 31#include "iwl-commands.h"
33 32
34struct iwl_priv;
35
36#define IWL_ABSOLUTE_ZERO 0 33#define IWL_ABSOLUTE_ZERO 0
37#define IWL_ABSOLUTE_MAX 0xFFFFFFFF 34#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
38#define IWL_TT_INCREASE_MARGIN 5 35#define IWL_TT_INCREASE_MARGIN 5
39 36
40/* Tx/Rx restrictions */ 37enum iwl_antenna_ok {
41#define IWL_TX_MULTI 0x02 38 IWL_ANT_OK_NONE,
42#define IWL_TX_SINGLE 0x01 39 IWL_ANT_OK_SINGLE,
43#define IWL_TX_NONE 0x00 40 IWL_ANT_OK_MULTI,
44#define IWL_RX_MULTI 0x02 41};
45#define IWL_RX_SINGLE 0x01
46#define IWL_RX_NONE 0x00
47 42
48/* Thermal Throttling State Machine states */ 43/* Thermal Throttling State Machine states */
49enum iwl_tt_state { 44enum iwl_tt_state {
@@ -55,27 +50,30 @@ enum iwl_tt_state {
55}; 50};
56 51
57/** 52/**
58 * struct iwl_tt_restriction - Thermal Throttling restriction table used 53 * struct iwl_tt_restriction - Thermal Throttling restriction table
59 * by advance thermal throttling management
60 * based on the current thermal throttling state, determine
61 * number of tx/rx streams; and the status of HT operation
62 * @tx_stream: number of tx stream allowed 54 * @tx_stream: number of tx stream allowed
63 * @is_ht: ht enable/disable 55 * @is_ht: ht enable/disable
64 * @rx_stream: number of rx stream allowed 56 * @rx_stream: number of rx stream allowed
57 *
58 * This table is used by advance thermal throttling management
59 * based on the current thermal throttling state, and determines
60 * the number of tx/rx streams and the status of HT operation.
65 */ 61 */
66struct iwl_tt_restriction { 62struct iwl_tt_restriction {
67 u8 tx_stream; 63 enum iwl_antenna_ok tx_stream;
64 enum iwl_antenna_ok rx_stream;
68 bool is_ht; 65 bool is_ht;
69 u8 rx_stream;
70}; 66};
71 67
72/** 68/**
73 * struct iwl_tt_trans - Thermal Throttling transaction table; used by 69 * struct iwl_tt_trans - Thermal Throttling transaction table
74 * advance thermal throttling algorithm to determine next
75 * thermal state to go based on the current temperature
76 * @next_state: next thermal throttling mode 70 * @next_state: next thermal throttling mode
77 * @tt_low: low temperature threshold to change state 71 * @tt_low: low temperature threshold to change state
78 * @tt_high: high temperature threshold to change state 72 * @tt_high: high temperature threshold to change state
73 *
74 * This is used by the advanced thermal throttling algorithm
75 * to determine the next thermal state to go based on the
76 * current temperature.
79 */ 77 */
80struct iwl_tt_trans { 78struct iwl_tt_trans {
81 enum iwl_tt_state next_state; 79 enum iwl_tt_state next_state;
@@ -85,34 +83,36 @@ struct iwl_tt_trans {
85 83
86/** 84/**
87 * struct iwl_tt_mgnt - Thermal Throttling Management structure 85 * struct iwl_tt_mgnt - Thermal Throttling Management structure
86 * @advanced_tt: advanced thermal throttle required
88 * @state: current Thermal Throttling state 87 * @state: current Thermal Throttling state
89 * @tt_power_mode: Thermal Throttling power mode index 88 * @tt_power_mode: Thermal Throttling power mode index
90 * being used to set power level when 89 * being used to set power level when
91 * when thermal throttling state != IWL_TI_0 90 * when thermal throttling state != IWL_TI_0
92 * the tt_power_mode should set to different 91 * the tt_power_mode should set to different
93 * power mode based on the current tt state 92 * power mode based on the current tt state
94 * @sys_power_mode: previous system power mode
95 * before transition into TT state
96 * @tt_previous_temperature: last measured temperature 93 * @tt_previous_temperature: last measured temperature
97 * @iwl_tt_restriction: ptr to restriction tbl, used by advance 94 * @iwl_tt_restriction: ptr to restriction tbl, used by advance
98 * thermal throttling to determine how many tx/rx streams 95 * thermal throttling to determine how many tx/rx streams
99 * should be used in tt state; and can HT be enabled or not 96 * should be used in tt state; and can HT be enabled or not
100 * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling 97 * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling
101 * state transaction 98 * state transaction
99 * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature
100 * @ct_kill_exit_tm: timer to exit thermal kill
102 */ 101 */
103struct iwl_tt_mgmt { 102struct iwl_tt_mgmt {
104 enum iwl_tt_state state; 103 enum iwl_tt_state state;
104 bool advanced_tt;
105 u8 tt_power_mode; 105 u8 tt_power_mode;
106 u8 sys_power_mode; 106 bool ct_kill_toggle;
107#ifdef CONFIG_IWLWIFI_DEBUG 107#ifdef CONFIG_IWLWIFI_DEBUG
108 s32 tt_previous_temp; 108 s32 tt_previous_temp;
109#endif 109#endif
110 struct iwl_tt_restriction *restriction; 110 struct iwl_tt_restriction *restriction;
111 struct iwl_tt_trans *transaction; 111 struct iwl_tt_trans *transaction;
112 struct timer_list ct_kill_exit_tm;
112}; 113};
113 114
114enum { 115enum iwl_power_level {
115 IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
116 IWL_POWER_INDEX_1, 116 IWL_POWER_INDEX_1,
117 IWL_POWER_INDEX_2, 117 IWL_POWER_INDEX_2,
118 IWL_POWER_INDEX_3, 118 IWL_POWER_INDEX_3,
@@ -121,36 +121,16 @@ enum {
121 IWL_POWER_NUM 121 IWL_POWER_NUM
122}; 122};
123 123
124/* Power management (not Tx power) structures */
125
126struct iwl_power_vec_entry {
127 struct iwl_powertable_cmd cmd;
128 u8 no_dtim;
129};
130
131struct iwl_power_mgr { 124struct iwl_power_mgr {
132 struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM]; 125 struct iwl_powertable_cmd sleep_cmd;
133 struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM]; 126 int debug_sleep_level_override;
134 struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM]; 127 bool pci_pm;
135 u32 dtim_period;
136 /* final power level that used to calculate final power command */
137 u8 power_mode;
138 u8 user_power_setting; /* set by user through sysfs */
139 u8 power_disabled; /* set by mac80211's CONF_PS */
140 struct iwl_tt_mgmt tt; /* Thermal Throttling Management */
141 bool adv_tt; /* false: legacy mode */
142 /* true: advance mode */
143 bool ct_kill_toggle; /* use to toggle the CSR bit when
144 * checking uCode temperature
145 */
146 struct timer_list ct_kill_exit_tm;
147}; 128};
148 129
149int iwl_power_update_mode(struct iwl_priv *priv, bool force); 130int iwl_power_update_mode(struct iwl_priv *priv, bool force);
150int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
151bool iwl_ht_enabled(struct iwl_priv *priv); 131bool iwl_ht_enabled(struct iwl_priv *priv);
152u8 iwl_tx_ant_restriction(struct iwl_priv *priv); 132enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
153u8 iwl_rx_ant_restriction(struct iwl_priv *priv); 133enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
154void iwl_tt_enter_ct_kill(struct iwl_priv *priv); 134void iwl_tt_enter_ct_kill(struct iwl_priv *priv);
155void iwl_tt_exit_ct_kill(struct iwl_priv *priv); 135void iwl_tt_exit_ct_kill(struct iwl_priv *priv);
156void iwl_tt_handler(struct iwl_priv *priv); 136void iwl_tt_handler(struct iwl_priv *priv);
@@ -158,4 +138,6 @@ void iwl_tt_initialize(struct iwl_priv *priv);
158void iwl_tt_exit(struct iwl_priv *priv); 138void iwl_tt_exit(struct iwl_priv *priv);
159void iwl_power_initialize(struct iwl_priv *priv); 139void iwl_power_initialize(struct iwl_priv *priv);
160 140
141extern bool no_sleep_autoadjust;
142
161#endif /* __iwl_power_setting_h__ */ 143#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index e002c8b56c49..43b2fce4cbf0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -544,8 +544,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
544 change = ((priv->statistics.general.temperature != 544 change = ((priv->statistics.general.temperature !=
545 pkt->u.stats.general.temperature) || 545 pkt->u.stats.general.temperature) ||
546 ((priv->statistics.flag & 546 ((priv->statistics.flag &
547 STATISTICS_REPLY_FLG_FAT_MODE_MSK) != 547 STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
548 (pkt->u.stats.flag & STATISTICS_REPLY_FLG_FAT_MODE_MSK))); 548 (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
549 549
550 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); 550 memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
551 551
@@ -645,7 +645,7 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
645 u32 tsf_low; 645 u32 tsf_low;
646 int rssi; 646 int rssi;
647 647
648 if (likely(!(iwl_debug_level & IWL_DL_RX))) 648 if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX)))
649 return; 649 return;
650 650
651 /* MAC header */ 651 /* MAC header */
@@ -741,18 +741,10 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
741 } 741 }
742 } 742 }
743 if (print_dump) 743 if (print_dump)
744 iwl_print_hex_dump(IWL_DL_RX, header, length); 744 iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
745} 745}
746#endif 746#endif
747 747
748static void iwl_update_rx_stats(struct iwl_priv *priv, u16 fc, u16 len)
749{
750 /* 0 - mgmt, 1 - cnt, 2 - data */
751 int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
752 priv->rx_stats[idx].cnt++;
753 priv->rx_stats[idx].bytes += len;
754}
755
756/* 748/*
757 * returns non-zero if packet should be dropped 749 * returns non-zero if packet should be dropped
758 */ 750 */
@@ -930,7 +922,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
930 iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) 922 iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
931 return; 923 return;
932 924
933 iwl_update_rx_stats(priv, le16_to_cpu(hdr->frame_control), len); 925 iwl_update_stats(priv, false, hdr->frame_control, len);
934 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); 926 memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
935 ieee80211_rx_irqsafe(priv->hw, rxb->skb); 927 ieee80211_rx_irqsafe(priv->hw, rxb->skb);
936 priv->alloc_rxb_skb--; 928 priv->alloc_rxb_skb--;
@@ -1060,9 +1052,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
1060 1052
1061 /* Set "1" to report good data frames in groups of 100 */ 1053 /* Set "1" to report good data frames in groups of 100 */
1062#ifdef CONFIG_IWLWIFI_DEBUG 1054#ifdef CONFIG_IWLWIFI_DEBUG
1063 if (unlikely(iwl_debug_level & IWL_DL_RX)) 1055 if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX))
1064 iwl_dbg_report_frame(priv, rx_start, len, header, 1); 1056 iwl_dbg_report_frame(priv, rx_start, len, header, 1);
1065#endif 1057#endif
1058 iwl_dbg_log_rx_data_frame(priv, len, header);
1066 IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", 1059 IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n",
1067 rx_status.signal, rx_status.noise, rx_status.qual, 1060 rx_status.signal, rx_status.noise, rx_status.qual,
1068 (unsigned long long)rx_status.mactime); 1061 (unsigned long long)rx_status.mactime);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index efcae0d5e193..c6633fec8216 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -214,10 +214,10 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
214 sta_flags |= cpu_to_le32( 214 sta_flags |= cpu_to_le32(
215 (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); 215 (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
216 216
217 if (iwl_is_fat_tx_allowed(priv, sta_ht_inf)) 217 if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf))
218 sta_flags |= STA_FLG_FAT_EN_MSK; 218 sta_flags |= STA_FLG_HT40_EN_MSK;
219 else 219 else
220 sta_flags &= ~STA_FLG_FAT_EN_MSK; 220 sta_flags &= ~STA_FLG_HT40_EN_MSK;
221 221
222 priv->stations[index].sta.station_flags = sta_flags; 222 priv->stations[index].sta.station_flags = sta_flags;
223 done: 223 done:
@@ -1088,7 +1088,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
1088 IWL_DEBUG_DROP(priv, "Station %pM not in station map. " 1088 IWL_DEBUG_DROP(priv, "Station %pM not in station map. "
1089 "Defaulting to broadcast...\n", 1089 "Defaulting to broadcast...\n",
1090 hdr->addr1); 1090 hdr->addr1);
1091 iwl_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); 1091 iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
1092 return priv->hw_params.bcast_sta_id; 1092 return priv->hw_params.bcast_sta_id;
1093 1093
1094 default: 1094 default:
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 288b871e974b..9b76bd41f214 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -668,14 +668,6 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
668 } 668 }
669} 669}
670 670
671static void iwl_update_tx_stats(struct iwl_priv *priv, u16 fc, u16 len)
672{
673 /* 0 - mgmt, 1 - cnt, 2 - data */
674 int idx = (fc & IEEE80211_FCTL_FTYPE) >> 2;
675 priv->tx_stats[idx].cnt++;
676 priv->tx_stats[idx].bytes += len;
677}
678
679/* 671/*
680 * start REPLY_TX command process 672 * start REPLY_TX command process
681 */ 673 */
@@ -808,12 +800,12 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
808 800
809 /* TODO need this for burst mode later on */ 801 /* TODO need this for burst mode later on */
810 iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); 802 iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
803 iwl_dbg_log_tx_data_frame(priv, len, hdr);
811 804
812 /* set is_hcca to 0; it probably will never be implemented */ 805 /* set is_hcca to 0; it probably will never be implemented */
813 iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0); 806 iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
814 807
815 iwl_update_tx_stats(priv, le16_to_cpu(fc), len); 808 iwl_update_stats(priv, true, fc, len);
816
817 /* 809 /*
818 * Use the first empty entry in this queue's command buffer array 810 * Use the first empty entry in this queue's command buffer array
819 * to contain the Tx command and MAC header concatenated together 811 * to contain the Tx command and MAC header concatenated together
@@ -884,8 +876,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
884 IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", 876 IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
885 le16_to_cpu(out_cmd->hdr.sequence)); 877 le16_to_cpu(out_cmd->hdr.sequence));
886 IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); 878 IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags));
887 iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); 879 iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
888 iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); 880 iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len);
889 881
890 /* Set up entry for this TFD in Tx byte-count array */ 882 /* Set up entry for this TFD in Tx byte-count array */
891 if (info->flags & IEEE80211_TX_CTL_AMPDU) 883 if (info->flags & IEEE80211_TX_CTL_AMPDU)
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index ea051b739ba2..e617411d0c5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -598,7 +598,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
598 len = (u16)skb->len; 598 len = (u16)skb->len;
599 tx->len = cpu_to_le16(len); 599 tx->len = cpu_to_le16(len);
600 600
601 601 iwl_dbg_log_tx_data_frame(priv, len, hdr);
602 iwl_update_stats(priv, true, fc, len);
602 tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; 603 tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
603 tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; 604 tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
604 605
@@ -614,8 +615,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
614 IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", 615 IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n",
615 le16_to_cpu(out_cmd->hdr.sequence)); 616 le16_to_cpu(out_cmd->hdr.sequence));
616 IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); 617 IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags));
617 iwl_print_hex_dump(IWL_DL_TX, tx, sizeof(*tx)); 618 iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx));
618 iwl_print_hex_dump(IWL_DL_TX, (u8 *)tx->hdr, 619 iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr,
619 ieee80211_hdrlen(fc)); 620 ieee80211_hdrlen(fc));
620 621
621 /* 622 /*
@@ -1646,7 +1647,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1646 iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); 1647 iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
1647 1648
1648#ifdef CONFIG_IWLWIFI_DEBUG 1649#ifdef CONFIG_IWLWIFI_DEBUG
1649 if (iwl_debug_level & IWL_DL_ISR) { 1650 if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
1650 /* just for debug */ 1651 /* just for debug */
1651 inta_mask = iwl_read32(priv, CSR_INT_MASK); 1652 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1652 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", 1653 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
@@ -1681,7 +1682,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1681 } 1682 }
1682 1683
1683#ifdef CONFIG_IWLWIFI_DEBUG 1684#ifdef CONFIG_IWLWIFI_DEBUG
1684 if (iwl_debug_level & (IWL_DL_ISR)) { 1685 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
1685 /* NIC fires this, but we don't use it, redundant with WAKEUP */ 1686 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1686 if (inta & CSR_INT_BIT_SCD) { 1687 if (inta & CSR_INT_BIT_SCD) {
1687 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " 1688 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
@@ -1760,7 +1761,7 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1760 iwl_enable_interrupts(priv); 1761 iwl_enable_interrupts(priv);
1761 1762
1762#ifdef CONFIG_IWLWIFI_DEBUG 1763#ifdef CONFIG_IWLWIFI_DEBUG
1763 if (iwl_debug_level & (IWL_DL_ISR)) { 1764 if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
1764 inta = iwl_read32(priv, CSR_INT); 1765 inta = iwl_read32(priv, CSR_INT);
1765 inta_mask = iwl_read32(priv, CSR_INT_MASK); 1766 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1766 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); 1767 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
@@ -3311,14 +3312,15 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3311 * 3312 *
3312 * See the level definitions in iwl for details. 3313 * See the level definitions in iwl for details.
3313 * 3314 *
3314 * FIXME This file can be deprecated as the module parameter is 3315 * The debug_level being managed using sysfs below is a per device debug
3315 * writable and users can thus also change the debug level 3316 * level that is used instead of the global debug level if it (the per
3316 * using the /sys/module/iwl3945/parameters/debug file. 3317 * device debug level) is set.
3317 */ 3318 */
3318static ssize_t show_debug_level(struct device *d, 3319static ssize_t show_debug_level(struct device *d,
3319 struct device_attribute *attr, char *buf) 3320 struct device_attribute *attr, char *buf)
3320{ 3321{
3321 return sprintf(buf, "0x%08X\n", iwl_debug_level); 3322 struct iwl_priv *priv = dev_get_drvdata(d);
3323 return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
3322} 3324}
3323static ssize_t store_debug_level(struct device *d, 3325static ssize_t store_debug_level(struct device *d,
3324 struct device_attribute *attr, 3326 struct device_attribute *attr,
@@ -3331,9 +3333,12 @@ static ssize_t store_debug_level(struct device *d,
3331 ret = strict_strtoul(buf, 0, &val); 3333 ret = strict_strtoul(buf, 0, &val);
3332 if (ret) 3334 if (ret)
3333 IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); 3335 IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
3334 else 3336 else {
3335 iwl_debug_level = val; 3337 priv->debug_level = val;
3336 3338 if (iwl_alloc_traffic_mem(priv))
3339 IWL_ERR(priv,
3340 "Not enough memory to generate traffic log\n");
3341 }
3337 return strnlen(buf, count); 3342 return strnlen(buf, count);
3338} 3343}
3339 3344
@@ -3549,65 +3554,6 @@ static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
3549 store_retry_rate); 3554 store_retry_rate);
3550 3555
3551 3556
3552static ssize_t store_power_level(struct device *d,
3553 struct device_attribute *attr,
3554 const char *buf, size_t count)
3555{
3556 struct iwl_priv *priv = dev_get_drvdata(d);
3557 int ret;
3558 unsigned long mode;
3559
3560
3561 mutex_lock(&priv->mutex);
3562
3563 ret = strict_strtoul(buf, 10, &mode);
3564 if (ret)
3565 goto out;
3566
3567 ret = iwl_power_set_user_mode(priv, mode);
3568 if (ret) {
3569 IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
3570 goto out;
3571 }
3572 ret = count;
3573
3574 out:
3575 mutex_unlock(&priv->mutex);
3576 return ret;
3577}
3578
3579static ssize_t show_power_level(struct device *d,
3580 struct device_attribute *attr, char *buf)
3581{
3582 struct iwl_priv *priv = dev_get_drvdata(d);
3583 int level = priv->power_data.power_mode;
3584 char *p = buf;
3585
3586 p += sprintf(p, "%d\n", level);
3587 return p - buf + 1;
3588}
3589
3590static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
3591 show_power_level, store_power_level);
3592
3593#define MAX_WX_STRING 80
3594
3595/* Values are in microsecond */
3596static const s32 timeout_duration[] = {
3597 350000,
3598 250000,
3599 75000,
3600 37000,
3601 25000,
3602};
3603static const s32 period_duration[] = {
3604 400000,
3605 700000,
3606 1000000,
3607 1000000,
3608 1000000
3609};
3610
3611static ssize_t show_channels(struct device *d, 3557static ssize_t show_channels(struct device *d,
3612 struct device_attribute *attr, char *buf) 3558 struct device_attribute *attr, char *buf)
3613{ 3559{
@@ -3784,7 +3730,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
3784#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT 3730#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
3785 &dev_attr_measurement.attr, 3731 &dev_attr_measurement.attr,
3786#endif 3732#endif
3787 &dev_attr_power_level.attr,
3788 &dev_attr_retry_rate.attr, 3733 &dev_attr_retry_rate.attr,
3789 &dev_attr_statistics.attr, 3734 &dev_attr_statistics.attr,
3790 &dev_attr_status.attr, 3735 &dev_attr_status.attr,
@@ -3849,8 +3794,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3849 priv->qos_data.qos_cap.val = 0; 3794 priv->qos_data.qos_cap.val = 0;
3850 3795
3851 priv->rates_mask = IWL_RATES_MASK; 3796 priv->rates_mask = IWL_RATES_MASK;
3852 /* If power management is turned on, default to CAM mode */
3853 priv->power_mode = IWL_POWER_MODE_CAM;
3854 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; 3797 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
3855 3798
3856 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { 3799 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -3897,7 +3840,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
3897 /* Tell mac80211 our characteristics */ 3840 /* Tell mac80211 our characteristics */
3898 hw->flags = IEEE80211_HW_SIGNAL_DBM | 3841 hw->flags = IEEE80211_HW_SIGNAL_DBM |
3899 IEEE80211_HW_NOISE_DBM | 3842 IEEE80211_HW_NOISE_DBM |
3900 IEEE80211_HW_SPECTRUM_MGMT; 3843 IEEE80211_HW_SPECTRUM_MGMT |
3844 IEEE80211_HW_SUPPORTS_PS |
3845 IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
3901 3846
3902 hw->wiphy->interface_modes = 3847 hw->wiphy->interface_modes =
3903 BIT(NL80211_IFTYPE_STATION) | 3848 BIT(NL80211_IFTYPE_STATION) |
@@ -3975,6 +3920,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
3975#ifdef CONFIG_IWLWIFI_DEBUG 3920#ifdef CONFIG_IWLWIFI_DEBUG
3976 atomic_set(&priv->restrict_refcnt, 0); 3921 atomic_set(&priv->restrict_refcnt, 0);
3977#endif 3922#endif
3923 if (iwl_alloc_traffic_mem(priv))
3924 IWL_ERR(priv, "Not enough memory to generate traffic log\n");
3978 3925
3979 /*************************** 3926 /***************************
3980 * 2. Initializing PCI bus 3927 * 2. Initializing PCI bus
@@ -4137,6 +4084,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4137 pci_disable_device(pdev); 4084 pci_disable_device(pdev);
4138 out_ieee80211_free_hw: 4085 out_ieee80211_free_hw:
4139 ieee80211_free_hw(priv->hw); 4086 ieee80211_free_hw(priv->hw);
4087 iwl_free_traffic_mem(priv);
4140 out: 4088 out:
4141 return err; 4089 return err;
4142} 4090}
@@ -4192,6 +4140,7 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
4192 * until now... */ 4140 * until now... */
4193 destroy_workqueue(priv->workqueue); 4141 destroy_workqueue(priv->workqueue);
4194 priv->workqueue = NULL; 4142 priv->workqueue = NULL;
4143 iwl_free_traffic_mem(priv);
4195 4144
4196 free_irq(pdev->irq, priv); 4145 free_irq(pdev->irq, priv);
4197 pci_disable_msi(pdev); 4146 pci_disable_msi(pdev);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 89575e448015..8df1cfd5f93a 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1176,7 +1176,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1176 /* Allocate an Ethernet device and register it */ 1176 /* Allocate an Ethernet device and register it */
1177 dev = alloc_etherdev(sizeof(struct lbs_private)); 1177 dev = alloc_etherdev(sizeof(struct lbs_private));
1178 if (!dev) { 1178 if (!dev) {
1179 lbs_pr_err("init ethX device failed\n"); 1179 lbs_pr_err("init wlanX device failed\n");
1180 goto done; 1180 goto done;
1181 } 1181 }
1182 priv = netdev_priv(dev); 1182 priv = netdev_priv(dev);
@@ -1204,6 +1204,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1204 SET_NETDEV_DEV(dev, dmdev); 1204 SET_NETDEV_DEV(dev, dmdev);
1205 1205
1206 priv->rtap_net_dev = NULL; 1206 priv->rtap_net_dev = NULL;
1207 strcpy(dev->name, "wlan%d");
1207 1208
1208 lbs_deb_thread("Starting main thread...\n"); 1209 lbs_deb_thread("Starting main thread...\n");
1209 init_waitqueue_head(&priv->waitq); 1210 init_waitqueue_head(&priv->waitq);
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index fa508af1a351..40d8dfa7eace 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -642,7 +642,7 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
642{ 642{
643 hermes_t *hw = &priv->hw; 643 hermes_t *hw = &priv->hw;
644 int err = 0; 644 int err = 0;
645 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE]; 645 u8 tsc_arr[4][ORINOCO_SEQ_LEN];
646 646
647 if ((key < 0) || (key > 4)) 647 if ((key < 0) || (key > 4))
648 return -EINVAL; 648 return -EINVAL;
@@ -768,12 +768,29 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
768{ 768{
769 hermes_t *hw = &priv->hw; 769 hermes_t *hw = &priv->hw;
770 int err = 0; 770 int err = 0;
771 int i;
771 772
772 switch (priv->firmware_type) { 773 switch (priv->firmware_type) {
773 case FIRMWARE_TYPE_AGERE: 774 case FIRMWARE_TYPE_AGERE:
775 {
776 struct orinoco_key keys[ORINOCO_MAX_KEYS];
777
778 memset(&keys, 0, sizeof(keys));
779 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
780 int len = min(priv->keys[i].key_len,
781 ORINOCO_MAX_KEY_SIZE);
782 memcpy(&keys[i].data, priv->keys[i].key, len);
783 if (len > SMALL_KEY_SIZE)
784 keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
785 else if (len > 0)
786 keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
787 else
788 keys[i].len = cpu_to_le16(0);
789 }
790
774 err = HERMES_WRITE_RECORD(hw, USER_BAP, 791 err = HERMES_WRITE_RECORD(hw, USER_BAP,
775 HERMES_RID_CNFWEPKEYS_AGERE, 792 HERMES_RID_CNFWEPKEYS_AGERE,
776 &priv->keys); 793 &keys);
777 if (err) 794 if (err)
778 return err; 795 return err;
779 err = hermes_write_wordrec(hw, USER_BAP, 796 err = hermes_write_wordrec(hw, USER_BAP,
@@ -782,28 +799,38 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
782 if (err) 799 if (err)
783 return err; 800 return err;
784 break; 801 break;
802 }
785 case FIRMWARE_TYPE_INTERSIL: 803 case FIRMWARE_TYPE_INTERSIL:
786 case FIRMWARE_TYPE_SYMBOL: 804 case FIRMWARE_TYPE_SYMBOL:
787 { 805 {
788 int keylen; 806 int keylen;
789 int i;
790 807
791 /* Force uniform key length to work around 808 /* Force uniform key length to work around
792 * firmware bugs */ 809 * firmware bugs */
793 keylen = le16_to_cpu(priv->keys[priv->tx_key].len); 810 keylen = priv->keys[priv->tx_key].key_len;
794 811
795 if (keylen > LARGE_KEY_SIZE) { 812 if (keylen > LARGE_KEY_SIZE) {
796 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", 813 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
797 priv->ndev->name, priv->tx_key, keylen); 814 priv->ndev->name, priv->tx_key, keylen);
798 return -E2BIG; 815 return -E2BIG;
799 } 816 } else if (keylen > SMALL_KEY_SIZE)
817 keylen = LARGE_KEY_SIZE;
818 else if (keylen > 0)
819 keylen = SMALL_KEY_SIZE;
820 else
821 keylen = 0;
800 822
801 /* Write all 4 keys */ 823 /* Write all 4 keys */
802 for (i = 0; i < ORINOCO_MAX_KEYS; i++) { 824 for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
825 u8 key[LARGE_KEY_SIZE] = { 0 };
826
827 memcpy(key, priv->keys[i].key,
828 priv->keys[i].key_len);
829
803 err = hermes_write_ltv(hw, USER_BAP, 830 err = hermes_write_ltv(hw, USER_BAP,
804 HERMES_RID_CNFDEFAULTKEY0 + i, 831 HERMES_RID_CNFDEFAULTKEY0 + i,
805 HERMES_BYTES_TO_RECLEN(keylen), 832 HERMES_BYTES_TO_RECLEN(keylen),
806 priv->keys[i].data); 833 key);
807 if (err) 834 if (err)
808 return err; 835 return err;
809 } 836 }
@@ -829,8 +856,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
829 int auth_flag; 856 int auth_flag;
830 int enc_flag; 857 int enc_flag;
831 858
832 /* Setup WEP keys for WEP and WPA */ 859 /* Setup WEP keys */
833 if (priv->encode_alg) 860 if (priv->encode_alg == ORINOCO_ALG_WEP)
834 __orinoco_hw_setup_wepkeys(priv); 861 __orinoco_hw_setup_wepkeys(priv);
835 862
836 if (priv->wep_restrict) 863 if (priv->wep_restrict)
@@ -840,14 +867,14 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
840 867
841 if (priv->wpa_enabled) 868 if (priv->wpa_enabled)
842 enc_flag = 2; 869 enc_flag = 2;
843 else if (priv->encode_alg == IW_ENCODE_ALG_WEP) 870 else if (priv->encode_alg == ORINOCO_ALG_WEP)
844 enc_flag = 1; 871 enc_flag = 1;
845 else 872 else
846 enc_flag = 0; 873 enc_flag = 0;
847 874
848 switch (priv->firmware_type) { 875 switch (priv->firmware_type) {
849 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ 876 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
850 if (priv->encode_alg == IW_ENCODE_ALG_WEP) { 877 if (priv->encode_alg == ORINOCO_ALG_WEP) {
851 /* Enable the shared-key authentication. */ 878 /* Enable the shared-key authentication. */
852 err = hermes_write_wordrec(hw, USER_BAP, 879 err = hermes_write_wordrec(hw, USER_BAP,
853 HERMES_RID_CNFAUTHENTICATION_AGERE, 880 HERMES_RID_CNFAUTHENTICATION_AGERE,
@@ -872,7 +899,7 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
872 899
873 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ 900 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
874 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ 901 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
875 if (priv->encode_alg == IW_ENCODE_ALG_WEP) { 902 if (priv->encode_alg == ORINOCO_ALG_WEP) {
876 if (priv->wep_restrict || 903 if (priv->wep_restrict ||
877 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)) 904 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
878 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED | 905 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
@@ -905,19 +932,20 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
905} 932}
906 933
907/* key must be 32 bytes, including the tx and rx MIC keys. 934/* key must be 32 bytes, including the tx and rx MIC keys.
908 * rsc must be 8 bytes 935 * rsc must be NULL or up to 8 bytes
909 * tsc must be 8 bytes or NULL 936 * tsc must be NULL or up to 8 bytes
910 */ 937 */
911int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, 938int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
912 int set_tx, u8 *key, u8 *rsc, u8 *tsc) 939 int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
940 u8 *tsc, size_t tsc_len)
913{ 941{
914 struct { 942 struct {
915 __le16 idx; 943 __le16 idx;
916 u8 rsc[IW_ENCODE_SEQ_MAX_SIZE]; 944 u8 rsc[ORINOCO_SEQ_LEN];
917 u8 key[TKIP_KEYLEN]; 945 u8 key[TKIP_KEYLEN];
918 u8 tx_mic[MIC_KEYLEN]; 946 u8 tx_mic[MIC_KEYLEN];
919 u8 rx_mic[MIC_KEYLEN]; 947 u8 rx_mic[MIC_KEYLEN];
920 u8 tsc[IW_ENCODE_SEQ_MAX_SIZE]; 948 u8 tsc[ORINOCO_SEQ_LEN];
921 } __attribute__ ((packed)) buf; 949 } __attribute__ ((packed)) buf;
922 hermes_t *hw = &priv->hw; 950 hermes_t *hw = &priv->hw;
923 int ret; 951 int ret;
@@ -934,17 +962,22 @@ int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
934 memcpy(buf.key, key, 962 memcpy(buf.key, key,
935 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic)); 963 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
936 964
937 if (rsc == NULL) 965 if (rsc_len > sizeof(buf.rsc))
938 memset(buf.rsc, 0, sizeof(buf.rsc)); 966 rsc_len = sizeof(buf.rsc);
939 else
940 memcpy(buf.rsc, rsc, sizeof(buf.rsc));
941 967
942 if (tsc == NULL) { 968 if (tsc_len > sizeof(buf.tsc))
943 memset(buf.tsc, 0, sizeof(buf.tsc)); 969 tsc_len = sizeof(buf.tsc);
970
971 memset(buf.rsc, 0, sizeof(buf.rsc));
972 memset(buf.tsc, 0, sizeof(buf.tsc));
973
974 if (rsc != NULL)
975 memcpy(buf.rsc, rsc, rsc_len);
976
977 if (tsc != NULL)
978 memcpy(buf.tsc, tsc, tsc_len);
979 else
944 buf.tsc[4] = 0x10; 980 buf.tsc[4] = 0x10;
945 } else {
946 memcpy(buf.tsc, tsc, sizeof(buf.tsc));
947 }
948 981
949 /* Wait upto 100ms for tx queue to empty */ 982 /* Wait upto 100ms for tx queue to empty */
950 for (k = 100; k > 0; k--) { 983 for (k = 100; k > 0; k--) {
@@ -970,7 +1003,6 @@ int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
970 hermes_t *hw = &priv->hw; 1003 hermes_t *hw = &priv->hw;
971 int err; 1004 int err;
972 1005
973 memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
974 err = hermes_write_wordrec(hw, USER_BAP, 1006 err = hermes_write_wordrec(hw, USER_BAP,
975 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE, 1007 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
976 key_idx); 1008 key_idx);
@@ -1242,3 +1274,39 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
1242 1274
1243 return err; 1275 return err;
1244} 1276}
1277
1278/* Disassociate from node with BSSID addr */
1279int orinoco_hw_disassociate(struct orinoco_private *priv,
1280 u8 *addr, u16 reason_code)
1281{
1282 hermes_t *hw = &priv->hw;
1283 int err;
1284
1285 struct {
1286 u8 addr[ETH_ALEN];
1287 __le16 reason_code;
1288 } __attribute__ ((packed)) buf;
1289
1290 /* Currently only supported by WPA enabled Agere fw */
1291 if (!priv->has_wpa)
1292 return -EOPNOTSUPP;
1293
1294 memcpy(buf.addr, addr, ETH_ALEN);
1295 buf.reason_code = cpu_to_le16(reason_code);
1296 err = HERMES_WRITE_RECORD(hw, USER_BAP,
1297 HERMES_RID_CNFDISASSOCIATE,
1298 &buf);
1299 return err;
1300}
1301
1302int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
1303 u8 *addr)
1304{
1305 hermes_t *hw = &priv->hw;
1306 int err;
1307
1308 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1309 ETH_ALEN, NULL, addr);
1310
1311 return err;
1312}
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 27b427649d1b..8df6e8752be6 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -38,7 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv);
38int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); 38int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
39int __orinoco_hw_setup_enc(struct orinoco_private *priv); 39int __orinoco_hw_setup_enc(struct orinoco_private *priv);
40int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, 40int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
41 int set_tx, u8 *key, u8 *rsc, u8 *tsc); 41 int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
42 u8 *tsc, size_t tsc_len);
42int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); 43int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
43int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, 44int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
44 struct dev_addr_list *mc_list, 45 struct dev_addr_list *mc_list,
@@ -50,5 +51,9 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
50 int *numrates, s32 *rates, int max); 51 int *numrates, s32 *rates, int max);
51int orinoco_hw_trigger_scan(struct orinoco_private *priv, 52int orinoco_hw_trigger_scan(struct orinoco_private *priv,
52 const struct cfg80211_ssid *ssid); 53 const struct cfg80211_ssid *ssid);
54int orinoco_hw_disassociate(struct orinoco_private *priv,
55 u8 *addr, u16 reason_code);
56int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
57 u8 *addr);
53 58
54#endif /* _ORINOCO_HW_H_ */ 59#endif /* _ORINOCO_HW_H_ */
diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c
index e8c550a61f33..2c7dc65cd2be 100644
--- a/drivers/net/wireless/orinoco/main.c
+++ b/drivers/net/wireless/orinoco/main.c
@@ -341,12 +341,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
341{ 341{
342 struct orinoco_private *priv = ndev_priv(dev); 342 struct orinoco_private *priv = ndev_priv(dev);
343 struct net_device_stats *stats = &priv->stats; 343 struct net_device_stats *stats = &priv->stats;
344 struct orinoco_tkip_key *key;
344 hermes_t *hw = &priv->hw; 345 hermes_t *hw = &priv->hw;
345 int err = 0; 346 int err = 0;
346 u16 txfid = priv->txfid; 347 u16 txfid = priv->txfid;
347 struct ethhdr *eh; 348 struct ethhdr *eh;
348 int tx_control; 349 int tx_control;
349 unsigned long flags; 350 unsigned long flags;
351 int do_mic;
350 352
351 if (!netif_running(dev)) { 353 if (!netif_running(dev)) {
352 printk(KERN_ERR "%s: Tx on stopped device!\n", 354 printk(KERN_ERR "%s: Tx on stopped device!\n",
@@ -378,9 +380,14 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
378 if (skb->len < ETH_HLEN) 380 if (skb->len < ETH_HLEN)
379 goto drop; 381 goto drop;
380 382
383 key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key;
384
385 do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) &&
386 (key != NULL));
387
381 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; 388 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
382 389
383 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) 390 if (do_mic)
384 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | 391 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
385 HERMES_TXCTRL_MIC; 392 HERMES_TXCTRL_MIC;
386 393
@@ -462,7 +469,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
462 } 469 }
463 470
464 /* Calculate Michael MIC */ 471 /* Calculate Michael MIC */
465 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) { 472 if (do_mic) {
466 u8 mic_buf[MICHAEL_MIC_LEN + 1]; 473 u8 mic_buf[MICHAEL_MIC_LEN + 1];
467 u8 *mic; 474 u8 *mic;
468 size_t offset; 475 size_t offset;
@@ -480,8 +487,7 @@ static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
480 len = MICHAEL_MIC_LEN; 487 len = MICHAEL_MIC_LEN;
481 } 488 }
482 489
483 orinoco_mic(priv->tx_tfm_mic, 490 orinoco_mic(priv->tx_tfm_mic, key->tx_mic,
484 priv->tkip_key[priv->tx_key].tx_mic,
485 eh->h_dest, eh->h_source, 0 /* priority */, 491 eh->h_dest, eh->h_source, 0 /* priority */,
486 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); 492 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
487 493
@@ -926,6 +932,7 @@ static void orinoco_rx(struct net_device *dev,
926 932
927 /* Calculate and check MIC */ 933 /* Calculate and check MIC */
928 if (status & HERMES_RXSTAT_MIC) { 934 if (status & HERMES_RXSTAT_MIC) {
935 struct orinoco_tkip_key *key;
929 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >> 936 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
930 HERMES_MIC_KEY_ID_SHIFT); 937 HERMES_MIC_KEY_ID_SHIFT);
931 u8 mic[MICHAEL_MIC_LEN]; 938 u8 mic[MICHAEL_MIC_LEN];
@@ -939,14 +946,18 @@ static void orinoco_rx(struct net_device *dev,
939 skb_trim(skb, skb->len - MICHAEL_MIC_LEN); 946 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
940 length -= MICHAEL_MIC_LEN; 947 length -= MICHAEL_MIC_LEN;
941 948
942 orinoco_mic(priv->rx_tfm_mic, 949 key = (struct orinoco_tkip_key *) priv->keys[key_id].key;
943 priv->tkip_key[key_id].rx_mic, 950
944 desc->addr1, 951 if (!key) {
945 src, 952 printk(KERN_WARNING "%s: Received encrypted frame from "
953 "%pM using key %i, but key is not installed\n",
954 dev->name, src, key_id);
955 goto drop;
956 }
957
958 orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src,
946 0, /* priority or QoS? */ 959 0, /* priority or QoS? */
947 skb->data, 960 skb->data, skb->len, &mic[0]);
948 skb->len,
949 &mic[0]);
950 961
951 if (memcmp(mic, rxmic, 962 if (memcmp(mic, rxmic,
952 MICHAEL_MIC_LEN)) { 963 MICHAEL_MIC_LEN)) {
@@ -2040,7 +2051,7 @@ int orinoco_init(struct orinoco_private *priv)
2040 priv->channel = 0; /* use firmware default */ 2051 priv->channel = 0; /* use firmware default */
2041 2052
2042 priv->promiscuous = 0; 2053 priv->promiscuous = 0;
2043 priv->encode_alg = IW_ENCODE_ALG_NONE; 2054 priv->encode_alg = ORINOCO_ALG_NONE;
2044 priv->tx_key = 0; 2055 priv->tx_key = 0;
2045 priv->wpa_enabled = 0; 2056 priv->wpa_enabled = 0;
2046 priv->tkip_cm_active = 0; 2057 priv->tkip_cm_active = 0;
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 5f4f5c9eef79..9ac6f1dda4b0 100644
--- a/drivers/net/wireless/orinoco/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -25,6 +25,7 @@
25 25
26#define MAX_SCAN_LEN 4096 26#define MAX_SCAN_LEN 4096
27 27
28#define ORINOCO_SEQ_LEN 8
28#define ORINOCO_MAX_KEY_SIZE 14 29#define ORINOCO_MAX_KEY_SIZE 14
29#define ORINOCO_MAX_KEYS 4 30#define ORINOCO_MAX_KEYS 4
30 31
@@ -42,6 +43,12 @@ struct orinoco_tkip_key {
42 u8 rx_mic[MIC_KEYLEN]; 43 u8 rx_mic[MIC_KEYLEN];
43}; 44};
44 45
46enum orinoco_alg {
47 ORINOCO_ALG_NONE,
48 ORINOCO_ALG_WEP,
49 ORINOCO_ALG_TKIP
50};
51
45typedef enum { 52typedef enum {
46 FIRMWARE_TYPE_AGERE, 53 FIRMWARE_TYPE_AGERE,
47 FIRMWARE_TYPE_INTERSIL, 54 FIRMWARE_TYPE_INTERSIL,
@@ -107,12 +114,14 @@ struct orinoco_private {
107 unsigned int do_fw_download:1; 114 unsigned int do_fw_download:1;
108 unsigned int broken_disableport:1; 115 unsigned int broken_disableport:1;
109 unsigned int broken_monitor:1; 116 unsigned int broken_monitor:1;
117 unsigned int prefer_port3:1;
110 118
111 /* Configuration paramaters */ 119 /* Configuration paramaters */
112 enum nl80211_iftype iw_mode; 120 enum nl80211_iftype iw_mode;
113 int prefer_port3; 121 enum orinoco_alg encode_alg;
114 u16 encode_alg, wep_restrict, tx_key; 122 u16 wep_restrict, tx_key;
115 struct orinoco_key keys[ORINOCO_MAX_KEYS]; 123 struct key_params keys[ORINOCO_MAX_KEYS];
124
116 int bitratemode; 125 int bitratemode;
117 char nick[IW_ESSID_MAX_SIZE+1]; 126 char nick[IW_ESSID_MAX_SIZE+1];
118 char desired_essid[IW_ESSID_MAX_SIZE+1]; 127 char desired_essid[IW_ESSID_MAX_SIZE+1];
@@ -142,7 +151,6 @@ struct orinoco_private {
142 u8 *wpa_ie; 151 u8 *wpa_ie;
143 int wpa_ie_len; 152 int wpa_ie_len;
144 153
145 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
146 struct crypto_hash *rx_tfm_mic; 154 struct crypto_hash *rx_tfm_mic;
147 struct crypto_hash *tx_tfm_mic; 155 struct crypto_hash *tx_tfm_mic;
148 156
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index b6ff3dbb7dd6..3e56f7643df5 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -22,6 +22,67 @@
22 22
23#define MAX_RID_LEN 1024 23#define MAX_RID_LEN 1024
24 24
25/* Helper routine to record keys
26 * Do not call from interrupt context */
27static int orinoco_set_key(struct orinoco_private *priv, int index,
28 enum orinoco_alg alg, const u8 *key, int key_len,
29 const u8 *seq, int seq_len)
30{
31 kzfree(priv->keys[index].key);
32 kzfree(priv->keys[index].seq);
33
34 if (key_len) {
35 priv->keys[index].key = kzalloc(key_len, GFP_KERNEL);
36 if (!priv->keys[index].key)
37 goto nomem;
38 } else
39 priv->keys[index].key = NULL;
40
41 if (seq_len) {
42 priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL);
43 if (!priv->keys[index].seq)
44 goto free_key;
45 } else
46 priv->keys[index].seq = NULL;
47
48 priv->keys[index].key_len = key_len;
49 priv->keys[index].seq_len = seq_len;
50
51 if (key_len)
52 memcpy(priv->keys[index].key, key, key_len);
53 if (seq_len)
54 memcpy(priv->keys[index].seq, seq, seq_len);
55
56 switch (alg) {
57 case ORINOCO_ALG_TKIP:
58 priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
59 break;
60
61 case ORINOCO_ALG_WEP:
62 priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
63 WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
64 break;
65
66 case ORINOCO_ALG_NONE:
67 default:
68 priv->keys[index].cipher = 0;
69 break;
70 }
71
72 return 0;
73
74free_key:
75 kfree(priv->keys[index].key);
76 priv->keys[index].key = NULL;
77
78nomem:
79 priv->keys[index].key_len = 0;
80 priv->keys[index].seq_len = 0;
81 priv->keys[index].cipher = 0;
82
83 return -ENOMEM;
84}
85
25static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) 86static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
26{ 87{
27 struct orinoco_private *priv = ndev_priv(dev); 88 struct orinoco_private *priv = ndev_priv(dev);
@@ -156,7 +217,6 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
156{ 217{
157 struct orinoco_private *priv = ndev_priv(dev); 218 struct orinoco_private *priv = ndev_priv(dev);
158 219
159 hermes_t *hw = &priv->hw;
160 int err = 0; 220 int err = 0;
161 unsigned long flags; 221 unsigned long flags;
162 222
@@ -164,8 +224,7 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
164 return -EBUSY; 224 return -EBUSY;
165 225
166 ap_addr->sa_family = ARPHRD_ETHER; 226 ap_addr->sa_family = ARPHRD_ETHER;
167 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, 227 err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
168 ETH_ALEN, NULL, ap_addr->sa_data);
169 228
170 orinoco_unlock(priv, &flags); 229 orinoco_unlock(priv, &flags);
171 230
@@ -180,9 +239,8 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
180 struct orinoco_private *priv = ndev_priv(dev); 239 struct orinoco_private *priv = ndev_priv(dev);
181 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 240 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
182 int setindex = priv->tx_key; 241 int setindex = priv->tx_key;
183 int encode_alg = priv->encode_alg; 242 enum orinoco_alg encode_alg = priv->encode_alg;
184 int restricted = priv->wep_restrict; 243 int restricted = priv->wep_restrict;
185 u16 xlen = 0;
186 int err = -EINPROGRESS; /* Call commit handler */ 244 int err = -EINPROGRESS; /* Call commit handler */
187 unsigned long flags; 245 unsigned long flags;
188 246
@@ -202,25 +260,17 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
202 return -EBUSY; 260 return -EBUSY;
203 261
204 /* Clear any TKIP key we have */ 262 /* Clear any TKIP key we have */
205 if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP)) 263 if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
206 (void) orinoco_clear_tkip_key(priv, setindex); 264 (void) orinoco_clear_tkip_key(priv, setindex);
207 265
208 if (erq->length > 0) { 266 if (erq->length > 0) {
209 if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) 267 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
210 index = priv->tx_key; 268 index = priv->tx_key;
211 269
212 /* Adjust key length to a supported value */
213 if (erq->length > SMALL_KEY_SIZE)
214 xlen = LARGE_KEY_SIZE;
215 else if (erq->length > 0)
216 xlen = SMALL_KEY_SIZE;
217 else
218 xlen = 0;
219
220 /* Switch on WEP if off */ 270 /* Switch on WEP if off */
221 if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) { 271 if (encode_alg != ORINOCO_ALG_WEP) {
222 setindex = index; 272 setindex = index;
223 encode_alg = IW_ENCODE_ALG_WEP; 273 encode_alg = ORINOCO_ALG_WEP;
224 } 274 }
225 } else { 275 } else {
226 /* Important note : if the user do "iwconfig eth0 enc off", 276 /* Important note : if the user do "iwconfig eth0 enc off",
@@ -233,7 +283,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
233 } 283 }
234 } else { 284 } else {
235 /* Set the index : Check that the key is valid */ 285 /* Set the index : Check that the key is valid */
236 if (priv->keys[index].len == 0) { 286 if (priv->keys[index].key_len == 0) {
237 err = -EINVAL; 287 err = -EINVAL;
238 goto out; 288 goto out;
239 } 289 }
@@ -242,17 +292,15 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
242 } 292 }
243 293
244 if (erq->flags & IW_ENCODE_DISABLED) 294 if (erq->flags & IW_ENCODE_DISABLED)
245 encode_alg = IW_ENCODE_ALG_NONE; 295 encode_alg = ORINOCO_ALG_NONE;
246 if (erq->flags & IW_ENCODE_OPEN) 296 if (erq->flags & IW_ENCODE_OPEN)
247 restricted = 0; 297 restricted = 0;
248 if (erq->flags & IW_ENCODE_RESTRICTED) 298 if (erq->flags & IW_ENCODE_RESTRICTED)
249 restricted = 1; 299 restricted = 1;
250 300
251 if (erq->pointer && erq->length > 0) { 301 if (erq->pointer && erq->length > 0) {
252 priv->keys[index].len = cpu_to_le16(xlen); 302 err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
253 memset(priv->keys[index].data, 0, 303 erq->length, NULL, 0);
254 sizeof(priv->keys[index].data));
255 memcpy(priv->keys[index].data, keybuf, erq->length);
256 } 304 }
257 priv->tx_key = setindex; 305 priv->tx_key = setindex;
258 306
@@ -281,7 +329,6 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
281{ 329{
282 struct orinoco_private *priv = ndev_priv(dev); 330 struct orinoco_private *priv = ndev_priv(dev);
283 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 331 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
284 u16 xlen = 0;
285 unsigned long flags; 332 unsigned long flags;
286 333
287 if (!priv->has_wep) 334 if (!priv->has_wep)
@@ -303,11 +350,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
303 else 350 else
304 erq->flags |= IW_ENCODE_OPEN; 351 erq->flags |= IW_ENCODE_OPEN;
305 352
306 xlen = le16_to_cpu(priv->keys[index].len); 353 erq->length = priv->keys[index].key_len;
307 354
308 erq->length = xlen; 355 memcpy(keybuf, priv->keys[index].key, erq->length);
309
310 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
311 356
312 orinoco_unlock(priv, &flags); 357 orinoco_unlock(priv, &flags);
313 return 0; 358 return 0;
@@ -793,7 +838,6 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
793 int idx, alg = ext->alg, set_key = 1; 838 int idx, alg = ext->alg, set_key = 1;
794 unsigned long flags; 839 unsigned long flags;
795 int err = -EINVAL; 840 int err = -EINVAL;
796 u16 key_len;
797 841
798 if (orinoco_lock(priv, &flags) != 0) 842 if (orinoco_lock(priv, &flags) != 0)
799 return -EBUSY; 843 return -EBUSY;
@@ -825,25 +869,18 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
825 /* Set the requested key first */ 869 /* Set the requested key first */
826 switch (alg) { 870 switch (alg) {
827 case IW_ENCODE_ALG_NONE: 871 case IW_ENCODE_ALG_NONE:
828 priv->encode_alg = alg; 872 priv->encode_alg = ORINOCO_ALG_NONE;
829 priv->keys[idx].len = 0; 873 err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
874 NULL, 0, NULL, 0);
830 break; 875 break;
831 876
832 case IW_ENCODE_ALG_WEP: 877 case IW_ENCODE_ALG_WEP:
833 if (ext->key_len > SMALL_KEY_SIZE) 878 if (ext->key_len <= 0)
834 key_len = LARGE_KEY_SIZE;
835 else if (ext->key_len > 0)
836 key_len = SMALL_KEY_SIZE;
837 else
838 goto out; 879 goto out;
839 880
840 priv->encode_alg = alg; 881 priv->encode_alg = ORINOCO_ALG_WEP;
841 priv->keys[idx].len = cpu_to_le16(key_len); 882 err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
842 883 ext->key, ext->key_len, NULL, 0);
843 key_len = min(ext->key_len, key_len);
844
845 memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
846 memcpy(priv->keys[idx].data, ext->key, key_len);
847 break; 884 break;
848 885
849 case IW_ENCODE_ALG_TKIP: 886 case IW_ENCODE_ALG_TKIP:
@@ -851,21 +888,22 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
851 u8 *tkip_iv = NULL; 888 u8 *tkip_iv = NULL;
852 889
853 if (!priv->has_wpa || 890 if (!priv->has_wpa ||
854 (ext->key_len > sizeof(priv->tkip_key[0]))) 891 (ext->key_len > sizeof(struct orinoco_tkip_key)))
855 goto out; 892 goto out;
856 893
857 priv->encode_alg = alg; 894 priv->encode_alg = ORINOCO_ALG_TKIP;
858 memset(&priv->tkip_key[idx], 0,
859 sizeof(priv->tkip_key[idx]));
860 memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
861 895
862 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) 896 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
863 tkip_iv = &ext->rx_seq[0]; 897 tkip_iv = &ext->rx_seq[0];
864 898
899 err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
900 ext->key, ext->key_len, tkip_iv,
901 ORINOCO_SEQ_LEN);
902
865 err = __orinoco_hw_set_tkip_key(priv, idx, 903 err = __orinoco_hw_set_tkip_key(priv, idx,
866 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, 904 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
867 (u8 *) &priv->tkip_key[idx], 905 priv->keys[idx].key,
868 tkip_iv, NULL); 906 tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
869 if (err) 907 if (err)
870 printk(KERN_ERR "%s: Error %d setting TKIP key" 908 printk(KERN_ERR "%s: Error %d setting TKIP key"
871 "\n", dev->name, err); 909 "\n", dev->name, err);
@@ -914,22 +952,22 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
914 encoding->flags = idx + 1; 952 encoding->flags = idx + 1;
915 memset(ext, 0, sizeof(*ext)); 953 memset(ext, 0, sizeof(*ext));
916 954
917 ext->alg = priv->encode_alg;
918 switch (priv->encode_alg) { 955 switch (priv->encode_alg) {
919 case IW_ENCODE_ALG_NONE: 956 case ORINOCO_ALG_NONE:
957 ext->alg = IW_ENCODE_ALG_NONE;
920 ext->key_len = 0; 958 ext->key_len = 0;
921 encoding->flags |= IW_ENCODE_DISABLED; 959 encoding->flags |= IW_ENCODE_DISABLED;
922 break; 960 break;
923 case IW_ENCODE_ALG_WEP: 961 case ORINOCO_ALG_WEP:
924 ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len), 962 ext->alg = IW_ENCODE_ALG_WEP;
925 max_key_len); 963 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
926 memcpy(ext->key, priv->keys[idx].data, ext->key_len); 964 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
927 encoding->flags |= IW_ENCODE_ENABLED; 965 encoding->flags |= IW_ENCODE_ENABLED;
928 break; 966 break;
929 case IW_ENCODE_ALG_TKIP: 967 case ORINOCO_ALG_TKIP:
930 ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key), 968 ext->alg = IW_ENCODE_ALG_TKIP;
931 max_key_len); 969 ext->key_len = min(priv->keys[idx].key_len, max_key_len);
932 memcpy(ext->key, &priv->tkip_key[idx], ext->key_len); 970 memcpy(ext->key, priv->keys[idx].key, ext->key_len);
933 encoding->flags |= IW_ENCODE_ENABLED; 971 encoding->flags |= IW_ENCODE_ENABLED;
934 break; 972 break;
935 } 973 }
@@ -1136,7 +1174,6 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
1136 union iwreq_data *wrqu, char *extra) 1174 union iwreq_data *wrqu, char *extra)
1137{ 1175{
1138 struct orinoco_private *priv = ndev_priv(dev); 1176 struct orinoco_private *priv = ndev_priv(dev);
1139 hermes_t *hw = &priv->hw;
1140 struct iw_mlme *mlme = (struct iw_mlme *)extra; 1177 struct iw_mlme *mlme = (struct iw_mlme *)extra;
1141 unsigned long flags; 1178 unsigned long flags;
1142 int ret = 0; 1179 int ret = 0;
@@ -1150,19 +1187,11 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
1150 break; 1187 break;
1151 1188
1152 case IW_MLME_DISASSOC: 1189 case IW_MLME_DISASSOC:
1153 { 1190
1154 struct { 1191 ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
1155 u8 addr[ETH_ALEN]; 1192 mlme->reason_code);
1156 __le16 reason_code;
1157 } __attribute__ ((packed)) buf;
1158
1159 memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
1160 buf.reason_code = cpu_to_le16(mlme->reason_code);
1161 ret = HERMES_WRITE_RECORD(hw, USER_BAP,
1162 HERMES_RID_CNFDISASSOCIATE,
1163 &buf);
1164 break; 1193 break;
1165 } 1194
1166 default: 1195 default:
1167 ret = -EOPNOTSUPP; 1196 ret = -EOPNOTSUPP;
1168 } 1197 }
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index 21f19018fab5..e7b9e9cb39f5 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -320,7 +320,7 @@ int p54_setup_mac(struct p54_common *priv)
320 return -ENOMEM; 320 return -ENOMEM;
321 321
322 setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup)); 322 setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
323 if (priv->hw->conf.radio_enabled) { 323 if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) {
324 switch (priv->mode) { 324 switch (priv->mode) {
325 case NL80211_IFTYPE_STATION: 325 case NL80211_IFTYPE_STATION:
326 mode = P54_FILTER_TYPE_STATION; 326 mode = P54_FILTER_TYPE_STATION;
@@ -348,8 +348,9 @@ int p54_setup_mac(struct p54_common *priv)
348 (priv->filter_flags & FIF_OTHER_BSS)) && 348 (priv->filter_flags & FIF_OTHER_BSS)) &&
349 (mode != P54_FILTER_TYPE_PROMISCUOUS)) 349 (mode != P54_FILTER_TYPE_PROMISCUOUS))
350 mode |= P54_FILTER_TYPE_TRANSPARENT; 350 mode |= P54_FILTER_TYPE_TRANSPARENT;
351 } else 351 } else {
352 mode = P54_FILTER_TYPE_HIBERNATE; 352 mode = P54_FILTER_TYPE_HIBERNATE;
353 }
353 354
354 setup->mac_mode = cpu_to_le16(mode); 355 setup->mac_mode = cpu_to_le16(mode);
355 memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); 356 memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index a0d0e726bc4e..4a741df9c081 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -288,6 +288,11 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed)
288 if (ret) 288 if (ret)
289 goto out; 289 goto out;
290 } 290 }
291 if (changed & IEEE80211_CONF_CHANGE_IDLE) {
292 ret = p54_setup_mac(priv);
293 if (ret)
294 goto out;
295 }
291 296
292out: 297out:
293 mutex_unlock(&priv->conf_mutex); 298 mutex_unlock(&priv->conf_mutex);
@@ -317,7 +322,7 @@ static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
317 int ret; 322 int ret;
318 323
319 mutex_lock(&priv->conf_mutex); 324 mutex_lock(&priv->conf_mutex);
320 if ((params) && !(queue > 4)) { 325 if (queue < dev->queues) {
321 P54_SET_QUEUE(priv->qos_params[queue], params->aifs, 326 P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
322 params->cw_min, params->cw_max, params->txop); 327 params->cw_min, params->cw_max, params->txop);
323 ret = p54_set_edcf(priv); 328 ret = p54_set_edcf(priv);
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 704685fab177..6fc0b6148c8a 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -552,6 +552,12 @@ static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb)
552 break; 552 break;
553 case P54_TRAP_TIMER: 553 case P54_TRAP_TIMER:
554 break; 554 break;
555 case P54_TRAP_FAA_RADIO_OFF:
556 wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
557 break;
558 case P54_TRAP_FAA_RADIO_ON:
559 wiphy_rfkill_set_hw_state(priv->hw->wiphy, false);
560 break;
555 default: 561 default:
556 printk(KERN_INFO "%s: received event:%x freq:%d\n", 562 printk(KERN_INFO "%s: received event:%x freq:%d\n",
557 wiphy_name(priv->hw->wiphy), event, freq); 563 wiphy_name(priv->hw->wiphy), event, freq);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 828dc1825bba..d42692dfbc67 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -1764,8 +1764,15 @@ static int rndis_iw_set_essid(struct net_device *dev,
1764 1764
1765 if (!wrqu->essid.flags || length == 0) 1765 if (!wrqu->essid.flags || length == 0)
1766 return disassociate(usbdev, 1); 1766 return disassociate(usbdev, 1);
1767 else 1767 else {
1768 /* Pause and purge rx queue, so we don't pass packets before
1769 * 'media connect'-indication.
1770 */
1771 usbnet_pause_rx(usbdev);
1772 usbnet_purge_paused_rxq(usbdev);
1773
1768 return set_essid(usbdev, &ssid); 1774 return set_essid(usbdev, &ssid);
1775 }
1769} 1776}
1770 1777
1771 1778
@@ -2328,6 +2335,8 @@ get_bssid:
2328 memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN); 2335 memcpy(evt.ap_addr.sa_data, bssid, ETH_ALEN);
2329 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); 2336 wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL);
2330 } 2337 }
2338
2339 usbnet_resume_rx(usbdev);
2331 } 2340 }
2332 2341
2333 if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) { 2342 if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) {
@@ -2541,6 +2550,8 @@ static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen)
2541 2550
2542 switch (msg->status) { 2551 switch (msg->status) {
2543 case RNDIS_STATUS_MEDIA_CONNECT: 2552 case RNDIS_STATUS_MEDIA_CONNECT:
2553 usbnet_pause_rx(usbdev);
2554
2544 devinfo(usbdev, "media connect"); 2555 devinfo(usbdev, "media connect");
2545 2556
2546 /* queue work to avoid recursive calls into rndis_command */ 2557 /* queue work to avoid recursive calls into rndis_command */
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 30185ad28d93..164df9347a2f 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1069,8 +1069,6 @@ static void rt2400pci_write_beacon(struct queue_entry *entry)
1069 * otherwise we might be sending out invalid data. 1069 * otherwise we might be sending out invalid data.
1070 */ 1070 */
1071 rt2x00pci_register_read(rt2x00dev, CSR14, &reg); 1071 rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
1072 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
1073 rt2x00_set_field32(&reg, CSR14_TBCN, 0);
1074 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0); 1072 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
1075 rt2x00pci_register_write(rt2x00dev, CSR14, reg); 1073 rt2x00pci_register_write(rt2x00dev, CSR14, reg);
1076 1074
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 3b3171578b14..4186582f2770 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1227,8 +1227,6 @@ static void rt2500pci_write_beacon(struct queue_entry *entry)
1227 * otherwise we might be sending out invalid data. 1227 * otherwise we might be sending out invalid data.
1228 */ 1228 */
1229 rt2x00pci_register_read(rt2x00dev, CSR14, &reg); 1229 rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
1230 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
1231 rt2x00_set_field32(&reg, CSR14_TBCN, 0);
1232 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0); 1230 rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
1233 rt2x00pci_register_write(rt2x00dev, CSR14, reg); 1231 rt2x00pci_register_write(rt2x00dev, CSR14, reg);
1234 1232
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index de48c5c68eff..09a589432dab 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1238,8 +1238,6 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
1238 * otherwise we might be sending out invalid data. 1238 * otherwise we might be sending out invalid data.
1239 */ 1239 */
1240 rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg); 1240 rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
1241 rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
1242 rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
1243 rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0); 1241 rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
1244 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 1242 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
1245 1243
@@ -1287,7 +1285,7 @@ static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
1287static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, 1285static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
1288 const enum data_queue_qid queue) 1286 const enum data_queue_qid queue)
1289{ 1287{
1290 u16 reg; 1288 u16 reg, reg0;
1291 1289
1292 if (queue != QID_BEACON) { 1290 if (queue != QID_BEACON) {
1293 rt2x00usb_kick_tx_queue(rt2x00dev, queue); 1291 rt2x00usb_kick_tx_queue(rt2x00dev, queue);
@@ -1298,16 +1296,19 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
1298 if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { 1296 if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) {
1299 rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1); 1297 rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
1300 rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1); 1298 rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
1299 reg0 = reg;
1301 rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1); 1300 rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 1);
1302 /* 1301 /*
1303 * Beacon generation will fail initially. 1302 * Beacon generation will fail initially.
1304 * To prevent this we need to register the TXRX_CSR19 1303 * To prevent this we need to change the TXRX_CSR19
1305 * register several times. 1304 * register several times (reg0 is the same as reg
1305 * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0
1306 * and 1 in reg).
1306 */ 1307 */
1307 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 1308 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
1308 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); 1309 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
1309 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 1310 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
1310 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); 1311 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0);
1311 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); 1312 rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
1312 } 1313 }
1313} 1314}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 9efb41710508..3856f06fdca7 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -518,7 +518,7 @@ static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev,
518 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS, 518 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_RTS,
519 !(filter_flags & FIF_CONTROL)); 519 !(filter_flags & FIF_CONTROL));
520 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL, 520 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_PSPOLL,
521 !(filter_flags & FIF_CONTROL)); 521 !(filter_flags & FIF_PSPOLL));
522 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1); 522 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BA, 1);
523 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0); 523 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_BAR, 0);
524 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL, 524 rt2x00_set_field32(&reg, RX_FILTER_CFG_DROP_CNTL,
@@ -2050,8 +2050,6 @@ static void rt2800usb_write_beacon(struct queue_entry *entry)
2050 * otherwise we might be sending out invalid data. 2050 * otherwise we might be sending out invalid data.
2051 */ 2051 */
2052 rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg); 2052 rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
2053 rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 0);
2054 rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
2055 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0); 2053 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
2056 rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); 2054 rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
2057 2055
@@ -2624,6 +2622,13 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
2624 return retval; 2622 return retval;
2625 2623
2626 /* 2624 /*
2625 * This device has multiple filters for control frames
2626 * and has a separate filter for PS Poll frames.
2627 */
2628 __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
2629 __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
2630
2631 /*
2627 * This device requires firmware. 2632 * This device requires firmware.
2628 */ 2633 */
2629 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); 2634 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index cbec91ef6f76..5bc100db28d4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -134,6 +134,17 @@
134 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) 134 GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
135 135
136/* 136/*
137 * Structure for average calculation
138 * The avg field contains the actual average value,
139 * but avg_weight is internally used during calculations
140 * to prevent rounding errors.
141 */
142struct avg_val {
143 int avg;
144 int avg_weight;
145};
146
147/*
137 * Chipset identification 148 * Chipset identification
138 * The chipset on the device is composed of a RT and RF chip. 149 * The chipset on the device is composed of a RT and RF chip.
139 * The chipset combination is important for determining device capabilities. 150 * The chipset combination is important for determining device capabilities.
@@ -245,21 +256,18 @@ struct link_ant {
245 struct antenna_setup active; 256 struct antenna_setup active;
246 257
247 /* 258 /*
248 * RSSI information for the different antennas. 259 * RSSI history information for the antenna.
249 * These statistics are used to determine when 260 * Used to determine when to switch antenna
250 * to switch antenna when using software diversity. 261 * when using software diversity.
251 *
252 * rssi[0] -> Antenna A RSSI
253 * rssi[1] -> Antenna B RSSI
254 */ 262 */
255 int rssi_history[2]; 263 int rssi_history;
256 264
257 /* 265 /*
258 * Current RSSI average of the currently active antenna. 266 * Current RSSI average of the currently active antenna.
259 * Similar to the avg_rssi in the link_qual structure 267 * Similar to the avg_rssi in the link_qual structure
260 * this value is updated by using the walking average. 268 * this value is updated by using the walking average.
261 */ 269 */
262 int rssi_ant; 270 struct avg_val rssi_ant;
263}; 271};
264 272
265/* 273/*
@@ -288,7 +296,7 @@ struct link {
288 /* 296 /*
289 * Currently active average RSSI value 297 * Currently active average RSSI value
290 */ 298 */
291 int avg_rssi; 299 struct avg_val avg_rssi;
292 300
293 /* 301 /*
294 * Currently precalculated percentages of successful 302 * Currently precalculated percentages of successful
@@ -326,6 +334,11 @@ struct rt2x00_intf {
326 u8 bssid[ETH_ALEN]; 334 u8 bssid[ETH_ALEN];
327 335
328 /* 336 /*
337 * beacon->skb must be protected with the mutex.
338 */
339 struct mutex beacon_skb_mutex;
340
341 /*
329 * Entry in the beacon queue which belongs to 342 * Entry in the beacon queue which belongs to
330 * this interface. Each interface has its own 343 * this interface. Each interface has its own
331 * dedicated beacon entry. 344 * dedicated beacon entry.
@@ -611,6 +624,8 @@ enum rt2x00_flags {
611 */ 624 */
612 CONFIG_SUPPORT_HW_BUTTON, 625 CONFIG_SUPPORT_HW_BUTTON,
613 CONFIG_SUPPORT_HW_CRYPTO, 626 CONFIG_SUPPORT_HW_CRYPTO,
627 DRIVER_SUPPORT_CONTROL_FILTERS,
628 DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
614 629
615 /* 630 /*
616 * Driver configuration 631 * Driver configuration
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 3845316ccd39..3501788ab498 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -124,8 +124,9 @@ enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
124} 124}
125 125
126void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, 126void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
127 struct antenna_setup ant) 127 struct antenna_setup config)
128{ 128{
129 struct link_ant *ant = &rt2x00dev->link.ant;
129 struct antenna_setup *def = &rt2x00dev->default_ant; 130 struct antenna_setup *def = &rt2x00dev->default_ant;
130 struct antenna_setup *active = &rt2x00dev->link.ant.active; 131 struct antenna_setup *active = &rt2x00dev->link.ant.active;
131 132
@@ -134,14 +135,23 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
134 * ANTENNA_SW_DIVERSITY state to the driver. 135 * ANTENNA_SW_DIVERSITY state to the driver.
135 * If that happens, fallback to hardware defaults, 136 * If that happens, fallback to hardware defaults,
136 * or our own default. 137 * or our own default.
138 * If diversity handling is active for a particular antenna,
139 * we shouldn't overwrite that antenna.
137 * The calls to rt2x00lib_config_antenna_check() 140 * The calls to rt2x00lib_config_antenna_check()
138 * might have caused that we restore back to the already 141 * might have caused that we restore back to the already
139 * active setting. If that has happened we can quit. 142 * active setting. If that has happened we can quit.
140 */ 143 */
141 ant.rx = rt2x00lib_config_antenna_check(ant.rx, def->rx); 144 if (!(ant->flags & ANTENNA_RX_DIVERSITY))
142 ant.tx = rt2x00lib_config_antenna_check(ant.tx, def->tx); 145 config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
146 else
147 config.rx = active->rx;
143 148
144 if (ant.rx == active->rx && ant.tx == active->tx) 149 if (!(ant->flags & ANTENNA_TX_DIVERSITY))
150 config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx);
151 else
152 config.tx = active->tx;
153
154 if (config.rx == active->rx && config.tx == active->tx)
145 return; 155 return;
146 156
147 /* 157 /*
@@ -156,11 +166,11 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
156 * The latter is required since we need to recalibrate the 166 * The latter is required since we need to recalibrate the
157 * noise-sensitivity ratio for the new setup. 167 * noise-sensitivity ratio for the new setup.
158 */ 168 */
159 rt2x00dev->ops->lib->config_ant(rt2x00dev, &ant); 169 rt2x00dev->ops->lib->config_ant(rt2x00dev, &config);
160 170
161 rt2x00link_reset_tuner(rt2x00dev, true); 171 rt2x00link_reset_tuner(rt2x00dev, true);
162 172
163 memcpy(active, &ant, sizeof(ant)); 173 memcpy(active, &config, sizeof(config));
164 174
165 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 175 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
166 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); 176 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index db54fcc94c8f..b6676c6722fc 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -186,7 +186,6 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work)
186static void rt2x00lib_beacondone_iter(void *data, u8 *mac, 186static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
187 struct ieee80211_vif *vif) 187 struct ieee80211_vif *vif)
188{ 188{
189 struct rt2x00_dev *rt2x00dev = data;
190 struct rt2x00_intf *intf = vif_to_intf(vif); 189 struct rt2x00_intf *intf = vif_to_intf(vif);
191 190
192 if (vif->type != NL80211_IFTYPE_AP && 191 if (vif->type != NL80211_IFTYPE_AP &&
@@ -195,12 +194,6 @@ static void rt2x00lib_beacondone_iter(void *data, u8 *mac,
195 vif->type != NL80211_IFTYPE_WDS) 194 vif->type != NL80211_IFTYPE_WDS)
196 return; 195 return;
197 196
198 /*
199 * Clean up the beacon skb.
200 */
201 rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
202 intf->beacon->skb = NULL;
203
204 spin_lock(&intf->lock); 197 spin_lock(&intf->lock);
205 intf->delayed_flags |= DELAYED_UPDATE_BEACON; 198 intf->delayed_flags |= DELAYED_UPDATE_BEACON;
206 spin_unlock(&intf->lock); 199 spin_unlock(&intf->lock);
@@ -785,6 +778,13 @@ int rt2x00lib_start(struct rt2x00_dev *rt2x00dev)
785 rt2x00dev->intf_sta_count = 0; 778 rt2x00dev->intf_sta_count = 0;
786 rt2x00dev->intf_associated = 0; 779 rt2x00dev->intf_associated = 0;
787 780
781 /* Enable the radio */
782 retval = rt2x00lib_enable_radio(rt2x00dev);
783 if (retval) {
784 rt2x00queue_uninitialize(rt2x00dev);
785 return retval;
786 }
787
788 set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); 788 set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags);
789 789
790 return 0; 790 return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index 917831689ccd..c64db0ba7f40 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -46,7 +46,15 @@
46#define DEFAULT_PERCENTAGE 50 46#define DEFAULT_PERCENTAGE 50
47 47
48/* 48/*
49 * Small helper macro to work with moving/walking averages. 49 * Small helper macro for percentage calculation
50 * This is a very simple macro with the only catch that it will
51 * produce a default value in case no total value was provided.
52 */
53#define PERCENTAGE(__value, __total) \
54 ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
55
56/*
57 * Helper struct and macro to work with moving/walking averages.
50 * When adding a value to the average value the following calculation 58 * When adding a value to the average value the following calculation
51 * is needed: 59 * is needed:
52 * 60 *
@@ -60,18 +68,28 @@
60 * for a few minutes but when the device is moved away from the AP 68 * for a few minutes but when the device is moved away from the AP
61 * the average will not decrease fast enough to compensate. 69 * the average will not decrease fast enough to compensate.
62 * The walking average compensates this and will move towards 70 * The walking average compensates this and will move towards
63 * the new values correctly allowing a effective link tuning. 71 * the new values correctly allowing a effective link tuning,
64 */ 72 * the speed of the average moving towards other values depends
65#define MOVING_AVERAGE(__avg, __val, __samples) \ 73 * on the value for the number of samples. The higher the number
66 ( (((__avg) * ((__samples) - 1)) + (__val)) / (__samples) ) 74 * of samples, the slower the average will move.
67 75 * We use two variables to keep track of the average value to
68/* 76 * compensate for the rounding errors. This can be a significant
69 * Small helper macro for percentage calculation 77 * error (>5dBm) if the factor is too low.
70 * This is a very simple macro with the only catch that it will
71 * produce a default value in case no total value was provided.
72 */ 78 */
73#define PERCENTAGE(__value, __total) \ 79#define AVG_SAMPLES 8
74 ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) 80#define AVG_FACTOR 1000
81#define MOVING_AVERAGE(__avg, __val) \
82({ \
83 struct avg_val __new; \
84 __new.avg_weight = \
85 (__avg).avg_weight ? \
86 ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \
87 ((__val) * (AVG_FACTOR))) / \
88 (AVG_SAMPLES) ) : \
89 ((__val) * (AVG_FACTOR)); \
90 __new.avg = __new.avg_weight / (AVG_FACTOR); \
91 __new; \
92})
75 93
76/* 94/*
77 * For calculating the Signal quality we have determined 95 * For calculating the Signal quality we have determined
@@ -98,56 +116,41 @@ static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
98{ 116{
99 struct link_ant *ant = &rt2x00dev->link.ant; 117 struct link_ant *ant = &rt2x00dev->link.ant;
100 118
101 if (ant->rssi_ant && rt2x00dev->link.qual.rx_success) 119 if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success)
102 return ant->rssi_ant; 120 return ant->rssi_ant.avg;
103 return DEFAULT_RSSI; 121 return DEFAULT_RSSI;
104} 122}
105 123
106static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev, 124static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev)
107 enum antenna antenna)
108{ 125{
109 struct link_ant *ant = &rt2x00dev->link.ant; 126 struct link_ant *ant = &rt2x00dev->link.ant;
110 127
111 if (ant->rssi_history[antenna - ANTENNA_A]) 128 if (ant->rssi_history)
112 return ant->rssi_history[antenna - ANTENNA_A]; 129 return ant->rssi_history;
113 return DEFAULT_RSSI; 130 return DEFAULT_RSSI;
114} 131}
115/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
116#define rt2x00link_antenna_get_rssi_rx_history(__dev) \
117 rt2x00link_antenna_get_rssi_history((__dev), \
118 (__dev)->link.ant.active.rx)
119#define rt2x00link_antenna_get_rssi_tx_history(__dev) \
120 rt2x00link_antenna_get_rssi_history((__dev), \
121 (__dev)->link.ant.active.tx)
122 132
123static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, 133static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev,
124 enum antenna antenna,
125 int rssi) 134 int rssi)
126{ 135{
127 struct link_ant *ant = &rt2x00dev->link.ant; 136 struct link_ant *ant = &rt2x00dev->link.ant;
128 ant->rssi_history[ant->active.rx - ANTENNA_A] = rssi; 137 ant->rssi_history = rssi;
129} 138}
130/* Small wrapper for rt2x00link_antenna_get_rssi_history() */
131#define rt2x00link_antenna_update_rssi_rx_history(__dev, __rssi) \
132 rt2x00link_antenna_update_rssi_history((__dev), \
133 (__dev)->link.ant.active.rx, \
134 (__rssi))
135#define rt2x00link_antenna_update_rssi_tx_history(__dev, __rssi) \
136 rt2x00link_antenna_update_rssi_history((__dev), \
137 (__dev)->link.ant.active.tx, \
138 (__rssi))
139 139
140static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) 140static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev)
141{ 141{
142 rt2x00dev->link.ant.rssi_ant = 0; 142 rt2x00dev->link.ant.rssi_ant.avg = 0;
143 rt2x00dev->link.ant.rssi_ant.avg_weight = 0;
143} 144}
144 145
145static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) 146static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
146{ 147{
147 struct link_ant *ant = &rt2x00dev->link.ant; 148 struct link_ant *ant = &rt2x00dev->link.ant;
148 struct antenna_setup new_ant; 149 struct antenna_setup new_ant;
149 int sample_a = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_A); 150 int other_antenna;
150 int sample_b = rt2x00link_antenna_get_rssi_history(rt2x00dev, ANTENNA_B); 151
152 int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev);
153 int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev);
151 154
152 memcpy(&new_ant, &ant->active, sizeof(new_ant)); 155 memcpy(&new_ant, &ant->active, sizeof(new_ant));
153 156
@@ -161,17 +164,22 @@ static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev)
161 * from both antennas. It now is time to determine 164 * from both antennas. It now is time to determine
162 * which antenna demonstrated the best performance. 165 * which antenna demonstrated the best performance.
163 * When we are already on the antenna with the best 166 * When we are already on the antenna with the best
164 * performance, then there really is nothing for us 167 * performance, just create a good starting point
165 * left to do. 168 * for the history and we are done.
166 */ 169 */
167 if (sample_a == sample_b) 170 if (sample_current >= sample_other) {
171 rt2x00link_antenna_update_rssi_history(rt2x00dev,
172 sample_current);
168 return; 173 return;
174 }
175
176 other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
169 177
170 if (ant->flags & ANTENNA_RX_DIVERSITY) 178 if (ant->flags & ANTENNA_RX_DIVERSITY)
171 new_ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 179 new_ant.rx = other_antenna;
172 180
173 if (ant->flags & ANTENNA_TX_DIVERSITY) 181 if (ant->flags & ANTENNA_TX_DIVERSITY)
174 new_ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B; 182 new_ant.tx = other_antenna;
175 183
176 rt2x00lib_config_antenna(rt2x00dev, new_ant); 184 rt2x00lib_config_antenna(rt2x00dev, new_ant);
177} 185}
@@ -190,8 +198,8 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
190 * after that update the history with the current value. 198 * after that update the history with the current value.
191 */ 199 */
192 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); 200 rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev);
193 rssi_old = rt2x00link_antenna_get_rssi_rx_history(rt2x00dev); 201 rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev);
194 rt2x00link_antenna_update_rssi_rx_history(rt2x00dev, rssi_curr); 202 rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr);
195 203
196 /* 204 /*
197 * Legacy driver indicates that we should swap antenna's 205 * Legacy driver indicates that we should swap antenna's
@@ -216,9 +224,10 @@ static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev)
216 rt2x00lib_config_antenna(rt2x00dev, new_ant); 224 rt2x00lib_config_antenna(rt2x00dev, new_ant);
217} 225}
218 226
219static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) 227static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
220{ 228{
221 struct link_ant *ant = &rt2x00dev->link.ant; 229 struct link_ant *ant = &rt2x00dev->link.ant;
230 unsigned int flags = ant->flags;
222 231
223 /* 232 /*
224 * Determine if software diversity is enabled for 233 * Determine if software diversity is enabled for
@@ -226,30 +235,38 @@ static void rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev)
226 * Always perform this check since within the link 235 * Always perform this check since within the link
227 * tuner interval the configuration might have changed. 236 * tuner interval the configuration might have changed.
228 */ 237 */
229 ant->flags &= ~ANTENNA_RX_DIVERSITY; 238 flags &= ~ANTENNA_RX_DIVERSITY;
230 ant->flags &= ~ANTENNA_TX_DIVERSITY; 239 flags &= ~ANTENNA_TX_DIVERSITY;
231 240
232 if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) 241 if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
233 ant->flags |= ANTENNA_RX_DIVERSITY; 242 flags |= ANTENNA_RX_DIVERSITY;
234 if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) 243 if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
235 ant->flags |= ANTENNA_TX_DIVERSITY; 244 flags |= ANTENNA_TX_DIVERSITY;
236 245
237 if (!(ant->flags & ANTENNA_RX_DIVERSITY) && 246 if (!(ant->flags & ANTENNA_RX_DIVERSITY) &&
238 !(ant->flags & ANTENNA_TX_DIVERSITY)) { 247 !(ant->flags & ANTENNA_TX_DIVERSITY)) {
239 ant->flags = 0; 248 ant->flags = 0;
240 return; 249 return true;
241 } 250 }
242 251
252 /* Update flags */
253 ant->flags = flags;
254
243 /* 255 /*
244 * If we have only sampled the data over the last period 256 * If we have only sampled the data over the last period
245 * we should now harvest the data. Otherwise just evaluate 257 * we should now harvest the data. Otherwise just evaluate
246 * the data. The latter should only be performed once 258 * the data. The latter should only be performed once
247 * every 2 seconds. 259 * every 2 seconds.
248 */ 260 */
249 if (ant->flags & ANTENNA_MODE_SAMPLE) 261 if (ant->flags & ANTENNA_MODE_SAMPLE) {
250 rt2x00lib_antenna_diversity_sample(rt2x00dev); 262 rt2x00lib_antenna_diversity_sample(rt2x00dev);
251 else if (rt2x00dev->link.count & 1) 263 return true;
264 } else if (rt2x00dev->link.count & 1) {
252 rt2x00lib_antenna_diversity_eval(rt2x00dev); 265 rt2x00lib_antenna_diversity_eval(rt2x00dev);
266 return true;
267 }
268
269 return false;
253} 270}
254 271
255void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, 272void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
@@ -260,8 +277,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
260 struct link_qual *qual = &rt2x00dev->link.qual; 277 struct link_qual *qual = &rt2x00dev->link.qual;
261 struct link_ant *ant = &rt2x00dev->link.ant; 278 struct link_ant *ant = &rt2x00dev->link.ant;
262 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 279 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
263 int avg_rssi = rxdesc->rssi;
264 int ant_rssi = rxdesc->rssi;
265 280
266 /* 281 /*
267 * Frame was received successfully since non-succesfull 282 * Frame was received successfully since non-succesfull
@@ -281,16 +296,12 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
281 /* 296 /*
282 * Update global RSSI 297 * Update global RSSI
283 */ 298 */
284 if (link->avg_rssi) 299 link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi);
285 avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi, 8);
286 link->avg_rssi = avg_rssi;
287 300
288 /* 301 /*
289 * Update antenna RSSI 302 * Update antenna RSSI
290 */ 303 */
291 if (ant->rssi_ant) 304 ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
292 ant_rssi = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi, 8);
293 ant->rssi_ant = ant_rssi;
294} 305}
295 306
296static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) 307static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
@@ -423,10 +434,10 @@ static void rt2x00link_tuner(struct work_struct *work)
423 * collect the RSSI data we could use this. Otherwise we 434 * collect the RSSI data we could use this. Otherwise we
424 * must fallback to the default RSSI value. 435 * must fallback to the default RSSI value.
425 */ 436 */
426 if (!link->avg_rssi || !qual->rx_success) 437 if (!link->avg_rssi.avg || !qual->rx_success)
427 qual->rssi = DEFAULT_RSSI; 438 qual->rssi = DEFAULT_RSSI;
428 else 439 else
429 qual->rssi = link->avg_rssi; 440 qual->rssi = link->avg_rssi.avg;
430 441
431 /* 442 /*
432 * Only perform the link tuning when Link tuning 443 * Only perform the link tuning when Link tuning
@@ -444,18 +455,15 @@ static void rt2x00link_tuner(struct work_struct *work)
444 /* 455 /*
445 * Send a signal to the led to update the led signal strength. 456 * Send a signal to the led to update the led signal strength.
446 */ 457 */
447 rt2x00leds_led_quality(rt2x00dev, link->avg_rssi); 458 rt2x00leds_led_quality(rt2x00dev, qual->rssi);
448
449 /*
450 * Evaluate antenna setup, make this the last step since this could
451 * possibly reset some statistics.
452 */
453 rt2x00lib_antenna_diversity(rt2x00dev);
454 459
455 /* 460 /*
456 * Reset the quality counters which recounted during each period. 461 * Evaluate antenna setup, make this the last step when
462 * rt2x00lib_antenna_diversity made changes the quality
463 * statistics will be reset.
457 */ 464 */
458 rt2x00link_reset_qual(rt2x00dev); 465 if (rt2x00lib_antenna_diversity(rt2x00dev))
466 rt2x00link_reset_qual(rt2x00dev);
459 467
460 /* 468 /*
461 * Increase tuner counter, and reschedule the next link tuner run. 469 * Increase tuner counter, and reschedule the next link tuner run.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 81febdfd6639..cb7b6d459331 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -274,6 +274,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
274 274
275 spin_lock_init(&intf->lock); 275 spin_lock_init(&intf->lock);
276 spin_lock_init(&intf->seqlock); 276 spin_lock_init(&intf->seqlock);
277 mutex_init(&intf->beacon_skb_mutex);
277 intf->beacon = entry; 278 intf->beacon = entry;
278 279
279 if (conf->type == NL80211_IFTYPE_AP) 280 if (conf->type == NL80211_IFTYPE_AP)
@@ -338,7 +339,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
338{ 339{
339 struct rt2x00_dev *rt2x00dev = hw->priv; 340 struct rt2x00_dev *rt2x00dev = hw->priv;
340 struct ieee80211_conf *conf = &hw->conf; 341 struct ieee80211_conf *conf = &hw->conf;
341 int status;
342 342
343 /* 343 /*
344 * mac80211 might be calling this function while we are trying 344 * mac80211 might be calling this function while we are trying
@@ -348,44 +348,29 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
348 return 0; 348 return 0;
349 349
350 /* 350 /*
351 * Only change device state when the radio is enabled. It does not 351 * Some configuration parameters (e.g. channel and antenna values) can
352 * matter what parameters we have configured when the radio is disabled 352 * only be set when the radio is enabled, but do require the RX to
353 * because we won't be able to send or receive anyway. Also note that 353 * be off.
354 * some configuration parameters (e.g. channel and antenna values) can
355 * only be set when the radio is enabled.
356 */ 354 */
357 if (conf->radio_enabled) { 355 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
358 /* For programming the values, we have to turn RX off */
359 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
360 356
361 /* Enable the radio */ 357 /*
362 status = rt2x00lib_enable_radio(rt2x00dev); 358 * When we've just turned on the radio, we want to reprogram
363 if (unlikely(status)) 359 * everything to ensure a consistent state
364 return status; 360 */
361 rt2x00lib_config(rt2x00dev, conf, changed);
365 362
366 /* 363 /*
367 * When we've just turned on the radio, we want to reprogram 364 * After the radio has been enabled we need to configure
368 * everything to ensure a consistent state 365 * the antenna to the default settings. rt2x00lib_config_antenna()
369 */ 366 * should determine if any action should be taken based on
370 rt2x00lib_config(rt2x00dev, conf, changed); 367 * checking if diversity has been enabled or no antenna changes
368 * have been made since the last configuration change.
369 */
370 rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant);
371 371
372 /* 372 /* Turn RX back on */
373 * The radio was enabled, configure the antenna to the 373 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
374 * default settings, the link tuner will later start
375 * continue configuring the antenna based on the software
376 * diversity. But for non-diversity configurations, we need
377 * to have configured the correct state now.
378 */
379 if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED)
380 rt2x00lib_config_antenna(rt2x00dev,
381 rt2x00dev->default_ant);
382
383 /* Turn RX back on */
384 rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
385 } else {
386 /* Disable the radio */
387 rt2x00lib_disable_radio(rt2x00dev);
388 }
389 374
390 return 0; 375 return 0;
391} 376}
@@ -407,6 +392,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
407 FIF_FCSFAIL | 392 FIF_FCSFAIL |
408 FIF_PLCPFAIL | 393 FIF_PLCPFAIL |
409 FIF_CONTROL | 394 FIF_CONTROL |
395 FIF_PSPOLL |
410 FIF_OTHER_BSS | 396 FIF_OTHER_BSS |
411 FIF_PROMISC_IN_BSS; 397 FIF_PROMISC_IN_BSS;
412 398
@@ -422,6 +408,22 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw,
422 *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; 408 *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS;
423 409
424 /* 410 /*
411 * If the device has a single filter for all control frames,
412 * FIF_CONTROL and FIF_PSPOLL flags imply each other.
413 * And if the device has more than one filter for control frames
414 * of different types, but has no a separate filter for PS Poll frames,
415 * FIF_CONTROL flag implies FIF_PSPOLL.
416 */
417 if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) {
418 if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL)
419 *total_flags |= FIF_CONTROL | FIF_PSPOLL;
420 }
421 if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) {
422 if (*total_flags & FIF_CONTROL)
423 *total_flags |= FIF_PSPOLL;
424 }
425
426 /*
425 * Check if there is any work left for us. 427 * Check if there is any work left for us.
426 */ 428 */
427 if (rt2x00dev->packet_filter == *total_flags) 429 if (rt2x00dev->packet_filter == *total_flags)
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 44e5b3279ca7..06af823efd83 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -324,7 +324,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
324 /* 324 /*
325 * Check if more fragments are pending 325 * Check if more fragments are pending
326 */ 326 */
327 if (ieee80211_has_morefrags(hdr->frame_control)) { 327 if (ieee80211_has_morefrags(hdr->frame_control) ||
328 (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) {
328 __set_bit(ENTRY_TXD_BURST, &txdesc->flags); 329 __set_bit(ENTRY_TXD_BURST, &txdesc->flags);
329 __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); 330 __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags);
330 } 331 }
@@ -452,9 +453,21 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
452 rt2x00crypto_tx_remove_iv(skb, &txdesc); 453 rt2x00crypto_tx_remove_iv(skb, &txdesc);
453 } 454 }
454 455
456 /*
457 * When DMA allocation is required we should guarentee to the
458 * driver that the DMA is aligned to a 4-byte boundary.
459 * Aligning the header to this boundary can be done by calling
460 * rt2x00queue_payload_align with the header length of 0.
461 * However some drivers require L2 padding to pad the payload
462 * rather then the header. This could be a requirement for
463 * PCI and USB devices, while header alignment only is valid
464 * for PCI devices.
465 */
455 if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) 466 if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags))
456 rt2x00queue_payload_align(entry->skb, true, 467 rt2x00queue_payload_align(entry->skb, true,
457 txdesc.header_length); 468 txdesc.header_length);
469 else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
470 rt2x00queue_payload_align(entry->skb, false, 0);
458 471
459 /* 472 /*
460 * It could be possible that the queue was corrupted and this 473 * It could be possible that the queue was corrupted and this
@@ -490,14 +503,25 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
490 if (unlikely(!intf->beacon)) 503 if (unlikely(!intf->beacon))
491 return -ENOBUFS; 504 return -ENOBUFS;
492 505
506 mutex_lock(&intf->beacon_skb_mutex);
507
508 /*
509 * Clean up the beacon skb.
510 */
511 rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb);
512 intf->beacon->skb = NULL;
513
493 if (!enable_beacon) { 514 if (!enable_beacon) {
494 rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON); 515 rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON);
516 mutex_unlock(&intf->beacon_skb_mutex);
495 return 0; 517 return 0;
496 } 518 }
497 519
498 intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); 520 intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
499 if (!intf->beacon->skb) 521 if (!intf->beacon->skb) {
522 mutex_unlock(&intf->beacon_skb_mutex);
500 return -ENOMEM; 523 return -ENOMEM;
524 }
501 525
502 /* 526 /*
503 * Copy all TX descriptor information into txdesc, 527 * Copy all TX descriptor information into txdesc,
@@ -535,6 +559,8 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
535 rt2x00dev->ops->lib->write_beacon(intf->beacon); 559 rt2x00dev->ops->lib->write_beacon(intf->beacon);
536 rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); 560 rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
537 561
562 mutex_unlock(&intf->beacon_skb_mutex);
563
538 return 0; 564 return 0;
539} 565}
540 566
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index e20dd7431f21..f4b4b86da4da 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -530,7 +530,7 @@ static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev,
530 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 530 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
531 !(filter_flags & FIF_PLCPFAIL)); 531 !(filter_flags & FIF_PLCPFAIL));
532 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 532 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
533 !(filter_flags & FIF_CONTROL)); 533 !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
534 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 534 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
535 !(filter_flags & FIF_PROMISC_IN_BSS)); 535 !(filter_flags & FIF_PROMISC_IN_BSS));
536 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 536 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
@@ -1855,8 +1855,6 @@ static void rt61pci_write_beacon(struct queue_entry *entry)
1855 * otherwise we might be sending out invalid data. 1855 * otherwise we might be sending out invalid data.
1856 */ 1856 */
1857 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg); 1857 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
1858 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
1859 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
1860 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0); 1858 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
1861 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); 1859 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
1862 1860
@@ -2624,6 +2622,12 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
2624 return retval; 2622 return retval;
2625 2623
2626 /* 2624 /*
2625 * This device has multiple filters for control frames,
2626 * but has no a separate filter for PS Poll frames.
2627 */
2628 __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
2629
2630 /*
2627 * This device requires firmware and DMA mapped skbs. 2631 * This device requires firmware and DMA mapped skbs.
2628 */ 2632 */
2629 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); 2633 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 4f9b1772e1a1..4d94b65943f1 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -493,7 +493,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
493 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL, 493 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
494 !(filter_flags & FIF_PLCPFAIL)); 494 !(filter_flags & FIF_PLCPFAIL));
495 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL, 495 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CONTROL,
496 !(filter_flags & FIF_CONTROL)); 496 !(filter_flags & (FIF_CONTROL | FIF_PSPOLL)));
497 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME, 497 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_NOT_TO_ME,
498 !(filter_flags & FIF_PROMISC_IN_BSS)); 498 !(filter_flags & FIF_PROMISC_IN_BSS));
499 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS, 499 rt2x00_set_field32(&reg, TXRX_CSR0_DROP_TO_DS,
@@ -1527,8 +1527,6 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
1527 * otherwise we might be sending out invalid data. 1527 * otherwise we might be sending out invalid data.
1528 */ 1528 */
1529 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg); 1529 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
1530 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
1531 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
1532 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0); 1530 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
1533 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); 1531 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
1534 1532
@@ -2144,6 +2142,12 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
2144 return retval; 2142 return retval;
2145 2143
2146 /* 2144 /*
2145 * This device has multiple filters for control frames,
2146 * but has no a separate filter for PS Poll frames.
2147 */
2148 __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
2149
2150 /*
2147 * This device requires firmware. 2151 * This device requires firmware.
2148 */ 2152 */
2149 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); 2153 __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags);
diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index 34a5555cc19c..562222e6cf1f 100644
--- a/drivers/net/wireless/rtl818x/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -194,8 +194,18 @@ struct rtl818x_rf_ops {
194 void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); 194 void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *);
195}; 195};
196 196
197/* Tx/Rx flags are common between RTL818X chips */ 197/**
198 198 * enum rtl818x_tx_desc_flags - Tx/Rx flags are common between RTL818X chips
199 *
200 * @RTL818X_TX_DESC_FLAG_NO_ENC: Disable hardware based encryption.
201 * @RTL818X_TX_DESC_FLAG_TX_OK: TX frame was ACKed.
202 * @RTL818X_TX_DESC_FLAG_SPLCP: Use short preamble.
203 * @RTL818X_TX_DESC_FLAG_MOREFRAG: More fragments follow.
204 * @RTL818X_TX_DESC_FLAG_CTS: Use CTS-to-self protection.
205 * @RTL818X_TX_DESC_FLAG_RTS: Use RTS/CTS protection.
206 * @RTL818X_TX_DESC_FLAG_LS: Last segment of the frame.
207 * @RTL818X_TX_DESC_FLAG_FS: First segment of the frame.
208 */
199enum rtl818x_tx_desc_flags { 209enum rtl818x_tx_desc_flags {
200 RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15), 210 RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15),
201 RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15), 211 RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15),
diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig
index 82a0f97975de..7b14d5bc63d6 100644
--- a/drivers/net/wireless/wl12xx/Kconfig
+++ b/drivers/net/wireless/wl12xx/Kconfig
@@ -7,12 +7,46 @@ menuconfig WL12XX
7 7
8config WL1251 8config WL1251
9 tristate "TI wl1251 support" 9 tristate "TI wl1251 support"
10 depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS 10 depends on WL12XX && GENERIC_HARDIRQS
11 select FW_LOADER 11 select FW_LOADER
12 select CRC7 12 select CRC7
13 ---help--- 13 ---help---
14 This module adds support for wireless adapters based on 14 This module adds support for wireless adapters based on
15 TI wl1251 chipset. 15 TI wl1251 chipset.
16 16
17 If you choose to build a module, it'll be called wl1251. Say N if 17 If you choose to build a module, it'll be called wl1251. Say
18 N if unsure.
19
20config WL1251_SPI
21 tristate "TI wl1251 SPI support"
22 depends on WL1251 && SPI_MASTER
23 ---help---
24 This module adds support for the SPI interface of adapters using
25 TI wl1251 chipset. Select this if your platform is using
26 the SPI bus.
27
28 If you choose to build a module, it'll be called wl1251_spi.
29 Say N if unsure.
30
31config WL1251_SDIO
32 tristate "TI wl1251 SDIO support"
33 depends on WL1251 && MMC
34 ---help---
35 This module adds support for the SDIO interface of adapters using
36 TI wl1251 chipset. Select this if your platform is using
37 the SDIO bus.
38
39 If you choose to build a module, it'll be called
40 wl1251_sdio. Say N if unsure.
41
42config WL1271
43 tristate "TI wl1271 support"
44 depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS
45 select FW_LOADER
46 select CRC7
47 ---help---
48 This module adds support for wireless adapters based on the
49 TI wl1271 chipset.
50
51 If you choose to build a module, it'll be called wl1271. Say N if
18 unsure. 52 unsure.
diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile
index d5595a841f5f..62e37ad01cc0 100644
--- a/drivers/net/wireless/wl12xx/Makefile
+++ b/drivers/net/wireless/wl12xx/Makefile
@@ -1,5 +1,14 @@
1wl1251-objs = wl1251_main.o wl1251_spi.o wl1251_event.o \ 1wl1251-objs = wl1251_main.o wl1251_event.o \
2 wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \ 2 wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \
3 wl1251_acx.o wl1251_boot.o wl1251_init.o \ 3 wl1251_acx.o wl1251_boot.o wl1251_init.o \
4 wl1251_ops.o wl1251_debugfs.o 4 wl1251_debugfs.o wl1251_io.o
5
5obj-$(CONFIG_WL1251) += wl1251.o 6obj-$(CONFIG_WL1251) += wl1251.o
7obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o
8obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o
9
10wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \
11 wl1271_event.o wl1271_tx.o wl1271_rx.o \
12 wl1271_ps.o wl1271_acx.o wl1271_boot.o \
13 wl1271_init.o wl1271_debugfs.o
14obj-$(CONFIG_WL1271) += wl1271.o
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h
index 665aca02bea9..998e4b6252bd 100644
--- a/drivers/net/wireless/wl12xx/wl1251.h
+++ b/drivers/net/wireless/wl12xx/wl1251.h
@@ -143,35 +143,6 @@ struct wl1251_partition_set {
143 143
144struct wl1251; 144struct wl1251;
145 145
146/* FIXME: I'm not sure about this structure name */
147struct wl1251_chip {
148 u32 id;
149
150 const char *fw_filename;
151 const char *nvs_filename;
152
153 char fw_ver[21];
154
155 unsigned int power_on_sleep;
156 int intr_cmd_complete;
157 int intr_init_complete;
158
159 int (*op_upload_fw)(struct wl1251 *wl);
160 int (*op_upload_nvs)(struct wl1251 *wl);
161 int (*op_boot)(struct wl1251 *wl);
162 void (*op_set_ecpu_ctrl)(struct wl1251 *wl, u32 flag);
163 void (*op_target_enable_interrupts)(struct wl1251 *wl);
164 int (*op_hw_init)(struct wl1251 *wl);
165 int (*op_plt_init)(struct wl1251 *wl);
166 void (*op_tx_flush)(struct wl1251 *wl);
167 void (*op_fw_version)(struct wl1251 *wl);
168 int (*op_cmd_join)(struct wl1251 *wl, u8 bss_type, u8 dtim_interval,
169 u16 beacon_interval, u8 wait);
170
171 struct wl1251_partition_set *p_table;
172 enum wl12xx_acx_int_reg *acx_reg_table;
173};
174
175struct wl1251_stats { 146struct wl1251_stats {
176 struct acx_statistics *fw_stats; 147 struct acx_statistics *fw_stats;
177 unsigned long fw_stats_update; 148 unsigned long fw_stats_update;
@@ -281,11 +252,20 @@ struct wl1251_debugfs {
281 struct dentry *excessive_retries; 252 struct dentry *excessive_retries;
282}; 253};
283 254
255struct wl1251_if_operations {
256 void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len);
257 void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len);
258 void (*reset)(struct wl1251 *wl);
259 void (*enable_irq)(struct wl1251 *wl);
260 void (*disable_irq)(struct wl1251 *wl);
261};
262
284struct wl1251 { 263struct wl1251 {
285 struct ieee80211_hw *hw; 264 struct ieee80211_hw *hw;
286 bool mac80211_registered; 265 bool mac80211_registered;
287 266
288 struct spi_device *spi; 267 void *if_priv;
268 const struct wl1251_if_operations *if_ops;
289 269
290 void (*set_power)(bool enable); 270 void (*set_power)(bool enable);
291 int irq; 271 int irq;
@@ -298,8 +278,6 @@ struct wl1251 {
298 int virtual_mem_addr; 278 int virtual_mem_addr;
299 int virtual_reg_addr; 279 int virtual_reg_addr;
300 280
301 struct wl1251_chip chip;
302
303 int cmd_box_addr; 281 int cmd_box_addr;
304 int event_box_addr; 282 int event_box_addr;
305 struct boot_attr boot_attr; 283 struct boot_attr boot_attr;
@@ -382,6 +360,9 @@ struct wl1251 {
382 /* PSM mode requested */ 360 /* PSM mode requested */
383 bool psm_requested; 361 bool psm_requested;
384 362
363 u16 beacon_int;
364 u8 dtim_period;
365
385 /* in dBm */ 366 /* in dBm */
386 int power_level; 367 int power_level;
387 368
@@ -392,11 +373,20 @@ struct wl1251 {
392 u32 buffer_cmd; 373 u32 buffer_cmd;
393 u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; 374 u8 buffer_busyword[WL1251_BUSY_WORD_LEN];
394 struct wl1251_rx_descriptor *rx_descriptor; 375 struct wl1251_rx_descriptor *rx_descriptor;
376
377 u32 chip_id;
378 char fw_ver[21];
395}; 379};
396 380
397int wl1251_plt_start(struct wl1251 *wl); 381int wl1251_plt_start(struct wl1251 *wl);
398int wl1251_plt_stop(struct wl1251 *wl); 382int wl1251_plt_stop(struct wl1251 *wl);
399 383
384struct ieee80211_hw *wl1251_alloc_hw(void);
385int wl1251_free_hw(struct wl1251 *wl);
386int wl1251_init_ieee80211(struct wl1251 *wl);
387void wl1251_enable_interrupts(struct wl1251 *wl);
388void wl1251_disable_interrupts(struct wl1251 *wl);
389
400#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ 390#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */
401#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS 391#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS
402#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ 392#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
@@ -405,11 +395,10 @@ int wl1251_plt_stop(struct wl1251 *wl);
405 395
406#define WL1251_TX_QUEUE_MAX_LENGTH 20 396#define WL1251_TX_QUEUE_MAX_LENGTH 20
407 397
408/* Different chips need different sleep times after power on. WL1271 needs 398#define WL1251_DEFAULT_BEACON_INT 100
409 * 200ms, WL1251 needs only 10ms. By default we use 200ms, but as soon as we 399#define WL1251_DEFAULT_DTIM_PERIOD 1
410 * know the chip ID, we change the sleep value in the wl1251 chip structure, 400
411 * so in subsequent power ons, we don't waste more time then needed. */ 401#define WL1251_DEFAULT_CHANNEL 0
412#define WL1251_DEFAULT_POWER_ON_SLEEP 200
413 402
414#define CHIP_ID_1251_PG10 (0x7010101) 403#define CHIP_ID_1251_PG10 (0x7010101)
415#define CHIP_ID_1251_PG11 (0x7020101) 404#define CHIP_ID_1251_PG11 (0x7020101)
@@ -417,4 +406,19 @@ int wl1251_plt_stop(struct wl1251 *wl);
417#define CHIP_ID_1271_PG10 (0x4030101) 406#define CHIP_ID_1271_PG10 (0x4030101)
418#define CHIP_ID_1271_PG20 (0x4030111) 407#define CHIP_ID_1271_PG20 (0x4030111)
419 408
409#define WL1251_FW_NAME "wl1251-fw.bin"
410#define WL1251_NVS_NAME "wl1251-nvs.bin"
411
412#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
413
414#define WL1251_PART_DOWN_MEM_START 0x0
415#define WL1251_PART_DOWN_MEM_SIZE 0x16800
416#define WL1251_PART_DOWN_REG_START REGISTERS_BASE
417#define WL1251_PART_DOWN_REG_SIZE REGISTERS_DOWN_SIZE
418
419#define WL1251_PART_WORK_MEM_START 0x28000
420#define WL1251_PART_WORK_MEM_SIZE 0x14000
421#define WL1251_PART_WORK_REG_START REGISTERS_BASE
422#define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE
423
420#endif 424#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c
index a46c92a29526..10b26c4532c9 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.c
@@ -2,11 +2,10 @@
2 2
3#include <linux/module.h> 3#include <linux/module.h>
4#include <linux/crc7.h> 4#include <linux/crc7.h>
5#include <linux/spi/spi.h>
6 5
7#include "wl1251.h" 6#include "wl1251.h"
8#include "reg.h" 7#include "wl1251_reg.h"
9#include "wl1251_spi.h" 8#include "wl1251_cmd.h"
10#include "wl1251_ps.h" 9#include "wl1251_ps.h"
11 10
12int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, 11int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod,
@@ -838,3 +837,82 @@ int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats)
838 837
839 return 0; 838 return 0;
840} 839}
840
841int wl1251_acx_rate_policies(struct wl1251 *wl)
842{
843 struct acx_rate_policy *acx;
844 int ret = 0;
845
846 wl1251_debug(DEBUG_ACX, "acx rate policies");
847
848 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
849
850 if (!acx) {
851 ret = -ENOMEM;
852 goto out;
853 }
854
855 /* configure one default (one-size-fits-all) rate class */
856 acx->rate_class_cnt = 1;
857 acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
858 acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
859 acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
860 acx->rate_class[0].aflags = 0;
861
862 ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
863 if (ret < 0) {
864 wl1251_warning("Setting of rate policies failed: %d", ret);
865 goto out;
866 }
867
868out:
869 kfree(acx);
870 return ret;
871}
872
873int wl1251_acx_mem_cfg(struct wl1251 *wl)
874{
875 struct wl1251_acx_config_memory *mem_conf;
876 int ret, i;
877
878 wl1251_debug(DEBUG_ACX, "acx mem cfg");
879
880 mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
881 if (!mem_conf) {
882 ret = -ENOMEM;
883 goto out;
884 }
885
886 /* memory config */
887 mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
888 mem_conf->mem_config.rx_mem_block_num = 35;
889 mem_conf->mem_config.tx_min_mem_block_num = 64;
890 mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
891 mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
892 mem_conf->mem_config.num_ssid_profiles = 1;
893 mem_conf->mem_config.debug_buffer_size =
894 cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
895
896 /* RX queue config */
897 mem_conf->rx_queue_config.dma_address = 0;
898 mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
899 mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
900 mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
901
902 /* TX queue config */
903 for (i = 0; i < MAX_TX_QUEUES; i++) {
904 mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
905 mem_conf->tx_queue_config[i].attributes = i;
906 }
907
908 ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
909 sizeof(*mem_conf));
910 if (ret < 0) {
911 wl1251_warning("wl1251 mem config failed: %d", ret);
912 goto out;
913 }
914
915out:
916 kfree(mem_conf);
917 return ret;
918}
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h
index 2e7b1933a8f9..cafb91459504 100644
--- a/drivers/net/wireless/wl12xx/wl1251_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1251_acx.h
@@ -1031,6 +1031,150 @@ struct acx_statistics {
1031 struct acx_rxpipe_statistics rxpipe; 1031 struct acx_rxpipe_statistics rxpipe;
1032} __attribute__ ((packed)); 1032} __attribute__ ((packed));
1033 1033
1034#define ACX_MAX_RATE_CLASSES 8
1035#define ACX_RATE_MASK_UNSPECIFIED 0
1036#define ACX_RATE_RETRY_LIMIT 10
1037
1038struct acx_rate_class {
1039 u32 enabled_rates;
1040 u8 short_retry_limit;
1041 u8 long_retry_limit;
1042 u8 aflags;
1043 u8 reserved;
1044};
1045
1046struct acx_rate_policy {
1047 struct acx_header header;
1048
1049 u32 rate_class_cnt;
1050 struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
1051} __attribute__ ((packed));
1052
1053struct wl1251_acx_memory {
1054 __le16 num_stations; /* number of STAs to be supported. */
1055 u16 reserved_1;
1056
1057 /*
1058 * Nmber of memory buffers for the RX mem pool.
1059 * The actual number may be less if there are
1060 * not enough blocks left for the minimum num
1061 * of TX ones.
1062 */
1063 u8 rx_mem_block_num;
1064 u8 reserved_2;
1065 u8 num_tx_queues; /* From 1 to 16 */
1066 u8 host_if_options; /* HOST_IF* */
1067 u8 tx_min_mem_block_num;
1068 u8 num_ssid_profiles;
1069 __le16 debug_buffer_size;
1070} __attribute__ ((packed));
1071
1072
1073#define ACX_RX_DESC_MIN 1
1074#define ACX_RX_DESC_MAX 127
1075#define ACX_RX_DESC_DEF 32
1076struct wl1251_acx_rx_queue_config {
1077 u8 num_descs;
1078 u8 pad;
1079 u8 type;
1080 u8 priority;
1081 __le32 dma_address;
1082} __attribute__ ((packed));
1083
1084#define ACX_TX_DESC_MIN 1
1085#define ACX_TX_DESC_MAX 127
1086#define ACX_TX_DESC_DEF 16
1087struct wl1251_acx_tx_queue_config {
1088 u8 num_descs;
1089 u8 pad[2];
1090 u8 attributes;
1091} __attribute__ ((packed));
1092
1093#define MAX_TX_QUEUE_CONFIGS 5
1094#define MAX_TX_QUEUES 4
1095struct wl1251_acx_config_memory {
1096 struct acx_header header;
1097
1098 struct wl1251_acx_memory mem_config;
1099 struct wl1251_acx_rx_queue_config rx_queue_config;
1100 struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
1101} __attribute__ ((packed));
1102
1103struct wl1251_acx_mem_map {
1104 struct acx_header header;
1105
1106 void *code_start;
1107 void *code_end;
1108
1109 void *wep_defkey_start;
1110 void *wep_defkey_end;
1111
1112 void *sta_table_start;
1113 void *sta_table_end;
1114
1115 void *packet_template_start;
1116 void *packet_template_end;
1117
1118 void *queue_memory_start;
1119 void *queue_memory_end;
1120
1121 void *packet_memory_pool_start;
1122 void *packet_memory_pool_end;
1123
1124 void *debug_buffer1_start;
1125 void *debug_buffer1_end;
1126
1127 void *debug_buffer2_start;
1128 void *debug_buffer2_end;
1129
1130 /* Number of blocks FW allocated for TX packets */
1131 u32 num_tx_mem_blocks;
1132
1133 /* Number of blocks FW allocated for RX packets */
1134 u32 num_rx_mem_blocks;
1135} __attribute__ ((packed));
1136
1137/*************************************************************************
1138
1139 Host Interrupt Register (WiLink -> Host)
1140
1141**************************************************************************/
1142
1143/* RX packet is ready in Xfer buffer #0 */
1144#define WL1251_ACX_INTR_RX0_DATA BIT(0)
1145
1146/* TX result(s) are in the TX complete buffer */
1147#define WL1251_ACX_INTR_TX_RESULT BIT(1)
1148
1149/* OBSOLETE */
1150#define WL1251_ACX_INTR_TX_XFR BIT(2)
1151
1152/* RX packet is ready in Xfer buffer #1 */
1153#define WL1251_ACX_INTR_RX1_DATA BIT(3)
1154
1155/* Event was entered to Event MBOX #A */
1156#define WL1251_ACX_INTR_EVENT_A BIT(4)
1157
1158/* Event was entered to Event MBOX #B */
1159#define WL1251_ACX_INTR_EVENT_B BIT(5)
1160
1161/* OBSOLETE */
1162#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6)
1163
1164/* Trace meassge on MBOX #A */
1165#define WL1251_ACX_INTR_TRACE_A BIT(7)
1166
1167/* Trace meassge on MBOX #B */
1168#define WL1251_ACX_INTR_TRACE_B BIT(8)
1169
1170/* Command processing completion */
1171#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9)
1172
1173/* Init sequence is done */
1174#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14)
1175
1176#define WL1251_ACX_INTR_ALL 0xFFFFFFFF
1177
1034enum { 1178enum {
1035 ACX_WAKE_UP_CONDITIONS = 0x0002, 1179 ACX_WAKE_UP_CONDITIONS = 0x0002,
1036 ACX_MEM_CFG = 0x0003, 1180 ACX_MEM_CFG = 0x0003,
@@ -1142,5 +1286,7 @@ int wl1251_acx_cts_protect(struct wl1251 *wl,
1142 enum acx_ctsprotect_type ctsprotect); 1286 enum acx_ctsprotect_type ctsprotect);
1143int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats); 1287int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats);
1144int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); 1288int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime);
1289int wl1251_acx_rate_policies(struct wl1251 *wl);
1290int wl1251_acx_mem_cfg(struct wl1251 *wl);
1145 1291
1146#endif /* __WL1251_ACX_H__ */ 1292#endif /* __WL1251_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c
index d8a155dc2fa1..592c3b5cc8f8 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.c
@@ -23,15 +23,12 @@
23 23
24#include <linux/gpio.h> 24#include <linux/gpio.h>
25 25
26#include "reg.h" 26#include "wl1251_reg.h"
27#include "wl1251_boot.h" 27#include "wl1251_boot.h"
28#include "wl1251_io.h"
28#include "wl1251_spi.h" 29#include "wl1251_spi.h"
29#include "wl1251_event.h" 30#include "wl1251_event.h"
30 31#include "wl1251_acx.h"
31static void wl1251_boot_enable_interrupts(struct wl1251 *wl)
32{
33 enable_irq(wl->irq);
34}
35 32
36void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) 33void wl1251_boot_target_enable_interrupts(struct wl1251 *wl)
37{ 34{
@@ -212,18 +209,30 @@ int wl1251_boot_init_seq(struct wl1251 *wl)
212 return 0; 209 return 0;
213} 210}
214 211
212static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
213{
214 u32 cpu_ctrl;
215
216 /* 10.5.0 run the firmware (I) */
217 cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
218
219 /* 10.5.1 run the firmware (II) */
220 cpu_ctrl &= ~flag;
221 wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
222}
223
215int wl1251_boot_run_firmware(struct wl1251 *wl) 224int wl1251_boot_run_firmware(struct wl1251 *wl)
216{ 225{
217 int loop, ret; 226 int loop, ret;
218 u32 chip_id, interrupt; 227 u32 chip_id, interrupt;
219 228
220 wl->chip.op_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); 229 wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
221 230
222 chip_id = wl1251_reg_read32(wl, CHIP_ID_B); 231 chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
223 232
224 wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); 233 wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
225 234
226 if (chip_id != wl->chip.id) { 235 if (chip_id != wl->chip_id) {
227 wl1251_error("chip id doesn't match after firmware boot"); 236 wl1251_error("chip id doesn't match after firmware boot");
228 return -EIO; 237 return -EIO;
229 } 238 }
@@ -240,9 +249,9 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
240 return -EIO; 249 return -EIO;
241 } 250 }
242 /* check that ACX_INTR_INIT_COMPLETE is enabled */ 251 /* check that ACX_INTR_INIT_COMPLETE is enabled */
243 else if (interrupt & wl->chip.intr_init_complete) { 252 else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) {
244 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, 253 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
245 wl->chip.intr_init_complete); 254 WL1251_ACX_INTR_INIT_COMPLETE);
246 break; 255 break;
247 } 256 }
248 } 257 }
@@ -260,16 +269,15 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
260 wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); 269 wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
261 270
262 /* set the working partition to its "running" mode offset */ 271 /* set the working partition to its "running" mode offset */
263 wl1251_set_partition(wl, 272 wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START,
264 wl->chip.p_table[PART_WORK].mem.start, 273 WL1251_PART_WORK_MEM_SIZE,
265 wl->chip.p_table[PART_WORK].mem.size, 274 WL1251_PART_WORK_REG_START,
266 wl->chip.p_table[PART_WORK].reg.start, 275 WL1251_PART_WORK_REG_SIZE);
267 wl->chip.p_table[PART_WORK].reg.size);
268 276
269 wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", 277 wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
270 wl->cmd_box_addr, wl->event_box_addr); 278 wl->cmd_box_addr, wl->event_box_addr);
271 279
272 wl->chip.op_fw_version(wl); 280 wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver));
273 281
274 /* 282 /*
275 * in case of full asynchronous mode the firmware event must be 283 * in case of full asynchronous mode the firmware event must be
@@ -277,9 +285,16 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
277 */ 285 */
278 286
279 /* enable gpio interrupts */ 287 /* enable gpio interrupts */
280 wl1251_boot_enable_interrupts(wl); 288 wl1251_enable_interrupts(wl);
281 289
282 wl->chip.op_target_enable_interrupts(wl); 290 /* Enable target's interrupts */
291 wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
292 WL1251_ACX_INTR_RX1_DATA |
293 WL1251_ACX_INTR_TX_RESULT |
294 WL1251_ACX_INTR_EVENT_A |
295 WL1251_ACX_INTR_EVENT_B |
296 WL1251_ACX_INTR_INIT_COMPLETE;
297 wl1251_boot_target_enable_interrupts(wl);
283 298
284 /* unmask all mbox events */ 299 /* unmask all mbox events */
285 wl->event_mask = 0xffffffff; 300 wl->event_mask = 0xffffffff;
@@ -295,3 +310,218 @@ int wl1251_boot_run_firmware(struct wl1251 *wl)
295 /* firmware startup completed */ 310 /* firmware startup completed */
296 return 0; 311 return 0;
297} 312}
313
314static int wl1251_boot_upload_firmware(struct wl1251 *wl)
315{
316 int addr, chunk_num, partition_limit;
317 size_t fw_data_len;
318 u8 *p;
319
320 /* whal_FwCtrl_LoadFwImageSm() */
321
322 wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
323 wl1251_reg_read32(wl, CHIP_ID_B));
324
325 /* 10.0 check firmware length and set partition */
326 fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
327 (wl->fw[6] << 8) | (wl->fw[7]);
328
329 wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
330 CHUNK_SIZE);
331
332 if ((fw_data_len % 4) != 0) {
333 wl1251_error("firmware length not multiple of four");
334 return -EIO;
335 }
336
337 wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START,
338 WL1251_PART_DOWN_MEM_SIZE,
339 WL1251_PART_DOWN_REG_START,
340 WL1251_PART_DOWN_REG_SIZE);
341
342 /* 10.1 set partition limit and chunk num */
343 chunk_num = 0;
344 partition_limit = WL1251_PART_DOWN_MEM_SIZE;
345
346 while (chunk_num < fw_data_len / CHUNK_SIZE) {
347 /* 10.2 update partition, if needed */
348 addr = WL1251_PART_DOWN_MEM_START +
349 (chunk_num + 2) * CHUNK_SIZE;
350 if (addr > partition_limit) {
351 addr = WL1251_PART_DOWN_MEM_START +
352 chunk_num * CHUNK_SIZE;
353 partition_limit = chunk_num * CHUNK_SIZE +
354 WL1251_PART_DOWN_MEM_SIZE;
355 wl1251_set_partition(wl,
356 addr,
357 WL1251_PART_DOWN_MEM_SIZE,
358 WL1251_PART_DOWN_REG_START,
359 WL1251_PART_DOWN_REG_SIZE);
360 }
361
362 /* 10.3 upload the chunk */
363 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
364 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
365 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
366 p, addr);
367 wl1251_mem_write(wl, addr, p, CHUNK_SIZE);
368
369 chunk_num++;
370 }
371
372 /* 10.4 upload the last chunk */
373 addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE;
374 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
375 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
376 fw_data_len % CHUNK_SIZE, p, addr);
377 wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
378
379 return 0;
380}
381
382static int wl1251_boot_upload_nvs(struct wl1251 *wl)
383{
384 size_t nvs_len, nvs_bytes_written, burst_len;
385 int nvs_start, i;
386 u32 dest_addr, val;
387 u8 *nvs_ptr, *nvs;
388
389 nvs = wl->nvs;
390 if (nvs == NULL)
391 return -ENODEV;
392
393 nvs_ptr = nvs;
394
395 nvs_len = wl->nvs_len;
396 nvs_start = wl->fw_len;
397
398 /*
399 * Layout before the actual NVS tables:
400 * 1 byte : burst length.
401 * 2 bytes: destination address.
402 * n bytes: data to burst copy.
403 *
404 * This is ended by a 0 length, then the NVS tables.
405 */
406
407 while (nvs_ptr[0]) {
408 burst_len = nvs_ptr[0];
409 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
410
411 /* We move our pointer to the data */
412 nvs_ptr += 3;
413
414 for (i = 0; i < burst_len; i++) {
415 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
416 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
417
418 wl1251_debug(DEBUG_BOOT,
419 "nvs burst write 0x%x: 0x%x",
420 dest_addr, val);
421 wl1251_mem_write32(wl, dest_addr, val);
422
423 nvs_ptr += 4;
424 dest_addr += 4;
425 }
426 }
427
428 /*
429 * We've reached the first zero length, the first NVS table
430 * is 7 bytes further.
431 */
432 nvs_ptr += 7;
433 nvs_len -= nvs_ptr - nvs;
434 nvs_len = ALIGN(nvs_len, 4);
435
436 /* Now we must set the partition correctly */
437 wl1251_set_partition(wl, nvs_start,
438 WL1251_PART_DOWN_MEM_SIZE,
439 WL1251_PART_DOWN_REG_START,
440 WL1251_PART_DOWN_REG_SIZE);
441
442 /* And finally we upload the NVS tables */
443 nvs_bytes_written = 0;
444 while (nvs_bytes_written < nvs_len) {
445 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
446 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
447
448 val = cpu_to_le32(val);
449
450 wl1251_debug(DEBUG_BOOT,
451 "nvs write table 0x%x: 0x%x",
452 nvs_start, val);
453 wl1251_mem_write32(wl, nvs_start, val);
454
455 nvs_ptr += 4;
456 nvs_bytes_written += 4;
457 nvs_start += 4;
458 }
459
460 return 0;
461}
462
463int wl1251_boot(struct wl1251 *wl)
464{
465 int ret = 0, minor_minor_e2_ver;
466 u32 tmp, boot_data;
467
468 ret = wl1251_boot_soft_reset(wl);
469 if (ret < 0)
470 goto out;
471
472 /* 2. start processing NVS file */
473 ret = wl1251_boot_upload_nvs(wl);
474 if (ret < 0)
475 goto out;
476
477 /* write firmware's last address (ie. it's length) to
478 * ACX_EEPROMLESS_IND_REG */
479 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
480
481 /* 6. read the EEPROM parameters */
482 tmp = wl1251_reg_read32(wl, SCR_PAD2);
483
484 /* 7. read bootdata */
485 wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
486 wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
487 tmp = wl1251_reg_read32(wl, SCR_PAD3);
488
489 /* 8. check bootdata and call restart sequence */
490 wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
491 minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
492
493 wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
494 "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
495 wl->boot_attr.radio_type, wl->boot_attr.major,
496 wl->boot_attr.minor, minor_minor_e2_ver);
497
498 ret = wl1251_boot_init_seq(wl);
499 if (ret < 0)
500 goto out;
501
502 /* 9. NVS processing done */
503 boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
504
505 wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
506
507 /* 10. check that ECPU_CONTROL_HALT bits are set in
508 * pWhalBus->uBootData and start uploading firmware
509 */
510 if ((boot_data & ECPU_CONTROL_HALT) == 0) {
511 wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
512 ret = -EIO;
513 goto out;
514 }
515
516 ret = wl1251_boot_upload_firmware(wl);
517 if (ret < 0)
518 goto out;
519
520 /* 10.5 start firmware */
521 ret = wl1251_boot_run_firmware(wl);
522 if (ret < 0)
523 goto out;
524
525out:
526 return ret;
527}
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h
index 798362d71e3f..90063697e8f2 100644
--- a/drivers/net/wireless/wl12xx/wl1251_boot.h
+++ b/drivers/net/wireless/wl12xx/wl1251_boot.h
@@ -30,6 +30,7 @@ int wl1251_boot_soft_reset(struct wl1251 *wl);
30int wl1251_boot_init_seq(struct wl1251 *wl); 30int wl1251_boot_init_seq(struct wl1251 *wl);
31int wl1251_boot_run_firmware(struct wl1251 *wl); 31int wl1251_boot_run_firmware(struct wl1251 *wl);
32void wl1251_boot_target_enable_interrupts(struct wl1251 *wl); 32void wl1251_boot_target_enable_interrupts(struct wl1251 *wl);
33int wl1251_boot(struct wl1251 *wl);
33 34
34/* number of times we try to read the INIT interrupt */ 35/* number of times we try to read the INIT interrupt */
35#define INIT_LOOP 20000 36#define INIT_LOOP 20000
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c
index dc04d1fc2ee4..770f260726bd 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c
@@ -2,11 +2,10 @@
2 2
3#include <linux/module.h> 3#include <linux/module.h>
4#include <linux/crc7.h> 4#include <linux/crc7.h>
5#include <linux/spi/spi.h>
6 5
7#include "wl1251.h" 6#include "wl1251.h"
8#include "reg.h" 7#include "wl1251_reg.h"
9#include "wl1251_spi.h" 8#include "wl1251_io.h"
10#include "wl1251_ps.h" 9#include "wl1251_ps.h"
11#include "wl1251_acx.h" 10#include "wl1251_acx.h"
12 11
@@ -31,14 +30,14 @@ int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
31 30
32 WARN_ON(len % 4 != 0); 31 WARN_ON(len % 4 != 0);
33 32
34 wl1251_spi_mem_write(wl, wl->cmd_box_addr, buf, len); 33 wl1251_mem_write(wl, wl->cmd_box_addr, buf, len);
35 34
36 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); 35 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
37 36
38 timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT); 37 timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT);
39 38
40 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); 39 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
41 while (!(intr & wl->chip.intr_cmd_complete)) { 40 while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) {
42 if (time_after(jiffies, timeout)) { 41 if (time_after(jiffies, timeout)) {
43 wl1251_error("command complete timeout"); 42 wl1251_error("command complete timeout");
44 ret = -ETIMEDOUT; 43 ret = -ETIMEDOUT;
@@ -51,7 +50,7 @@ int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len)
51 } 50 }
52 51
53 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, 52 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
54 wl->chip.intr_cmd_complete); 53 WL1251_ACX_INTR_CMD_COMPLETE);
55 54
56out: 55out:
57 return ret; 56 return ret;
@@ -86,7 +85,7 @@ int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer)
86 * The answer would be a wl1251_command, where the 85 * The answer would be a wl1251_command, where the
87 * parameter array contains the actual answer. 86 * parameter array contains the actual answer.
88 */ 87 */
89 wl1251_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); 88 wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
90 89
91 cmd_answer = buf; 90 cmd_answer = buf;
92 91
@@ -125,7 +124,7 @@ int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
125 } 124 }
126 125
127 /* the interrogate command got in, we can read the answer */ 126 /* the interrogate command got in, we can read the answer */
128 wl1251_spi_mem_read(wl, wl->cmd_box_addr, buf, len); 127 wl1251_mem_read(wl, wl->cmd_box_addr, buf, len);
129 128
130 acx = buf; 129 acx = buf;
131 if (acx->cmd.status != CMD_STATUS_SUCCESS) 130 if (acx->cmd.status != CMD_STATUS_SUCCESS)
@@ -252,10 +251,9 @@ out:
252 return ret; 251 return ret;
253} 252}
254 253
255int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 dtim_interval, 254int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
256 u16 beacon_interval, u8 wait) 255 u16 beacon_interval, u8 dtim_interval)
257{ 256{
258 unsigned long timeout;
259 struct cmd_join *join; 257 struct cmd_join *join;
260 int ret, i; 258 int ret, i;
261 u8 *bssid; 259 u8 *bssid;
@@ -266,15 +264,9 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 dtim_interval,
266 goto out; 264 goto out;
267 } 265 }
268 266
269 /* FIXME: this should be in main.c */ 267 wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d",
270 ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, 268 bss_type == BSS_TYPE_IBSS ? " ibss" : "",
271 DEFAULT_HW_GEN_MODULATION_TYPE, 269 channel, beacon_interval, dtim_interval);
272 wl->tx_mgmt_frm_rate,
273 wl->tx_mgmt_frm_mod);
274 if (ret < 0)
275 goto out;
276
277 wl1251_debug(DEBUG_CMD, "cmd join");
278 270
279 /* Reverse order BSSID */ 271 /* Reverse order BSSID */
280 bssid = (u8 *) &join->bssid_lsb; 272 bssid = (u8 *) &join->bssid_lsb;
@@ -284,13 +276,22 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 dtim_interval,
284 join->rx_config_options = wl->rx_config; 276 join->rx_config_options = wl->rx_config;
285 join->rx_filter_options = wl->rx_filter; 277 join->rx_filter_options = wl->rx_filter;
286 278
279 /*
280 * FIXME: disable temporarily all filters because after commit
281 * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
282 * association. The filter logic needs to be implemented properly
283 * and once that is done, this hack can be removed.
284 */
285 join->rx_config_options = 0;
286 join->rx_filter_options = WL1251_DEFAULT_RX_FILTER;
287
287 join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | 288 join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
288 RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; 289 RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
289 290
290 join->beacon_interval = beacon_interval; 291 join->beacon_interval = beacon_interval;
291 join->dtim_interval = dtim_interval; 292 join->dtim_interval = dtim_interval;
292 join->bss_type = bss_type; 293 join->bss_type = bss_type;
293 join->channel = wl->channel; 294 join->channel = channel;
294 join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; 295 join->ctrl = JOIN_CMD_CTRL_TX_FLUSH;
295 296
296 ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); 297 ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
@@ -299,15 +300,6 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 dtim_interval,
299 goto out; 300 goto out;
300 } 301 }
301 302
302 timeout = msecs_to_jiffies(JOIN_TIMEOUT);
303
304 /*
305 * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
306 * simplify locking we just sleep instead, for now
307 */
308 if (wait)
309 msleep(10);
310
311out: 303out:
312 kfree(join); 304 kfree(join);
313 return ret; 305 return ret;
@@ -318,14 +310,6 @@ int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode)
318 struct wl1251_cmd_ps_params *ps_params = NULL; 310 struct wl1251_cmd_ps_params *ps_params = NULL;
319 int ret = 0; 311 int ret = 0;
320 312
321 /* FIXME: this should be in ps.c */
322 ret = wl1251_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP,
323 wl->listen_int);
324 if (ret < 0) {
325 wl1251_error("couldn't set wake up conditions");
326 goto out;
327 }
328
329 wl1251_debug(DEBUG_CMD, "cmd set ps mode"); 313 wl1251_debug(DEBUG_CMD, "cmd set ps mode");
330 314
331 ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); 315 ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
@@ -379,7 +363,7 @@ int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
379 } 363 }
380 364
381 /* the read command got in, we can now read the answer */ 365 /* the read command got in, we can now read the answer */
382 wl1251_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); 366 wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
383 367
384 if (cmd->header.status != CMD_STATUS_SUCCESS) 368 if (cmd->header.status != CMD_STATUS_SUCCESS)
385 wl1251_error("error in read command result: %d", 369 wl1251_error("error in read command result: %d",
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h
index 64f228dd9a9b..dff798ad0ef5 100644
--- a/drivers/net/wireless/wl12xx/wl1251_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h
@@ -36,8 +36,8 @@ int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len);
36int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, 36int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity,
37 void *bitmap, u16 bitmap_len, u8 bitmap_control); 37 void *bitmap, u16 bitmap_len, u8 bitmap_control);
38int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable); 38int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable);
39int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 dtim_interval, 39int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel,
40 u16 beacon_interval, u8 wait); 40 u16 beacon_interval, u8 dtim_interval);
41int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode); 41int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode);
42int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, 42int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer,
43 size_t len); 43 size_t len);
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c
index 1a0a0bc1a31f..00076c4a8a21 100644
--- a/drivers/net/wireless/wl12xx/wl1251_event.c
+++ b/drivers/net/wireless/wl12xx/wl1251_event.c
@@ -23,8 +23,8 @@
23 */ 23 */
24 24
25#include "wl1251.h" 25#include "wl1251.h"
26#include "reg.h" 26#include "wl1251_reg.h"
27#include "wl1251_spi.h" 27#include "wl1251_io.h"
28#include "wl1251_event.h" 28#include "wl1251_event.h"
29#include "wl1251_ps.h" 29#include "wl1251_ps.h"
30 30
@@ -39,6 +39,7 @@ static int wl1251_event_scan_complete(struct wl1251 *wl,
39 mutex_unlock(&wl->mutex); 39 mutex_unlock(&wl->mutex);
40 ieee80211_scan_completed(wl->hw, false); 40 ieee80211_scan_completed(wl->hw, false);
41 mutex_lock(&wl->mutex); 41 mutex_lock(&wl->mutex);
42 wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed");
42 wl->scanning = false; 43 wl->scanning = false;
43 } 44 }
44 45
@@ -112,7 +113,7 @@ int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num)
112 return -EINVAL; 113 return -EINVAL;
113 114
114 /* first we read the mbox descriptor */ 115 /* first we read the mbox descriptor */
115 wl1251_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, 116 wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
116 sizeof(struct event_mailbox)); 117 sizeof(struct event_mailbox));
117 118
118 /* process the descriptor */ 119 /* process the descriptor */
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c
index df6c60f0fd66..b2ee4f468fc4 100644
--- a/drivers/net/wireless/wl12xx/wl1251_init.c
+++ b/drivers/net/wireless/wl12xx/wl1251_init.c
@@ -28,6 +28,7 @@
28#include "wl12xx_80211.h" 28#include "wl12xx_80211.h"
29#include "wl1251_acx.h" 29#include "wl1251_acx.h"
30#include "wl1251_cmd.h" 30#include "wl1251_cmd.h"
31#include "wl1251_reg.h"
31 32
32int wl1251_hw_init_hwenc_config(struct wl1251 *wl) 33int wl1251_hw_init_hwenc_config(struct wl1251 *wl)
33{ 34{
@@ -198,3 +199,215 @@ int wl1251_hw_init_power_auth(struct wl1251 *wl)
198{ 199{
199 return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); 200 return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
200} 201}
202
203int wl1251_hw_init_mem_config(struct wl1251 *wl)
204{
205 int ret;
206
207 ret = wl1251_acx_mem_cfg(wl);
208 if (ret < 0)
209 return ret;
210
211 wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
212 GFP_KERNEL);
213 if (!wl->target_mem_map) {
214 wl1251_error("couldn't allocate target memory map");
215 return -ENOMEM;
216 }
217
218 /* we now ask for the firmware built memory map */
219 ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
220 sizeof(struct wl1251_acx_mem_map));
221 if (ret < 0) {
222 wl1251_error("couldn't retrieve firmware memory map");
223 kfree(wl->target_mem_map);
224 wl->target_mem_map = NULL;
225 return ret;
226 }
227
228 return 0;
229}
230
231static int wl1251_hw_init_txq_fill(u8 qid,
232 struct acx_tx_queue_qos_config *config,
233 u32 num_blocks)
234{
235 config->qid = qid;
236
237 switch (qid) {
238 case QOS_AC_BE:
239 config->high_threshold =
240 (QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
241 config->low_threshold =
242 (QOS_TX_LOW_BE_DEF * num_blocks) / 100;
243 break;
244 case QOS_AC_BK:
245 config->high_threshold =
246 (QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
247 config->low_threshold =
248 (QOS_TX_LOW_BK_DEF * num_blocks) / 100;
249 break;
250 case QOS_AC_VI:
251 config->high_threshold =
252 (QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
253 config->low_threshold =
254 (QOS_TX_LOW_VI_DEF * num_blocks) / 100;
255 break;
256 case QOS_AC_VO:
257 config->high_threshold =
258 (QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
259 config->low_threshold =
260 (QOS_TX_LOW_VO_DEF * num_blocks) / 100;
261 break;
262 default:
263 wl1251_error("Invalid TX queue id: %d", qid);
264 return -EINVAL;
265 }
266
267 return 0;
268}
269
270static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
271{
272 struct acx_tx_queue_qos_config *config;
273 struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
274 int ret, i;
275
276 wl1251_debug(DEBUG_ACX, "acx tx queue config");
277
278 config = kzalloc(sizeof(*config), GFP_KERNEL);
279 if (!config) {
280 ret = -ENOMEM;
281 goto out;
282 }
283
284 for (i = 0; i < MAX_NUM_OF_AC; i++) {
285 ret = wl1251_hw_init_txq_fill(i, config,
286 wl_mem_map->num_tx_mem_blocks);
287 if (ret < 0)
288 goto out;
289
290 ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG,
291 config, sizeof(*config));
292 if (ret < 0)
293 goto out;
294 }
295
296out:
297 kfree(config);
298 return ret;
299}
300
301static int wl1251_hw_init_data_path_config(struct wl1251 *wl)
302{
303 int ret;
304
305 /* asking for the data path parameters */
306 wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
307 GFP_KERNEL);
308 if (!wl->data_path) {
309 wl1251_error("Couldnt allocate data path parameters");
310 return -ENOMEM;
311 }
312
313 ret = wl1251_acx_data_path_params(wl, wl->data_path);
314 if (ret < 0) {
315 kfree(wl->data_path);
316 wl->data_path = NULL;
317 return ret;
318 }
319
320 return 0;
321}
322
323
324int wl1251_hw_init(struct wl1251 *wl)
325{
326 struct wl1251_acx_mem_map *wl_mem_map;
327 int ret;
328
329 ret = wl1251_hw_init_hwenc_config(wl);
330 if (ret < 0)
331 return ret;
332
333 /* Template settings */
334 ret = wl1251_hw_init_templates_config(wl);
335 if (ret < 0)
336 return ret;
337
338 /* Default memory configuration */
339 ret = wl1251_hw_init_mem_config(wl);
340 if (ret < 0)
341 return ret;
342
343 /* Default data path configuration */
344 ret = wl1251_hw_init_data_path_config(wl);
345 if (ret < 0)
346 goto out_free_memmap;
347
348 /* RX config */
349 ret = wl1251_hw_init_rx_config(wl,
350 RX_CFG_PROMISCUOUS | RX_CFG_TSF,
351 RX_FILTER_OPTION_DEF);
352 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
353 RX_FILTER_OPTION_FILTER_ALL); */
354 if (ret < 0)
355 goto out_free_data_path;
356
357 /* TX queues config */
358 ret = wl1251_hw_init_tx_queue_config(wl);
359 if (ret < 0)
360 goto out_free_data_path;
361
362 /* PHY layer config */
363 ret = wl1251_hw_init_phy_config(wl);
364 if (ret < 0)
365 goto out_free_data_path;
366
367 /* Beacon filtering */
368 ret = wl1251_hw_init_beacon_filter(wl);
369 if (ret < 0)
370 goto out_free_data_path;
371
372 /* Bluetooth WLAN coexistence */
373 ret = wl1251_hw_init_pta(wl);
374 if (ret < 0)
375 goto out_free_data_path;
376
377 /* Energy detection */
378 ret = wl1251_hw_init_energy_detection(wl);
379 if (ret < 0)
380 goto out_free_data_path;
381
382 /* Beacons and boradcast settings */
383 ret = wl1251_hw_init_beacon_broadcast(wl);
384 if (ret < 0)
385 goto out_free_data_path;
386
387 /* Enable data path */
388 ret = wl1251_cmd_data_path(wl, wl->channel, 1);
389 if (ret < 0)
390 goto out_free_data_path;
391
392 /* Default power state */
393 ret = wl1251_hw_init_power_auth(wl);
394 if (ret < 0)
395 goto out_free_data_path;
396
397 wl_mem_map = wl->target_mem_map;
398 wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
399 wl_mem_map->num_tx_mem_blocks,
400 wl->data_path->tx_control_addr,
401 wl_mem_map->num_rx_mem_blocks,
402 wl->data_path->rx_control_addr);
403
404 return 0;
405
406 out_free_data_path:
407 kfree(wl->data_path);
408
409 out_free_memmap:
410 kfree(wl->target_mem_map);
411
412 return ret;
413}
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h
index 8596188e834e..b3b25ec885ea 100644
--- a/drivers/net/wireless/wl12xx/wl1251_init.h
+++ b/drivers/net/wireless/wl12xx/wl1251_init.h
@@ -35,5 +35,7 @@ int wl1251_hw_init_pta(struct wl1251 *wl);
35int wl1251_hw_init_energy_detection(struct wl1251 *wl); 35int wl1251_hw_init_energy_detection(struct wl1251 *wl);
36int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl); 36int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl);
37int wl1251_hw_init_power_auth(struct wl1251 *wl); 37int wl1251_hw_init_power_auth(struct wl1251 *wl);
38int wl1251_hw_init_mem_config(struct wl1251 *wl);
39int wl1251_hw_init(struct wl1251 *wl);
38 40
39#endif 41#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c
new file mode 100644
index 000000000000..f1c232e0887f
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.c
@@ -0,0 +1,196 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 *
6 * Contact: Kalle Valo <kalle.valo@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1251.h"
25#include "wl1251_reg.h"
26#include "wl1251_io.h"
27
28/* FIXME: this is static data nowadays and the table can be removed */
29static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = {
30 [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474),
31 [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478),
32 [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494),
33 [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498),
34 [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C),
35 [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
36 [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4),
37 [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8),
38 [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000),
39 [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C),
40 [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804)
41};
42
43static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr)
44{
45 /* If the address is lower than REGISTERS_BASE, it means that this is
46 * a chip-specific register address, so look it up in the registers
47 * table */
48 if (addr < REGISTERS_BASE) {
49 /* Make sure we don't go over the table */
50 if (addr >= ACX_REG_TABLE_LEN) {
51 wl1251_error("address out of range (%d)", addr);
52 return -EINVAL;
53 }
54 addr = wl1251_io_reg_table[addr];
55 }
56
57 return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
58}
59
60static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr)
61{
62 return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
63}
64
65void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len)
66{
67 int physical;
68
69 physical = wl1251_translate_mem_addr(wl, addr);
70
71 wl->if_ops->read(wl, physical, buf, len);
72}
73
74void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len)
75{
76 int physical;
77
78 physical = wl1251_translate_mem_addr(wl, addr);
79
80 wl->if_ops->write(wl, physical, buf, len);
81}
82
83u32 wl1251_mem_read32(struct wl1251 *wl, int addr)
84{
85 return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr));
86}
87
88void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val)
89{
90 wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val);
91}
92
93u32 wl1251_reg_read32(struct wl1251 *wl, int addr)
94{
95 return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr));
96}
97
98void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val)
99{
100 wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val);
101}
102
103/* Set the partitions to access the chip addresses.
104 *
105 * There are two VIRTUAL partitions (the memory partition and the
106 * registers partition), which are mapped to two different areas of the
107 * PHYSICAL (hardware) memory. This function also makes other checks to
108 * ensure that the partitions are not overlapping. In the diagram below, the
109 * memory partition comes before the register partition, but the opposite is
110 * also supported.
111 *
112 * PHYSICAL address
113 * space
114 *
115 * | |
116 * ...+----+--> mem_start
117 * VIRTUAL address ... | |
118 * space ... | | [PART_0]
119 * ... | |
120 * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
121 * | | ... | |
122 * |MEM | ... | |
123 * | | ... | |
124 * part_size <--+----+... | | {unused area)
125 * | | ... | |
126 * |REG | ... | |
127 * part_size | | ... | |
128 * + <--+----+... ...+----+--> reg_start
129 * reg_size ... | |
130 * ... | | [PART_1]
131 * ... | |
132 * ...+----+--> reg_start + reg_size
133 * | |
134 *
135 */
136void wl1251_set_partition(struct wl1251 *wl,
137 u32 mem_start, u32 mem_size,
138 u32 reg_start, u32 reg_size)
139{
140 struct wl1251_partition partition[2];
141
142 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
143 mem_start, mem_size);
144 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
145 reg_start, reg_size);
146
147 /* Make sure that the two partitions together don't exceed the
148 * address range */
149 if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
150 wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
151 " address range. Truncating partition[0].");
152 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
153 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
154 mem_start, mem_size);
155 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
156 reg_start, reg_size);
157 }
158
159 if ((mem_start < reg_start) &&
160 ((mem_start + mem_size) > reg_start)) {
161 /* Guarantee that the memory partition doesn't overlap the
162 * registers partition */
163 wl1251_debug(DEBUG_SPI, "End of partition[0] is "
164 "overlapping partition[1]. Adjusted.");
165 mem_size = reg_start - mem_start;
166 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
167 mem_start, mem_size);
168 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
169 reg_start, reg_size);
170 } else if ((reg_start < mem_start) &&
171 ((reg_start + reg_size) > mem_start)) {
172 /* Guarantee that the register partition doesn't overlap the
173 * memory partition */
174 wl1251_debug(DEBUG_SPI, "End of partition[1] is"
175 " overlapping partition[0]. Adjusted.");
176 reg_size = mem_start - reg_start;
177 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
178 mem_start, mem_size);
179 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
180 reg_start, reg_size);
181 }
182
183 partition[0].start = mem_start;
184 partition[0].size = mem_size;
185 partition[1].start = reg_start;
186 partition[1].size = reg_size;
187
188 wl->physical_mem_addr = mem_start;
189 wl->physical_reg_addr = reg_start;
190
191 wl->virtual_mem_addr = 0;
192 wl->virtual_reg_addr = mem_size;
193
194 wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition,
195 sizeof(partition));
196}
diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h
new file mode 100644
index 000000000000..b89d2ac62efb
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_io.h
@@ -0,0 +1,64 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21#ifndef __WL1251_IO_H__
22#define __WL1251_IO_H__
23
24#include "wl1251.h"
25
26#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
27
28#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
29#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
30#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
31#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
32
33#define HW_ACCESS_REGISTER_SIZE 4
34
35#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
36
37static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
38{
39 u32 response;
40
41 wl->if_ops->read(wl, addr, &response, sizeof(u32));
42
43 return response;
44}
45
46static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
47{
48 wl->if_ops->write(wl, addr, &val, sizeof(u32));
49}
50
51/* Memory target IO, address is translated to partition 0 */
52void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
53void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
54u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
55void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
56/* Registers IO */
57u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
58void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);
59
60void wl1251_set_partition(struct wl1251 *wl,
61 u32 part_start, u32 part_size,
62 u32 reg_start, u32 reg_size);
63
64#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c
index da4c688c46af..7148934e464d 100644
--- a/drivers/net/wireless/wl12xx/wl1251_main.c
+++ b/drivers/net/wireless/wl12xx/wl1251_main.c
@@ -26,26 +26,30 @@
26#include <linux/firmware.h> 26#include <linux/firmware.h>
27#include <linux/delay.h> 27#include <linux/delay.h>
28#include <linux/irq.h> 28#include <linux/irq.h>
29#include <linux/spi/spi.h>
30#include <linux/crc32.h> 29#include <linux/crc32.h>
31#include <linux/etherdevice.h> 30#include <linux/etherdevice.h>
32#include <linux/spi/wl12xx.h>
33 31
34#include "wl1251.h" 32#include "wl1251.h"
35#include "wl12xx_80211.h" 33#include "wl12xx_80211.h"
36#include "reg.h" 34#include "wl1251_reg.h"
37#include "wl1251_ops.h" 35#include "wl1251_io.h"
38#include "wl1251_spi.h" 36#include "wl1251_cmd.h"
39#include "wl1251_event.h" 37#include "wl1251_event.h"
40#include "wl1251_tx.h" 38#include "wl1251_tx.h"
41#include "wl1251_rx.h" 39#include "wl1251_rx.h"
42#include "wl1251_ps.h" 40#include "wl1251_ps.h"
43#include "wl1251_init.h" 41#include "wl1251_init.h"
44#include "wl1251_debugfs.h" 42#include "wl1251_debugfs.h"
43#include "wl1251_boot.h"
45 44
46static void wl1251_disable_interrupts(struct wl1251 *wl) 45void wl1251_enable_interrupts(struct wl1251 *wl)
47{ 46{
48 disable_irq(wl->irq); 47 wl->if_ops->enable_irq(wl);
48}
49
50void wl1251_disable_interrupts(struct wl1251 *wl)
51{
52 wl->if_ops->disable_irq(wl);
49} 53}
50 54
51static void wl1251_power_off(struct wl1251 *wl) 55static void wl1251_power_off(struct wl1251 *wl)
@@ -58,25 +62,13 @@ static void wl1251_power_on(struct wl1251 *wl)
58 wl->set_power(true); 62 wl->set_power(true);
59} 63}
60 64
61static irqreturn_t wl1251_irq(int irq, void *cookie)
62{
63 struct wl1251 *wl;
64
65 wl1251_debug(DEBUG_IRQ, "IRQ");
66
67 wl = cookie;
68
69 schedule_work(&wl->irq_work);
70
71 return IRQ_HANDLED;
72}
73
74static int wl1251_fetch_firmware(struct wl1251 *wl) 65static int wl1251_fetch_firmware(struct wl1251 *wl)
75{ 66{
76 const struct firmware *fw; 67 const struct firmware *fw;
68 struct device *dev = wiphy_dev(wl->hw->wiphy);
77 int ret; 69 int ret;
78 70
79 ret = request_firmware(&fw, wl->chip.fw_filename, &wl->spi->dev); 71 ret = request_firmware(&fw, WL1251_FW_NAME, dev);
80 72
81 if (ret < 0) { 73 if (ret < 0) {
82 wl1251_error("could not get firmware: %d", ret); 74 wl1251_error("could not get firmware: %d", ret);
@@ -112,9 +104,10 @@ out:
112static int wl1251_fetch_nvs(struct wl1251 *wl) 104static int wl1251_fetch_nvs(struct wl1251 *wl)
113{ 105{
114 const struct firmware *fw; 106 const struct firmware *fw;
107 struct device *dev = wiphy_dev(wl->hw->wiphy);
115 int ret; 108 int ret;
116 109
117 ret = request_firmware(&fw, wl->chip.nvs_filename, &wl->spi->dev); 110 ret = request_firmware(&fw, WL1251_NVS_NAME, dev);
118 111
119 if (ret < 0) { 112 if (ret < 0) {
120 wl1251_error("could not get nvs file: %d", ret); 113 wl1251_error("could not get nvs file: %d", ret);
@@ -164,9 +157,8 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
164 int ret = 0; 157 int ret = 0;
165 158
166 wl1251_power_on(wl); 159 wl1251_power_on(wl);
167 msleep(wl->chip.power_on_sleep); 160 msleep(WL1251_POWER_ON_SLEEP);
168 wl1251_spi_reset(wl); 161 wl->if_ops->reset(wl);
169 wl1251_spi_init(wl);
170 162
171 /* We don't need a real memory partition here, because we only want 163 /* We don't need a real memory partition here, because we only want
172 * to use the registers at this point. */ 164 * to use the registers at this point. */
@@ -182,22 +174,19 @@ static int wl1251_chip_wakeup(struct wl1251 *wl)
182 /* whal_FwCtrl_BootSm() */ 174 /* whal_FwCtrl_BootSm() */
183 175
184 /* 0. read chip id from CHIP_ID */ 176 /* 0. read chip id from CHIP_ID */
185 wl->chip.id = wl1251_reg_read32(wl, CHIP_ID_B); 177 wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B);
186 178
187 /* 1. check if chip id is valid */ 179 /* 1. check if chip id is valid */
188 180
189 switch (wl->chip.id) { 181 switch (wl->chip_id) {
190 case CHIP_ID_1251_PG12: 182 case CHIP_ID_1251_PG12:
191 wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", 183 wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)",
192 wl->chip.id); 184 wl->chip_id);
193
194 wl1251_setup(wl);
195
196 break; 185 break;
197 case CHIP_ID_1251_PG10: 186 case CHIP_ID_1251_PG10:
198 case CHIP_ID_1251_PG11: 187 case CHIP_ID_1251_PG11:
199 default: 188 default:
200 wl1251_error("unsupported chip id: 0x%x", wl->chip.id); 189 wl1251_error("unsupported chip id: 0x%x", wl->chip_id);
201 ret = -ENODEV; 190 ret = -ENODEV;
202 goto out; 191 goto out;
203 } 192 }
@@ -219,6 +208,135 @@ out:
219 return ret; 208 return ret;
220} 209}
221 210
211static void wl1251_irq_work(struct work_struct *work)
212{
213 u32 intr;
214 struct wl1251 *wl =
215 container_of(work, struct wl1251, irq_work);
216 int ret;
217
218 mutex_lock(&wl->mutex);
219
220 wl1251_debug(DEBUG_IRQ, "IRQ work");
221
222 if (wl->state == WL1251_STATE_OFF)
223 goto out;
224
225 ret = wl1251_ps_elp_wakeup(wl);
226 if (ret < 0)
227 goto out;
228
229 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
230
231 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
232 wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
233
234 if (wl->data_path) {
235 wl->rx_counter =
236 wl1251_mem_read32(wl, wl->data_path->rx_control_addr);
237
238 /* We handle a frmware bug here */
239 switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
240 case 0:
241 wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync");
242 intr &= ~WL1251_ACX_INTR_RX0_DATA;
243 intr &= ~WL1251_ACX_INTR_RX1_DATA;
244 break;
245 case 1:
246 wl1251_debug(DEBUG_IRQ, "RX: FW +1");
247 intr |= WL1251_ACX_INTR_RX0_DATA;
248 intr &= ~WL1251_ACX_INTR_RX1_DATA;
249 break;
250 case 2:
251 wl1251_debug(DEBUG_IRQ, "RX: FW +2");
252 intr |= WL1251_ACX_INTR_RX0_DATA;
253 intr |= WL1251_ACX_INTR_RX1_DATA;
254 break;
255 default:
256 wl1251_warning("RX: FW and host out of sync: %d",
257 wl->rx_counter - wl->rx_handled);
258 break;
259 }
260
261 wl->rx_handled = wl->rx_counter;
262
263
264 wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
265 }
266
267 intr &= wl->intr_mask;
268
269 if (intr == 0) {
270 wl1251_debug(DEBUG_IRQ, "INTR is 0");
271 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
272 ~(wl->intr_mask));
273
274 goto out_sleep;
275 }
276
277 if (intr & WL1251_ACX_INTR_RX0_DATA) {
278 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
279 wl1251_rx(wl);
280 }
281
282 if (intr & WL1251_ACX_INTR_RX1_DATA) {
283 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
284 wl1251_rx(wl);
285 }
286
287 if (intr & WL1251_ACX_INTR_TX_RESULT) {
288 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
289 wl1251_tx_complete(wl);
290 }
291
292 if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
293 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
294 if (intr & WL1251_ACX_INTR_EVENT_A)
295 wl1251_event_handle(wl, 0);
296 else
297 wl1251_event_handle(wl, 1);
298 }
299
300 if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
301 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
302
303 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
304
305out_sleep:
306 wl1251_ps_elp_sleep(wl);
307
308out:
309 mutex_unlock(&wl->mutex);
310}
311
312static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel,
313 u16 beacon_interval, u8 dtim_period)
314{
315 int ret;
316
317 ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE,
318 DEFAULT_HW_GEN_MODULATION_TYPE,
319 wl->tx_mgmt_frm_rate,
320 wl->tx_mgmt_frm_mod);
321 if (ret < 0)
322 goto out;
323
324
325 ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval,
326 dtim_period);
327 if (ret < 0)
328 goto out;
329
330 /*
331 * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify
332 * locking we just sleep instead, for now
333 */
334 msleep(10);
335
336out:
337 return ret;
338}
339
222static void wl1251_filter_work(struct work_struct *work) 340static void wl1251_filter_work(struct work_struct *work)
223{ 341{
224 struct wl1251 *wl = 342 struct wl1251 *wl =
@@ -234,8 +352,8 @@ static void wl1251_filter_work(struct work_struct *work)
234 if (ret < 0) 352 if (ret < 0)
235 goto out; 353 goto out;
236 354
237 /* FIXME: replace the magic numbers with proper definitions */ 355 ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int,
238 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 356 wl->dtim_period);
239 if (ret < 0) 357 if (ret < 0)
240 goto out_sleep; 358 goto out_sleep;
241 359
@@ -257,7 +375,7 @@ static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
257 * before that, the tx_work will not be initialized! 375 * before that, the tx_work will not be initialized!
258 */ 376 */
259 377
260 schedule_work(&wl->tx_work); 378 ieee80211_queue_work(wl->hw, &wl->tx_work);
261 379
262 /* 380 /*
263 * The workqueue is slow to process the tx_queue and we need stop 381 * The workqueue is slow to process the tx_queue and we need stop
@@ -297,11 +415,11 @@ static int wl1251_op_start(struct ieee80211_hw *hw)
297 if (ret < 0) 415 if (ret < 0)
298 goto out; 416 goto out;
299 417
300 ret = wl->chip.op_boot(wl); 418 ret = wl1251_boot(wl);
301 if (ret < 0) 419 if (ret < 0)
302 goto out; 420 goto out;
303 421
304 ret = wl->chip.op_hw_init(wl); 422 ret = wl1251_hw_init(wl);
305 if (ret < 0) 423 if (ret < 0)
306 goto out; 424 goto out;
307 425
@@ -311,7 +429,7 @@ static int wl1251_op_start(struct ieee80211_hw *hw)
311 429
312 wl->state = WL1251_STATE_ON; 430 wl->state = WL1251_STATE_ON;
313 431
314 wl1251_info("firmware booted (%s)", wl->chip.fw_ver); 432 wl1251_info("firmware booted (%s)", wl->fw_ver);
315 433
316out: 434out:
317 if (ret < 0) 435 if (ret < 0)
@@ -354,7 +472,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
354 mutex_lock(&wl->mutex); 472 mutex_lock(&wl->mutex);
355 473
356 /* let's notify MAC80211 about the remaining pending TX frames */ 474 /* let's notify MAC80211 about the remaining pending TX frames */
357 wl->chip.op_tx_flush(wl); 475 wl1251_tx_flush(wl);
358 wl1251_power_off(wl); 476 wl1251_power_off(wl);
359 477
360 memset(wl->bssid, 0, ETH_ALEN); 478 memset(wl->bssid, 0, ETH_ALEN);
@@ -371,6 +489,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
371 wl->psm = 0; 489 wl->psm = 0;
372 wl->tx_queue_stopped = false; 490 wl->tx_queue_stopped = false;
373 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 491 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
492 wl->channel = WL1251_DEFAULT_CHANNEL;
374 493
375 wl1251_debugfs_reset(wl); 494 wl1251_debugfs_reset(wl);
376 495
@@ -474,12 +593,12 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
474 goto out; 593 goto out;
475 594
476 if (channel != wl->channel) { 595 if (channel != wl->channel) {
477 /* FIXME: use beacon interval provided by mac80211 */ 596 wl->channel = channel;
478 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 597
598 ret = wl1251_join(wl, wl->bss_type, wl->channel,
599 wl->beacon_int, wl->dtim_period);
479 if (ret < 0) 600 if (ret < 0)
480 goto out_sleep; 601 goto out_sleep;
481
482 wl->channel = channel;
483 } 602 }
484 603
485 ret = wl1251_build_null_data(wl); 604 ret = wl1251_build_null_data(wl);
@@ -877,7 +996,7 @@ static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len,
877 if (ret < 0) 996 if (ret < 0)
878 wl1251_error("SCAN failed"); 997 wl1251_error("SCAN failed");
879 998
880 wl1251_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); 999 wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
881 1000
882 if (params->header.status != CMD_STATUS_SUCCESS) { 1001 if (params->header.status != CMD_STATUS_SUCCESS) {
883 wl1251_error("TEST command answer error: %d", 1002 wl1251_error("TEST command answer error: %d",
@@ -967,6 +1086,11 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
967 1086
968 if (changed & BSS_CHANGED_ASSOC) { 1087 if (changed & BSS_CHANGED_ASSOC) {
969 if (bss_conf->assoc) { 1088 if (bss_conf->assoc) {
1089 wl->beacon_int = bss_conf->beacon_int;
1090 wl->dtim_period = bss_conf->dtim_period;
1091
1092 /* FIXME: call join */
1093
970 wl->aid = bss_conf->aid; 1094 wl->aid = bss_conf->aid;
971 1095
972 ret = wl1251_build_ps_poll(wl, wl->aid); 1096 ret = wl1251_build_ps_poll(wl, wl->aid);
@@ -984,6 +1108,10 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
984 if (ret < 0) 1108 if (ret < 0)
985 goto out_sleep; 1109 goto out_sleep;
986 } 1110 }
1111 } else {
1112 /* use defaults when not associated */
1113 wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
1114 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
987 } 1115 }
988 } 1116 }
989 if (changed & BSS_CHANGED_ERP_SLOT) { 1117 if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1023,7 +1151,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
1023 goto out; 1151 goto out;
1024 1152
1025 if (wl->bss_type != BSS_TYPE_IBSS) { 1153 if (wl->bss_type != BSS_TYPE_IBSS) {
1026 ret = wl1251_cmd_join(wl, wl->bss_type, 5, 100, 1); 1154 ret = wl1251_join(wl, wl->bss_type, wl->channel,
1155 wl->beacon_int, wl->dtim_period);
1027 if (ret < 0) 1156 if (ret < 0)
1028 goto out_sleep; 1157 goto out_sleep;
1029 wl1251_warning("Set ctsprotect failed %d", ret); 1158 wl1251_warning("Set ctsprotect failed %d", ret);
@@ -1049,7 +1178,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
1049 if (ret < 0) 1178 if (ret < 0)
1050 goto out; 1179 goto out;
1051 1180
1052 ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); 1181 ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
1182 wl->channel, wl->dtim_period);
1053 1183
1054 if (ret < 0) 1184 if (ret < 0)
1055 goto out; 1185 goto out;
@@ -1167,8 +1297,10 @@ static int wl1251_register_hw(struct wl1251 *wl)
1167 return 0; 1297 return 0;
1168} 1298}
1169 1299
1170static int wl1251_init_ieee80211(struct wl1251 *wl) 1300int wl1251_init_ieee80211(struct wl1251 *wl)
1171{ 1301{
1302 int ret;
1303
1172 /* The tx descriptor buffer and the TKIP space */ 1304 /* The tx descriptor buffer and the TKIP space */
1173 wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc) 1305 wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc)
1174 + WL1251_TKIP_IV_SPACE; 1306 + WL1251_TKIP_IV_SPACE;
@@ -1184,38 +1316,37 @@ static int wl1251_init_ieee80211(struct wl1251 *wl)
1184 wl->hw->wiphy->max_scan_ssids = 1; 1316 wl->hw->wiphy->max_scan_ssids = 1;
1185 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; 1317 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
1186 1318
1187 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); 1319 ret = wl1251_register_hw(wl);
1320 if (ret)
1321 goto out;
1188 1322
1189 return 0; 1323 wl1251_debugfs_init(wl);
1324 wl1251_notice("initialized");
1325
1326 ret = 0;
1327
1328out:
1329 return ret;
1190} 1330}
1331EXPORT_SYMBOL_GPL(wl1251_init_ieee80211);
1191 1332
1192#define WL1251_DEFAULT_CHANNEL 1 1333struct ieee80211_hw *wl1251_alloc_hw(void)
1193static int __devinit wl1251_probe(struct spi_device *spi)
1194{ 1334{
1195 struct wl12xx_platform_data *pdata;
1196 struct ieee80211_hw *hw; 1335 struct ieee80211_hw *hw;
1197 struct wl1251 *wl; 1336 struct wl1251 *wl;
1198 int ret, i; 1337 int i;
1199 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; 1338 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1200 1339
1201 pdata = spi->dev.platform_data;
1202 if (!pdata) {
1203 wl1251_error("no platform data");
1204 return -ENODEV;
1205 }
1206
1207 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops); 1340 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops);
1208 if (!hw) { 1341 if (!hw) {
1209 wl1251_error("could not alloc ieee80211_hw"); 1342 wl1251_error("could not alloc ieee80211_hw");
1210 return -ENOMEM; 1343 return ERR_PTR(-ENOMEM);
1211 } 1344 }
1212 1345
1213 wl = hw->priv; 1346 wl = hw->priv;
1214 memset(wl, 0, sizeof(*wl)); 1347 memset(wl, 0, sizeof(*wl));
1215 1348
1216 wl->hw = hw; 1349 wl->hw = hw;
1217 dev_set_drvdata(&spi->dev, wl);
1218 wl->spi = spi;
1219 1350
1220 wl->data_in_count = 0; 1351 wl->data_in_count = 0;
1221 1352
@@ -1237,16 +1368,17 @@ static int __devinit wl1251_probe(struct spi_device *spi)
1237 wl->psm_requested = false; 1368 wl->psm_requested = false;
1238 wl->tx_queue_stopped = false; 1369 wl->tx_queue_stopped = false;
1239 wl->power_level = WL1251_DEFAULT_POWER_LEVEL; 1370 wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
1240 1371 wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
1241 /* We use the default power on sleep time until we know which chip 1372 wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
1242 * we're using */
1243 wl->chip.power_on_sleep = WL1251_DEFAULT_POWER_ON_SLEEP;
1244 1373
1245 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) 1374 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1246 wl->tx_frames[i] = NULL; 1375 wl->tx_frames[i] = NULL;
1247 1376
1248 wl->next_tx_complete = 0; 1377 wl->next_tx_complete = 0;
1249 1378
1379 INIT_WORK(&wl->irq_work, wl1251_irq_work);
1380 INIT_WORK(&wl->tx_work, wl1251_tx_work);
1381
1250 /* 1382 /*
1251 * In case our MAC address is not correctly set, 1383 * In case our MAC address is not correctly set,
1252 * we use a random but Nokia MAC. 1384 * we use a random but Nokia MAC.
@@ -1263,79 +1395,20 @@ static int __devinit wl1251_probe(struct spi_device *spi)
1263 wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); 1395 wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
1264 if (!wl->rx_descriptor) { 1396 if (!wl->rx_descriptor) {
1265 wl1251_error("could not allocate memory for rx descriptor"); 1397 wl1251_error("could not allocate memory for rx descriptor");
1266 ret = -ENOMEM; 1398 ieee80211_free_hw(hw);
1267 goto out_free; 1399 return ERR_PTR(-ENOMEM);
1268 }
1269
1270 /* This is the only SPI value that we need to set here, the rest
1271 * comes from the board-peripherals file */
1272 spi->bits_per_word = 32;
1273
1274 ret = spi_setup(spi);
1275 if (ret < 0) {
1276 wl1251_error("spi_setup failed");
1277 goto out_free;
1278 } 1400 }
1279 1401
1280 wl->set_power = pdata->set_power; 1402 return hw;
1281 if (!wl->set_power) {
1282 wl1251_error("set power function missing in platform data");
1283 ret = -ENODEV;
1284 goto out_free;
1285 }
1286
1287 wl->irq = spi->irq;
1288 if (wl->irq < 0) {
1289 wl1251_error("irq missing in platform data");
1290 ret = -ENODEV;
1291 goto out_free;
1292 }
1293
1294 ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
1295 if (ret < 0) {
1296 wl1251_error("request_irq() failed: %d", ret);
1297 goto out_free;
1298 }
1299
1300 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1301
1302 disable_irq(wl->irq);
1303
1304 ret = wl1251_init_ieee80211(wl);
1305 if (ret)
1306 goto out_irq;
1307
1308 ret = wl1251_register_hw(wl);
1309 if (ret)
1310 goto out_irq;
1311
1312 wl1251_debugfs_init(wl);
1313
1314 wl1251_notice("initialized");
1315
1316 return 0;
1317
1318 out_irq:
1319 free_irq(wl->irq, wl);
1320
1321 out_free:
1322 kfree(wl->rx_descriptor);
1323 wl->rx_descriptor = NULL;
1324
1325 ieee80211_free_hw(hw);
1326
1327 return ret;
1328} 1403}
1404EXPORT_SYMBOL_GPL(wl1251_alloc_hw);
1329 1405
1330static int __devexit wl1251_remove(struct spi_device *spi) 1406int wl1251_free_hw(struct wl1251 *wl)
1331{ 1407{
1332 struct wl1251 *wl = dev_get_drvdata(&spi->dev);
1333
1334 ieee80211_unregister_hw(wl->hw); 1408 ieee80211_unregister_hw(wl->hw);
1335 1409
1336 wl1251_debugfs_exit(wl); 1410 wl1251_debugfs_exit(wl);
1337 1411
1338 free_irq(wl->irq, wl);
1339 kfree(wl->target_mem_map); 1412 kfree(wl->target_mem_map);
1340 kfree(wl->data_path); 1413 kfree(wl->data_path);
1341 kfree(wl->fw); 1414 kfree(wl->fw);
@@ -1350,44 +1423,8 @@ static int __devexit wl1251_remove(struct spi_device *spi)
1350 1423
1351 return 0; 1424 return 0;
1352} 1425}
1426EXPORT_SYMBOL_GPL(wl1251_free_hw);
1353 1427
1354 1428MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
1355static struct spi_driver wl1251_spi_driver = {
1356 .driver = {
1357 /* FIXME: use wl12xx name to not break the user space */
1358 .name = "wl12xx",
1359 .bus = &spi_bus_type,
1360 .owner = THIS_MODULE,
1361 },
1362
1363 .probe = wl1251_probe,
1364 .remove = __devexit_p(wl1251_remove),
1365};
1366
1367static int __init wl1251_init(void)
1368{
1369 int ret;
1370
1371 ret = spi_register_driver(&wl1251_spi_driver);
1372 if (ret < 0) {
1373 wl1251_error("failed to register spi driver: %d", ret);
1374 goto out;
1375 }
1376
1377out:
1378 return ret;
1379}
1380
1381static void __exit wl1251_exit(void)
1382{
1383 spi_unregister_driver(&wl1251_spi_driver);
1384
1385 wl1251_notice("unloaded");
1386}
1387
1388module_init(wl1251_init);
1389module_exit(wl1251_exit);
1390
1391MODULE_LICENSE("GPL"); 1429MODULE_LICENSE("GPL");
1392MODULE_AUTHOR("Kalle Valo <Kalle.Valo@nokia.com>, " 1430MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
1393 "Luciano Coelho <luciano.coelho@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.c b/drivers/net/wireless/wl12xx/wl1251_ops.c
deleted file mode 100644
index e7b9aab3682f..000000000000
--- a/drivers/net/wireless/wl12xx/wl1251_ops.c
+++ /dev/null
@@ -1,728 +0,0 @@
1/*
2 * This file is part of wl1251
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Kalle Valo <kalle.valo@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26
27#include "wl1251_ops.h"
28#include "reg.h"
29#include "wl1251_spi.h"
30#include "wl1251_boot.h"
31#include "wl1251_event.h"
32#include "wl1251_acx.h"
33#include "wl1251_tx.h"
34#include "wl1251_rx.h"
35#include "wl1251_ps.h"
36#include "wl1251_init.h"
37
38static struct wl1251_partition_set wl1251_part_table[PART_TABLE_LEN] = {
39 [PART_DOWN] = {
40 .mem = {
41 .start = 0x00000000,
42 .size = 0x00016800
43 },
44 .reg = {
45 .start = REGISTERS_BASE,
46 .size = REGISTERS_DOWN_SIZE
47 },
48 },
49
50 [PART_WORK] = {
51 .mem = {
52 .start = 0x00028000,
53 .size = 0x00014000
54 },
55 .reg = {
56 .start = REGISTERS_BASE,
57 .size = REGISTERS_WORK_SIZE
58 },
59 },
60
61 /* WL1251 doesn't use the DRPW partition, so we don't set it here */
62};
63
64static enum wl12xx_acx_int_reg wl1251_acx_reg_table[ACX_REG_TABLE_LEN] = {
65 [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474),
66 [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478),
67 [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494),
68 [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498),
69 [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C),
70 [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0),
71 [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4),
72 [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8),
73 [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000),
74 [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C),
75 [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804)
76};
77
78static int wl1251_upload_firmware(struct wl1251 *wl)
79{
80 struct wl1251_partition_set *p_table = wl->chip.p_table;
81 int addr, chunk_num, partition_limit;
82 size_t fw_data_len;
83 u8 *p;
84
85 /* whal_FwCtrl_LoadFwImageSm() */
86
87 wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x",
88 wl1251_reg_read32(wl, CHIP_ID_B));
89
90 /* 10.0 check firmware length and set partition */
91 fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) |
92 (wl->fw[6] << 8) | (wl->fw[7]);
93
94 wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len,
95 CHUNK_SIZE);
96
97 if ((fw_data_len % 4) != 0) {
98 wl1251_error("firmware length not multiple of four");
99 return -EIO;
100 }
101
102 wl1251_set_partition(wl,
103 p_table[PART_DOWN].mem.start,
104 p_table[PART_DOWN].mem.size,
105 p_table[PART_DOWN].reg.start,
106 p_table[PART_DOWN].reg.size);
107
108 /* 10.1 set partition limit and chunk num */
109 chunk_num = 0;
110 partition_limit = p_table[PART_DOWN].mem.size;
111
112 while (chunk_num < fw_data_len / CHUNK_SIZE) {
113 /* 10.2 update partition, if needed */
114 addr = p_table[PART_DOWN].mem.start +
115 (chunk_num + 2) * CHUNK_SIZE;
116 if (addr > partition_limit) {
117 addr = p_table[PART_DOWN].mem.start +
118 chunk_num * CHUNK_SIZE;
119 partition_limit = chunk_num * CHUNK_SIZE +
120 p_table[PART_DOWN].mem.size;
121 wl1251_set_partition(wl,
122 addr,
123 p_table[PART_DOWN].mem.size,
124 p_table[PART_DOWN].reg.start,
125 p_table[PART_DOWN].reg.size);
126 }
127
128 /* 10.3 upload the chunk */
129 addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE;
130 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
131 wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
132 p, addr);
133 wl1251_spi_mem_write(wl, addr, p, CHUNK_SIZE);
134
135 chunk_num++;
136 }
137
138 /* 10.4 upload the last chunk */
139 addr = p_table[PART_DOWN].mem.start + chunk_num * CHUNK_SIZE;
140 p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE;
141 wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x",
142 fw_data_len % CHUNK_SIZE, p, addr);
143 wl1251_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
144
145 return 0;
146}
147
148static int wl1251_upload_nvs(struct wl1251 *wl)
149{
150 size_t nvs_len, nvs_bytes_written, burst_len;
151 int nvs_start, i;
152 u32 dest_addr, val;
153 u8 *nvs_ptr, *nvs;
154
155 nvs = wl->nvs;
156 if (nvs == NULL)
157 return -ENODEV;
158
159 nvs_ptr = nvs;
160
161 nvs_len = wl->nvs_len;
162 nvs_start = wl->fw_len;
163
164 /*
165 * Layout before the actual NVS tables:
166 * 1 byte : burst length.
167 * 2 bytes: destination address.
168 * n bytes: data to burst copy.
169 *
170 * This is ended by a 0 length, then the NVS tables.
171 */
172
173 while (nvs_ptr[0]) {
174 burst_len = nvs_ptr[0];
175 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
176
177 /* We move our pointer to the data */
178 nvs_ptr += 3;
179
180 for (i = 0; i < burst_len; i++) {
181 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
182 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
183
184 wl1251_debug(DEBUG_BOOT,
185 "nvs burst write 0x%x: 0x%x",
186 dest_addr, val);
187 wl1251_mem_write32(wl, dest_addr, val);
188
189 nvs_ptr += 4;
190 dest_addr += 4;
191 }
192 }
193
194 /*
195 * We've reached the first zero length, the first NVS table
196 * is 7 bytes further.
197 */
198 nvs_ptr += 7;
199 nvs_len -= nvs_ptr - nvs;
200 nvs_len = ALIGN(nvs_len, 4);
201
202 /* Now we must set the partition correctly */
203 wl1251_set_partition(wl, nvs_start,
204 wl->chip.p_table[PART_DOWN].mem.size,
205 wl->chip.p_table[PART_DOWN].reg.start,
206 wl->chip.p_table[PART_DOWN].reg.size);
207
208 /* And finally we upload the NVS tables */
209 nvs_bytes_written = 0;
210 while (nvs_bytes_written < nvs_len) {
211 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
212 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
213
214 val = cpu_to_le32(val);
215
216 wl1251_debug(DEBUG_BOOT,
217 "nvs write table 0x%x: 0x%x",
218 nvs_start, val);
219 wl1251_mem_write32(wl, nvs_start, val);
220
221 nvs_ptr += 4;
222 nvs_bytes_written += 4;
223 nvs_start += 4;
224 }
225
226 return 0;
227}
228
229static int wl1251_boot(struct wl1251 *wl)
230{
231 int ret = 0, minor_minor_e2_ver;
232 u32 tmp, boot_data;
233
234 ret = wl1251_boot_soft_reset(wl);
235 if (ret < 0)
236 goto out;
237
238 /* 2. start processing NVS file */
239 ret = wl->chip.op_upload_nvs(wl);
240 if (ret < 0)
241 goto out;
242
243 /* write firmware's last address (ie. it's length) to
244 * ACX_EEPROMLESS_IND_REG */
245 wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len);
246
247 /* 6. read the EEPROM parameters */
248 tmp = wl1251_reg_read32(wl, SCR_PAD2);
249
250 /* 7. read bootdata */
251 wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8;
252 wl->boot_attr.major = (tmp & 0x00FF0000) >> 16;
253 tmp = wl1251_reg_read32(wl, SCR_PAD3);
254
255 /* 8. check bootdata and call restart sequence */
256 wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16;
257 minor_minor_e2_ver = (tmp & 0xFF000000) >> 24;
258
259 wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x "
260 "minorE2Ver 0x%x minor_minor_e2_ver 0x%x",
261 wl->boot_attr.radio_type, wl->boot_attr.major,
262 wl->boot_attr.minor, minor_minor_e2_ver);
263
264 ret = wl1251_boot_init_seq(wl);
265 if (ret < 0)
266 goto out;
267
268 /* 9. NVS processing done */
269 boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
270
271 wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data);
272
273 /* 10. check that ECPU_CONTROL_HALT bits are set in
274 * pWhalBus->uBootData and start uploading firmware
275 */
276 if ((boot_data & ECPU_CONTROL_HALT) == 0) {
277 wl1251_error("boot failed, ECPU_CONTROL_HALT not set");
278 ret = -EIO;
279 goto out;
280 }
281
282 ret = wl->chip.op_upload_fw(wl);
283 if (ret < 0)
284 goto out;
285
286 /* 10.5 start firmware */
287 ret = wl1251_boot_run_firmware(wl);
288 if (ret < 0)
289 goto out;
290
291out:
292 return ret;
293}
294
295static int wl1251_mem_cfg(struct wl1251 *wl)
296{
297 struct wl1251_acx_config_memory *mem_conf;
298 int ret, i;
299
300 wl1251_debug(DEBUG_ACX, "wl1251 mem cfg");
301
302 mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
303 if (!mem_conf) {
304 ret = -ENOMEM;
305 goto out;
306 }
307
308 /* memory config */
309 mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
310 mem_conf->mem_config.rx_mem_block_num = 35;
311 mem_conf->mem_config.tx_min_mem_block_num = 64;
312 mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES;
313 mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING;
314 mem_conf->mem_config.num_ssid_profiles = 1;
315 mem_conf->mem_config.debug_buffer_size =
316 cpu_to_le16(TRACE_BUFFER_MAX_SIZE);
317
318 /* RX queue config */
319 mem_conf->rx_queue_config.dma_address = 0;
320 mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF;
321 mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY;
322 mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE;
323
324 /* TX queue config */
325 for (i = 0; i < MAX_TX_QUEUES; i++) {
326 mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF;
327 mem_conf->tx_queue_config[i].attributes = i;
328 }
329
330 ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
331 sizeof(*mem_conf));
332 if (ret < 0) {
333 wl1251_warning("wl1251 mem config failed: %d", ret);
334 goto out;
335 }
336
337out:
338 kfree(mem_conf);
339 return ret;
340}
341
342static int wl1251_hw_init_mem_config(struct wl1251 *wl)
343{
344 int ret;
345
346 ret = wl1251_mem_cfg(wl);
347 if (ret < 0)
348 return ret;
349
350 wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map),
351 GFP_KERNEL);
352 if (!wl->target_mem_map) {
353 wl1251_error("couldn't allocate target memory map");
354 return -ENOMEM;
355 }
356
357 /* we now ask for the firmware built memory map */
358 ret = wl1251_acx_mem_map(wl, wl->target_mem_map,
359 sizeof(struct wl1251_acx_mem_map));
360 if (ret < 0) {
361 wl1251_error("couldn't retrieve firmware memory map");
362 kfree(wl->target_mem_map);
363 wl->target_mem_map = NULL;
364 return ret;
365 }
366
367 return 0;
368}
369
370static void wl1251_set_ecpu_ctrl(struct wl1251 *wl, u32 flag)
371{
372 u32 cpu_ctrl;
373
374 /* 10.5.0 run the firmware (I) */
375 cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL);
376
377 /* 10.5.1 run the firmware (II) */
378 cpu_ctrl &= ~flag;
379 wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
380}
381
382static void wl1251_target_enable_interrupts(struct wl1251 *wl)
383{
384 /* Enable target's interrupts */
385 wl->intr_mask = WL1251_ACX_INTR_RX0_DATA |
386 WL1251_ACX_INTR_RX1_DATA |
387 WL1251_ACX_INTR_TX_RESULT |
388 WL1251_ACX_INTR_EVENT_A |
389 WL1251_ACX_INTR_EVENT_B |
390 WL1251_ACX_INTR_INIT_COMPLETE;
391 wl1251_boot_target_enable_interrupts(wl);
392}
393
394static void wl1251_fw_version(struct wl1251 *wl)
395{
396 wl1251_acx_fw_version(wl, wl->chip.fw_ver, sizeof(wl->chip.fw_ver));
397}
398
399static void wl1251_irq_work(struct work_struct *work)
400{
401 u32 intr;
402 struct wl1251 *wl =
403 container_of(work, struct wl1251, irq_work);
404 int ret;
405
406 mutex_lock(&wl->mutex);
407
408 wl1251_debug(DEBUG_IRQ, "IRQ work");
409
410 if (wl->state == WL1251_STATE_OFF)
411 goto out;
412
413 ret = wl1251_ps_elp_wakeup(wl);
414 if (ret < 0)
415 goto out;
416
417 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL);
418
419 intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
420 wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr);
421
422 if (wl->data_path) {
423 wl->rx_counter =
424 wl1251_mem_read32(wl, wl->data_path->rx_control_addr);
425
426 /* We handle a firmware bug here */
427 switch ((wl->rx_counter - wl->rx_handled) & 0xf) {
428 case 0:
429 wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync");
430 intr &= ~WL1251_ACX_INTR_RX0_DATA;
431 intr &= ~WL1251_ACX_INTR_RX1_DATA;
432 break;
433 case 1:
434 wl1251_debug(DEBUG_IRQ, "RX: FW +1");
435 intr |= WL1251_ACX_INTR_RX0_DATA;
436 intr &= ~WL1251_ACX_INTR_RX1_DATA;
437 break;
438 case 2:
439 wl1251_debug(DEBUG_IRQ, "RX: FW +2");
440 intr |= WL1251_ACX_INTR_RX0_DATA;
441 intr |= WL1251_ACX_INTR_RX1_DATA;
442 break;
443 default:
444 wl1251_warning("RX: FW and host out of sync: %d",
445 wl->rx_counter - wl->rx_handled);
446 break;
447 }
448
449 wl->rx_handled = wl->rx_counter;
450
451
452 wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter);
453 }
454
455 intr &= wl->intr_mask;
456
457 if (intr == 0) {
458 wl1251_debug(DEBUG_IRQ, "INTR is 0");
459 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
460 ~(wl->intr_mask));
461
462 goto out_sleep;
463 }
464
465 if (intr & WL1251_ACX_INTR_RX0_DATA) {
466 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA");
467 wl1251_rx(wl);
468 }
469
470 if (intr & WL1251_ACX_INTR_RX1_DATA) {
471 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA");
472 wl1251_rx(wl);
473 }
474
475 if (intr & WL1251_ACX_INTR_TX_RESULT) {
476 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT");
477 wl1251_tx_complete(wl);
478 }
479
480 if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) {
481 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr);
482 if (intr & WL1251_ACX_INTR_EVENT_A)
483 wl1251_event_handle(wl, 0);
484 else
485 wl1251_event_handle(wl, 1);
486 }
487
488 if (intr & WL1251_ACX_INTR_INIT_COMPLETE)
489 wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE");
490
491 wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask));
492
493out_sleep:
494 wl1251_ps_elp_sleep(wl);
495
496out:
497 mutex_unlock(&wl->mutex);
498}
499
500static int wl1251_hw_init_txq_fill(u8 qid,
501 struct acx_tx_queue_qos_config *config,
502 u32 num_blocks)
503{
504 config->qid = qid;
505
506 switch (qid) {
507 case QOS_AC_BE:
508 config->high_threshold =
509 (QOS_TX_HIGH_BE_DEF * num_blocks) / 100;
510 config->low_threshold =
511 (QOS_TX_LOW_BE_DEF * num_blocks) / 100;
512 break;
513 case QOS_AC_BK:
514 config->high_threshold =
515 (QOS_TX_HIGH_BK_DEF * num_blocks) / 100;
516 config->low_threshold =
517 (QOS_TX_LOW_BK_DEF * num_blocks) / 100;
518 break;
519 case QOS_AC_VI:
520 config->high_threshold =
521 (QOS_TX_HIGH_VI_DEF * num_blocks) / 100;
522 config->low_threshold =
523 (QOS_TX_LOW_VI_DEF * num_blocks) / 100;
524 break;
525 case QOS_AC_VO:
526 config->high_threshold =
527 (QOS_TX_HIGH_VO_DEF * num_blocks) / 100;
528 config->low_threshold =
529 (QOS_TX_LOW_VO_DEF * num_blocks) / 100;
530 break;
531 default:
532 wl1251_error("Invalid TX queue id: %d", qid);
533 return -EINVAL;
534 }
535
536 return 0;
537}
538
539static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl)
540{
541 struct acx_tx_queue_qos_config *config;
542 struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map;
543 int ret, i;
544
545 wl1251_debug(DEBUG_ACX, "acx tx queue config");
546
547 config = kzalloc(sizeof(*config), GFP_KERNEL);
548 if (!config) {
549 ret = -ENOMEM;
550 goto out;
551 }
552
553 for (i = 0; i < MAX_NUM_OF_AC; i++) {
554 ret = wl1251_hw_init_txq_fill(i, config,
555 wl_mem_map->num_tx_mem_blocks);
556 if (ret < 0)
557 goto out;
558
559 ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG,
560 config, sizeof(*config));
561 if (ret < 0)
562 goto out;
563 }
564
565out:
566 kfree(config);
567 return ret;
568}
569
570static int wl1251_hw_init_data_path_config(struct wl1251 *wl)
571{
572 int ret;
573
574 /* asking for the data path parameters */
575 wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp),
576 GFP_KERNEL);
577 if (!wl->data_path) {
578 wl1251_error("Couldn't allocate data path parameters");
579 return -ENOMEM;
580 }
581
582 ret = wl1251_acx_data_path_params(wl, wl->data_path);
583 if (ret < 0) {
584 kfree(wl->data_path);
585 wl->data_path = NULL;
586 return ret;
587 }
588
589 return 0;
590}
591
592static int wl1251_hw_init(struct wl1251 *wl)
593{
594 struct wl1251_acx_mem_map *wl_mem_map;
595 int ret;
596
597 ret = wl1251_hw_init_hwenc_config(wl);
598 if (ret < 0)
599 return ret;
600
601 /* Template settings */
602 ret = wl1251_hw_init_templates_config(wl);
603 if (ret < 0)
604 return ret;
605
606 /* Default memory configuration */
607 ret = wl1251_hw_init_mem_config(wl);
608 if (ret < 0)
609 return ret;
610
611 /* Default data path configuration */
612 ret = wl1251_hw_init_data_path_config(wl);
613 if (ret < 0)
614 goto out_free_memmap;
615
616 /* RX config */
617 ret = wl1251_hw_init_rx_config(wl,
618 RX_CFG_PROMISCUOUS | RX_CFG_TSF,
619 RX_FILTER_OPTION_DEF);
620 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
621 RX_FILTER_OPTION_FILTER_ALL); */
622 if (ret < 0)
623 goto out_free_data_path;
624
625 /* TX queues config */
626 ret = wl1251_hw_init_tx_queue_config(wl);
627 if (ret < 0)
628 goto out_free_data_path;
629
630 /* PHY layer config */
631 ret = wl1251_hw_init_phy_config(wl);
632 if (ret < 0)
633 goto out_free_data_path;
634
635 /* Beacon filtering */
636 ret = wl1251_hw_init_beacon_filter(wl);
637 if (ret < 0)
638 goto out_free_data_path;
639
640 /* Bluetooth WLAN coexistence */
641 ret = wl1251_hw_init_pta(wl);
642 if (ret < 0)
643 goto out_free_data_path;
644
645 /* Energy detection */
646 ret = wl1251_hw_init_energy_detection(wl);
647 if (ret < 0)
648 goto out_free_data_path;
649
650 /* Beacons and boradcast settings */
651 ret = wl1251_hw_init_beacon_broadcast(wl);
652 if (ret < 0)
653 goto out_free_data_path;
654
655 /* Enable data path */
656 ret = wl1251_cmd_data_path(wl, wl->channel, 1);
657 if (ret < 0)
658 goto out_free_data_path;
659
660 /* Default power state */
661 ret = wl1251_hw_init_power_auth(wl);
662 if (ret < 0)
663 goto out_free_data_path;
664
665 wl_mem_map = wl->target_mem_map;
666 wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x",
667 wl_mem_map->num_tx_mem_blocks,
668 wl->data_path->tx_control_addr,
669 wl_mem_map->num_rx_mem_blocks,
670 wl->data_path->rx_control_addr);
671
672 return 0;
673
674 out_free_data_path:
675 kfree(wl->data_path);
676
677 out_free_memmap:
678 kfree(wl->target_mem_map);
679
680 return ret;
681}
682
683static int wl1251_plt_init(struct wl1251 *wl)
684{
685 int ret;
686
687 ret = wl1251_hw_init_mem_config(wl);
688 if (ret < 0)
689 return ret;
690
691 ret = wl1251_cmd_data_path(wl, wl->channel, 1);
692 if (ret < 0)
693 return ret;
694
695 return 0;
696}
697
698void wl1251_setup(struct wl1251 *wl)
699{
700 /* FIXME: Is it better to use strncpy here or is this ok? */
701 wl->chip.fw_filename = WL1251_FW_NAME;
702 wl->chip.nvs_filename = WL1251_NVS_NAME;
703
704 /* Now we know what chip we're using, so adjust the power on sleep
705 * time accordingly */
706 wl->chip.power_on_sleep = WL1251_POWER_ON_SLEEP;
707
708 wl->chip.intr_cmd_complete = WL1251_ACX_INTR_CMD_COMPLETE;
709 wl->chip.intr_init_complete = WL1251_ACX_INTR_INIT_COMPLETE;
710
711 wl->chip.op_upload_nvs = wl1251_upload_nvs;
712 wl->chip.op_upload_fw = wl1251_upload_firmware;
713 wl->chip.op_boot = wl1251_boot;
714 wl->chip.op_set_ecpu_ctrl = wl1251_set_ecpu_ctrl;
715 wl->chip.op_target_enable_interrupts = wl1251_target_enable_interrupts;
716 wl->chip.op_hw_init = wl1251_hw_init;
717 wl->chip.op_plt_init = wl1251_plt_init;
718 wl->chip.op_fw_version = wl1251_fw_version;
719 wl->chip.op_tx_flush = wl1251_tx_flush;
720 wl->chip.op_cmd_join = wl1251_cmd_join;
721
722 wl->chip.p_table = wl1251_part_table;
723 wl->chip.acx_reg_table = wl1251_acx_reg_table;
724
725 INIT_WORK(&wl->irq_work, wl1251_irq_work);
726 INIT_WORK(&wl->tx_work, wl1251_tx_work);
727
728}
diff --git a/drivers/net/wireless/wl12xx/wl1251_ops.h b/drivers/net/wireless/wl12xx/wl1251_ops.h
deleted file mode 100644
index 68183c472e43..000000000000
--- a/drivers/net/wireless/wl12xx/wl1251_ops.h
+++ /dev/null
@@ -1,165 +0,0 @@
1/*
2 * This file is part of wl1251
3 *
4 * Copyright (C) 2008 Nokia Corporation
5 *
6 * Contact: Kalle Valo <kalle.valo@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __WL1251_OPS_H__
25#define __WL1251_OPS_H__
26
27#include <linux/bitops.h>
28
29#include "wl1251.h"
30#include "wl1251_acx.h"
31
32#define WL1251_FW_NAME "wl1251-fw.bin"
33#define WL1251_NVS_NAME "wl1251-nvs.bin"
34
35#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */
36
37void wl1251_setup(struct wl1251 *wl);
38
39
40struct wl1251_acx_memory {
41 __le16 num_stations; /* number of STAs to be supported. */
42 u16 reserved_1;
43
44 /*
45 * Nmber of memory buffers for the RX mem pool.
46 * The actual number may be less if there are
47 * not enough blocks left for the minimum num
48 * of TX ones.
49 */
50 u8 rx_mem_block_num;
51 u8 reserved_2;
52 u8 num_tx_queues; /* From 1 to 16 */
53 u8 host_if_options; /* HOST_IF* */
54 u8 tx_min_mem_block_num;
55 u8 num_ssid_profiles;
56 __le16 debug_buffer_size;
57} __attribute__ ((packed));
58
59
60#define ACX_RX_DESC_MIN 1
61#define ACX_RX_DESC_MAX 127
62#define ACX_RX_DESC_DEF 32
63struct wl1251_acx_rx_queue_config {
64 u8 num_descs;
65 u8 pad;
66 u8 type;
67 u8 priority;
68 __le32 dma_address;
69} __attribute__ ((packed));
70
71#define ACX_TX_DESC_MIN 1
72#define ACX_TX_DESC_MAX 127
73#define ACX_TX_DESC_DEF 16
74struct wl1251_acx_tx_queue_config {
75 u8 num_descs;
76 u8 pad[2];
77 u8 attributes;
78} __attribute__ ((packed));
79
80#define MAX_TX_QUEUE_CONFIGS 5
81#define MAX_TX_QUEUES 4
82struct wl1251_acx_config_memory {
83 struct acx_header header;
84
85 struct wl1251_acx_memory mem_config;
86 struct wl1251_acx_rx_queue_config rx_queue_config;
87 struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS];
88} __attribute__ ((packed));
89
90struct wl1251_acx_mem_map {
91 struct acx_header header;
92
93 void *code_start;
94 void *code_end;
95
96 void *wep_defkey_start;
97 void *wep_defkey_end;
98
99 void *sta_table_start;
100 void *sta_table_end;
101
102 void *packet_template_start;
103 void *packet_template_end;
104
105 void *queue_memory_start;
106 void *queue_memory_end;
107
108 void *packet_memory_pool_start;
109 void *packet_memory_pool_end;
110
111 void *debug_buffer1_start;
112 void *debug_buffer1_end;
113
114 void *debug_buffer2_start;
115 void *debug_buffer2_end;
116
117 /* Number of blocks FW allocated for TX packets */
118 u32 num_tx_mem_blocks;
119
120 /* Number of blocks FW allocated for RX packets */
121 u32 num_rx_mem_blocks;
122} __attribute__ ((packed));
123
124/*************************************************************************
125
126 Host Interrupt Register (WiLink -> Host)
127
128**************************************************************************/
129
130/* RX packet is ready in Xfer buffer #0 */
131#define WL1251_ACX_INTR_RX0_DATA BIT(0)
132
133/* TX result(s) are in the TX complete buffer */
134#define WL1251_ACX_INTR_TX_RESULT BIT(1)
135
136/* OBSOLETE */
137#define WL1251_ACX_INTR_TX_XFR BIT(2)
138
139/* RX packet is ready in Xfer buffer #1 */
140#define WL1251_ACX_INTR_RX1_DATA BIT(3)
141
142/* Event was entered to Event MBOX #A */
143#define WL1251_ACX_INTR_EVENT_A BIT(4)
144
145/* Event was entered to Event MBOX #B */
146#define WL1251_ACX_INTR_EVENT_B BIT(5)
147
148/* OBSOLETE */
149#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6)
150
151/* Trace meassge on MBOX #A */
152#define WL1251_ACX_INTR_TRACE_A BIT(7)
153
154/* Trace meassge on MBOX #B */
155#define WL1251_ACX_INTR_TRACE_B BIT(8)
156
157/* Command processing completion */
158#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9)
159
160/* Init sequence is done */
161#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14)
162
163#define WL1251_ACX_INTR_ALL 0xFFFFFFFF
164
165#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c
index 68ff7f1900ed..c53e28727ed4 100644
--- a/drivers/net/wireless/wl12xx/wl1251_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1251_ps.c
@@ -21,9 +21,10 @@
21 * 21 *
22 */ 22 */
23 23
24#include "reg.h" 24#include "wl1251_reg.h"
25#include "wl1251_ps.h" 25#include "wl1251_ps.h"
26#include "wl1251_spi.h" 26#include "wl1251_cmd.h"
27#include "wl1251_io.h"
27 28
28#define WL1251_WAKEUP_TIMEOUT 2000 29#define WL1251_WAKEUP_TIMEOUT 2000
29 30
@@ -117,6 +118,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
117 switch (mode) { 118 switch (mode) {
118 case STATION_POWER_SAVE_MODE: 119 case STATION_POWER_SAVE_MODE:
119 wl1251_debug(DEBUG_PSM, "entering psm"); 120 wl1251_debug(DEBUG_PSM, "entering psm");
121
122 ret = wl1251_acx_wake_up_conditions(wl,
123 WAKE_UP_EVENT_DTIM_BITMAP,
124 wl->listen_int);
125 if (ret < 0)
126 return ret;
127
120 ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); 128 ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
121 if (ret < 0) 129 if (ret < 0)
122 return ret; 130 return ret;
@@ -134,6 +142,12 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
134 if (ret < 0) 142 if (ret < 0)
135 return ret; 143 return ret;
136 144
145 ret = wl1251_acx_wake_up_conditions(wl,
146 WAKE_UP_EVENT_DTIM_BITMAP,
147 wl->listen_int);
148 if (ret < 0)
149 return ret;
150
137 ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); 151 ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
138 if (ret < 0) 152 if (ret < 0)
139 return ret; 153 return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h
new file mode 100644
index 000000000000..bdd561001dcb
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_reg.h
@@ -0,0 +1,644 @@
1/*
2 * This file is part of wl12xx
3 *
4 * Copyright (c) 1998-2007 Texas Instruments Incorporated
5 * Copyright (C) 2008 Nokia Corporation
6 *
7 * Contact: Kalle Valo <kalle.valo@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __REG_H__
26#define __REG_H__
27
28#include <linux/bitops.h>
29
30#define REGISTERS_BASE 0x00300000
31#define DRPW_BASE 0x00310000
32
33#define REGISTERS_DOWN_SIZE 0x00008800
34#define REGISTERS_WORK_SIZE 0x0000b000
35
36#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
37
38/* ELP register commands */
39#define ELPCTRL_WAKE_UP 0x1
40#define ELPCTRL_WAKE_UP_WLAN_READY 0x5
41#define ELPCTRL_SLEEP 0x0
42/* ELP WLAN_READY bit */
43#define ELPCTRL_WLAN_READY 0x2
44
45/* Device Configuration registers*/
46#define SOR_CFG (REGISTERS_BASE + 0x0800)
47#define ECPU_CTRL (REGISTERS_BASE + 0x0804)
48#define HI_CFG (REGISTERS_BASE + 0x0808)
49#define EE_START (REGISTERS_BASE + 0x080C)
50
51#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
52
53#define CHIP_ID_1251_PG10 (0x7010101)
54#define CHIP_ID_1251_PG11 (0x7020101)
55#define CHIP_ID_1251_PG12 (0x7030101)
56
57#define ENABLE (REGISTERS_BASE + 0x5450)
58
59/* Power Management registers */
60#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
61#define ELP_CMD (REGISTERS_BASE + 0x5808)
62#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
63#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
64#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
65
66#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
67
68/* Scratch Pad registers*/
69#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
70#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
71#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
72#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
73#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
74#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
75#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
76#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
77#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
78#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
79#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
80#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
81#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
82#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
83
84/* Spare registers*/
85#define SPARE_A1 (REGISTERS_BASE + 0x0994)
86#define SPARE_A2 (REGISTERS_BASE + 0x0998)
87#define SPARE_A3 (REGISTERS_BASE + 0x099C)
88#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
89#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
90#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
91#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
92#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
93#define SPARE_B1 (REGISTERS_BASE + 0x5420)
94#define SPARE_B2 (REGISTERS_BASE + 0x5424)
95#define SPARE_B3 (REGISTERS_BASE + 0x5428)
96#define SPARE_B4 (REGISTERS_BASE + 0x542C)
97#define SPARE_B5 (REGISTERS_BASE + 0x5430)
98#define SPARE_B6 (REGISTERS_BASE + 0x5434)
99#define SPARE_B7 (REGISTERS_BASE + 0x5438)
100#define SPARE_B8 (REGISTERS_BASE + 0x543C)
101
102enum wl12xx_acx_int_reg {
103 ACX_REG_INTERRUPT_TRIG,
104 ACX_REG_INTERRUPT_TRIG_H,
105
106/*=============================================
107 Host Interrupt Mask Register - 32bit (RW)
108 ------------------------------------------
109 Setting a bit in this register masks the
110 corresponding interrupt to the host.
111 0 - RX0 - Rx first dubble buffer Data Interrupt
112 1 - TXD - Tx Data Interrupt
113 2 - TXXFR - Tx Transfer Interrupt
114 3 - RX1 - Rx second dubble buffer Data Interrupt
115 4 - RXXFR - Rx Transfer Interrupt
116 5 - EVENT_A - Event Mailbox interrupt
117 6 - EVENT_B - Event Mailbox interrupt
118 7 - WNONHST - Wake On Host Interrupt
119 8 - TRACE_A - Debug Trace interrupt
120 9 - TRACE_B - Debug Trace interrupt
121 10 - CDCMP - Command Complete Interrupt
122 11 -
123 12 -
124 13 -
125 14 - ICOMP - Initialization Complete Interrupt
126 16 - SG SE - Soft Gemini - Sense enable interrupt
127 17 - SG SD - Soft Gemini - Sense disable interrupt
128 18 - -
129 19 - -
130 20 - -
131 21- -
132 Default: 0x0001
133*==============================================*/
134 ACX_REG_INTERRUPT_MASK,
135
136/*=============================================
137 Host Interrupt Mask Set 16bit, (Write only)
138 ------------------------------------------
139 Setting a bit in this register sets
140 the corresponding bin in ACX_HINT_MASK register
141 without effecting the mask
142 state of other bits (0 = no effect).
143==============================================*/
144 ACX_REG_HINT_MASK_SET,
145
146/*=============================================
147 Host Interrupt Mask Clear 16bit,(Write only)
148 ------------------------------------------
149 Setting a bit in this register clears
150 the corresponding bin in ACX_HINT_MASK register
151 without effecting the mask
152 state of other bits (0 = no effect).
153=============================================*/
154 ACX_REG_HINT_MASK_CLR,
155
156/*=============================================
157 Host Interrupt Status Nondestructive Read
158 16bit,(Read only)
159 ------------------------------------------
160 The host can read this register to determine
161 which interrupts are active.
162 Reading this register doesn't
163 effect its content.
164=============================================*/
165 ACX_REG_INTERRUPT_NO_CLEAR,
166
167/*=============================================
168 Host Interrupt Status Clear on Read Register
169 16bit,(Read only)
170 ------------------------------------------
171 The host can read this register to determine
172 which interrupts are active.
173 Reading this register clears it,
174 thus making all interrupts inactive.
175==============================================*/
176 ACX_REG_INTERRUPT_CLEAR,
177
178/*=============================================
179 Host Interrupt Acknowledge Register
180 16bit,(Write only)
181 ------------------------------------------
182 The host can set individual bits in this
183 register to clear (acknowledge) the corresp.
184 interrupt status bits in the HINT_STS_CLR and
185 HINT_STS_ND registers, thus making the
186 assotiated interrupt inactive. (0-no effect)
187==============================================*/
188 ACX_REG_INTERRUPT_ACK,
189
190/*===============================================
191 Host Software Reset - 32bit RW
192 ------------------------------------------
193 [31:1] Reserved
194 0 SOFT_RESET Soft Reset - When this bit is set,
195 it holds the Wlan hardware in a soft reset state.
196 This reset disables all MAC and baseband processor
197 clocks except the CardBus/PCI interface clock.
198 It also initializes all MAC state machines except
199 the host interface. It does not reload the
200 contents of the EEPROM. When this bit is cleared
201 (not self-clearing), the Wlan hardware
202 exits the software reset state.
203===============================================*/
204 ACX_REG_SLV_SOFT_RESET,
205
206/*===============================================
207 EEPROM Burst Read Start - 32bit RW
208 ------------------------------------------
209 [31:1] Reserved
210 0 ACX_EE_START - EEPROM Burst Read Start 0
211 Setting this bit starts a burst read from
212 the external EEPROM.
213 If this bit is set (after reset) before an EEPROM read/write,
214 the burst read starts at EEPROM address 0.
215 Otherwise, it starts at the address
216 following the address of the previous access.
217 TheWlan hardware hardware clears this bit automatically.
218
219 Default: 0x00000000
220*================================================*/
221 ACX_REG_EE_START,
222
223/* Embedded ARM CPU Control */
224
225/*===============================================
226 Halt eCPU - 32bit RW
227 ------------------------------------------
228 0 HALT_ECPU Halt Embedded CPU - This bit is the
229 compliment of bit 1 (MDATA2) in the SOR_CFG register.
230 During a hardware reset, this bit holds
231 the inverse of MDATA2.
232 When downloading firmware from the host,
233 set this bit (pull down MDATA2).
234 The host clears this bit after downloading the firmware into
235 zero-wait-state SSRAM.
236 When loading firmware from Flash, clear this bit (pull up MDATA2)
237 so that the eCPU can run the bootloader code in Flash
238 HALT_ECPU eCPU State
239 --------------------
240 1 halt eCPU
241 0 enable eCPU
242 ===============================================*/
243 ACX_REG_ECPU_CONTROL,
244
245 ACX_REG_TABLE_LEN
246};
247
248#define ACX_SLV_SOFT_RESET_BIT BIT(1)
249#define ACX_REG_EEPROM_START_BIT BIT(1)
250
251/* Command/Information Mailbox Pointers */
252
253/*===============================================
254 Command Mailbox Pointer - 32bit RW
255 ------------------------------------------
256 This register holds the start address of
257 the command mailbox located in the Wlan hardware memory.
258 The host must read this pointer after a reset to
259 find the location of the command mailbox.
260 The Wlan hardware initializes the command mailbox
261 pointer with the default address of the command mailbox.
262 The command mailbox pointer is not valid until after
263 the host receives the Init Complete interrupt from
264 the Wlan hardware.
265 ===============================================*/
266#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0)
267
268/*===============================================
269 Information Mailbox Pointer - 32bit RW
270 ------------------------------------------
271 This register holds the start address of
272 the information mailbox located in the Wlan hardware memory.
273 The host must read this pointer after a reset to find
274 the location of the information mailbox.
275 The Wlan hardware initializes the information mailbox pointer
276 with the default address of the information mailbox.
277 The information mailbox pointer is not valid
278 until after the host receives the Init Complete interrupt from
279 the Wlan hardware.
280 ===============================================*/
281#define REG_EVENT_MAILBOX_PTR (SCR_PAD1)
282
283
284/* Misc */
285
286#define REG_ENABLE_TX_RX (ENABLE)
287/*
288 * Rx configuration (filter) information element
289 * ---------------------------------------------
290 */
291#define REG_RX_CONFIG (RX_CFG)
292#define REG_RX_FILTER (RX_FILTER_CFG)
293
294
295#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002
296
297/* promiscuous - receives all valid frames */
298#define RX_CFG_PROMISCUOUS 0x0008
299
300/* receives frames from any BSSID */
301#define RX_CFG_BSSID 0x0020
302
303/* receives frames destined to any MAC address */
304#define RX_CFG_MAC 0x0010
305
306#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010
307#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000
308#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020
309#define RX_CFG_ENABLE_ANY_BSSID 0x0000
310
311/* discards all broadcast frames */
312#define RX_CFG_DISABLE_BCAST 0x0200
313
314#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400
315#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
316#define RX_CFG_COPY_RX_STATUS 0x2000
317#define RX_CFG_TSF 0x10000
318
319#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
320 RX_CFG_ENABLE_ONLY_MY_BSSID)
321
322#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
323 | RX_CFG_ENABLE_ANY_BSSID)
324
325#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
326 RX_CFG_ENABLE_ANY_BSSID)
327
328#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
329 | RX_CFG_ENABLE_ONLY_MY_BSSID)
330
331#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \
332 | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
333 | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
334
335#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
336
337#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \
338 RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
339
340#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \
341 RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
342
343#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
344 | CFG_RX_CTL_EN | CFG_RX_BCN_EN\
345 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
346
347#define RX_FILTER_OPTION_FILTER_ALL 0
348
349#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
350 | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
351
352#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
353 | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
354 | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
355 | CFG_RX_PRSP_EN)
356
357
358/*===============================================
359 EEPROM Read/Write Request 32bit RW
360 ------------------------------------------
361 1 EE_READ - EEPROM Read Request 1 - Setting this bit
362 loads a single byte of data into the EE_DATA
363 register from the EEPROM location specified in
364 the EE_ADDR register.
365 The Wlan hardware hardware clears this bit automatically.
366 EE_DATA is valid when this bit is cleared.
367
368 0 EE_WRITE - EEPROM Write Request - Setting this bit
369 writes a single byte of data from the EE_DATA register into the
370 EEPROM location specified in the EE_ADDR register.
371 The Wlan hardware hardware clears this bit automatically.
372*===============================================*/
373#define ACX_EE_CTL_REG EE_CTL
374#define EE_WRITE 0x00000001ul
375#define EE_READ 0x00000002ul
376
377/*===============================================
378 EEPROM Address - 32bit RW
379 ------------------------------------------
380 This register specifies the address
381 within the EEPROM from/to which to read/write data.
382 ===============================================*/
383#define ACX_EE_ADDR_REG EE_ADDR
384
385/*===============================================
386 EEPROM Data - 32bit RW
387 ------------------------------------------
388 This register either holds the read 8 bits of
389 data from the EEPROM or the write data
390 to be written to the EEPROM.
391 ===============================================*/
392#define ACX_EE_DATA_REG EE_DATA
393
394/*===============================================
395 EEPROM Base Address - 32bit RW
396 ------------------------------------------
397 This register holds the upper nine bits
398 [23:15] of the 24-bit Wlan hardware memory
399 address for burst reads from EEPROM accesses.
400 The EEPROM provides the lower 15 bits of this address.
401 The MSB of the address from the EEPROM is ignored.
402 ===============================================*/
403#define ACX_EE_CFG EE_CFG
404
405/*===============================================
406 GPIO Output Values -32bit, RW
407 ------------------------------------------
408 [31:16] Reserved
409 [15: 0] Specify the output values (at the output driver inputs) for
410 GPIO[15:0], respectively.
411 ===============================================*/
412#define ACX_GPIO_OUT_REG GPIO_OUT
413#define ACX_MAX_GPIO_LINES 15
414
415/*===============================================
416 Contention window -32bit, RW
417 ------------------------------------------
418 [31:26] Reserved
419 [25:16] Max (0x3ff)
420 [15:07] Reserved
421 [06:00] Current contention window value - default is 0x1F
422 ===============================================*/
423#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG
424#define ACX_CONT_WIND_MIN_MASK 0x0000007f
425#define ACX_CONT_WIND_MAX 0x03ff0000
426
427/*===============================================
428 HI_CFG Interface Configuration Register Values
429 ------------------------------------------
430 ===============================================*/
431#define HI_CFG_UART_ENABLE 0x00000004
432#define HI_CFG_RST232_ENABLE 0x00000008
433#define HI_CFG_CLOCK_REQ_SELECT 0x00000010
434#define HI_CFG_HOST_INT_ENABLE 0x00000020
435#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040
436#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080
437#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100
438#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200
439#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400
440
441/*
442 * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile
443 * for platforms using active high interrupt level
444 */
445#ifdef USE_ACTIVE_HIGH
446#define HI_CFG_DEF_VAL \
447 (HI_CFG_UART_ENABLE | \
448 HI_CFG_RST232_ENABLE | \
449 HI_CFG_CLOCK_REQ_SELECT | \
450 HI_CFG_HOST_INT_ENABLE)
451#else
452#define HI_CFG_DEF_VAL \
453 (HI_CFG_UART_ENABLE | \
454 HI_CFG_RST232_ENABLE | \
455 HI_CFG_CLOCK_REQ_SELECT | \
456 HI_CFG_HOST_INT_ENABLE)
457
458#endif
459
460#define REF_FREQ_19_2 0
461#define REF_FREQ_26_0 1
462#define REF_FREQ_38_4 2
463#define REF_FREQ_40_0 3
464#define REF_FREQ_33_6 4
465#define REF_FREQ_NUM 5
466
467#define LUT_PARAM_INTEGER_DIVIDER 0
468#define LUT_PARAM_FRACTIONAL_DIVIDER 1
469#define LUT_PARAM_ATTN_BB 2
470#define LUT_PARAM_ALPHA_BB 3
471#define LUT_PARAM_STOP_TIME_BB 4
472#define LUT_PARAM_BB_PLL_LOOP_FILTER 5
473#define LUT_PARAM_NUM 6
474
475#define ACX_EEPROMLESS_IND_REG (SCR_PAD4)
476#define USE_EEPROM 0
477#define SOFT_RESET_MAX_TIME 1000000
478#define SOFT_RESET_STALL_TIME 1000
479#define NVS_DATA_BUNDARY_ALIGNMENT 4
480
481
482/* Firmware image load chunk size */
483#define CHUNK_SIZE 512
484
485/* Firmware image header size */
486#define FW_HDR_SIZE 8
487
488#define ECPU_CONTROL_HALT 0x00000101
489
490
491/******************************************************************************
492
493 CHANNELS, BAND & REG DOMAINS definitions
494
495******************************************************************************/
496
497
498enum {
499 RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */
500 RADIO_BAND_5GHZ = 1, /* 5 Ghz band */
501 RADIO_BAND_JAPAN_4_9_GHZ = 2,
502 DEFAULT_BAND = RADIO_BAND_2_4GHZ,
503 INVALID_BAND = 0xFE,
504 MAX_RADIO_BANDS = 0xFF
505};
506
507enum {
508 NO_RATE = 0,
509 RATE_1MBPS = 0x0A,
510 RATE_2MBPS = 0x14,
511 RATE_5_5MBPS = 0x37,
512 RATE_6MBPS = 0x0B,
513 RATE_9MBPS = 0x0F,
514 RATE_11MBPS = 0x6E,
515 RATE_12MBPS = 0x0A,
516 RATE_18MBPS = 0x0E,
517 RATE_22MBPS = 0xDC,
518 RATE_24MBPS = 0x09,
519 RATE_36MBPS = 0x0D,
520 RATE_48MBPS = 0x08,
521 RATE_54MBPS = 0x0C
522};
523
524enum {
525 RATE_INDEX_1MBPS = 0,
526 RATE_INDEX_2MBPS = 1,
527 RATE_INDEX_5_5MBPS = 2,
528 RATE_INDEX_6MBPS = 3,
529 RATE_INDEX_9MBPS = 4,
530 RATE_INDEX_11MBPS = 5,
531 RATE_INDEX_12MBPS = 6,
532 RATE_INDEX_18MBPS = 7,
533 RATE_INDEX_22MBPS = 8,
534 RATE_INDEX_24MBPS = 9,
535 RATE_INDEX_36MBPS = 10,
536 RATE_INDEX_48MBPS = 11,
537 RATE_INDEX_54MBPS = 12,
538 RATE_INDEX_MAX = RATE_INDEX_54MBPS,
539 MAX_RATE_INDEX,
540 INVALID_RATE_INDEX = MAX_RATE_INDEX,
541 RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF
542};
543
544enum {
545 RATE_MASK_1MBPS = 0x1,
546 RATE_MASK_2MBPS = 0x2,
547 RATE_MASK_5_5MBPS = 0x4,
548 RATE_MASK_11MBPS = 0x20,
549};
550
551#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */
552#define OFDM_RATE_BIT BIT(6)
553#define PBCC_RATE_BIT BIT(7)
554
555enum {
556 CCK_LONG = 0,
557 CCK_SHORT = SHORT_PREAMBLE_BIT,
558 PBCC_LONG = PBCC_RATE_BIT,
559 PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT,
560 OFDM = OFDM_RATE_BIT
561};
562
563/******************************************************************************
564
565Transmit-Descriptor RATE-SET field definitions...
566
567Define a new "Rate-Set" for TX path that incorporates the
568Rate & Modulation info into a single 16-bit field.
569
570TxdRateSet_t:
571b15 - Indicates Preamble type (1=SHORT, 0=LONG).
572 Notes:
573 Must be LONG (0) for 1Mbps rate.
574 Does not apply (set to 0) for RevG-OFDM rates.
575b14 - Indicates PBCC encoding (1=PBCC, 0=not).
576 Notes:
577 Does not apply (set to 0) for rates 1 and 2 Mbps.
578 Does not apply (set to 0) for RevG-OFDM rates.
579b13 - Unused (set to 0).
580b12-b0 - Supported Rate indicator bits as defined below.
581
582******************************************************************************/
583
584
585/*************************************************************************
586
587 Interrupt Trigger Register (Host -> WiLink)
588
589**************************************************************************/
590
591/* Hardware to Embedded CPU Interrupts - first 32-bit register set */
592
593/*
594 * Host Command Interrupt. Setting this bit masks
595 * the interrupt that the host issues to inform
596 * the FW that it has sent a command
597 * to the Wlan hardware Command Mailbox.
598 */
599#define INTR_TRIG_CMD BIT(0)
600
601/*
602 * Host Event Acknowlegde Interrupt. The host
603 * sets this bit to acknowledge that it received
604 * the unsolicited information from the event
605 * mailbox.
606 */
607#define INTR_TRIG_EVENT_ACK BIT(1)
608
609/*
610 * The host sets this bit to inform the Wlan
611 * FW that a TX packet is in the XFER
612 * Buffer #0.
613 */
614#define INTR_TRIG_TX_PROC0 BIT(2)
615
616/*
617 * The host sets this bit to inform the FW
618 * that it read a packet from RX XFER
619 * Buffer #0.
620 */
621#define INTR_TRIG_RX_PROC0 BIT(3)
622
623#define INTR_TRIG_DEBUG_ACK BIT(4)
624
625#define INTR_TRIG_STATE_CHANGED BIT(5)
626
627
628/* Hardware to Embedded CPU Interrupts - second 32-bit register set */
629
630/*
631 * The host sets this bit to inform the FW
632 * that it read a packet from RX XFER
633 * Buffer #1.
634 */
635#define INTR_TRIG_RX_PROC1 BIT(17)
636
637/*
638 * The host sets this bit to inform the Wlan
639 * hardware that a TX packet is in the XFER
640 * Buffer #1.
641 */
642#define INTR_TRIG_TX_PROC1 BIT(18)
643
644#endif
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c
index 0dbb483a0973..17c54b59ef86 100644
--- a/drivers/net/wireless/wl12xx/wl1251_rx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_rx.c
@@ -26,9 +26,10 @@
26#include <net/mac80211.h> 26#include <net/mac80211.h>
27 27
28#include "wl1251.h" 28#include "wl1251.h"
29#include "reg.h" 29#include "wl1251_reg.h"
30#include "wl1251_spi.h" 30#include "wl1251_io.h"
31#include "wl1251_rx.h" 31#include "wl1251_rx.h"
32#include "wl1251_cmd.h"
32#include "wl1251_acx.h" 33#include "wl1251_acx.h"
33 34
34static void wl1251_rx_header(struct wl1251 *wl, 35static void wl1251_rx_header(struct wl1251 *wl,
@@ -40,7 +41,7 @@ static void wl1251_rx_header(struct wl1251 *wl,
40 if (wl->rx_current_buffer) 41 if (wl->rx_current_buffer)
41 rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; 42 rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size;
42 43
43 wl1251_spi_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc)); 44 wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc));
44} 45}
45 46
46static void wl1251_rx_status(struct wl1251 *wl, 47static void wl1251_rx_status(struct wl1251 *wl,
@@ -136,7 +137,7 @@ static void wl1251_rx_body(struct wl1251 *wl,
136 } 137 }
137 138
138 rx_buffer = skb_put(skb, length); 139 rx_buffer = skb_put(skb, length);
139 wl1251_spi_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); 140 wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
140 141
141 /* The actual lenght doesn't include the target's alignment */ 142 /* The actual lenght doesn't include the target's alignment */
142 skb->len = desc->length - PLCP_HEADER_LENGTH; 143 skb->len = desc->length - PLCP_HEADER_LENGTH;
diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c
new file mode 100644
index 000000000000..9423f22bdced
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1251_sdio.c
@@ -0,0 +1,205 @@
1/*
2 * wl12xx SDIO routines
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 *
18 * Copyright (C) 2005 Texas Instruments Incorporated
19 * Copyright (C) 2008 Google Inc
20 * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com)
21 */
22#include <linux/module.h>
23#include <linux/crc7.h>
24#include <linux/mod_devicetable.h>
25#include <linux/irq.h>
26#include <linux/mmc/sdio_func.h>
27#include <linux/mmc/sdio_ids.h>
28#include <linux/platform_device.h>
29
30#include "wl1251.h"
31#include "wl12xx_80211.h"
32#include "wl1251_reg.h"
33#include "wl1251_ps.h"
34#include "wl1251_io.h"
35#include "wl1251_tx.h"
36#include "wl1251_debugfs.h"
37
38#ifndef SDIO_VENDOR_ID_TI
39#define SDIO_VENDOR_ID_TI 0x104c
40#endif
41
42#ifndef SDIO_DEVICE_ID_TI_WL1251
43#define SDIO_DEVICE_ID_TI_WL1251 0x9066
44#endif
45
46static struct sdio_func *wl_to_func(struct wl1251 *wl)
47{
48 return wl->if_priv;
49}
50
51static void wl1251_sdio_interrupt(struct sdio_func *func)
52{
53 struct wl1251 *wl = sdio_get_drvdata(func);
54
55 wl1251_debug(DEBUG_IRQ, "IRQ");
56
57 /* FIXME should be synchronous for sdio */
58 ieee80211_queue_work(wl->hw, &wl->irq_work);
59}
60
61static const struct sdio_device_id wl1251_devices[] = {
62 { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) },
63 {}
64};
65MODULE_DEVICE_TABLE(sdio, wl1251_devices);
66
67
68void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len)
69{
70 int ret;
71 struct sdio_func *func = wl_to_func(wl);
72
73 sdio_claim_host(func);
74 ret = sdio_memcpy_fromio(func, buf, addr, len);
75 if (ret)
76 wl1251_error("sdio read failed (%d)", ret);
77 sdio_release_host(func);
78}
79
80void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len)
81{
82 int ret;
83 struct sdio_func *func = wl_to_func(wl);
84
85 sdio_claim_host(func);
86 ret = sdio_memcpy_toio(func, addr, buf, len);
87 if (ret)
88 wl1251_error("sdio write failed (%d)", ret);
89 sdio_release_host(func);
90}
91
92void wl1251_sdio_reset(struct wl1251 *wl)
93{
94}
95
96static void wl1251_sdio_enable_irq(struct wl1251 *wl)
97{
98 struct sdio_func *func = wl_to_func(wl);
99
100 sdio_claim_host(func);
101 sdio_claim_irq(func, wl1251_sdio_interrupt);
102 sdio_release_host(func);
103}
104
105static void wl1251_sdio_disable_irq(struct wl1251 *wl)
106{
107 struct sdio_func *func = wl_to_func(wl);
108
109 sdio_claim_host(func);
110 sdio_release_irq(func);
111 sdio_release_host(func);
112}
113
114void wl1251_sdio_set_power(bool enable)
115{
116}
117
118struct wl1251_if_operations wl1251_sdio_ops = {
119 .read = wl1251_sdio_read,
120 .write = wl1251_sdio_write,
121 .reset = wl1251_sdio_reset,
122 .enable_irq = wl1251_sdio_enable_irq,
123 .disable_irq = wl1251_sdio_disable_irq,
124};
125
126int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
127{
128 int ret;
129 struct wl1251 *wl;
130 struct ieee80211_hw *hw;
131
132 hw = wl1251_alloc_hw();
133 if (IS_ERR(hw))
134 return PTR_ERR(hw);
135
136 wl = hw->priv;
137
138 sdio_claim_host(func);
139 ret = sdio_enable_func(func);
140 if (ret)
141 goto release;
142
143 sdio_set_block_size(func, 512);
144
145 SET_IEEE80211_DEV(hw, &func->dev);
146 wl->if_priv = func;
147 wl->if_ops = &wl1251_sdio_ops;
148 wl->set_power = wl1251_sdio_set_power;
149
150 sdio_release_host(func);
151 ret = wl1251_init_ieee80211(wl);
152 if (ret)
153 goto disable;
154
155 sdio_set_drvdata(func, wl);
156 return ret;
157
158disable:
159 sdio_claim_host(func);
160 sdio_disable_func(func);
161release:
162 sdio_release_host(func);
163 return ret;
164}
165
166static void __devexit wl1251_sdio_remove(struct sdio_func *func)
167{
168 struct wl1251 *wl = sdio_get_drvdata(func);
169
170 wl1251_free_hw(wl);
171
172 sdio_claim_host(func);
173 sdio_release_irq(func);
174 sdio_disable_func(func);
175 sdio_release_host(func);
176}
177
178static struct sdio_driver wl1251_sdio_driver = {
179 .name = "wl1251_sdio",
180 .id_table = wl1251_devices,
181 .probe = wl1251_sdio_probe,
182 .remove = __devexit_p(wl1251_sdio_remove),
183};
184
185static int __init wl1251_sdio_init(void)
186{
187 int err;
188
189 err = sdio_register_driver(&wl1251_sdio_driver);
190 if (err)
191 wl1251_error("failed to register sdio driver: %d", err);
192 return err;
193}
194
195static void __exit wl1251_sdio_exit(void)
196{
197 sdio_unregister_driver(&wl1251_sdio_driver);
198 wl1251_notice("unloaded");
199}
200
201module_init(wl1251_sdio_init);
202module_exit(wl1251_sdio_exit);
203
204MODULE_LICENSE("GPL");
205MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c
index c5da79dbc49c..14eff2b3d4c6 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.c
@@ -21,38 +21,35 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/irq.h>
24#include <linux/module.h> 25#include <linux/module.h>
25#include <linux/crc7.h> 26#include <linux/crc7.h>
26#include <linux/spi/spi.h> 27#include <linux/spi/spi.h>
28#include <linux/spi/wl12xx.h>
27 29
28#include "wl1251.h" 30#include "wl1251.h"
29#include "reg.h" 31#include "wl1251_reg.h"
30#include "wl1251_spi.h" 32#include "wl1251_spi.h"
31 33
32static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr) 34static irqreturn_t wl1251_irq(int irq, void *cookie)
33{ 35{
34 /* If the address is lower than REGISTERS_BASE, it means that this is 36 struct wl1251 *wl;
35 * a chip-specific register address, so look it up in the registers 37
36 * table */ 38 wl1251_debug(DEBUG_IRQ, "IRQ");
37 if (addr < REGISTERS_BASE) { 39
38 /* Make sure we don't go over the table */ 40 wl = cookie;
39 if (addr >= ACX_REG_TABLE_LEN) {
40 wl1251_error("address out of range (%d)", addr);
41 return -EINVAL;
42 }
43 addr = wl->chip.acx_reg_table[addr];
44 }
45 41
46 return addr - wl->physical_reg_addr + wl->virtual_reg_addr; 42 ieee80211_queue_work(wl->hw, &wl->irq_work);
43
44 return IRQ_HANDLED;
47} 45}
48 46
49static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr) 47static struct spi_device *wl_to_spi(struct wl1251 *wl)
50{ 48{
51 return addr - wl->physical_mem_addr + wl->virtual_mem_addr; 49 return wl->if_priv;
52} 50}
53 51
54 52static void wl1251_spi_reset(struct wl1251 *wl)
55void wl1251_spi_reset(struct wl1251 *wl)
56{ 53{
57 u8 *cmd; 54 u8 *cmd;
58 struct spi_transfer t; 55 struct spi_transfer t;
@@ -73,12 +70,12 @@ void wl1251_spi_reset(struct wl1251 *wl)
73 t.len = WSPI_INIT_CMD_LEN; 70 t.len = WSPI_INIT_CMD_LEN;
74 spi_message_add_tail(&t, &m); 71 spi_message_add_tail(&t, &m);
75 72
76 spi_sync(wl->spi, &m); 73 spi_sync(wl_to_spi(wl), &m);
77 74
78 wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); 75 wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
79} 76}
80 77
81void wl1251_spi_init(struct wl1251 *wl) 78static void wl1251_spi_wake(struct wl1251 *wl)
82{ 79{
83 u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; 80 u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
84 struct spi_transfer t; 81 struct spi_transfer t;
@@ -127,136 +124,19 @@ void wl1251_spi_init(struct wl1251 *wl)
127 t.len = WSPI_INIT_CMD_LEN; 124 t.len = WSPI_INIT_CMD_LEN;
128 spi_message_add_tail(&t, &m); 125 spi_message_add_tail(&t, &m);
129 126
130 spi_sync(wl->spi, &m); 127 spi_sync(wl_to_spi(wl), &m);
131 128
132 wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); 129 wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
133} 130}
134 131
135/* Set the SPI partitions to access the chip addresses 132static void wl1251_spi_reset_wake(struct wl1251 *wl)
136 *
137 * There are two VIRTUAL (SPI) partitions (the memory partition and the
138 * registers partition), which are mapped to two different areas of the
139 * PHYSICAL (hardware) memory. This function also makes other checks to
140 * ensure that the partitions are not overlapping. In the diagram below, the
141 * memory partition comes before the register partition, but the opposite is
142 * also supported.
143 *
144 * PHYSICAL address
145 * space
146 *
147 * | |
148 * ...+----+--> mem_start
149 * VIRTUAL address ... | |
150 * space ... | | [PART_0]
151 * ... | |
152 * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
153 * | | ... | |
154 * |MEM | ... | |
155 * | | ... | |
156 * part_size <--+----+... | | {unused area)
157 * | | ... | |
158 * |REG | ... | |
159 * part_size | | ... | |
160 * + <--+----+... ...+----+--> reg_start
161 * reg_size ... | |
162 * ... | | [PART_1]
163 * ... | |
164 * ...+----+--> reg_start + reg_size
165 * | |
166 *
167 */
168int wl1251_set_partition(struct wl1251 *wl,
169 u32 mem_start, u32 mem_size,
170 u32 reg_start, u32 reg_size)
171{ 133{
172 struct wl1251_partition *partition; 134 wl1251_spi_reset(wl);
173 struct spi_transfer t; 135 wl1251_spi_wake(wl);
174 struct spi_message m;
175 size_t len, cmd_len;
176 u32 *cmd;
177 int addr;
178
179 cmd_len = sizeof(u32) + 2 * sizeof(struct wl1251_partition);
180 cmd = kzalloc(cmd_len, GFP_KERNEL);
181 if (!cmd)
182 return -ENOMEM;
183
184 spi_message_init(&m);
185 memset(&t, 0, sizeof(t));
186
187 partition = (struct wl1251_partition *) (cmd + 1);
188 addr = HW_ACCESS_PART0_SIZE_ADDR;
189 len = 2 * sizeof(struct wl1251_partition);
190
191 *cmd |= WSPI_CMD_WRITE;
192 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
193 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
194
195 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
196 mem_start, mem_size);
197 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
198 reg_start, reg_size);
199
200 /* Make sure that the two partitions together don't exceed the
201 * address range */
202 if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
203 wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
204 " address range. Truncating partition[0].");
205 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
206 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
207 mem_start, mem_size);
208 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
209 reg_start, reg_size);
210 }
211
212 if ((mem_start < reg_start) &&
213 ((mem_start + mem_size) > reg_start)) {
214 /* Guarantee that the memory partition doesn't overlap the
215 * registers partition */
216 wl1251_debug(DEBUG_SPI, "End of partition[0] is "
217 "overlapping partition[1]. Adjusted.");
218 mem_size = reg_start - mem_start;
219 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
220 mem_start, mem_size);
221 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
222 reg_start, reg_size);
223 } else if ((reg_start < mem_start) &&
224 ((reg_start + reg_size) > mem_start)) {
225 /* Guarantee that the register partition doesn't overlap the
226 * memory partition */
227 wl1251_debug(DEBUG_SPI, "End of partition[1] is"
228 " overlapping partition[0]. Adjusted.");
229 reg_size = mem_start - reg_start;
230 wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
231 mem_start, mem_size);
232 wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
233 reg_start, reg_size);
234 }
235
236 partition[0].start = mem_start;
237 partition[0].size = mem_size;
238 partition[1].start = reg_start;
239 partition[1].size = reg_size;
240
241 wl->physical_mem_addr = mem_start;
242 wl->physical_reg_addr = reg_start;
243
244 wl->virtual_mem_addr = 0;
245 wl->virtual_reg_addr = mem_size;
246
247 t.tx_buf = cmd;
248 t.len = cmd_len;
249 spi_message_add_tail(&t, &m);
250
251 spi_sync(wl->spi, &m);
252
253 kfree(cmd);
254
255 return 0;
256} 136}
257 137
258void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, 138static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
259 size_t len, bool fixed) 139 size_t len)
260{ 140{
261 struct spi_transfer t[3]; 141 struct spi_transfer t[3];
262 struct spi_message m; 142 struct spi_message m;
@@ -271,9 +151,6 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
271 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; 151 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
272 *cmd |= addr & WSPI_CMD_BYTE_ADDR; 152 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
273 153
274 if (fixed)
275 *cmd |= WSPI_CMD_FIXED;
276
277 spi_message_init(&m); 154 spi_message_init(&m);
278 memset(t, 0, sizeof(t)); 155 memset(t, 0, sizeof(t));
279 156
@@ -290,7 +167,7 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
290 t[2].len = len; 167 t[2].len = len;
291 spi_message_add_tail(&t[2], &m); 168 spi_message_add_tail(&t[2], &m);
292 169
293 spi_sync(wl->spi, &m); 170 spi_sync(wl_to_spi(wl), &m);
294 171
295 /* FIXME: check busy words */ 172 /* FIXME: check busy words */
296 173
@@ -298,8 +175,8 @@ void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
298 wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); 175 wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
299} 176}
300 177
301void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, 178static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
302 size_t len, bool fixed) 179 size_t len)
303{ 180{
304 struct spi_transfer t[2]; 181 struct spi_transfer t[2];
305 struct spi_message m; 182 struct spi_message m;
@@ -312,9 +189,6 @@ void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
312 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; 189 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
313 *cmd |= addr & WSPI_CMD_BYTE_ADDR; 190 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
314 191
315 if (fixed)
316 *cmd |= WSPI_CMD_FIXED;
317
318 spi_message_init(&m); 192 spi_message_init(&m);
319 memset(t, 0, sizeof(t)); 193 memset(t, 0, sizeof(t));
320 194
@@ -326,68 +200,145 @@ void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
326 t[1].len = len; 200 t[1].len = len;
327 spi_message_add_tail(&t[1], &m); 201 spi_message_add_tail(&t[1], &m);
328 202
329 spi_sync(wl->spi, &m); 203 spi_sync(wl_to_spi(wl), &m);
330 204
331 wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); 205 wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
332 wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); 206 wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
333} 207}
334 208
335void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf, 209static void wl1251_spi_enable_irq(struct wl1251 *wl)
336 size_t len)
337{ 210{
338 int physical; 211 return enable_irq(wl->irq);
339 212}
340 physical = wl1251_translate_mem_addr(wl, addr);
341 213
342 wl1251_spi_read(wl, physical, buf, len, false); 214static void wl1251_spi_disable_irq(struct wl1251 *wl)
215{
216 return disable_irq(wl->irq);
343} 217}
344 218
345void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf, 219static const struct wl1251_if_operations wl1251_spi_ops = {
346 size_t len) 220 .read = wl1251_spi_read,
221 .write = wl1251_spi_write,
222 .reset = wl1251_spi_reset_wake,
223 .enable_irq = wl1251_spi_enable_irq,
224 .disable_irq = wl1251_spi_disable_irq,
225};
226
227static int __devinit wl1251_spi_probe(struct spi_device *spi)
347{ 228{
348 int physical; 229 struct wl12xx_platform_data *pdata;
230 struct ieee80211_hw *hw;
231 struct wl1251 *wl;
232 int ret;
233
234 pdata = spi->dev.platform_data;
235 if (!pdata) {
236 wl1251_error("no platform data");
237 return -ENODEV;
238 }
349 239
350 physical = wl1251_translate_mem_addr(wl, addr); 240 hw = wl1251_alloc_hw();
241 if (IS_ERR(hw))
242 return PTR_ERR(hw);
351 243
352 wl1251_spi_write(wl, physical, buf, len, false); 244 wl = hw->priv;
353}
354 245
355void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len, 246 SET_IEEE80211_DEV(hw, &spi->dev);
356 bool fixed) 247 dev_set_drvdata(&spi->dev, wl);
357{ 248 wl->if_priv = spi;
358 int physical; 249 wl->if_ops = &wl1251_spi_ops;
359 250
360 physical = wl1251_translate_reg_addr(wl, addr); 251 /* This is the only SPI value that we need to set here, the rest
252 * comes from the board-peripherals file */
253 spi->bits_per_word = 32;
361 254
362 wl1251_spi_read(wl, physical, buf, len, fixed); 255 ret = spi_setup(spi);
363} 256 if (ret < 0) {
257 wl1251_error("spi_setup failed");
258 goto out_free;
259 }
364 260
365void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len, 261 wl->set_power = pdata->set_power;
366 bool fixed) 262 if (!wl->set_power) {
367{ 263 wl1251_error("set power function missing in platform data");
368 int physical; 264 return -ENODEV;
265 }
369 266
370 physical = wl1251_translate_reg_addr(wl, addr); 267 wl->irq = spi->irq;
268 if (wl->irq < 0) {
269 wl1251_error("irq missing in platform data");
270 return -ENODEV;
271 }
371 272
372 wl1251_spi_write(wl, physical, buf, len, fixed); 273 ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl);
373} 274 if (ret < 0) {
275 wl1251_error("request_irq() failed: %d", ret);
276 goto out_free;
277 }
374 278
375u32 wl1251_mem_read32(struct wl1251 *wl, int addr) 279 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
376{ 280
377 return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr)); 281 disable_irq(wl->irq);
282
283 ret = wl1251_init_ieee80211(wl);
284 if (ret)
285 goto out_irq;
286
287 return 0;
288
289 out_irq:
290 free_irq(wl->irq, wl);
291
292 out_free:
293 ieee80211_free_hw(hw);
294
295 return ret;
378} 296}
379 297
380void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val) 298static int __devexit wl1251_spi_remove(struct spi_device *spi)
381{ 299{
382 wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val); 300 struct wl1251 *wl = dev_get_drvdata(&spi->dev);
301
302 free_irq(wl->irq, wl);
303 wl1251_free_hw(wl);
304
305 return 0;
383} 306}
384 307
385u32 wl1251_reg_read32(struct wl1251 *wl, int addr) 308static struct spi_driver wl1251_spi_driver = {
309 .driver = {
310 .name = "wl12xx",
311 .bus = &spi_bus_type,
312 .owner = THIS_MODULE,
313 },
314
315 .probe = wl1251_spi_probe,
316 .remove = __devexit_p(wl1251_spi_remove),
317};
318
319static int __init wl1251_spi_init(void)
386{ 320{
387 return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr)); 321 int ret;
322
323 ret = spi_register_driver(&wl1251_spi_driver);
324 if (ret < 0) {
325 wl1251_error("failed to register spi driver: %d", ret);
326 goto out;
327 }
328
329out:
330 return ret;
388} 331}
389 332
390void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val) 333static void __exit wl1251_spi_exit(void)
391{ 334{
392 wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val); 335 spi_unregister_driver(&wl1251_spi_driver);
336
337 wl1251_notice("unloaded");
393} 338}
339
340module_init(wl1251_spi_init);
341module_exit(wl1251_spi_exit);
342
343MODULE_LICENSE("GPL");
344MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h
index 6e8daf4e1085..2e273a97e7f3 100644
--- a/drivers/net/wireless/wl12xx/wl1251_spi.h
+++ b/drivers/net/wireless/wl12xx/wl1251_spi.h
@@ -27,18 +27,7 @@
27 27
28#include "wl1251_cmd.h" 28#include "wl1251_cmd.h"
29#include "wl1251_acx.h" 29#include "wl1251_acx.h"
30#include "reg.h" 30#include "wl1251_reg.h"
31
32#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
33
34#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
35#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
36#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
37#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
38
39#define HW_ACCESS_REGISTER_SIZE 4
40
41#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
42 31
43#define WSPI_CMD_READ 0x40000000 32#define WSPI_CMD_READ 0x40000000
44#define WSPI_CMD_WRITE 0x00000000 33#define WSPI_CMD_WRITE 0x00000000
@@ -69,47 +58,4 @@
69 ((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32)) 58 ((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32))
70#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 59#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
71 60
72
73/* Raw target IO, address is not translated */
74void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf,
75 size_t len, bool fixed);
76void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf,
77 size_t len, bool fixed);
78
79/* Memory target IO, address is tranlated to partition 0 */
80void wl1251_spi_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len);
81void wl1251_spi_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len);
82u32 wl1251_mem_read32(struct wl1251 *wl, int addr);
83void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val);
84
85/* Registers IO */
86void wl1251_spi_reg_read(struct wl1251 *wl, int addr, void *buf, size_t len,
87 bool fixed);
88void wl1251_spi_reg_write(struct wl1251 *wl, int addr, void *buf, size_t len,
89 bool fixed);
90u32 wl1251_reg_read32(struct wl1251 *wl, int addr);
91void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val);
92
93/* INIT and RESET words */
94void wl1251_spi_reset(struct wl1251 *wl);
95void wl1251_spi_init(struct wl1251 *wl);
96int wl1251_set_partition(struct wl1251 *wl,
97 u32 part_start, u32 part_size,
98 u32 reg_start, u32 reg_size);
99
100static inline u32 wl1251_read32(struct wl1251 *wl, int addr)
101{
102 wl1251_spi_read(wl, addr, &wl->buffer_32,
103 sizeof(wl->buffer_32), false);
104
105 return wl->buffer_32;
106}
107
108static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val)
109{
110 wl->buffer_32 = val;
111 wl1251_spi_write(wl, addr, &wl->buffer_32,
112 sizeof(wl->buffer_32), false);
113}
114
115#endif /* __WL1251_SPI_H__ */ 61#endif /* __WL1251_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c
index 2652a222383a..f85970615849 100644
--- a/drivers/net/wireless/wl12xx/wl1251_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1251_tx.c
@@ -26,10 +26,10 @@
26#include <linux/module.h> 26#include <linux/module.h>
27 27
28#include "wl1251.h" 28#include "wl1251.h"
29#include "reg.h" 29#include "wl1251_reg.h"
30#include "wl1251_spi.h"
31#include "wl1251_tx.h" 30#include "wl1251_tx.h"
32#include "wl1251_ps.h" 31#include "wl1251_ps.h"
32#include "wl1251_io.h"
33 33
34static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) 34static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count)
35{ 35{
@@ -235,7 +235,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb,
235 else 235 else
236 addr = wl->data_path->tx_packet_ring_addr; 236 addr = wl->data_path->tx_packet_ring_addr;
237 237
238 wl1251_spi_mem_write(wl, addr, skb->data, len); 238 wl1251_mem_write(wl, addr, skb->data, len);
239 239
240 wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", 240 wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x",
241 tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); 241 tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate);
@@ -451,7 +451,7 @@ void wl1251_tx_complete(struct wl1251 *wl)
451 return; 451 return;
452 452
453 /* First we read the result */ 453 /* First we read the result */
454 wl1251_spi_mem_read(wl, wl->data_path->tx_complete_addr, 454 wl1251_mem_read(wl, wl->data_path->tx_complete_addr,
455 result, sizeof(result)); 455 result, sizeof(result));
456 456
457 result_index = wl->next_tx_complete; 457 result_index = wl->next_tx_complete;
@@ -482,41 +482,41 @@ void wl1251_tx_complete(struct wl1251 *wl)
482 */ 482 */
483 if (result_index > wl->next_tx_complete) { 483 if (result_index > wl->next_tx_complete) {
484 /* Only 1 write is needed */ 484 /* Only 1 write is needed */
485 wl1251_spi_mem_write(wl, 485 wl1251_mem_write(wl,
486 wl->data_path->tx_complete_addr + 486 wl->data_path->tx_complete_addr +
487 (wl->next_tx_complete * 487 (wl->next_tx_complete *
488 sizeof(struct tx_result)), 488 sizeof(struct tx_result)),
489 &result[wl->next_tx_complete], 489 &result[wl->next_tx_complete],
490 num_complete * 490 num_complete *
491 sizeof(struct tx_result)); 491 sizeof(struct tx_result));
492 492
493 493
494 } else if (result_index < wl->next_tx_complete) { 494 } else if (result_index < wl->next_tx_complete) {
495 /* 2 writes are needed */ 495 /* 2 writes are needed */
496 wl1251_spi_mem_write(wl, 496 wl1251_mem_write(wl,
497 wl->data_path->tx_complete_addr + 497 wl->data_path->tx_complete_addr +
498 (wl->next_tx_complete * 498 (wl->next_tx_complete *
499 sizeof(struct tx_result)), 499 sizeof(struct tx_result)),
500 &result[wl->next_tx_complete], 500 &result[wl->next_tx_complete],
501 (FW_TX_CMPLT_BLOCK_SIZE - 501 (FW_TX_CMPLT_BLOCK_SIZE -
502 wl->next_tx_complete) * 502 wl->next_tx_complete) *
503 sizeof(struct tx_result)); 503 sizeof(struct tx_result));
504 504
505 wl1251_spi_mem_write(wl, 505 wl1251_mem_write(wl,
506 wl->data_path->tx_complete_addr, 506 wl->data_path->tx_complete_addr,
507 result, 507 result,
508 (num_complete - 508 (num_complete -
509 FW_TX_CMPLT_BLOCK_SIZE + 509 FW_TX_CMPLT_BLOCK_SIZE +
510 wl->next_tx_complete) * 510 wl->next_tx_complete) *
511 sizeof(struct tx_result)); 511 sizeof(struct tx_result));
512 512
513 } else { 513 } else {
514 /* We have to write the whole array */ 514 /* We have to write the whole array */
515 wl1251_spi_mem_write(wl, 515 wl1251_mem_write(wl,
516 wl->data_path->tx_complete_addr, 516 wl->data_path->tx_complete_addr,
517 result, 517 result,
518 FW_TX_CMPLT_BLOCK_SIZE * 518 FW_TX_CMPLT_BLOCK_SIZE *
519 sizeof(struct tx_result)); 519 sizeof(struct tx_result));
520 } 520 }
521 521
522 } 522 }
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
new file mode 100644
index 000000000000..55818f94017b
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -0,0 +1,407 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_H__
26#define __WL1271_H__
27
28#include <linux/mutex.h>
29#include <linux/completion.h>
30#include <linux/spinlock.h>
31#include <linux/list.h>
32#include <linux/bitops.h>
33#include <net/mac80211.h>
34
35#define DRIVER_NAME "wl1271"
36#define DRIVER_PREFIX DRIVER_NAME ": "
37
38enum {
39 DEBUG_NONE = 0,
40 DEBUG_IRQ = BIT(0),
41 DEBUG_SPI = BIT(1),
42 DEBUG_BOOT = BIT(2),
43 DEBUG_MAILBOX = BIT(3),
44 DEBUG_NETLINK = BIT(4),
45 DEBUG_EVENT = BIT(5),
46 DEBUG_TX = BIT(6),
47 DEBUG_RX = BIT(7),
48 DEBUG_SCAN = BIT(8),
49 DEBUG_CRYPT = BIT(9),
50 DEBUG_PSM = BIT(10),
51 DEBUG_MAC80211 = BIT(11),
52 DEBUG_CMD = BIT(12),
53 DEBUG_ACX = BIT(13),
54 DEBUG_ALL = ~0,
55};
56
57#define DEBUG_LEVEL (DEBUG_NONE)
58
59#define DEBUG_DUMP_LIMIT 1024
60
61#define wl1271_error(fmt, arg...) \
62 printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
63
64#define wl1271_warning(fmt, arg...) \
65 printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
66
67#define wl1271_notice(fmt, arg...) \
68 printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
69
70#define wl1271_info(fmt, arg...) \
71 printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg)
72
73#define wl1271_debug(level, fmt, arg...) \
74 do { \
75 if (level & DEBUG_LEVEL) \
76 printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
77 } while (0)
78
79#define wl1271_dump(level, prefix, buf, len) \
80 do { \
81 if (level & DEBUG_LEVEL) \
82 print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
83 DUMP_PREFIX_OFFSET, 16, 1, \
84 buf, \
85 min_t(size_t, len, DEBUG_DUMP_LIMIT), \
86 0); \
87 } while (0)
88
89#define wl1271_dump_ascii(level, prefix, buf, len) \
90 do { \
91 if (level & DEBUG_LEVEL) \
92 print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \
93 DUMP_PREFIX_OFFSET, 16, 1, \
94 buf, \
95 min_t(size_t, len, DEBUG_DUMP_LIMIT), \
96 true); \
97 } while (0)
98
99#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \
100 CFG_BSSID_FILTER_EN)
101
102#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \
103 CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
104 CFG_RX_CTL_EN | CFG_RX_BCN_EN | \
105 CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
106
107#define WL1271_FW_NAME "wl1271-fw.bin"
108#define WL1271_NVS_NAME "wl1271-nvs.bin"
109
110#define WL1271_BUSY_WORD_LEN 8
111
112#define WL1271_ELP_HW_STATE_ASLEEP 0
113#define WL1271_ELP_HW_STATE_IRQ 1
114
115enum wl1271_state {
116 WL1271_STATE_OFF,
117 WL1271_STATE_ON,
118 WL1271_STATE_PLT,
119};
120
121enum wl1271_partition_type {
122 PART_DOWN,
123 PART_WORK,
124 PART_DRPW,
125
126 PART_TABLE_LEN
127};
128
129struct wl1271_partition {
130 u32 size;
131 u32 start;
132};
133
134struct wl1271_partition_set {
135 struct wl1271_partition mem;
136 struct wl1271_partition reg;
137};
138
139struct wl1271;
140
141/* FIXME: I'm not sure about this structure name */
142struct wl1271_chip {
143 u32 id;
144 char fw_ver[21];
145};
146
147struct wl1271_stats {
148 struct acx_statistics *fw_stats;
149 unsigned long fw_stats_update;
150
151 unsigned int retry_count;
152 unsigned int excessive_retries;
153};
154
155struct wl1271_debugfs {
156 struct dentry *rootdir;
157 struct dentry *fw_statistics;
158
159 struct dentry *tx_internal_desc_overflow;
160
161 struct dentry *rx_out_of_mem;
162 struct dentry *rx_hdr_overflow;
163 struct dentry *rx_hw_stuck;
164 struct dentry *rx_dropped;
165 struct dentry *rx_fcs_err;
166 struct dentry *rx_xfr_hint_trig;
167 struct dentry *rx_path_reset;
168 struct dentry *rx_reset_counter;
169
170 struct dentry *dma_rx_requested;
171 struct dentry *dma_rx_errors;
172 struct dentry *dma_tx_requested;
173 struct dentry *dma_tx_errors;
174
175 struct dentry *isr_cmd_cmplt;
176 struct dentry *isr_fiqs;
177 struct dentry *isr_rx_headers;
178 struct dentry *isr_rx_mem_overflow;
179 struct dentry *isr_rx_rdys;
180 struct dentry *isr_irqs;
181 struct dentry *isr_tx_procs;
182 struct dentry *isr_decrypt_done;
183 struct dentry *isr_dma0_done;
184 struct dentry *isr_dma1_done;
185 struct dentry *isr_tx_exch_complete;
186 struct dentry *isr_commands;
187 struct dentry *isr_rx_procs;
188 struct dentry *isr_hw_pm_mode_changes;
189 struct dentry *isr_host_acknowledges;
190 struct dentry *isr_pci_pm;
191 struct dentry *isr_wakeups;
192 struct dentry *isr_low_rssi;
193
194 struct dentry *wep_addr_key_count;
195 struct dentry *wep_default_key_count;
196 /* skipping wep.reserved */
197 struct dentry *wep_key_not_found;
198 struct dentry *wep_decrypt_fail;
199 struct dentry *wep_packets;
200 struct dentry *wep_interrupt;
201
202 struct dentry *pwr_ps_enter;
203 struct dentry *pwr_elp_enter;
204 struct dentry *pwr_missing_bcns;
205 struct dentry *pwr_wake_on_host;
206 struct dentry *pwr_wake_on_timer_exp;
207 struct dentry *pwr_tx_with_ps;
208 struct dentry *pwr_tx_without_ps;
209 struct dentry *pwr_rcvd_beacons;
210 struct dentry *pwr_power_save_off;
211 struct dentry *pwr_enable_ps;
212 struct dentry *pwr_disable_ps;
213 struct dentry *pwr_fix_tsf_ps;
214 /* skipping cont_miss_bcns_spread for now */
215 struct dentry *pwr_rcvd_awake_beacons;
216
217 struct dentry *mic_rx_pkts;
218 struct dentry *mic_calc_failure;
219
220 struct dentry *aes_encrypt_fail;
221 struct dentry *aes_decrypt_fail;
222 struct dentry *aes_encrypt_packets;
223 struct dentry *aes_decrypt_packets;
224 struct dentry *aes_encrypt_interrupt;
225 struct dentry *aes_decrypt_interrupt;
226
227 struct dentry *event_heart_beat;
228 struct dentry *event_calibration;
229 struct dentry *event_rx_mismatch;
230 struct dentry *event_rx_mem_empty;
231 struct dentry *event_rx_pool;
232 struct dentry *event_oom_late;
233 struct dentry *event_phy_transmit_error;
234 struct dentry *event_tx_stuck;
235
236 struct dentry *ps_pspoll_timeouts;
237 struct dentry *ps_upsd_timeouts;
238 struct dentry *ps_upsd_max_sptime;
239 struct dentry *ps_upsd_max_apturn;
240 struct dentry *ps_pspoll_max_apturn;
241 struct dentry *ps_pspoll_utilization;
242 struct dentry *ps_upsd_utilization;
243
244 struct dentry *rxpipe_rx_prep_beacon_drop;
245 struct dentry *rxpipe_descr_host_int_trig_rx_data;
246 struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data;
247 struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data;
248 struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data;
249
250 struct dentry *tx_queue_len;
251
252 struct dentry *retry_count;
253 struct dentry *excessive_retries;
254};
255
256#define NUM_TX_QUEUES 4
257#define NUM_RX_PKT_DESC 8
258
259/* FW status registers */
260struct wl1271_fw_status {
261 u32 intr;
262 u8 fw_rx_counter;
263 u8 drv_rx_counter;
264 u8 reserved;
265 u8 tx_results_counter;
266 u32 rx_pkt_descs[NUM_RX_PKT_DESC];
267 u32 tx_released_blks[NUM_TX_QUEUES];
268 u32 fw_localtime;
269 u32 padding[2];
270} __attribute__ ((packed));
271
272struct wl1271_rx_mem_pool_addr {
273 u32 addr;
274 u32 addr_extra;
275};
276
277struct wl1271 {
278 struct ieee80211_hw *hw;
279 bool mac80211_registered;
280
281 struct spi_device *spi;
282
283 void (*set_power)(bool enable);
284 int irq;
285
286 spinlock_t wl_lock;
287
288 enum wl1271_state state;
289 struct mutex mutex;
290
291 int physical_mem_addr;
292 int physical_reg_addr;
293 int virtual_mem_addr;
294 int virtual_reg_addr;
295
296 struct wl1271_chip chip;
297
298 int cmd_box_addr;
299 int event_box_addr;
300
301 u8 *fw;
302 size_t fw_len;
303 u8 *nvs;
304 size_t nvs_len;
305
306 u8 bssid[ETH_ALEN];
307 u8 mac_addr[ETH_ALEN];
308 u8 bss_type;
309 u8 ssid[IW_ESSID_MAX_SIZE + 1];
310 u8 ssid_len;
311 u8 listen_int;
312 int channel;
313
314 struct wl1271_acx_mem_map *target_mem_map;
315
316 /* Accounting for allocated / available TX blocks on HW */
317 u32 tx_blocks_freed[NUM_TX_QUEUES];
318 u32 tx_blocks_available;
319 u8 tx_results_count;
320
321 /* Transmitted TX packets counter for chipset interface */
322 int tx_packets_count;
323
324 /* Time-offset between host and chipset clocks */
325 int time_offset;
326
327 /* Session counter for the chipset */
328 int session_counter;
329
330 /* Frames scheduled for transmission, not handled yet */
331 struct sk_buff_head tx_queue;
332 bool tx_queue_stopped;
333
334 struct work_struct tx_work;
335 struct work_struct filter_work;
336
337 /* Pending TX frames */
338 struct sk_buff *tx_frames[16];
339
340 /* FW Rx counter */
341 u32 rx_counter;
342
343 /* Rx memory pool address */
344 struct wl1271_rx_mem_pool_addr rx_mem_pool_addr;
345
346 /* The target interrupt mask */
347 struct work_struct irq_work;
348
349 /* The mbox event mask */
350 u32 event_mask;
351
352 /* Mailbox pointers */
353 u32 mbox_ptr[2];
354
355 /* Are we currently scanning */
356 bool scanning;
357
358 /* Our association ID */
359 u16 aid;
360
361 /* Default key (for WEP) */
362 u32 default_key;
363
364 unsigned int rx_config;
365 unsigned int rx_filter;
366
367 /* is firmware in elp mode */
368 bool elp;
369
370 struct completion *elp_compl;
371
372 /* we can be in psm, but not in elp, we have to differentiate */
373 bool psm;
374
375 /* PSM mode requested */
376 bool psm_requested;
377
378 /* in dBm */
379 int power_level;
380
381 struct wl1271_stats stats;
382 struct wl1271_debugfs debugfs;
383
384 u32 buffer_32;
385 u32 buffer_cmd;
386 u8 buffer_busyword[WL1271_BUSY_WORD_LEN];
387 struct wl1271_rx_descriptor *rx_descriptor;
388
389 struct wl1271_fw_status *fw_status;
390 struct wl1271_tx_hw_res_if *tx_res_if;
391};
392
393int wl1271_plt_start(struct wl1271 *wl);
394int wl1271_plt_stop(struct wl1271 *wl);
395
396#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */
397
398#define SESSION_COUNTER_MAX 7 /* maximum value for the session counter */
399
400#define WL1271_DEFAULT_POWER_LEVEL 0
401
402#define WL1271_TX_QUEUE_MAX_LENGTH 20
403
404/* WL1271 needs a 200ms sleep after power on */
405#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
406
407#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
new file mode 100644
index 000000000000..f622a4092615
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -0,0 +1,961 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1271_acx.h"
25
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/crc7.h>
29#include <linux/spi/spi.h>
30
31#include "wl1271.h"
32#include "wl12xx_80211.h"
33#include "wl1271_reg.h"
34#include "wl1271_spi.h"
35#include "wl1271_ps.h"
36
37int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event,
38 u8 listen_interval)
39{
40 struct acx_wake_up_condition *wake_up;
41 int ret;
42
43 wl1271_debug(DEBUG_ACX, "acx wake up conditions");
44
45 wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
46 if (!wake_up) {
47 ret = -ENOMEM;
48 goto out;
49 }
50
51 wake_up->wake_up_event = wake_up_event;
52 wake_up->listen_interval = listen_interval;
53
54 ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
55 wake_up, sizeof(*wake_up));
56 if (ret < 0) {
57 wl1271_warning("could not set wake up conditions: %d", ret);
58 goto out;
59 }
60
61out:
62 kfree(wake_up);
63 return ret;
64}
65
66int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth)
67{
68 struct acx_sleep_auth *auth;
69 int ret;
70
71 wl1271_debug(DEBUG_ACX, "acx sleep auth");
72
73 auth = kzalloc(sizeof(*auth), GFP_KERNEL);
74 if (!auth) {
75 ret = -ENOMEM;
76 goto out;
77 }
78
79 auth->sleep_auth = sleep_auth;
80
81 ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth));
82 if (ret < 0)
83 return ret;
84
85out:
86 kfree(auth);
87 return ret;
88}
89
90int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
91{
92 struct acx_revision *rev;
93 int ret;
94
95 wl1271_debug(DEBUG_ACX, "acx fw rev");
96
97 rev = kzalloc(sizeof(*rev), GFP_KERNEL);
98 if (!rev) {
99 ret = -ENOMEM;
100 goto out;
101 }
102
103 ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
104 if (ret < 0) {
105 wl1271_warning("ACX_FW_REV interrogate failed");
106 goto out;
107 }
108
109 /* be careful with the buffer sizes */
110 strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
111
112 /*
113 * if the firmware version string is exactly
114 * sizeof(rev->fw_version) long or fw_len is less than
115 * sizeof(rev->fw_version) it won't be null terminated
116 */
117 buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
118
119out:
120 kfree(rev);
121 return ret;
122}
123
124int wl1271_acx_tx_power(struct wl1271 *wl, int power)
125{
126 struct acx_current_tx_power *acx;
127 int ret;
128
129 wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr");
130
131 if (power < 0 || power > 25)
132 return -EINVAL;
133
134 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
135 if (!acx) {
136 ret = -ENOMEM;
137 goto out;
138 }
139
140 acx->current_tx_power = power * 10;
141
142 ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
143 if (ret < 0) {
144 wl1271_warning("configure of tx power failed: %d", ret);
145 goto out;
146 }
147
148out:
149 kfree(acx);
150 return ret;
151}
152
153int wl1271_acx_feature_cfg(struct wl1271 *wl)
154{
155 struct acx_feature_config *feature;
156 int ret;
157
158 wl1271_debug(DEBUG_ACX, "acx feature cfg");
159
160 feature = kzalloc(sizeof(*feature), GFP_KERNEL);
161 if (!feature) {
162 ret = -ENOMEM;
163 goto out;
164 }
165
166 /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
167 feature->data_flow_options = 0;
168 feature->options = 0;
169
170 ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
171 feature, sizeof(*feature));
172 if (ret < 0) {
173 wl1271_error("Couldnt set HW encryption");
174 goto out;
175 }
176
177out:
178 kfree(feature);
179 return ret;
180}
181
182int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map,
183 size_t len)
184{
185 int ret;
186
187 wl1271_debug(DEBUG_ACX, "acx mem map");
188
189 ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len);
190 if (ret < 0)
191 return ret;
192
193 return 0;
194}
195
196int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time)
197{
198 struct acx_rx_msdu_lifetime *acx;
199 int ret;
200
201 wl1271_debug(DEBUG_ACX, "acx rx msdu life time");
202
203 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
204 if (!acx) {
205 ret = -ENOMEM;
206 goto out;
207 }
208
209 acx->lifetime = life_time;
210 ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME,
211 acx, sizeof(*acx));
212 if (ret < 0) {
213 wl1271_warning("failed to set rx msdu life time: %d", ret);
214 goto out;
215 }
216
217out:
218 kfree(acx);
219 return ret;
220}
221
222int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
223{
224 struct acx_rx_config *rx_config;
225 int ret;
226
227 wl1271_debug(DEBUG_ACX, "acx rx config");
228
229 rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
230 if (!rx_config) {
231 ret = -ENOMEM;
232 goto out;
233 }
234
235 rx_config->config_options = config;
236 rx_config->filter_options = filter;
237
238 ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
239 rx_config, sizeof(*rx_config));
240 if (ret < 0) {
241 wl1271_warning("failed to set rx config: %d", ret);
242 goto out;
243 }
244
245out:
246 kfree(rx_config);
247 return ret;
248}
249
250int wl1271_acx_pd_threshold(struct wl1271 *wl)
251{
252 struct acx_packet_detection *pd;
253 int ret;
254
255 wl1271_debug(DEBUG_ACX, "acx data pd threshold");
256
257 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
258 if (!pd) {
259 ret = -ENOMEM;
260 goto out;
261 }
262
263 /* FIXME: threshold value not set */
264
265 ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd));
266 if (ret < 0) {
267 wl1271_warning("failed to set pd threshold: %d", ret);
268 goto out;
269 }
270
271out:
272 kfree(pd);
273 return 0;
274}
275
276int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
277{
278 struct acx_slot *slot;
279 int ret;
280
281 wl1271_debug(DEBUG_ACX, "acx slot");
282
283 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
284 if (!slot) {
285 ret = -ENOMEM;
286 goto out;
287 }
288
289 slot->wone_index = STATION_WONE_INDEX;
290 slot->slot_time = slot_time;
291
292 ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
293 if (ret < 0) {
294 wl1271_warning("failed to set slot time: %d", ret);
295 goto out;
296 }
297
298out:
299 kfree(slot);
300 return ret;
301}
302
303int wl1271_acx_group_address_tbl(struct wl1271 *wl)
304{
305 struct acx_dot11_grp_addr_tbl *acx;
306 int ret;
307
308 wl1271_debug(DEBUG_ACX, "acx group address tbl");
309
310 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
311 if (!acx) {
312 ret = -ENOMEM;
313 goto out;
314 }
315
316 /* MAC filtering */
317 acx->enabled = 0;
318 acx->num_groups = 0;
319 memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN);
320
321 ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
322 acx, sizeof(*acx));
323 if (ret < 0) {
324 wl1271_warning("failed to set group addr table: %d", ret);
325 goto out;
326 }
327
328out:
329 kfree(acx);
330 return ret;
331}
332
333int wl1271_acx_service_period_timeout(struct wl1271 *wl)
334{
335 struct acx_rx_timeout *rx_timeout;
336 int ret;
337
338 rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL);
339 if (!rx_timeout) {
340 ret = -ENOMEM;
341 goto out;
342 }
343
344 wl1271_debug(DEBUG_ACX, "acx service period timeout");
345
346 rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF;
347 rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF;
348
349 ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
350 rx_timeout, sizeof(*rx_timeout));
351 if (ret < 0) {
352 wl1271_warning("failed to set service period timeout: %d",
353 ret);
354 goto out;
355 }
356
357out:
358 kfree(rx_timeout);
359 return ret;
360}
361
362int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold)
363{
364 struct acx_rts_threshold *rts;
365 int ret;
366
367 wl1271_debug(DEBUG_ACX, "acx rts threshold");
368
369 rts = kzalloc(sizeof(*rts), GFP_KERNEL);
370 if (!rts) {
371 ret = -ENOMEM;
372 goto out;
373 }
374
375 rts->threshold = rts_threshold;
376
377 ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
378 if (ret < 0) {
379 wl1271_warning("failed to set rts threshold: %d", ret);
380 goto out;
381 }
382
383out:
384 kfree(rts);
385 return ret;
386}
387
388int wl1271_acx_beacon_filter_opt(struct wl1271 *wl)
389{
390 struct acx_beacon_filter_option *beacon_filter;
391 int ret;
392
393 wl1271_debug(DEBUG_ACX, "acx beacon filter opt");
394
395 beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
396 if (!beacon_filter) {
397 ret = -ENOMEM;
398 goto out;
399 }
400
401 beacon_filter->enable = 0;
402 beacon_filter->max_num_beacons = 0;
403
404 ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT,
405 beacon_filter, sizeof(*beacon_filter));
406 if (ret < 0) {
407 wl1271_warning("failed to set beacon filter opt: %d", ret);
408 goto out;
409 }
410
411out:
412 kfree(beacon_filter);
413 return ret;
414}
415
416int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
417{
418 struct acx_beacon_filter_ie_table *ie_table;
419 int ret;
420
421 wl1271_debug(DEBUG_ACX, "acx beacon filter table");
422
423 ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL);
424 if (!ie_table) {
425 ret = -ENOMEM;
426 goto out;
427 }
428
429 ie_table->num_ie = 0;
430 memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE);
431
432 ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE,
433 ie_table, sizeof(*ie_table));
434 if (ret < 0) {
435 wl1271_warning("failed to set beacon filter table: %d", ret);
436 goto out;
437 }
438
439out:
440 kfree(ie_table);
441 return ret;
442}
443
444int wl1271_acx_sg_enable(struct wl1271 *wl)
445{
446 struct acx_bt_wlan_coex *pta;
447 int ret;
448
449 wl1271_debug(DEBUG_ACX, "acx sg enable");
450
451 pta = kzalloc(sizeof(*pta), GFP_KERNEL);
452 if (!pta) {
453 ret = -ENOMEM;
454 goto out;
455 }
456
457 pta->enable = SG_ENABLE;
458
459 ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
460 if (ret < 0) {
461 wl1271_warning("failed to set softgemini enable: %d", ret);
462 goto out;
463 }
464
465out:
466 kfree(pta);
467 return ret;
468}
469
470int wl1271_acx_sg_cfg(struct wl1271 *wl)
471{
472 struct acx_bt_wlan_coex_param *param;
473 int ret;
474
475 wl1271_debug(DEBUG_ACX, "acx sg cfg");
476
477 param = kzalloc(sizeof(*param), GFP_KERNEL);
478 if (!param) {
479 ret = -ENOMEM;
480 goto out;
481 }
482
483 /* BT-WLAN coext parameters */
484 param->min_rate = RATE_INDEX_24MBPS;
485 param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF;
486 param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF;
487 param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF;
488 param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF;
489 param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF;
490 param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF;
491 param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF;
492 param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF;
493 param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF;
494 param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF;
495 param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF;
496 param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF;
497 param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF;
498 param->antenna_type = PTA_ANTENNA_TYPE_DEF;
499 param->signal_type = PTA_SIGNALING_TYPE_DEF;
500 param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF;
501 param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF;
502 param->max_cts = PTA_MAX_NUM_CTS_DEF;
503 param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF;
504 param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF;
505 param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF;
506 param->wlan_elp_hp = PTA_ELP_HP_DEF;
507 param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF;
508 param->ack_mode_dual_ant = PTA_ACK_MODE_DEF;
509 param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF;
510 param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF;
511 param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF;
512
513 ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
514 if (ret < 0) {
515 wl1271_warning("failed to set sg config: %d", ret);
516 goto out;
517 }
518
519out:
520 kfree(param);
521 return ret;
522}
523
524int wl1271_acx_cca_threshold(struct wl1271 *wl)
525{
526 struct acx_energy_detection *detection;
527 int ret;
528
529 wl1271_debug(DEBUG_ACX, "acx cca threshold");
530
531 detection = kzalloc(sizeof(*detection), GFP_KERNEL);
532 if (!detection) {
533 ret = -ENOMEM;
534 goto out;
535 }
536
537 detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D;
538 detection->tx_energy_detection = 0;
539
540 ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD,
541 detection, sizeof(*detection));
542 if (ret < 0) {
543 wl1271_warning("failed to set cca threshold: %d", ret);
544 return ret;
545 }
546
547out:
548 kfree(detection);
549 return ret;
550}
551
552int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
553{
554 struct acx_beacon_broadcast *bb;
555 int ret;
556
557 wl1271_debug(DEBUG_ACX, "acx bcn dtim options");
558
559 bb = kzalloc(sizeof(*bb), GFP_KERNEL);
560 if (!bb) {
561 ret = -ENOMEM;
562 goto out;
563 }
564
565 bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE;
566 bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE;
567 bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE;
568 bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF;
569
570 ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
571 if (ret < 0) {
572 wl1271_warning("failed to set rx config: %d", ret);
573 goto out;
574 }
575
576out:
577 kfree(bb);
578 return ret;
579}
580
581int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
582{
583 struct acx_aid *acx_aid;
584 int ret;
585
586 wl1271_debug(DEBUG_ACX, "acx aid");
587
588 acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
589 if (!acx_aid) {
590 ret = -ENOMEM;
591 goto out;
592 }
593
594 acx_aid->aid = aid;
595
596 ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
597 if (ret < 0) {
598 wl1271_warning("failed to set aid: %d", ret);
599 goto out;
600 }
601
602out:
603 kfree(acx_aid);
604 return ret;
605}
606
607int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask)
608{
609 struct acx_event_mask *mask;
610 int ret;
611
612 wl1271_debug(DEBUG_ACX, "acx event mbox mask");
613
614 mask = kzalloc(sizeof(*mask), GFP_KERNEL);
615 if (!mask) {
616 ret = -ENOMEM;
617 goto out;
618 }
619
620 /* high event mask is unused */
621 mask->high_event_mask = 0xffffffff;
622
623 mask->event_mask = event_mask;
624
625 ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK,
626 mask, sizeof(*mask));
627 if (ret < 0) {
628 wl1271_warning("failed to set acx_event_mbox_mask: %d", ret);
629 goto out;
630 }
631
632out:
633 kfree(mask);
634 return ret;
635}
636
637int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
638{
639 struct acx_preamble *acx;
640 int ret;
641
642 wl1271_debug(DEBUG_ACX, "acx_set_preamble");
643
644 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
645 if (!acx) {
646 ret = -ENOMEM;
647 goto out;
648 }
649
650 acx->preamble = preamble;
651
652 ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
653 if (ret < 0) {
654 wl1271_warning("Setting of preamble failed: %d", ret);
655 goto out;
656 }
657
658out:
659 kfree(acx);
660 return ret;
661}
662
663int wl1271_acx_cts_protect(struct wl1271 *wl,
664 enum acx_ctsprotect_type ctsprotect)
665{
666 struct acx_ctsprotect *acx;
667 int ret;
668
669 wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect");
670
671 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
672 if (!acx) {
673 ret = -ENOMEM;
674 goto out;
675 }
676
677 acx->ctsprotect = ctsprotect;
678
679 ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
680 if (ret < 0) {
681 wl1271_warning("Setting of ctsprotect failed: %d", ret);
682 goto out;
683 }
684
685out:
686 kfree(acx);
687 return ret;
688}
689
690int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
691{
692 int ret;
693
694 wl1271_debug(DEBUG_ACX, "acx statistics");
695
696 ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats,
697 sizeof(*stats));
698 if (ret < 0) {
699 wl1271_warning("acx statistics failed: %d", ret);
700 return -ENOMEM;
701 }
702
703 return 0;
704}
705
706int wl1271_acx_rate_policies(struct wl1271 *wl)
707{
708 struct acx_rate_policy *acx;
709 int ret = 0;
710
711 wl1271_debug(DEBUG_ACX, "acx rate policies");
712
713 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
714
715 if (!acx) {
716 ret = -ENOMEM;
717 goto out;
718 }
719
720 /* configure one default (one-size-fits-all) rate class */
721 acx->rate_class_cnt = 1;
722 acx->rate_class[0].enabled_rates = ACX_RATE_MASK_ALL;
723 acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT;
724 acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT;
725 acx->rate_class[0].aflags = 0;
726
727 ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
728 if (ret < 0) {
729 wl1271_warning("Setting of rate policies failed: %d", ret);
730 goto out;
731 }
732
733out:
734 kfree(acx);
735 return ret;
736}
737
738int wl1271_acx_ac_cfg(struct wl1271 *wl)
739{
740 struct acx_ac_cfg *acx;
741 int i, ret = 0;
742
743 wl1271_debug(DEBUG_ACX, "acx access category config");
744
745 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
746
747 if (!acx) {
748 ret = -ENOMEM;
749 goto out;
750 }
751
752 /*
753 * FIXME: Configure each AC with appropriate values (most suitable
754 * values will probably be different for each AC.
755 */
756 for (i = 0; i < WL1271_ACX_AC_COUNT; i++) {
757 acx->ac = i;
758
759 /*
760 * FIXME: The following default values originate from
761 * the TI reference driver. What do they mean?
762 */
763 acx->cw_min = 15;
764 acx->cw_max = 63;
765 acx->aifsn = 3;
766 acx->reserved = 0;
767 acx->tx_op_limit = 0;
768
769 ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx));
770 if (ret < 0) {
771 wl1271_warning("Setting of access category "
772 "config: %d", ret);
773 goto out;
774 }
775 }
776
777out:
778 kfree(acx);
779 return ret;
780}
781
782int wl1271_acx_tid_cfg(struct wl1271 *wl)
783{
784 struct acx_tid_config *acx;
785 int i, ret = 0;
786
787 wl1271_debug(DEBUG_ACX, "acx tid config");
788
789 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
790
791 if (!acx) {
792 ret = -ENOMEM;
793 goto out;
794 }
795
796 /* FIXME: configure each TID with a different AC reference */
797 for (i = 0; i < WL1271_ACX_TID_COUNT; i++) {
798 acx->queue_id = i;
799 acx->tsid = WL1271_ACX_AC_BE;
800 acx->ps_scheme = WL1271_ACX_PS_SCHEME_LEGACY;
801 acx->ack_policy = WL1271_ACX_ACK_POLICY_LEGACY;
802
803 ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx));
804 if (ret < 0) {
805 wl1271_warning("Setting of tid config failed: %d", ret);
806 goto out;
807 }
808 }
809
810out:
811 kfree(acx);
812 return ret;
813}
814
815int wl1271_acx_frag_threshold(struct wl1271 *wl)
816{
817 struct acx_frag_threshold *acx;
818 int ret = 0;
819
820 wl1271_debug(DEBUG_ACX, "acx frag threshold");
821
822 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
823
824 if (!acx) {
825 ret = -ENOMEM;
826 goto out;
827 }
828
829 acx->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD;
830 ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx));
831 if (ret < 0) {
832 wl1271_warning("Setting of frag threshold failed: %d", ret);
833 goto out;
834 }
835
836out:
837 kfree(acx);
838 return ret;
839}
840
841int wl1271_acx_tx_config_options(struct wl1271 *wl)
842{
843 struct acx_tx_config_options *acx;
844 int ret = 0;
845
846 wl1271_debug(DEBUG_ACX, "acx tx config options");
847
848 acx = kzalloc(sizeof(*acx), GFP_KERNEL);
849
850 if (!acx) {
851 ret = -ENOMEM;
852 goto out;
853 }
854
855 acx->tx_compl_timeout = WL1271_ACX_TX_COMPL_TIMEOUT;
856 acx->tx_compl_threshold = WL1271_ACX_TX_COMPL_THRESHOLD;
857 ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx));
858 if (ret < 0) {
859 wl1271_warning("Setting of tx options failed: %d", ret);
860 goto out;
861 }
862
863out:
864 kfree(acx);
865 return ret;
866}
867
868int wl1271_acx_mem_cfg(struct wl1271 *wl)
869{
870 struct wl1271_acx_config_memory *mem_conf;
871 int ret;
872
873 wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
874
875 mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
876 if (!mem_conf) {
877 ret = -ENOMEM;
878 goto out;
879 }
880
881 /* memory config */
882 mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS);
883 mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
884 mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
885 mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
886 mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS;
887
888 ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
889 sizeof(*mem_conf));
890 if (ret < 0) {
891 wl1271_warning("wl1271 mem config failed: %d", ret);
892 goto out;
893 }
894
895out:
896 kfree(mem_conf);
897 return ret;
898}
899
900int wl1271_acx_init_mem_config(struct wl1271 *wl)
901{
902 int ret;
903
904 ret = wl1271_acx_mem_cfg(wl);
905 if (ret < 0)
906 return ret;
907
908 wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
909 GFP_KERNEL);
910 if (!wl->target_mem_map) {
911 wl1271_error("couldn't allocate target memory map");
912 return -ENOMEM;
913 }
914
915 /* we now ask for the firmware built memory map */
916 ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map,
917 sizeof(struct wl1271_acx_mem_map));
918 if (ret < 0) {
919 wl1271_error("couldn't retrieve firmware memory map");
920 kfree(wl->target_mem_map);
921 wl->target_mem_map = NULL;
922 return ret;
923 }
924
925 /* initialize TX block book keeping */
926 wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks;
927 wl1271_debug(DEBUG_TX, "available tx blocks: %d",
928 wl->tx_blocks_available);
929
930 return 0;
931}
932
933int wl1271_acx_init_rx_interrupt(struct wl1271 *wl)
934{
935 struct wl1271_acx_rx_config_opt *rx_conf;
936 int ret;
937
938 wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config");
939
940 rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL);
941 if (!rx_conf) {
942 ret = -ENOMEM;
943 goto out;
944 }
945
946 rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF;
947 rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF;
948 rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */
949 rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY;
950
951 ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf,
952 sizeof(*rx_conf));
953 if (ret < 0) {
954 wl1271_warning("wl1271 rx config opt failed: %d", ret);
955 goto out;
956 }
957
958out:
959 kfree(rx_conf);
960 return ret;
961}
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
new file mode 100644
index 000000000000..9068daaf0ddf
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -0,0 +1,1221 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_ACX_H__
26#define __WL1271_ACX_H__
27
28#include "wl1271.h"
29#include "wl1271_cmd.h"
30
31/*************************************************************************
32
33 Host Interrupt Register (WiLink -> Host)
34
35**************************************************************************/
36/* HW Initiated interrupt Watchdog timer expiration */
37#define WL1271_ACX_INTR_WATCHDOG BIT(0)
38/* Init sequence is done (masked interrupt, detection through polling only ) */
39#define WL1271_ACX_INTR_INIT_COMPLETE BIT(1)
40/* Event was entered to Event MBOX #A*/
41#define WL1271_ACX_INTR_EVENT_A BIT(2)
42/* Event was entered to Event MBOX #B*/
43#define WL1271_ACX_INTR_EVENT_B BIT(3)
44/* Command processing completion*/
45#define WL1271_ACX_INTR_CMD_COMPLETE BIT(4)
46/* Signaling the host on HW wakeup */
47#define WL1271_ACX_INTR_HW_AVAILABLE BIT(5)
48/* The MISC bit is used for aggregation of RX, TxComplete and TX rate update */
49#define WL1271_ACX_INTR_DATA BIT(6)
50/* Trace meassge on MBOX #A */
51#define WL1271_ACX_INTR_TRACE_A BIT(7)
52/* Trace meassge on MBOX #B */
53#define WL1271_ACX_INTR_TRACE_B BIT(8)
54
55#define WL1271_ACX_INTR_ALL 0xFFFFFFFF
56#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \
57 WL1271_ACX_INTR_INIT_COMPLETE | \
58 WL1271_ACX_INTR_EVENT_A | \
59 WL1271_ACX_INTR_EVENT_B | \
60 WL1271_ACX_INTR_CMD_COMPLETE | \
61 WL1271_ACX_INTR_HW_AVAILABLE | \
62 WL1271_ACX_INTR_DATA)
63
64#define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \
65 WL1271_ACX_INTR_EVENT_B | \
66 WL1271_ACX_INTR_DATA)
67
68/* Target's information element */
69struct acx_header {
70 struct wl1271_cmd_header cmd;
71
72 /* acx (or information element) header */
73 u16 id;
74
75 /* payload length (not including headers */
76 u16 len;
77};
78
79struct acx_error_counter {
80 struct acx_header header;
81
82 /* The number of PLCP errors since the last time this */
83 /* information element was interrogated. This field is */
84 /* automatically cleared when it is interrogated.*/
85 u32 PLCP_error;
86
87 /* The number of FCS errors since the last time this */
88 /* information element was interrogated. This field is */
89 /* automatically cleared when it is interrogated.*/
90 u32 FCS_error;
91
92 /* The number of MPDUs without PLCP header errors received*/
93 /* since the last time this information element was interrogated. */
94 /* This field is automatically cleared when it is interrogated.*/
95 u32 valid_frame;
96
97 /* the number of missed sequence numbers in the squentially */
98 /* values of frames seq numbers */
99 u32 seq_num_miss;
100} __attribute__ ((packed));
101
102struct acx_revision {
103 struct acx_header header;
104
105 /*
106 * The WiLink firmware version, an ASCII string x.x.x.x,
107 * that uniquely identifies the current firmware.
108 * The left most digit is incremented each time a
109 * significant change is made to the firmware, such as
110 * code redesign or new platform support.
111 * The second digit is incremented when major enhancements
112 * are added or major fixes are made.
113 * The third digit is incremented for each GA release.
114 * The fourth digit is incremented for each build.
115 * The first two digits identify a firmware release version,
116 * in other words, a unique set of features.
117 * The first three digits identify a GA release.
118 */
119 char fw_version[20];
120
121 /*
122 * This 4 byte field specifies the WiLink hardware version.
123 * bits 0 - 15: Reserved.
124 * bits 16 - 23: Version ID - The WiLink version ID
125 * (1 = first spin, 2 = second spin, and so on).
126 * bits 24 - 31: Chip ID - The WiLink chip ID.
127 */
128 u32 hw_version;
129} __attribute__ ((packed));
130
131enum wl1271_psm_mode {
132 /* Active mode */
133 WL1271_PSM_CAM = 0,
134
135 /* Power save mode */
136 WL1271_PSM_PS = 1,
137
138 /* Extreme low power */
139 WL1271_PSM_ELP = 2,
140};
141
142struct acx_sleep_auth {
143 struct acx_header header;
144
145 /* The sleep level authorization of the device. */
146 /* 0 - Always active*/
147 /* 1 - Power down mode: light / fast sleep*/
148 /* 2 - ELP mode: Deep / Max sleep*/
149 u8 sleep_auth;
150 u8 padding[3];
151} __attribute__ ((packed));
152
153enum {
154 HOSTIF_PCI_MASTER_HOST_INDIRECT,
155 HOSTIF_PCI_MASTER_HOST_DIRECT,
156 HOSTIF_SLAVE,
157 HOSTIF_PKT_RING,
158 HOSTIF_DONTCARE = 0xFF
159};
160
161#define DEFAULT_UCAST_PRIORITY 0
162#define DEFAULT_RX_Q_PRIORITY 0
163#define DEFAULT_NUM_STATIONS 1
164#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */
165#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */
166#define TRACE_BUFFER_MAX_SIZE 256
167
168#define DP_RX_PACKET_RING_CHUNK_SIZE 1600
169#define DP_TX_PACKET_RING_CHUNK_SIZE 1600
170#define DP_RX_PACKET_RING_CHUNK_NUM 2
171#define DP_TX_PACKET_RING_CHUNK_NUM 2
172#define DP_TX_COMPLETE_TIME_OUT 20
173#define FW_TX_CMPLT_BLOCK_SIZE 16
174
175#define TX_MSDU_LIFETIME_MIN 0
176#define TX_MSDU_LIFETIME_MAX 3000
177#define TX_MSDU_LIFETIME_DEF 512
178#define RX_MSDU_LIFETIME_MIN 0
179#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF
180#define RX_MSDU_LIFETIME_DEF 512000
181
182struct acx_rx_msdu_lifetime {
183 struct acx_header header;
184
185 /*
186 * The maximum amount of time, in TU, before the
187 * firmware discards the MSDU.
188 */
189 u32 lifetime;
190} __attribute__ ((packed));
191
192/*
193 * RX Config Options Table
194 * Bit Definition
195 * === ==========
196 * 31:14 Reserved
197 * 13 Copy RX Status - when set, write three receive status words
198 * to top of rx'd MPDUs.
199 * When cleared, do not write three status words (added rev 1.5)
200 * 12 Reserved
201 * 11 RX Complete upon FCS error - when set, give rx complete
202 * interrupt for FCS errors, after the rx filtering, e.g. unicast
203 * frames not to us with FCS error will not generate an interrupt.
204 * 10 SSID Filter Enable - When set, the WiLink discards all beacon,
205 * probe request, and probe response frames with an SSID that does
206 * not match the SSID specified by the host in the START/JOIN
207 * command.
208 * When clear, the WiLink receives frames with any SSID.
209 * 9 Broadcast Filter Enable - When set, the WiLink discards all
210 * broadcast frames. When clear, the WiLink receives all received
211 * broadcast frames.
212 * 8:6 Reserved
213 * 5 BSSID Filter Enable - When set, the WiLink discards any frames
214 * with a BSSID that does not match the BSSID specified by the
215 * host.
216 * When clear, the WiLink receives frames from any BSSID.
217 * 4 MAC Addr Filter - When set, the WiLink discards any frames
218 * with a destination address that does not match the MAC address
219 * of the adaptor.
220 * When clear, the WiLink receives frames destined to any MAC
221 * address.
222 * 3 Promiscuous - When set, the WiLink receives all valid frames
223 * (i.e., all frames that pass the FCS check).
224 * When clear, only frames that pass the other filters specified
225 * are received.
226 * 2 FCS - When set, the WiLink includes the FCS with the received
227 * frame.
228 * When cleared, the FCS is discarded.
229 * 1 PLCP header - When set, write all data from baseband to frame
230 * buffer including PHY header.
231 * 0 Reserved - Always equal to 0.
232 *
233 * RX Filter Options Table
234 * Bit Definition
235 * === ==========
236 * 31:12 Reserved - Always equal to 0.
237 * 11 Association - When set, the WiLink receives all association
238 * related frames (association request/response, reassocation
239 * request/response, and disassociation). When clear, these frames
240 * are discarded.
241 * 10 Auth/De auth - When set, the WiLink receives all authentication
242 * and de-authentication frames. When clear, these frames are
243 * discarded.
244 * 9 Beacon - When set, the WiLink receives all beacon frames.
245 * When clear, these frames are discarded.
246 * 8 Contention Free - When set, the WiLink receives all contention
247 * free frames.
248 * When clear, these frames are discarded.
249 * 7 Control - When set, the WiLink receives all control frames.
250 * When clear, these frames are discarded.
251 * 6 Data - When set, the WiLink receives all data frames.
252 * When clear, these frames are discarded.
253 * 5 FCS Error - When set, the WiLink receives frames that have FCS
254 * errors.
255 * When clear, these frames are discarded.
256 * 4 Management - When set, the WiLink receives all management
257 * frames.
258 * When clear, these frames are discarded.
259 * 3 Probe Request - When set, the WiLink receives all probe request
260 * frames.
261 * When clear, these frames are discarded.
262 * 2 Probe Response - When set, the WiLink receives all probe
263 * response frames.
264 * When clear, these frames are discarded.
265 * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
266 * frames.
267 * When clear, these frames are discarded.
268 * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames
269 * that have reserved frame types and sub types as defined by the
270 * 802.11 specification.
271 * When clear, these frames are discarded.
272 */
273struct acx_rx_config {
274 struct acx_header header;
275
276 u32 config_options;
277 u32 filter_options;
278} __attribute__ ((packed));
279
280struct acx_packet_detection {
281 struct acx_header header;
282
283 u32 threshold;
284} __attribute__ ((packed));
285
286
287enum acx_slot_type {
288 SLOT_TIME_LONG = 0,
289 SLOT_TIME_SHORT = 1,
290 DEFAULT_SLOT_TIME = SLOT_TIME_SHORT,
291 MAX_SLOT_TIMES = 0xFF
292};
293
294#define STATION_WONE_INDEX 0
295
296struct acx_slot {
297 struct acx_header header;
298
299 u8 wone_index; /* Reserved */
300 u8 slot_time;
301 u8 reserved[6];
302} __attribute__ ((packed));
303
304
305#define ADDRESS_GROUP_MAX (8)
306#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX)
307
308struct acx_dot11_grp_addr_tbl {
309 struct acx_header header;
310
311 u8 enabled;
312 u8 num_groups;
313 u8 pad[2];
314 u8 mac_table[ADDRESS_GROUP_MAX_LEN];
315} __attribute__ ((packed));
316
317
318#define RX_TIMEOUT_PS_POLL_MIN 0
319#define RX_TIMEOUT_PS_POLL_MAX (200000)
320#define RX_TIMEOUT_PS_POLL_DEF (15)
321#define RX_TIMEOUT_UPSD_MIN 0
322#define RX_TIMEOUT_UPSD_MAX (200000)
323#define RX_TIMEOUT_UPSD_DEF (15)
324
325struct acx_rx_timeout {
326 struct acx_header header;
327
328 /*
329 * The longest time the STA will wait to receive
330 * traffic from the AP after a PS-poll has been
331 * transmitted.
332 */
333 u16 ps_poll_timeout;
334
335 /*
336 * The longest time the STA will wait to receive
337 * traffic from the AP after a frame has been sent
338 * from an UPSD enabled queue.
339 */
340 u16 upsd_timeout;
341} __attribute__ ((packed));
342
343#define RTS_THRESHOLD_MIN 0
344#define RTS_THRESHOLD_MAX 4096
345#define RTS_THRESHOLD_DEF 2347
346
347struct acx_rts_threshold {
348 struct acx_header header;
349
350 u16 threshold;
351 u8 pad[2];
352} __attribute__ ((packed));
353
354struct acx_beacon_filter_option {
355 struct acx_header header;
356
357 u8 enable;
358
359 /*
360 * The number of beacons without the unicast TIM
361 * bit set that the firmware buffers before
362 * signaling the host about ready frames.
363 * When set to 0 and the filter is enabled, beacons
364 * without the unicast TIM bit set are dropped.
365 */
366 u8 max_num_beacons;
367 u8 pad[2];
368} __attribute__ ((packed));
369
370/*
371 * ACXBeaconFilterEntry (not 221)
372 * Byte Offset Size (Bytes) Definition
373 * =========== ============ ==========
374 * 0 1 IE identifier
375 * 1 1 Treatment bit mask
376 *
377 * ACXBeaconFilterEntry (221)
378 * Byte Offset Size (Bytes) Definition
379 * =========== ============ ==========
380 * 0 1 IE identifier
381 * 1 1 Treatment bit mask
382 * 2 3 OUI
383 * 5 1 Type
384 * 6 2 Version
385 *
386 *
387 * Treatment bit mask - The information element handling:
388 * bit 0 - The information element is compared and transferred
389 * in case of change.
390 * bit 1 - The information element is transferred to the host
391 * with each appearance or disappearance.
392 * Note that both bits can be set at the same time.
393 */
394#define BEACON_FILTER_TABLE_MAX_IE_NUM (32)
395#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6)
396#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2)
397#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6)
398#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \
399 BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \
400 (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
401 BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
402
403struct acx_beacon_filter_ie_table {
404 struct acx_header header;
405
406 u8 num_ie;
407 u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
408 u8 pad[3];
409} __attribute__ ((packed));
410
411enum {
412 SG_ENABLE = 0,
413 SG_DISABLE,
414 SG_SENSE_NO_ACTIVITY,
415 SG_SENSE_ACTIVE
416};
417
418struct acx_bt_wlan_coex {
419 struct acx_header header;
420
421 /*
422 * 0 -> PTA enabled
423 * 1 -> PTA disabled
424 * 2 -> sense no active mode, i.e.
425 * an interrupt is sent upon
426 * BT activity.
427 * 3 -> PTA is switched on in response
428 * to the interrupt sending.
429 */
430 u8 enable;
431 u8 pad[3];
432} __attribute__ ((packed));
433
434#define PTA_ANTENNA_TYPE_DEF (0)
435#define PTA_BT_HP_MAXTIME_DEF (2000)
436#define PTA_WLAN_HP_MAX_TIME_DEF (5000)
437#define PTA_SENSE_DISABLE_TIMER_DEF (1350)
438#define PTA_PROTECTIVE_RX_TIME_DEF (1500)
439#define PTA_PROTECTIVE_TX_TIME_DEF (1500)
440#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000)
441#define PTA_SIGNALING_TYPE_DEF (1)
442#define PTA_AFH_LEVERAGE_ON_DEF (0)
443#define PTA_NUMBER_QUIET_CYCLE_DEF (0)
444#define PTA_MAX_NUM_CTS_DEF (3)
445#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2)
446#define PTA_NUMBER_OF_BT_PACKETS_DEF (2)
447#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500)
448#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000)
449#define PTA_CYCLE_TIME_FAST_DEF (8700)
450#define PTA_RX_FOR_AVALANCHE_DEF (5)
451#define PTA_ELP_HP_DEF (0)
452#define PTA_ANTI_STARVE_PERIOD_DEF (500)
453#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4)
454#define PTA_ALLOW_PA_SD_DEF (1)
455#define PTA_TIME_BEFORE_BEACON_DEF (6300)
456#define PTA_HPDM_MAX_TIME_DEF (1600)
457#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550)
458#define PTA_AUTO_MODE_NO_CTS_DEF (0)
459#define PTA_BT_HP_RESPECTED_DEF (3)
460#define PTA_WLAN_RX_MIN_RATE_DEF (24)
461#define PTA_ACK_MODE_DEF (1)
462
463struct acx_bt_wlan_coex_param {
464 struct acx_header header;
465
466 /*
467 * The minimum rate of a received WLAN packet in the STA,
468 * during protective mode, of which a new BT-HP request
469 * during this Rx will always be respected and gain the antenna.
470 */
471 u32 min_rate;
472
473 /* Max time the BT HP will be respected. */
474 u16 bt_hp_max_time;
475
476 /* Max time the WLAN HP will be respected. */
477 u16 wlan_hp_max_time;
478
479 /*
480 * The time between the last BT activity
481 * and the moment when the sense mode returns
482 * to SENSE_INACTIVE.
483 */
484 u16 sense_disable_timer;
485
486 /* Time before the next BT HP instance */
487 u16 rx_time_bt_hp;
488 u16 tx_time_bt_hp;
489
490 /* range: 10-20000 default: 1500 */
491 u16 rx_time_bt_hp_fast;
492 u16 tx_time_bt_hp_fast;
493
494 /* range: 2000-65535 default: 8700 */
495 u16 wlan_cycle_fast;
496
497 /* range: 0 - 15000 (Msec) default: 1000 */
498 u16 bt_anti_starvation_period;
499
500 /* range 400-10000(Usec) default: 3000 */
501 u16 next_bt_lp_packet;
502
503 /* Deafult: worst case for BT DH5 traffic */
504 u16 wake_up_beacon;
505
506 /* range: 0-50000(Usec) default: 1050 */
507 u16 hp_dm_max_guard_time;
508
509 /*
510 * This is to prevent both BT & WLAN antenna
511 * starvation.
512 * Range: 100-50000(Usec) default:2550
513 */
514 u16 next_wlan_packet;
515
516 /* 0 -> shared antenna */
517 u8 antenna_type;
518
519 /*
520 * 0 -> TI legacy
521 * 1 -> Palau
522 */
523 u8 signal_type;
524
525 /*
526 * BT AFH status
527 * 0 -> no AFH
528 * 1 -> from dedicated GPIO
529 * 2 -> AFH on (from host)
530 */
531 u8 afh_leverage_on;
532
533 /*
534 * The number of cycles during which no
535 * TX will be sent after 1 cycle of RX
536 * transaction in protective mode
537 */
538 u8 quiet_cycle_num;
539
540 /*
541 * The maximum number of CTSs that will
542 * be sent for receiving RX packet in
543 * protective mode
544 */
545 u8 max_cts;
546
547 /*
548 * The number of WLAN packets
549 * transferred in common mode before
550 * switching to BT.
551 */
552 u8 wlan_packets_num;
553
554 /*
555 * The number of BT packets
556 * transferred in common mode before
557 * switching to WLAN.
558 */
559 u8 bt_packets_num;
560
561 /* range: 1-255 default: 5 */
562 u8 missed_rx_avalanche;
563
564 /* range: 0-1 default: 1 */
565 u8 wlan_elp_hp;
566
567 /* range: 0 - 15 default: 4 */
568 u8 bt_anti_starvation_cycles;
569
570 u8 ack_mode_dual_ant;
571
572 /*
573 * Allow PA_SD assertion/de-assertion
574 * during enabled BT activity.
575 */
576 u8 pa_sd_enable;
577
578 /*
579 * Enable/Disable PTA in auto mode:
580 * Support Both Active & P.S modes
581 */
582 u8 pta_auto_mode_enable;
583
584 /* range: 0 - 20 default: 1 */
585 u8 bt_hp_respected_num;
586} __attribute__ ((packed));
587
588#define CCA_THRSH_ENABLE_ENERGY_D 0x140A
589#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF
590
591struct acx_energy_detection {
592 struct acx_header header;
593
594 /* The RX Clear Channel Assessment threshold in the PHY */
595 u16 rx_cca_threshold;
596 u8 tx_energy_detection;
597 u8 pad;
598} __attribute__ ((packed));
599
600#define BCN_RX_TIMEOUT_DEF_VALUE 10000
601#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000
602#define RX_BROADCAST_IN_PS_DEF_VALUE 1
603#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4
604
605struct acx_beacon_broadcast {
606 struct acx_header header;
607
608 u16 beacon_rx_timeout;
609 u16 broadcast_timeout;
610
611 /* Enables receiving of broadcast packets in PS mode */
612 u8 rx_broadcast_in_ps;
613
614 /* Consecutive PS Poll failures before updating the host */
615 u8 ps_poll_threshold;
616 u8 pad[2];
617} __attribute__ ((packed));
618
619struct acx_event_mask {
620 struct acx_header header;
621
622 u32 event_mask;
623 u32 high_event_mask; /* Unused */
624} __attribute__ ((packed));
625
626#define CFG_RX_FCS BIT(2)
627#define CFG_RX_ALL_GOOD BIT(3)
628#define CFG_UNI_FILTER_EN BIT(4)
629#define CFG_BSSID_FILTER_EN BIT(5)
630#define CFG_MC_FILTER_EN BIT(6)
631#define CFG_MC_ADDR0_EN BIT(7)
632#define CFG_MC_ADDR1_EN BIT(8)
633#define CFG_BC_REJECT_EN BIT(9)
634#define CFG_SSID_FILTER_EN BIT(10)
635#define CFG_RX_INT_FCS_ERROR BIT(11)
636#define CFG_RX_INT_ENCRYPTED BIT(12)
637#define CFG_RX_WR_RX_STATUS BIT(13)
638#define CFG_RX_FILTER_NULTI BIT(14)
639#define CFG_RX_RESERVE BIT(15)
640#define CFG_RX_TIMESTAMP_TSF BIT(16)
641
642#define CFG_RX_RSV_EN BIT(0)
643#define CFG_RX_RCTS_ACK BIT(1)
644#define CFG_RX_PRSP_EN BIT(2)
645#define CFG_RX_PREQ_EN BIT(3)
646#define CFG_RX_MGMT_EN BIT(4)
647#define CFG_RX_FCS_ERROR BIT(5)
648#define CFG_RX_DATA_EN BIT(6)
649#define CFG_RX_CTL_EN BIT(7)
650#define CFG_RX_CF_EN BIT(8)
651#define CFG_RX_BCN_EN BIT(9)
652#define CFG_RX_AUTH_EN BIT(10)
653#define CFG_RX_ASSOC_EN BIT(11)
654
655#define SCAN_PASSIVE BIT(0)
656#define SCAN_5GHZ_BAND BIT(1)
657#define SCAN_TRIGGERED BIT(2)
658#define SCAN_PRIORITY_HIGH BIT(3)
659
660struct acx_feature_config {
661 struct acx_header header;
662
663 u32 options;
664 u32 data_flow_options;
665} __attribute__ ((packed));
666
667struct acx_current_tx_power {
668 struct acx_header header;
669
670 u8 current_tx_power;
671 u8 padding[3];
672} __attribute__ ((packed));
673
674enum acx_wake_up_event {
675 WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/
676 WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/
677 WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */
678 WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */
679 WAKE_UP_EVENT_BITS_MASK = 0x0F
680};
681
682struct acx_wake_up_condition {
683 struct acx_header header;
684
685 u8 wake_up_event; /* Only one bit can be set */
686 u8 listen_interval;
687 u8 pad[2];
688} __attribute__ ((packed));
689
690struct acx_aid {
691 struct acx_header header;
692
693 /*
694 * To be set when associated with an AP.
695 */
696 u16 aid;
697 u8 pad[2];
698} __attribute__ ((packed));
699
700enum acx_preamble_type {
701 ACX_PREAMBLE_LONG = 0,
702 ACX_PREAMBLE_SHORT = 1
703};
704
705struct acx_preamble {
706 struct acx_header header;
707
708 /*
709 * When set, the WiLink transmits the frames with a short preamble and
710 * when cleared, the WiLink transmits the frames with a long preamble.
711 */
712 u8 preamble;
713 u8 padding[3];
714} __attribute__ ((packed));
715
716enum acx_ctsprotect_type {
717 CTSPROTECT_DISABLE = 0,
718 CTSPROTECT_ENABLE = 1
719};
720
721struct acx_ctsprotect {
722 struct acx_header header;
723 u8 ctsprotect;
724 u8 padding[3];
725} __attribute__ ((packed));
726
727struct acx_tx_statistics {
728 u32 internal_desc_overflow;
729} __attribute__ ((packed));
730
731struct acx_rx_statistics {
732 u32 out_of_mem;
733 u32 hdr_overflow;
734 u32 hw_stuck;
735 u32 dropped;
736 u32 fcs_err;
737 u32 xfr_hint_trig;
738 u32 path_reset;
739 u32 reset_counter;
740} __attribute__ ((packed));
741
742struct acx_dma_statistics {
743 u32 rx_requested;
744 u32 rx_errors;
745 u32 tx_requested;
746 u32 tx_errors;
747} __attribute__ ((packed));
748
749struct acx_isr_statistics {
750 /* host command complete */
751 u32 cmd_cmplt;
752
753 /* fiqisr() */
754 u32 fiqs;
755
756 /* (INT_STS_ND & INT_TRIG_RX_HEADER) */
757 u32 rx_headers;
758
759 /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */
760 u32 rx_completes;
761
762 /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */
763 u32 rx_mem_overflow;
764
765 /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */
766 u32 rx_rdys;
767
768 /* irqisr() */
769 u32 irqs;
770
771 /* (INT_STS_ND & INT_TRIG_TX_PROC) */
772 u32 tx_procs;
773
774 /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */
775 u32 decrypt_done;
776
777 /* (INT_STS_ND & INT_TRIG_DMA0) */
778 u32 dma0_done;
779
780 /* (INT_STS_ND & INT_TRIG_DMA1) */
781 u32 dma1_done;
782
783 /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */
784 u32 tx_exch_complete;
785
786 /* (INT_STS_ND & INT_TRIG_COMMAND) */
787 u32 commands;
788
789 /* (INT_STS_ND & INT_TRIG_RX_PROC) */
790 u32 rx_procs;
791
792 /* (INT_STS_ND & INT_TRIG_PM_802) */
793 u32 hw_pm_mode_changes;
794
795 /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */
796 u32 host_acknowledges;
797
798 /* (INT_STS_ND & INT_TRIG_PM_PCI) */
799 u32 pci_pm;
800
801 /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */
802 u32 wakeups;
803
804 /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */
805 u32 low_rssi;
806} __attribute__ ((packed));
807
808struct acx_wep_statistics {
809 /* WEP address keys configured */
810 u32 addr_key_count;
811
812 /* default keys configured */
813 u32 default_key_count;
814
815 u32 reserved;
816
817 /* number of times that WEP key not found on lookup */
818 u32 key_not_found;
819
820 /* number of times that WEP key decryption failed */
821 u32 decrypt_fail;
822
823 /* WEP packets decrypted */
824 u32 packets;
825
826 /* WEP decrypt interrupts */
827 u32 interrupt;
828} __attribute__ ((packed));
829
830#define ACX_MISSED_BEACONS_SPREAD 10
831
832struct acx_pwr_statistics {
833 /* the amount of enters into power save mode (both PD & ELP) */
834 u32 ps_enter;
835
836 /* the amount of enters into ELP mode */
837 u32 elp_enter;
838
839 /* the amount of missing beacon interrupts to the host */
840 u32 missing_bcns;
841
842 /* the amount of wake on host-access times */
843 u32 wake_on_host;
844
845 /* the amount of wake on timer-expire */
846 u32 wake_on_timer_exp;
847
848 /* the number of packets that were transmitted with PS bit set */
849 u32 tx_with_ps;
850
851 /* the number of packets that were transmitted with PS bit clear */
852 u32 tx_without_ps;
853
854 /* the number of received beacons */
855 u32 rcvd_beacons;
856
857 /* the number of entering into PowerOn (power save off) */
858 u32 power_save_off;
859
860 /* the number of entries into power save mode */
861 u16 enable_ps;
862
863 /*
864 * the number of exits from power save, not including failed PS
865 * transitions
866 */
867 u16 disable_ps;
868
869 /*
870 * the number of times the TSF counter was adjusted because
871 * of drift
872 */
873 u32 fix_tsf_ps;
874
875 /* Gives statistics about the spread continuous missed beacons.
876 * The 16 LSB are dedicated for the PS mode.
877 * The 16 MSB are dedicated for the PS mode.
878 * cont_miss_bcns_spread[0] - single missed beacon.
879 * cont_miss_bcns_spread[1] - two continuous missed beacons.
880 * cont_miss_bcns_spread[2] - three continuous missed beacons.
881 * ...
882 * cont_miss_bcns_spread[9] - ten and more continuous missed beacons.
883 */
884 u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD];
885
886 /* the number of beacons in awake mode */
887 u32 rcvd_awake_beacons;
888} __attribute__ ((packed));
889
890struct acx_mic_statistics {
891 u32 rx_pkts;
892 u32 calc_failure;
893} __attribute__ ((packed));
894
895struct acx_aes_statistics {
896 u32 encrypt_fail;
897 u32 decrypt_fail;
898 u32 encrypt_packets;
899 u32 decrypt_packets;
900 u32 encrypt_interrupt;
901 u32 decrypt_interrupt;
902} __attribute__ ((packed));
903
904struct acx_event_statistics {
905 u32 heart_beat;
906 u32 calibration;
907 u32 rx_mismatch;
908 u32 rx_mem_empty;
909 u32 rx_pool;
910 u32 oom_late;
911 u32 phy_transmit_error;
912 u32 tx_stuck;
913} __attribute__ ((packed));
914
915struct acx_ps_statistics {
916 u32 pspoll_timeouts;
917 u32 upsd_timeouts;
918 u32 upsd_max_sptime;
919 u32 upsd_max_apturn;
920 u32 pspoll_max_apturn;
921 u32 pspoll_utilization;
922 u32 upsd_utilization;
923} __attribute__ ((packed));
924
925struct acx_rxpipe_statistics {
926 u32 rx_prep_beacon_drop;
927 u32 descr_host_int_trig_rx_data;
928 u32 beacon_buffer_thres_host_int_trig_rx_data;
929 u32 missed_beacon_host_int_trig_rx_data;
930 u32 tx_xfr_host_int_trig_rx_data;
931} __attribute__ ((packed));
932
933struct acx_statistics {
934 struct acx_header header;
935
936 struct acx_tx_statistics tx;
937 struct acx_rx_statistics rx;
938 struct acx_dma_statistics dma;
939 struct acx_isr_statistics isr;
940 struct acx_wep_statistics wep;
941 struct acx_pwr_statistics pwr;
942 struct acx_aes_statistics aes;
943 struct acx_mic_statistics mic;
944 struct acx_event_statistics event;
945 struct acx_ps_statistics ps;
946 struct acx_rxpipe_statistics rxpipe;
947} __attribute__ ((packed));
948
949#define ACX_MAX_RATE_CLASSES 8
950#define ACX_RATE_MASK_UNSPECIFIED 0
951#define ACX_RATE_MASK_ALL 0x1eff
952#define ACX_RATE_RETRY_LIMIT 10
953
954struct acx_rate_class {
955 u32 enabled_rates;
956 u8 short_retry_limit;
957 u8 long_retry_limit;
958 u8 aflags;
959 u8 reserved;
960};
961
962struct acx_rate_policy {
963 struct acx_header header;
964
965 u32 rate_class_cnt;
966 struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES];
967} __attribute__ ((packed));
968
969#define WL1271_ACX_AC_COUNT 4
970
971struct acx_ac_cfg {
972 struct acx_header header;
973 u8 ac;
974 u8 cw_min;
975 u16 cw_max;
976 u8 aifsn;
977 u8 reserved;
978 u16 tx_op_limit;
979} __attribute__ ((packed));
980
981enum wl1271_acx_ac {
982 WL1271_ACX_AC_BE = 0,
983 WL1271_ACX_AC_BK = 1,
984 WL1271_ACX_AC_VI = 2,
985 WL1271_ACX_AC_VO = 3,
986 WL1271_ACX_AC_CTS2SELF = 4,
987 WL1271_ACX_AC_ANY_TID = 0x1F,
988 WL1271_ACX_AC_INVALID = 0xFF,
989};
990
991enum wl1271_acx_ps_scheme {
992 WL1271_ACX_PS_SCHEME_LEGACY = 0,
993 WL1271_ACX_PS_SCHEME_UPSD_TRIGGER = 1,
994 WL1271_ACX_PS_SCHEME_LEGACY_PSPOLL = 2,
995 WL1271_ACX_PS_SCHEME_SAPSD = 3,
996};
997
998enum wl1271_acx_ack_policy {
999 WL1271_ACX_ACK_POLICY_LEGACY = 0,
1000 WL1271_ACX_ACK_POLICY_NO_ACK = 1,
1001 WL1271_ACX_ACK_POLICY_BLOCK = 2,
1002};
1003
1004#define WL1271_ACX_TID_COUNT 7
1005
1006struct acx_tid_config {
1007 struct acx_header header;
1008 u8 queue_id;
1009 u8 channel_type;
1010 u8 tsid;
1011 u8 ps_scheme;
1012 u8 ack_policy;
1013 u8 padding[3];
1014 u32 apsd_conf[2];
1015} __attribute__ ((packed));
1016
1017struct acx_frag_threshold {
1018 struct acx_header header;
1019 u16 frag_threshold;
1020 u8 padding[2];
1021} __attribute__ ((packed));
1022
1023#define WL1271_ACX_TX_COMPL_TIMEOUT 5
1024#define WL1271_ACX_TX_COMPL_THRESHOLD 5
1025
1026struct acx_tx_config_options {
1027 struct acx_header header;
1028 u16 tx_compl_timeout; /* msec */
1029 u16 tx_compl_threshold; /* number of packets */
1030} __attribute__ ((packed));
1031
1032#define ACX_RX_MEM_BLOCKS 64
1033#define ACX_TX_MIN_MEM_BLOCKS 64
1034#define ACX_TX_DESCRIPTORS 32
1035#define ACX_NUM_SSID_PROFILES 1
1036
1037struct wl1271_acx_config_memory {
1038 struct acx_header header;
1039
1040 u8 rx_mem_block_num;
1041 u8 tx_min_mem_block_num;
1042 u8 num_stations;
1043 u8 num_ssid_profiles;
1044 u32 total_tx_descriptors;
1045} __attribute__ ((packed));
1046
1047struct wl1271_acx_mem_map {
1048 struct acx_header header;
1049
1050 void *code_start;
1051 void *code_end;
1052
1053 void *wep_defkey_start;
1054 void *wep_defkey_end;
1055
1056 void *sta_table_start;
1057 void *sta_table_end;
1058
1059 void *packet_template_start;
1060 void *packet_template_end;
1061
1062 /* Address of the TX result interface (control block) */
1063 u32 tx_result;
1064 u32 tx_result_queue_start;
1065
1066 void *queue_memory_start;
1067 void *queue_memory_end;
1068
1069 u32 packet_memory_pool_start;
1070 u32 packet_memory_pool_end;
1071
1072 void *debug_buffer1_start;
1073 void *debug_buffer1_end;
1074
1075 void *debug_buffer2_start;
1076 void *debug_buffer2_end;
1077
1078 /* Number of blocks FW allocated for TX packets */
1079 u32 num_tx_mem_blocks;
1080
1081 /* Number of blocks FW allocated for RX packets */
1082 u32 num_rx_mem_blocks;
1083
1084 /* the following 4 fields are valid in SLAVE mode only */
1085 u8 *tx_cbuf;
1086 u8 *rx_cbuf;
1087 void *rx_ctrl;
1088 void *tx_ctrl;
1089} __attribute__ ((packed));
1090
1091enum wl1271_acx_rx_queue_type {
1092 RX_QUEUE_TYPE_RX_LOW_PRIORITY, /* All except the high priority */
1093 RX_QUEUE_TYPE_RX_HIGH_PRIORITY, /* Management and voice packets */
1094 RX_QUEUE_TYPE_NUM,
1095 RX_QUEUE_TYPE_MAX = USHORT_MAX
1096};
1097
1098#define WL1271_RX_INTR_THRESHOLD_DEF 0 /* no pacing, send interrupt on
1099 * every event */
1100#define WL1271_RX_INTR_THRESHOLD_MIN 0
1101#define WL1271_RX_INTR_THRESHOLD_MAX 15
1102
1103#define WL1271_RX_INTR_TIMEOUT_DEF 5
1104#define WL1271_RX_INTR_TIMEOUT_MIN 1
1105#define WL1271_RX_INTR_TIMEOUT_MAX 100
1106
1107struct wl1271_acx_rx_config_opt {
1108 struct acx_header header;
1109
1110 u16 mblk_threshold;
1111 u16 threshold;
1112 u16 timeout;
1113 u8 queue_type;
1114 u8 reserved;
1115} __attribute__ ((packed));
1116
1117enum {
1118 ACX_WAKE_UP_CONDITIONS = 0x0002,
1119 ACX_MEM_CFG = 0x0003,
1120 ACX_SLOT = 0x0004,
1121 ACX_AC_CFG = 0x0007,
1122 ACX_MEM_MAP = 0x0008,
1123 ACX_AID = 0x000A,
1124 /* ACX_FW_REV is missing in the ref driver, but seems to work */
1125 ACX_FW_REV = 0x000D,
1126 ACX_MEDIUM_USAGE = 0x000F,
1127 ACX_RX_CFG = 0x0010,
1128 ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */
1129 ACX_STATISTICS = 0x0013, /* Debug API */
1130 ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
1131 ACX_FEATURE_CFG = 0x0015,
1132 ACX_TID_CFG = 0x001A,
1133 ACX_PS_RX_STREAMING = 0x001B,
1134 ACX_BEACON_FILTER_OPT = 0x001F,
1135 ACX_NOISE_HIST = 0x0021,
1136 ACX_HDK_VERSION = 0x0022, /* ??? */
1137 ACX_PD_THRESHOLD = 0x0023,
1138 ACX_TX_CONFIG_OPT = 0x0024,
1139 ACX_CCA_THRESHOLD = 0x0025,
1140 ACX_EVENT_MBOX_MASK = 0x0026,
1141 ACX_CONN_MONIT_PARAMS = 0x002D,
1142 ACX_CONS_TX_FAILURE = 0x002F,
1143 ACX_BCN_DTIM_OPTIONS = 0x0031,
1144 ACX_SG_ENABLE = 0x0032,
1145 ACX_SG_CFG = 0x0033,
1146 ACX_BEACON_FILTER_TABLE = 0x0038,
1147 ACX_ARP_IP_FILTER = 0x0039,
1148 ACX_ROAMING_STATISTICS_TBL = 0x003B,
1149 ACX_RATE_POLICY = 0x003D,
1150 ACX_CTS_PROTECTION = 0x003E,
1151 ACX_SLEEP_AUTH = 0x003F,
1152 ACX_PREAMBLE_TYPE = 0x0040,
1153 ACX_ERROR_CNT = 0x0041,
1154 ACX_IBSS_FILTER = 0x0044,
1155 ACX_SERVICE_PERIOD_TIMEOUT = 0x0045,
1156 ACX_TSF_INFO = 0x0046,
1157 ACX_CONFIG_PS_WMM = 0x0049,
1158 ACX_ENABLE_RX_DATA_FILTER = 0x004A,
1159 ACX_SET_RX_DATA_FILTER = 0x004B,
1160 ACX_GET_DATA_FILTER_STATISTICS = 0x004C,
1161 ACX_RX_CONFIG_OPT = 0x004E,
1162 ACX_FRAG_CFG = 0x004F,
1163 ACX_BET_ENABLE = 0x0050,
1164 ACX_RSSI_SNR_TRIGGER = 0x0051,
1165 ACX_RSSI_SNR_WEIGHTS = 0x0051,
1166 ACX_KEEP_ALIVE_MODE = 0x0052,
1167 ACX_SET_KEEP_ALIVE_CONFIG = 0x0054,
1168 ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
1169 ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
1170 ACX_PEER_HT_CAP = 0x0057,
1171 ACX_HT_BSS_OPERATION = 0x0058,
1172 ACX_COEX_ACTIVITY = 0x0059,
1173 DOT11_RX_MSDU_LIFE_TIME = 0x1004,
1174 DOT11_CUR_TX_PWR = 0x100D,
1175 DOT11_RX_DOT11_MODE = 0x1012,
1176 DOT11_RTS_THRESHOLD = 0x1013,
1177 DOT11_GROUP_ADDRESS_TBL = 0x1014,
1178
1179 MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
1180
1181 MAX_IE = 0xFFFF
1182};
1183
1184
1185int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event,
1186 u8 listen_interval);
1187int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
1188int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
1189int wl1271_acx_tx_power(struct wl1271 *wl, int power);
1190int wl1271_acx_feature_cfg(struct wl1271 *wl);
1191int wl1271_acx_mem_map(struct wl1271 *wl,
1192 struct acx_header *mem_map, size_t len);
1193int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time);
1194int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
1195int wl1271_acx_pd_threshold(struct wl1271 *wl);
1196int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
1197int wl1271_acx_group_address_tbl(struct wl1271 *wl);
1198int wl1271_acx_service_period_timeout(struct wl1271 *wl);
1199int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold);
1200int wl1271_acx_beacon_filter_opt(struct wl1271 *wl);
1201int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
1202int wl1271_acx_sg_enable(struct wl1271 *wl);
1203int wl1271_acx_sg_cfg(struct wl1271 *wl);
1204int wl1271_acx_cca_threshold(struct wl1271 *wl);
1205int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
1206int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
1207int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask);
1208int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
1209int wl1271_acx_cts_protect(struct wl1271 *wl,
1210 enum acx_ctsprotect_type ctsprotect);
1211int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
1212int wl1271_acx_rate_policies(struct wl1271 *wl);
1213int wl1271_acx_ac_cfg(struct wl1271 *wl);
1214int wl1271_acx_tid_cfg(struct wl1271 *wl);
1215int wl1271_acx_frag_threshold(struct wl1271 *wl);
1216int wl1271_acx_tx_config_options(struct wl1271 *wl);
1217int wl1271_acx_mem_cfg(struct wl1271 *wl);
1218int wl1271_acx_init_mem_config(struct wl1271 *wl);
1219int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
1220
1221#endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
new file mode 100644
index 000000000000..8228ef474a7e
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -0,0 +1,541 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/gpio.h>
25
26#include "wl1271_acx.h"
27#include "wl1271_reg.h"
28#include "wl1271_boot.h"
29#include "wl1271_spi.h"
30#include "wl1271_event.h"
31
32static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
33 [PART_DOWN] = {
34 .mem = {
35 .start = 0x00000000,
36 .size = 0x000177c0
37 },
38 .reg = {
39 .start = REGISTERS_BASE,
40 .size = 0x00008800
41 },
42 },
43
44 [PART_WORK] = {
45 .mem = {
46 .start = 0x00040000,
47 .size = 0x00014fc0
48 },
49 .reg = {
50 .start = REGISTERS_BASE,
51 .size = 0x0000b000
52 },
53 },
54
55 [PART_DRPW] = {
56 .mem = {
57 .start = 0x00040000,
58 .size = 0x00014fc0
59 },
60 .reg = {
61 .start = DRPW_BASE,
62 .size = 0x00006000
63 }
64 }
65};
66
67static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
68{
69 u32 cpu_ctrl;
70
71 /* 10.5.0 run the firmware (I) */
72 cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL);
73
74 /* 10.5.1 run the firmware (II) */
75 cpu_ctrl |= flag;
76 wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
77}
78
79static void wl1271_boot_fw_version(struct wl1271 *wl)
80{
81 struct wl1271_static_data static_data;
82
83 wl1271_spi_mem_read(wl, wl->cmd_box_addr,
84 &static_data, sizeof(static_data));
85
86 strncpy(wl->chip.fw_ver, static_data.fw_version,
87 sizeof(wl->chip.fw_ver));
88
89 /* make sure the string is NULL-terminated */
90 wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
91}
92
93static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
94 size_t fw_data_len, u32 dest)
95{
96 int addr, chunk_num, partition_limit;
97 u8 *p;
98
99 /* whal_FwCtrl_LoadFwImageSm() */
100
101 wl1271_debug(DEBUG_BOOT, "starting firmware upload");
102
103 wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d",
104 fw_data_len, CHUNK_SIZE);
105
106
107 if ((fw_data_len % 4) != 0) {
108 wl1271_error("firmware length not multiple of four");
109 return -EIO;
110 }
111
112 wl1271_set_partition(wl, dest,
113 part_table[PART_DOWN].mem.size,
114 part_table[PART_DOWN].reg.start,
115 part_table[PART_DOWN].reg.size);
116
117 /* 10.1 set partition limit and chunk num */
118 chunk_num = 0;
119 partition_limit = part_table[PART_DOWN].mem.size;
120
121 while (chunk_num < fw_data_len / CHUNK_SIZE) {
122 /* 10.2 update partition, if needed */
123 addr = dest + (chunk_num + 2) * CHUNK_SIZE;
124 if (addr > partition_limit) {
125 addr = dest + chunk_num * CHUNK_SIZE;
126 partition_limit = chunk_num * CHUNK_SIZE +
127 part_table[PART_DOWN].mem.size;
128
129 /* FIXME: Over 80 chars! */
130 wl1271_set_partition(wl,
131 addr,
132 part_table[PART_DOWN].mem.size,
133 part_table[PART_DOWN].reg.start,
134 part_table[PART_DOWN].reg.size);
135 }
136
137 /* 10.3 upload the chunk */
138 addr = dest + chunk_num * CHUNK_SIZE;
139 p = buf + chunk_num * CHUNK_SIZE;
140 wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x",
141 p, addr);
142 wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE);
143
144 chunk_num++;
145 }
146
147 /* 10.4 upload the last chunk */
148 addr = dest + chunk_num * CHUNK_SIZE;
149 p = buf + chunk_num * CHUNK_SIZE;
150 wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x",
151 fw_data_len % CHUNK_SIZE, p, addr);
152 wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE);
153
154 return 0;
155}
156
157static int wl1271_boot_upload_firmware(struct wl1271 *wl)
158{
159 u32 chunks, addr, len;
160 u8 *fw;
161
162 fw = wl->fw;
163 chunks = be32_to_cpup((u32 *) fw);
164 fw += sizeof(u32);
165
166 wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks);
167
168 while (chunks--) {
169 addr = be32_to_cpup((u32 *) fw);
170 fw += sizeof(u32);
171 len = be32_to_cpup((u32 *) fw);
172 fw += sizeof(u32);
173
174 if (len > 300000) {
175 wl1271_info("firmware chunk too long: %u", len);
176 return -EINVAL;
177 }
178 wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u",
179 chunks, addr, len);
180 wl1271_boot_upload_firmware_chunk(wl, fw, len, addr);
181 fw += len;
182 }
183
184 return 0;
185}
186
187static int wl1271_boot_upload_nvs(struct wl1271 *wl)
188{
189 size_t nvs_len, burst_len;
190 int i;
191 u32 dest_addr, val;
192 u8 *nvs_ptr, *nvs, *nvs_aligned;
193
194 nvs = wl->nvs;
195 if (nvs == NULL)
196 return -ENODEV;
197
198 nvs_ptr = nvs;
199
200 nvs_len = wl->nvs_len;
201
202 /* Update the device MAC address into the nvs */
203 nvs[11] = wl->mac_addr[0];
204 nvs[10] = wl->mac_addr[1];
205 nvs[6] = wl->mac_addr[2];
206 nvs[5] = wl->mac_addr[3];
207 nvs[4] = wl->mac_addr[4];
208 nvs[3] = wl->mac_addr[5];
209
210 /*
211 * Layout before the actual NVS tables:
212 * 1 byte : burst length.
213 * 2 bytes: destination address.
214 * n bytes: data to burst copy.
215 *
216 * This is ended by a 0 length, then the NVS tables.
217 */
218
219 /* FIXME: Do we need to check here whether the LSB is 1? */
220 while (nvs_ptr[0]) {
221 burst_len = nvs_ptr[0];
222 dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
223
224 /* FIXME: Due to our new wl1271_translate_reg_addr function,
225 we need to add the REGISTER_BASE to the destination */
226 dest_addr += REGISTERS_BASE;
227
228 /* We move our pointer to the data */
229 nvs_ptr += 3;
230
231 for (i = 0; i < burst_len; i++) {
232 val = (nvs_ptr[0] | (nvs_ptr[1] << 8)
233 | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24));
234
235 wl1271_debug(DEBUG_BOOT,
236 "nvs burst write 0x%x: 0x%x",
237 dest_addr, val);
238 wl1271_reg_write32(wl, dest_addr, val);
239
240 nvs_ptr += 4;
241 dest_addr += 4;
242 }
243 }
244
245 /*
246 * We've reached the first zero length, the first NVS table
247 * is 7 bytes further.
248 */
249 nvs_ptr += 7;
250 nvs_len -= nvs_ptr - nvs;
251 nvs_len = ALIGN(nvs_len, 4);
252
253 /* FIXME: The driver sets the partition here, but this is not needed,
254 since it sets to the same one as currently in use */
255 /* Now we must set the partition correctly */
256 wl1271_set_partition(wl,
257 part_table[PART_WORK].mem.start,
258 part_table[PART_WORK].mem.size,
259 part_table[PART_WORK].reg.start,
260 part_table[PART_WORK].reg.size);
261
262 /* Copy the NVS tables to a new block to ensure alignment */
263 nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL);
264
265 /* And finally we upload the NVS tables */
266 /* FIXME: In wl1271, we upload everything at once.
267 No endianness handling needed here?! The ref driver doesn't do
268 anything about it at this point */
269 wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len);
270
271 kfree(nvs_aligned);
272 return 0;
273}
274
275static void wl1271_boot_enable_interrupts(struct wl1271 *wl)
276{
277 enable_irq(wl->irq);
278 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
279 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
280 wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL);
281}
282
283static int wl1271_boot_soft_reset(struct wl1271 *wl)
284{
285 unsigned long timeout;
286 u32 boot_data;
287
288 /* perform soft reset */
289 wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT);
290
291 /* SOFT_RESET is self clearing */
292 timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME);
293 while (1) {
294 boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET);
295 wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data);
296 if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0)
297 break;
298
299 if (time_after(jiffies, timeout)) {
300 /* 1.2 check pWhalBus->uSelfClearTime if the
301 * timeout was reached */
302 wl1271_error("soft reset timeout");
303 return -1;
304 }
305
306 udelay(SOFT_RESET_STALL_TIME);
307 }
308
309 /* disable Rx/Tx */
310 wl1271_reg_write32(wl, ENABLE, 0x0);
311
312 /* disable auto calibration on start*/
313 wl1271_reg_write32(wl, SPARE_A2, 0xffff);
314
315 return 0;
316}
317
318static int wl1271_boot_run_firmware(struct wl1271 *wl)
319{
320 int loop, ret;
321 u32 chip_id, interrupt;
322
323 wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
324
325 chip_id = wl1271_reg_read32(wl, CHIP_ID_B);
326
327 wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id);
328
329 if (chip_id != wl->chip.id) {
330 wl1271_error("chip id doesn't match after firmware boot");
331 return -EIO;
332 }
333
334 /* wait for init to complete */
335 loop = 0;
336 while (loop++ < INIT_LOOP) {
337 udelay(INIT_LOOP_DELAY);
338 interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
339
340 if (interrupt == 0xffffffff) {
341 wl1271_error("error reading hardware complete "
342 "init indication");
343 return -EIO;
344 }
345 /* check that ACX_INTR_INIT_COMPLETE is enabled */
346 else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
347 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
348 WL1271_ACX_INTR_INIT_COMPLETE);
349 break;
350 }
351 }
352
353 if (loop >= INIT_LOOP) {
354 wl1271_error("timeout waiting for the hardware to "
355 "complete initialization");
356 return -EIO;
357 }
358
359 /* get hardware config command mail box */
360 wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR);
361
362 /* get hardware config event mail box */
363 wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
364
365 /* set the working partition to its "running" mode offset */
366 wl1271_set_partition(wl,
367 part_table[PART_WORK].mem.start,
368 part_table[PART_WORK].mem.size,
369 part_table[PART_WORK].reg.start,
370 part_table[PART_WORK].reg.size);
371
372 wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x",
373 wl->cmd_box_addr, wl->event_box_addr);
374
375 wl1271_boot_fw_version(wl);
376
377 /*
378 * in case of full asynchronous mode the firmware event must be
379 * ready to receive event from the command mailbox
380 */
381
382 /* enable gpio interrupts */
383 wl1271_boot_enable_interrupts(wl);
384
385 /* unmask all mbox events */
386 wl->event_mask = 0xffffffff;
387
388 ret = wl1271_event_unmask(wl);
389 if (ret < 0) {
390 wl1271_error("EVENT mask setting failed");
391 return ret;
392 }
393
394 wl1271_event_mbox_config(wl);
395
396 /* firmware startup completed */
397 return 0;
398}
399
400static int wl1271_boot_write_irq_polarity(struct wl1271 *wl)
401{
402 u32 polarity, status, i;
403
404 wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
405 wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ);
406
407 /* Wait until the command is complete (ie. bit 18 is set) */
408 for (i = 0; i < OCP_CMD_LOOP; i++) {
409 polarity = wl1271_reg_read32(wl, OCP_DATA_READ);
410 if (polarity & OCP_READY_MASK)
411 break;
412 }
413 if (i == OCP_CMD_LOOP) {
414 wl1271_error("OCP command timeout!");
415 return -EIO;
416 }
417
418 status = polarity & OCP_STATUS_MASK;
419 if (status != OCP_STATUS_OK) {
420 wl1271_error("OCP command failed (%d)", status);
421 return -EIO;
422 }
423
424 /* We use HIGH polarity, so unset the LOW bit */
425 polarity &= ~POLARITY_LOW;
426
427 wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY);
428 wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity);
429 wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE);
430
431 return 0;
432}
433
434int wl1271_boot(struct wl1271 *wl)
435{
436 int ret = 0;
437 u32 tmp, clk, pause;
438
439 if (REF_CLOCK == 0 || REF_CLOCK == 2)
440 /* ref clk: 19.2/38.4 */
441 clk = 0x3;
442 else if (REF_CLOCK == 1 || REF_CLOCK == 3)
443 /* ref clk: 26/52 */
444 clk = 0x5;
445
446 wl1271_reg_write32(wl, PLL_PARAMETERS, clk);
447
448 pause = wl1271_reg_read32(wl, PLL_PARAMETERS);
449
450 wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
451
452 pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
453 * WU_COUNTER_PAUSE_VAL instead of
454 * 0x3ff (magic number ). How does
455 * this work?! */
456 pause |= WU_COUNTER_PAUSE_VAL;
457 wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause);
458
459 /* Continue the ELP wake up sequence */
460 wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL);
461 udelay(500);
462
463 wl1271_set_partition(wl,
464 part_table[PART_DRPW].mem.start,
465 part_table[PART_DRPW].mem.size,
466 part_table[PART_DRPW].reg.start,
467 part_table[PART_DRPW].reg.size);
468
469 /* Read-modify-write DRPW_SCRATCH_START register (see next state)
470 to be used by DRPw FW. The RTRIM value will be added by the FW
471 before taking DRPw out of reset */
472
473 wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START);
474 clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START);
475
476 wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk);
477
478 /* 2 */
479 clk |= (REF_CLOCK << 1) << 4;
480 wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk);
481
482 wl1271_set_partition(wl,
483 part_table[PART_WORK].mem.start,
484 part_table[PART_WORK].mem.size,
485 part_table[PART_WORK].reg.start,
486 part_table[PART_WORK].reg.size);
487
488 /* Disable interrupts */
489 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
490
491 ret = wl1271_boot_soft_reset(wl);
492 if (ret < 0)
493 goto out;
494
495 /* 2. start processing NVS file */
496 ret = wl1271_boot_upload_nvs(wl);
497 if (ret < 0)
498 goto out;
499
500 /* write firmware's last address (ie. it's length) to
501 * ACX_EEPROMLESS_IND_REG */
502 wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG");
503
504 wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG);
505
506 tmp = wl1271_reg_read32(wl, CHIP_ID_B);
507
508 wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp);
509
510 /* 6. read the EEPROM parameters */
511 tmp = wl1271_reg_read32(wl, SCR_PAD2);
512
513 ret = wl1271_boot_write_irq_polarity(wl);
514 if (ret < 0)
515 goto out;
516
517 /* FIXME: Need to check whether this is really what we want */
518 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
519 WL1271_ACX_ALL_EVENTS_VECTOR);
520
521 /* WL1271: The reference driver skips steps 7 to 10 (jumps directly
522 * to upload_fw) */
523
524 ret = wl1271_boot_upload_firmware(wl);
525 if (ret < 0)
526 goto out;
527
528 /* 10.5 start firmware */
529 ret = wl1271_boot_run_firmware(wl);
530 if (ret < 0)
531 goto out;
532
533 /* set the wl1271 default filters */
534 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
535 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
536
537 wl1271_event_mbox_config(wl);
538
539out:
540 return ret;
541}
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h
new file mode 100644
index 000000000000..b0d8fb46a439
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.h
@@ -0,0 +1,72 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __BOOT_H__
25#define __BOOT_H__
26
27#include "wl1271.h"
28
29int wl1271_boot(struct wl1271 *wl);
30
31#define WL1271_NO_SUBBANDS 8
32#define WL1271_NO_POWER_LEVELS 4
33#define WL1271_FW_VERSION_MAX_LEN 20
34
35struct wl1271_static_data {
36 u8 mac_address[ETH_ALEN];
37 u8 padding[2];
38 u8 fw_version[WL1271_FW_VERSION_MAX_LEN];
39 u32 hw_version;
40 u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS];
41};
42
43/* number of times we try to read the INIT interrupt */
44#define INIT_LOOP 20000
45
46/* delay between retries */
47#define INIT_LOOP_DELAY 50
48
49#define REF_CLOCK 2
50#define WU_COUNTER_PAUSE_VAL 0x3FF
51#define WELP_ARM_COMMAND_VAL 0x4
52
53#define OCP_CMD_LOOP 32
54
55#define OCP_CMD_WRITE 0x1
56#define OCP_CMD_READ 0x2
57
58#define OCP_READY_MASK BIT(18)
59#define OCP_STATUS_MASK (BIT(16) | BIT(17))
60
61#define OCP_STATUS_NO_RESP 0x00000
62#define OCP_STATUS_OK 0x10000
63#define OCP_STATUS_REQ_FAILED 0x20000
64#define OCP_STATUS_RESP_ERROR 0x30000
65
66#define OCP_REG_POLARITY 0x30032
67
68#define CMD_MBOX_ADDRESS 0x407B4
69
70#define POLARITY_LOW BIT(1)
71
72#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
new file mode 100644
index 000000000000..2a4351ff54dc
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -0,0 +1,813 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/crc7.h>
27#include <linux/spi/spi.h>
28#include <linux/etherdevice.h>
29
30#include "wl1271.h"
31#include "wl1271_reg.h"
32#include "wl1271_spi.h"
33#include "wl1271_acx.h"
34#include "wl12xx_80211.h"
35#include "wl1271_cmd.h"
36
37/*
38 * send command to firmware
39 *
40 * @wl: wl struct
41 * @id: command id
42 * @buf: buffer containing the command, must work with dma
43 * @len: length of the buffer
44 */
45int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len)
46{
47 struct wl1271_cmd_header *cmd;
48 unsigned long timeout;
49 u32 intr;
50 int ret = 0;
51
52 cmd = buf;
53 cmd->id = id;
54 cmd->status = 0;
55
56 WARN_ON(len % 4 != 0);
57
58 wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len);
59
60 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD);
61
62 timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT);
63
64 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
65 while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) {
66 if (time_after(jiffies, timeout)) {
67 wl1271_error("command complete timeout");
68 ret = -ETIMEDOUT;
69 goto out;
70 }
71
72 msleep(1);
73
74 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
75 }
76
77 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK,
78 WL1271_ACX_INTR_CMD_COMPLETE);
79
80out:
81 return ret;
82}
83
84int wl1271_cmd_cal_channel_tune(struct wl1271 *wl)
85{
86 struct wl1271_cmd_cal_channel_tune *cmd;
87 int ret = 0;
88
89 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
90 if (!cmd)
91 return -ENOMEM;
92
93 cmd->test.id = TEST_CMD_CHANNEL_TUNE;
94
95 cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4;
96 /* set up any channel, 7 is in the middle of the range */
97 cmd->channel = 7;
98
99 ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
100 if (ret < 0)
101 wl1271_warning("TEST_CMD_CHANNEL_TUNE failed");
102
103 kfree(cmd);
104 return ret;
105}
106
107int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl)
108{
109 struct wl1271_cmd_cal_update_ref_point *cmd;
110 int ret = 0;
111
112 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
113 if (!cmd)
114 return -ENOMEM;
115
116 cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT;
117
118 /* FIXME: still waiting for the correct values */
119 cmd->ref_power = 0;
120 cmd->ref_detector = 0;
121
122 cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G;
123
124 ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
125 if (ret < 0)
126 wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed");
127
128 kfree(cmd);
129 return ret;
130}
131
132int wl1271_cmd_cal_p2g(struct wl1271 *wl)
133{
134 struct wl1271_cmd_cal_p2g *cmd;
135 int ret = 0;
136
137 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
138 if (!cmd)
139 return -ENOMEM;
140
141 cmd->test.id = TEST_CMD_P2G_CAL;
142
143 cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G;
144
145 ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0);
146 if (ret < 0)
147 wl1271_warning("TEST_CMD_P2G_CAL failed");
148
149 kfree(cmd);
150 return ret;
151}
152
153int wl1271_cmd_cal(struct wl1271 *wl)
154{
155 /*
156 * FIXME: we must make sure that we're not sleeping when calibration
157 * is done
158 */
159 int ret;
160
161 wl1271_notice("performing tx calibration");
162
163 ret = wl1271_cmd_cal_channel_tune(wl);
164 if (ret < 0)
165 return ret;
166
167 ret = wl1271_cmd_cal_update_ref_point(wl);
168 if (ret < 0)
169 return ret;
170
171 ret = wl1271_cmd_cal_p2g(wl);
172 if (ret < 0)
173 return ret;
174
175 return ret;
176}
177
178int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
179 u16 beacon_interval, u8 wait)
180{
181 static bool do_cal = true;
182 unsigned long timeout;
183 struct wl1271_cmd_join *join;
184 int ret, i;
185 u8 *bssid;
186
187 /* FIXME: remove when we get calibration from the factory */
188 if (do_cal) {
189 ret = wl1271_cmd_cal(wl);
190 if (ret < 0)
191 wl1271_warning("couldn't calibrate");
192 else
193 do_cal = false;
194 }
195
196
197 join = kzalloc(sizeof(*join), GFP_KERNEL);
198 if (!join) {
199 ret = -ENOMEM;
200 goto out;
201 }
202
203 wl1271_debug(DEBUG_CMD, "cmd join");
204
205 /* Reverse order BSSID */
206 bssid = (u8 *) &join->bssid_lsb;
207 for (i = 0; i < ETH_ALEN; i++)
208 bssid[i] = wl->bssid[ETH_ALEN - i - 1];
209
210 join->rx_config_options = wl->rx_config;
211 join->rx_filter_options = wl->rx_filter;
212
213 join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS |
214 RATE_MASK_5_5MBPS | RATE_MASK_11MBPS;
215
216 join->beacon_interval = beacon_interval;
217 join->dtim_interval = dtim_interval;
218 join->bss_type = bss_type;
219 join->channel = wl->channel;
220 join->ssid_len = wl->ssid_len;
221 memcpy(join->ssid, wl->ssid, wl->ssid_len);
222 join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH;
223
224 /* increment the session counter */
225 wl->session_counter++;
226 if (wl->session_counter >= SESSION_COUNTER_MAX)
227 wl->session_counter = 0;
228
229 join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
230
231
232 ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join));
233 if (ret < 0) {
234 wl1271_error("failed to initiate cmd join");
235 goto out_free;
236 }
237
238 timeout = msecs_to_jiffies(JOIN_TIMEOUT);
239
240 /*
241 * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to
242 * simplify locking we just sleep instead, for now
243 */
244 if (wait)
245 msleep(10);
246
247out_free:
248 kfree(join);
249
250out:
251 return ret;
252}
253
254/**
255 * send test command to firmware
256 *
257 * @wl: wl struct
258 * @buf: buffer containing the command, with all headers, must work with dma
259 * @len: length of the buffer
260 * @answer: is answer needed
261 */
262int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer)
263{
264 int ret;
265
266 wl1271_debug(DEBUG_CMD, "cmd test");
267
268 ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len);
269
270 if (ret < 0) {
271 wl1271_warning("TEST command failed");
272 return ret;
273 }
274
275 if (answer) {
276 struct wl1271_command *cmd_answer;
277
278 /*
279 * The test command got in, we can read the answer.
280 * The answer would be a wl1271_command, where the
281 * parameter array contains the actual answer.
282 */
283 wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len);
284
285 cmd_answer = buf;
286
287 if (cmd_answer->header.status != CMD_STATUS_SUCCESS)
288 wl1271_error("TEST command answer error: %d",
289 cmd_answer->header.status);
290 }
291
292 return 0;
293}
294
295/**
296 * read acx from firmware
297 *
298 * @wl: wl struct
299 * @id: acx id
300 * @buf: buffer for the response, including all headers, must work with dma
301 * @len: lenght of buf
302 */
303int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
304{
305 struct acx_header *acx = buf;
306 int ret;
307
308 wl1271_debug(DEBUG_CMD, "cmd interrogate");
309
310 acx->id = id;
311
312 /* payload length, does not include any headers */
313 acx->len = len - sizeof(*acx);
314
315 ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx));
316 if (ret < 0) {
317 wl1271_error("INTERROGATE command failed");
318 goto out;
319 }
320
321 /* the interrogate command got in, we can read the answer */
322 wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len);
323
324 acx = buf;
325 if (acx->cmd.status != CMD_STATUS_SUCCESS)
326 wl1271_error("INTERROGATE command error: %d",
327 acx->cmd.status);
328
329out:
330 return ret;
331}
332
333/**
334 * write acx value to firmware
335 *
336 * @wl: wl struct
337 * @id: acx id
338 * @buf: buffer containing acx, including all headers, must work with dma
339 * @len: length of buf
340 */
341int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len)
342{
343 struct acx_header *acx = buf;
344 int ret;
345
346 wl1271_debug(DEBUG_CMD, "cmd configure");
347
348 acx->id = id;
349
350 /* payload length, does not include any headers */
351 acx->len = len - sizeof(*acx);
352
353 ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len);
354 if (ret < 0) {
355 wl1271_warning("CONFIGURE command NOK");
356 return ret;
357 }
358
359 return 0;
360}
361
362int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable)
363{
364 struct cmd_enabledisable_path *cmd;
365 int ret;
366 u16 cmd_rx, cmd_tx;
367
368 wl1271_debug(DEBUG_CMD, "cmd data path");
369
370 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
371 if (!cmd) {
372 ret = -ENOMEM;
373 goto out;
374 }
375
376 cmd->channel = channel;
377
378 if (enable) {
379 cmd_rx = CMD_ENABLE_RX;
380 cmd_tx = CMD_ENABLE_TX;
381 } else {
382 cmd_rx = CMD_DISABLE_RX;
383 cmd_tx = CMD_DISABLE_TX;
384 }
385
386 ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd));
387 if (ret < 0) {
388 wl1271_error("rx %s cmd for channel %d failed",
389 enable ? "start" : "stop", channel);
390 goto out;
391 }
392
393 wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d",
394 enable ? "start" : "stop", channel);
395
396 ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd));
397 if (ret < 0) {
398 wl1271_error("tx %s cmd for channel %d failed",
399 enable ? "start" : "stop", channel);
400 return ret;
401 }
402
403 wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d",
404 enable ? "start" : "stop", channel);
405
406out:
407 kfree(cmd);
408 return ret;
409}
410
411int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
412{
413 struct wl1271_cmd_ps_params *ps_params = NULL;
414 int ret = 0;
415
416 /* FIXME: this should be in ps.c */
417 ret = wl1271_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP,
418 wl->listen_int);
419 if (ret < 0) {
420 wl1271_error("couldn't set wake up conditions");
421 goto out;
422 }
423
424 wl1271_debug(DEBUG_CMD, "cmd set ps mode");
425
426 ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
427 if (!ps_params) {
428 ret = -ENOMEM;
429 goto out;
430 }
431
432 ps_params->ps_mode = ps_mode;
433 ps_params->send_null_data = 1;
434 ps_params->retries = 5;
435 ps_params->hang_over_period = 128;
436 ps_params->null_data_rate = 1; /* 1 Mbps */
437
438 ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
439 sizeof(*ps_params));
440 if (ret < 0) {
441 wl1271_error("cmd set_ps_mode failed");
442 goto out;
443 }
444
445out:
446 kfree(ps_params);
447 return ret;
448}
449
450int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
451 size_t len)
452{
453 struct cmd_read_write_memory *cmd;
454 int ret = 0;
455
456 wl1271_debug(DEBUG_CMD, "cmd read memory");
457
458 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
459 if (!cmd) {
460 ret = -ENOMEM;
461 goto out;
462 }
463
464 WARN_ON(len > MAX_READ_SIZE);
465 len = min_t(size_t, len, MAX_READ_SIZE);
466
467 cmd->addr = addr;
468 cmd->size = len;
469
470 ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd));
471 if (ret < 0) {
472 wl1271_error("read memory command failed: %d", ret);
473 goto out;
474 }
475
476 /* the read command got in, we can now read the answer */
477 wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd));
478
479 if (cmd->header.status != CMD_STATUS_SUCCESS)
480 wl1271_error("error in read command result: %d",
481 cmd->header.status);
482
483 memcpy(answer, cmd->value, len);
484
485out:
486 kfree(cmd);
487 return ret;
488}
489
490int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
491 u8 active_scan, u8 high_prio, u8 num_channels,
492 u8 probe_requests)
493{
494
495 struct wl1271_cmd_trigger_scan_to *trigger = NULL;
496 struct wl1271_cmd_scan *params = NULL;
497 int i, ret;
498 u16 scan_options = 0;
499
500 if (wl->scanning)
501 return -EINVAL;
502
503 params = kzalloc(sizeof(*params), GFP_KERNEL);
504 if (!params)
505 return -ENOMEM;
506
507 params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
508 params->params.rx_filter_options =
509 cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
510
511 if (!active_scan)
512 scan_options |= WL1271_SCAN_OPT_PASSIVE;
513 if (high_prio)
514 scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH;
515 params->params.scan_options = scan_options;
516
517 params->params.num_channels = num_channels;
518 params->params.num_probe_requests = probe_requests;
519 params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS);
520 params->params.tid_trigger = 0;
521 params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
522
523 for (i = 0; i < num_channels; i++) {
524 params->channels[i].min_duration =
525 cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
526 params->channels[i].max_duration =
527 cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
528 memset(&params->channels[i].bssid_lsb, 0xff, 4);
529 memset(&params->channels[i].bssid_msb, 0xff, 2);
530 params->channels[i].early_termination = 0;
531 params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR;
532 params->channels[i].channel = i + 1;
533 }
534
535 if (len && ssid) {
536 params->params.ssid_len = len;
537 memcpy(params->params.ssid, ssid, len);
538 }
539
540 ret = wl1271_cmd_build_probe_req(wl, ssid, len);
541 if (ret < 0) {
542 wl1271_error("PROBE request template failed");
543 goto out;
544 }
545
546 trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
547 if (!trigger) {
548 ret = -ENOMEM;
549 goto out;
550 }
551
552 /* disable the timeout */
553 trigger->timeout = 0;
554
555 ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger,
556 sizeof(*trigger));
557 if (ret < 0) {
558 wl1271_error("trigger scan to failed for hw scan");
559 goto out;
560 }
561
562 wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params));
563
564 wl->scanning = true;
565
566 ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params));
567 if (ret < 0) {
568 wl1271_error("SCAN failed");
569 goto out;
570 }
571
572 wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params));
573
574 if (params->header.status != CMD_STATUS_SUCCESS) {
575 wl1271_error("Scan command error: %d",
576 params->header.status);
577 wl->scanning = false;
578 ret = -EIO;
579 goto out;
580 }
581
582out:
583 kfree(params);
584 return ret;
585}
586
587int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
588 void *buf, size_t buf_len)
589{
590 struct wl1271_cmd_template_set *cmd;
591 int ret = 0;
592
593 wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id);
594
595 WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE);
596 buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE);
597
598 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
599 if (!cmd) {
600 ret = -ENOMEM;
601 goto out;
602 }
603
604 cmd->len = cpu_to_le16(buf_len);
605 cmd->template_type = template_id;
606 cmd->enabled_rates = ACX_RATE_MASK_UNSPECIFIED;
607 cmd->short_retry_limit = ACX_RATE_RETRY_LIMIT;
608 cmd->long_retry_limit = ACX_RATE_RETRY_LIMIT;
609
610 if (buf)
611 memcpy(cmd->template_data, buf, buf_len);
612
613 ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd));
614 if (ret < 0) {
615 wl1271_warning("cmd set_template failed: %d", ret);
616 goto out_free;
617 }
618
619out_free:
620 kfree(cmd);
621
622out:
623 return ret;
624}
625
626static int wl1271_build_basic_rates(char *rates)
627{
628 u8 index = 0;
629
630 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
631 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
632 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
633 rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
634
635 return index;
636}
637
638static int wl1271_build_extended_rates(char *rates)
639{
640 u8 index = 0;
641
642 rates[index++] = IEEE80211_OFDM_RATE_6MB;
643 rates[index++] = IEEE80211_OFDM_RATE_9MB;
644 rates[index++] = IEEE80211_OFDM_RATE_12MB;
645 rates[index++] = IEEE80211_OFDM_RATE_18MB;
646 rates[index++] = IEEE80211_OFDM_RATE_24MB;
647 rates[index++] = IEEE80211_OFDM_RATE_36MB;
648 rates[index++] = IEEE80211_OFDM_RATE_48MB;
649 rates[index++] = IEEE80211_OFDM_RATE_54MB;
650
651 return index;
652}
653
654int wl1271_cmd_build_null_data(struct wl1271 *wl)
655{
656 struct wl12xx_null_data_template template;
657
658 if (!is_zero_ether_addr(wl->bssid)) {
659 memcpy(template.header.da, wl->bssid, ETH_ALEN);
660 memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
661 } else {
662 memset(template.header.da, 0xff, ETH_ALEN);
663 memset(template.header.bssid, 0xff, ETH_ALEN);
664 }
665
666 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
667 template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
668 IEEE80211_STYPE_NULLFUNC);
669
670 return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template,
671 sizeof(template));
672
673}
674
675int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
676{
677 struct wl12xx_ps_poll_template template;
678
679 memcpy(template.bssid, wl->bssid, ETH_ALEN);
680 memcpy(template.ta, wl->mac_addr, ETH_ALEN);
681 template.aid = aid;
682 template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
683
684 return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template,
685 sizeof(template));
686
687}
688
689int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len)
690{
691 struct wl12xx_probe_req_template template;
692 struct wl12xx_ie_rates *rates;
693 char *ptr;
694 u16 size;
695
696 ptr = (char *)&template;
697 size = sizeof(struct ieee80211_header);
698
699 memset(template.header.da, 0xff, ETH_ALEN);
700 memset(template.header.bssid, 0xff, ETH_ALEN);
701 memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
702 template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
703
704 /* IEs */
705 /* SSID */
706 template.ssid.header.id = WLAN_EID_SSID;
707 template.ssid.header.len = ssid_len;
708 if (ssid_len && ssid)
709 memcpy(template.ssid.ssid, ssid, ssid_len);
710 size += sizeof(struct wl12xx_ie_header) + ssid_len;
711 ptr += size;
712
713 /* Basic Rates */
714 rates = (struct wl12xx_ie_rates *)ptr;
715 rates->header.id = WLAN_EID_SUPP_RATES;
716 rates->header.len = wl1271_build_basic_rates(rates->rates);
717 size += sizeof(struct wl12xx_ie_header) + rates->header.len;
718 ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
719
720 /* Extended rates */
721 rates = (struct wl12xx_ie_rates *)ptr;
722 rates->header.id = WLAN_EID_EXT_SUPP_RATES;
723 rates->header.len = wl1271_build_extended_rates(rates->rates);
724 size += sizeof(struct wl12xx_ie_header) + rates->header.len;
725
726 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
727
728 return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
729 &template, size);
730}
731
732int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
733{
734 struct wl1271_cmd_set_keys *cmd;
735 int ret = 0;
736
737 wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
738
739 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
740 if (!cmd) {
741 ret = -ENOMEM;
742 goto out;
743 }
744
745 cmd->id = id;
746 cmd->key_action = KEY_SET_ID;
747 cmd->key_type = KEY_WEP;
748
749 ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
750 if (ret < 0) {
751 wl1271_warning("cmd set_default_wep_key failed: %d", ret);
752 goto out;
753 }
754
755out:
756 kfree(cmd);
757
758 return ret;
759}
760
761int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
762 u8 key_size, const u8 *key, const u8 *addr)
763{
764 struct wl1271_cmd_set_keys *cmd;
765 int ret = 0;
766
767 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
768 if (!cmd) {
769 ret = -ENOMEM;
770 goto out;
771 }
772
773 if (key_type != KEY_WEP)
774 memcpy(cmd->addr, addr, ETH_ALEN);
775
776 cmd->key_action = action;
777 cmd->key_size = key_size;
778 cmd->key_type = key_type;
779
780 /* we have only one SSID profile */
781 cmd->ssid_profile = 0;
782
783 cmd->id = id;
784
785 /* FIXME: this is from wl1251, needs to be checked */
786 if (key_type == KEY_TKIP) {
787 /*
788 * We get the key in the following form:
789 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
790 * but the target is expecting:
791 * TKIP - RX MIC - TX MIC
792 */
793 memcpy(cmd->key, key, 16);
794 memcpy(cmd->key + 16, key + 24, 8);
795 memcpy(cmd->key + 24, key + 16, 8);
796
797 } else {
798 memcpy(cmd->key, key, key_size);
799 }
800
801 wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd));
802
803 ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd));
804 if (ret < 0) {
805 wl1271_warning("could not set keys");
806 goto out;
807 }
808
809out:
810 kfree(cmd);
811
812 return ret;
813}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
new file mode 100644
index 000000000000..951a8447a516
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -0,0 +1,464 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_CMD_H__
26#define __WL1271_CMD_H__
27
28#include "wl1271.h"
29
30struct acx_header;
31
32int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len);
33int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval,
34 u16 beacon_interval, u8 wait);
35int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
36int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
37int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
38int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable);
39int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
40int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
41 size_t len);
42int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
43 u8 active_scan, u8 high_prio, u8 num_channels,
44 u8 probe_requests);
45int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
46 void *buf, size_t buf_len);
47int wl1271_cmd_build_null_data(struct wl1271 *wl);
48int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
49int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len);
50int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
51int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
52 u8 key_size, const u8 *key, const u8 *addr);
53
54enum wl1271_commands {
55 CMD_INTERROGATE = 1, /*use this to read information elements*/
56 CMD_CONFIGURE = 2, /*use this to write information elements*/
57 CMD_ENABLE_RX = 3,
58 CMD_ENABLE_TX = 4,
59 CMD_DISABLE_RX = 5,
60 CMD_DISABLE_TX = 6,
61 CMD_SCAN = 8,
62 CMD_STOP_SCAN = 9,
63 CMD_START_JOIN = 11,
64 CMD_SET_KEYS = 12,
65 CMD_READ_MEMORY = 13,
66 CMD_WRITE_MEMORY = 14,
67 CMD_SET_TEMPLATE = 19,
68 CMD_TEST = 23,
69 CMD_NOISE_HIST = 28,
70 CMD_LNA_CONTROL = 32,
71 CMD_SET_BCN_MODE = 33,
72 CMD_MEASUREMENT = 34,
73 CMD_STOP_MEASUREMENT = 35,
74 CMD_DISCONNECT = 36,
75 CMD_SET_PS_MODE = 37,
76 CMD_CHANNEL_SWITCH = 38,
77 CMD_STOP_CHANNEL_SWICTH = 39,
78 CMD_AP_DISCOVERY = 40,
79 CMD_STOP_AP_DISCOVERY = 41,
80 CMD_SPS_SCAN = 42,
81 CMD_STOP_SPS_SCAN = 43,
82 CMD_HEALTH_CHECK = 45,
83 CMD_DEBUG = 46,
84 CMD_TRIGGER_SCAN_TO = 47,
85 CMD_CONNECTION_SCAN_CFG = 48,
86 CMD_CONNECTION_SCAN_SSID_CFG = 49,
87 CMD_START_PERIODIC_SCAN = 50,
88 CMD_STOP_PERIODIC_SCAN = 51,
89 CMD_SET_STA_STATE = 52,
90
91 NUM_COMMANDS,
92 MAX_COMMAND_ID = 0xFFFF,
93};
94
95#define MAX_CMD_PARAMS 572
96
97enum cmd_templ {
98 CMD_TEMPL_NULL_DATA = 0,
99 CMD_TEMPL_BEACON,
100 CMD_TEMPL_CFG_PROBE_REQ_2_4,
101 CMD_TEMPL_CFG_PROBE_REQ_5,
102 CMD_TEMPL_PROBE_RESPONSE,
103 CMD_TEMPL_QOS_NULL_DATA,
104 CMD_TEMPL_PS_POLL,
105 CMD_TEMPL_KLV,
106 CMD_TEMPL_DISCONNECT,
107 CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */
108 CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */
109 CMD_TEMPL_BAR, /* for firmware internal use only */
110 CMD_TEMPL_CTS, /*
111 * For CTS-to-self (FastCTS) mechanism
112 * for BT/WLAN coexistence (SoftGemini). */
113 CMD_TEMPL_MAX = 0xff
114};
115
116/* unit ms */
117#define WL1271_COMMAND_TIMEOUT 2000
118#define WL1271_CMD_TEMPL_MAX_SIZE 252
119
120struct wl1271_cmd_header {
121 u16 id;
122 u16 status;
123 /* payload */
124 u8 data[0];
125} __attribute__ ((packed));
126
127#define WL1271_CMD_MAX_PARAMS 572
128
129struct wl1271_command {
130 struct wl1271_cmd_header header;
131 u8 parameters[WL1271_CMD_MAX_PARAMS];
132} __attribute__ ((packed));
133
134enum {
135 CMD_MAILBOX_IDLE = 0,
136 CMD_STATUS_SUCCESS = 1,
137 CMD_STATUS_UNKNOWN_CMD = 2,
138 CMD_STATUS_UNKNOWN_IE = 3,
139 CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11,
140 CMD_STATUS_RX_BUSY = 13,
141 CMD_STATUS_INVALID_PARAM = 14,
142 CMD_STATUS_TEMPLATE_TOO_LARGE = 15,
143 CMD_STATUS_OUT_OF_MEMORY = 16,
144 CMD_STATUS_STA_TABLE_FULL = 17,
145 CMD_STATUS_RADIO_ERROR = 18,
146 CMD_STATUS_WRONG_NESTING = 19,
147 CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/
148 CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/
149 MAX_COMMAND_STATUS = 0xff
150};
151
152
153/*
154 * CMD_READ_MEMORY
155 *
156 * The host issues this command to read the WiLink device memory/registers.
157 *
158 * Note: The Base Band address has special handling (16 bits registers and
159 * addresses). For more information, see the hardware specification.
160 */
161/*
162 * CMD_WRITE_MEMORY
163 *
164 * The host issues this command to write the WiLink device memory/registers.
165 *
166 * The Base Band address has special handling (16 bits registers and
167 * addresses). For more information, see the hardware specification.
168 */
169#define MAX_READ_SIZE 256
170
171struct cmd_read_write_memory {
172 struct wl1271_cmd_header header;
173
174 /* The address of the memory to read from or write to.*/
175 u32 addr;
176
177 /* The amount of data in bytes to read from or write to the WiLink
178 * device.*/
179 u32 size;
180
181 /* The actual value read from or written to the Wilink. The source
182 of this field is the Host in WRITE command or the Wilink in READ
183 command. */
184 u8 value[MAX_READ_SIZE];
185};
186
187#define CMDMBOX_HEADER_LEN 4
188#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
189
190enum {
191 BSS_TYPE_IBSS = 0,
192 BSS_TYPE_STA_BSS = 2,
193 BSS_TYPE_AP_BSS = 3,
194 MAX_BSS_TYPE = 0xFF
195};
196
197#define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */
198#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
199
200struct wl1271_cmd_join {
201 struct wl1271_cmd_header header;
202
203 u32 bssid_lsb;
204 u16 bssid_msb;
205 u16 beacon_interval; /* in TBTTs */
206 u32 rx_config_options;
207 u32 rx_filter_options;
208
209 /*
210 * The target uses this field to determine the rate at
211 * which to transmit control frame responses (such as
212 * ACK or CTS frames).
213 */
214 u32 basic_rate_set;
215 u8 dtim_interval;
216 /*
217 * bits 0-2: This bitwise field specifies the type
218 * of BSS to start or join (BSS_TYPE_*).
219 * bit 4: Band - The radio band in which to join
220 * or start.
221 * 0 - 2.4GHz band
222 * 1 - 5GHz band
223 * bits 3, 5-7: Reserved
224 */
225 u8 bss_type;
226 u8 channel;
227 u8 ssid_len;
228 u8 ssid[IW_ESSID_MAX_SIZE];
229 u8 ctrl; /* JOIN_CMD_CTRL_* */
230 u8 reserved[3];
231} __attribute__ ((packed));
232
233struct cmd_enabledisable_path {
234 struct wl1271_cmd_header header;
235
236 u8 channel;
237 u8 padding[3];
238} __attribute__ ((packed));
239
240struct wl1271_cmd_template_set {
241 struct wl1271_cmd_header header;
242
243 u16 len;
244 u8 template_type;
245 u8 index; /* relevant only for KLV_TEMPLATE type */
246 u32 enabled_rates;
247 u8 short_retry_limit;
248 u8 long_retry_limit;
249 u8 aflags;
250 u8 reserved;
251 u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE];
252} __attribute__ ((packed));
253
254#define TIM_ELE_ID 5
255#define PARTIAL_VBM_MAX 251
256
257struct wl1271_tim {
258 u8 identity;
259 u8 length;
260 u8 dtim_count;
261 u8 dtim_period;
262 u8 bitmap_ctrl;
263 u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */
264} __attribute__ ((packed));
265
266enum wl1271_cmd_ps_mode {
267 STATION_ACTIVE_MODE,
268 STATION_POWER_SAVE_MODE
269};
270
271struct wl1271_cmd_ps_params {
272 struct wl1271_cmd_header header;
273
274 u8 ps_mode; /* STATION_* */
275 u8 send_null_data; /* Do we have to send NULL data packet ? */
276 u8 retries; /* Number of retires for the initial NULL data packet */
277
278 /*
279 * TUs during which the target stays awake after switching
280 * to power save mode.
281 */
282 u8 hang_over_period;
283 u32 null_data_rate;
284} __attribute__ ((packed));
285
286/* HW encryption keys */
287#define NUM_ACCESS_CATEGORIES_COPY 4
288#define MAX_KEY_SIZE 32
289
290/* When set, disable HW encryption */
291#define DF_ENCRYPTION_DISABLE 0x01
292/* When set, disable HW decryption */
293#define DF_SNIFF_MODE_ENABLE 0x80
294
295enum wl1271_cmd_key_action {
296 KEY_ADD_OR_REPLACE = 1,
297 KEY_REMOVE = 2,
298 KEY_SET_ID = 3,
299 MAX_KEY_ACTION = 0xffff,
300};
301
302enum wl1271_cmd_key_type {
303 KEY_NONE = 0,
304 KEY_WEP = 1,
305 KEY_TKIP = 2,
306 KEY_AES = 3,
307 KEY_GEM = 4
308};
309
310/* FIXME: Add description for key-types */
311
312struct wl1271_cmd_set_keys {
313 struct wl1271_cmd_header header;
314
315 /* Ignored for default WEP key */
316 u8 addr[ETH_ALEN];
317
318 /* key_action_e */
319 u16 key_action;
320
321 u16 reserved_1;
322
323 /* key size in bytes */
324 u8 key_size;
325
326 /* key_type_e */
327 u8 key_type;
328 u8 ssid_profile;
329
330 /*
331 * TKIP, AES: frame's key id field.
332 * For WEP default key: key id;
333 */
334 u8 id;
335 u8 reserved_2[6];
336 u8 key[MAX_KEY_SIZE];
337 u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
338 u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
339} __attribute__ ((packed));
340
341
342#define WL1271_SCAN_MAX_CHANNELS 24
343#define WL1271_SCAN_DEFAULT_TAG 1
344#define WL1271_SCAN_CURRENT_TX_PWR 0
345#define WL1271_SCAN_OPT_ACTIVE 0
346#define WL1271_SCAN_OPT_PASSIVE 1
347#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
348#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
349#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
350
351struct basic_scan_params {
352 u32 rx_config_options;
353 u32 rx_filter_options;
354 /* Scan option flags (WL1271_SCAN_OPT_*) */
355 u16 scan_options;
356 /* Number of scan channels in the list (maximum 30) */
357 u8 num_channels;
358 /* This field indicates the number of probe requests to send
359 per channel for an active scan */
360 u8 num_probe_requests;
361 /* Rate bit field for sending the probes */
362 u32 tx_rate;
363 u8 tid_trigger;
364 u8 ssid_len;
365 /* in order to align */
366 u8 padding1[2];
367 u8 ssid[IW_ESSID_MAX_SIZE];
368 /* Band to scan */
369 u8 band;
370 u8 use_ssid_list;
371 u8 scan_tag;
372 u8 padding2;
373} __attribute__ ((packed));
374
375struct basic_scan_channel_params {
376 /* Duration in TU to wait for frames on a channel for active scan */
377 u32 min_duration;
378 u32 max_duration;
379 u32 bssid_lsb;
380 u16 bssid_msb;
381 u8 early_termination;
382 u8 tx_power_att;
383 u8 channel;
384 /* FW internal use only! */
385 u8 dfs_candidate;
386 u8 activity_detected;
387 u8 pad;
388} __attribute__ ((packed));
389
390struct wl1271_cmd_scan {
391 struct wl1271_cmd_header header;
392
393 struct basic_scan_params params;
394 struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
395} __attribute__ ((packed));
396
397struct wl1271_cmd_trigger_scan_to {
398 struct wl1271_cmd_header header;
399
400 u32 timeout;
401};
402
403struct wl1271_cmd_test_header {
404 u8 id;
405 u8 padding[3];
406};
407
408enum wl1271_channel_tune_bands {
409 WL1271_CHANNEL_TUNE_BAND_2_4,
410 WL1271_CHANNEL_TUNE_BAND_5,
411 WL1271_CHANNEL_TUNE_BAND_4_9
412};
413
414#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0
415
416#define TEST_CMD_P2G_CAL 0x02
417#define TEST_CMD_CHANNEL_TUNE 0x0d
418#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
419
420struct wl1271_cmd_cal_channel_tune {
421 struct wl1271_cmd_header header;
422
423 struct wl1271_cmd_test_header test;
424
425 u8 band;
426 u8 channel;
427
428 u16 radio_status;
429} __attribute__ ((packed));
430
431struct wl1271_cmd_cal_update_ref_point {
432 struct wl1271_cmd_header header;
433
434 struct wl1271_cmd_test_header test;
435
436 s32 ref_power;
437 s32 ref_detector;
438 u8 sub_band;
439 u8 padding[3];
440} __attribute__ ((packed));
441
442#define MAX_TLV_LENGTH 400
443#define MAX_NVS_VERSION_LENGTH 12
444
445#define WL1271_CAL_P2G_BAND_B_G BIT(0)
446
447struct wl1271_cmd_cal_p2g {
448 struct wl1271_cmd_header header;
449
450 struct wl1271_cmd_test_header test;
451
452 u16 len;
453 u8 buf[MAX_TLV_LENGTH];
454 u8 type;
455 u8 padding;
456
457 s16 radio_status;
458 u8 nvs_version[MAX_NVS_VERSION_LENGTH];
459
460 u8 sub_band_mask;
461 u8 padding2;
462} __attribute__ ((packed));
463
464#endif /* __WL1271_CMD_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
new file mode 100644
index 000000000000..c1805e5f8964
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -0,0 +1,518 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1271_debugfs.h"
25
26#include <linux/skbuff.h>
27
28#include "wl1271.h"
29#include "wl1271_acx.h"
30#include "wl1271_ps.h"
31
32/* ms */
33#define WL1271_DEBUGFS_STATS_LIFETIME 1000
34
35/* debugfs macros idea from mac80211 */
36
37#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
38static ssize_t name## _read(struct file *file, char __user *userbuf, \
39 size_t count, loff_t *ppos) \
40{ \
41 struct wl1271 *wl = file->private_data; \
42 char buf[buflen]; \
43 int res; \
44 \
45 res = scnprintf(buf, buflen, fmt "\n", ##value); \
46 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
47} \
48 \
49static const struct file_operations name## _ops = { \
50 .read = name## _read, \
51 .open = wl1271_open_file_generic, \
52};
53
54#define DEBUGFS_ADD(name, parent) \
55 wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \
56 wl, &name## _ops); \
57 if (IS_ERR(wl->debugfs.name)) { \
58 ret = PTR_ERR(wl->debugfs.name); \
59 wl->debugfs.name = NULL; \
60 goto out; \
61 }
62
63#define DEBUGFS_DEL(name) \
64 do { \
65 debugfs_remove(wl->debugfs.name); \
66 wl->debugfs.name = NULL; \
67 } while (0)
68
69#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \
70static ssize_t sub## _ ##name## _read(struct file *file, \
71 char __user *userbuf, \
72 size_t count, loff_t *ppos) \
73{ \
74 struct wl1271 *wl = file->private_data; \
75 char buf[buflen]; \
76 int res; \
77 \
78 wl1271_debugfs_update_stats(wl); \
79 \
80 res = scnprintf(buf, buflen, fmt "\n", \
81 wl->stats.fw_stats->sub.name); \
82 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
83} \
84 \
85static const struct file_operations sub## _ ##name## _ops = { \
86 .read = sub## _ ##name## _read, \
87 .open = wl1271_open_file_generic, \
88};
89
90#define DEBUGFS_FWSTATS_ADD(sub, name) \
91 DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics)
92
93#define DEBUGFS_FWSTATS_DEL(sub, name) \
94 DEBUGFS_DEL(sub## _ ##name)
95
96static void wl1271_debugfs_update_stats(struct wl1271 *wl)
97{
98 int ret;
99
100 mutex_lock(&wl->mutex);
101
102 ret = wl1271_ps_elp_wakeup(wl, false);
103 if (ret < 0)
104 goto out;
105
106 if (wl->state == WL1271_STATE_ON &&
107 time_after(jiffies, wl->stats.fw_stats_update +
108 msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) {
109 wl1271_acx_statistics(wl, wl->stats.fw_stats);
110 wl->stats.fw_stats_update = jiffies;
111 }
112
113 wl1271_ps_elp_sleep(wl);
114
115out:
116 mutex_unlock(&wl->mutex);
117}
118
119static int wl1271_open_file_generic(struct inode *inode, struct file *file)
120{
121 file->private_data = inode->i_private;
122 return 0;
123}
124
125DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u");
126
127DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u");
128DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u");
129DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u");
130DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u");
131DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u");
132DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u");
133DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u");
134DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u");
135
136DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u");
137DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u");
138DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u");
139DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u");
140
141DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u");
142DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u");
143DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u");
144DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u");
145DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u");
146DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u");
147DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u");
148DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u");
149DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u");
150DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u");
151DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u");
152DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u");
153DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u");
154DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u");
155DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u");
156DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u");
157DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u");
158DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u");
159
160DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u");
161DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u");
162/* skipping wep.reserved */
163DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u");
164DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u");
165DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u");
166DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u");
167
168DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u");
169DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u");
170DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u");
171DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u");
172DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u");
173DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u");
174DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u");
175DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u");
176DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u");
177DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u");
178DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u");
179DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u");
180/* skipping cont_miss_bcns_spread for now */
181DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u");
182
183DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u");
184DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u");
185
186DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u");
187DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u");
188DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u");
189DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u");
190DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u");
191DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u");
192
193DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u");
194DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u");
195DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u");
196DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u");
197DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u");
198DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u");
199DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u");
200DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u");
201
202DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u");
203DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u");
204DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u");
205DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u");
206DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u");
207DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u");
208DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u");
209
210DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u");
211DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u");
212DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data,
213 20, "%u");
214DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u");
215DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u");
216
217DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count);
218DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u",
219 wl->stats.excessive_retries);
220
221static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf,
222 size_t count, loff_t *ppos)
223{
224 struct wl1271 *wl = file->private_data;
225 u32 queue_len;
226 char buf[20];
227 int res;
228
229 queue_len = skb_queue_len(&wl->tx_queue);
230
231 res = scnprintf(buf, sizeof(buf), "%u\n", queue_len);
232 return simple_read_from_buffer(userbuf, count, ppos, buf, res);
233}
234
235static const struct file_operations tx_queue_len_ops = {
236 .read = tx_queue_len_read,
237 .open = wl1271_open_file_generic,
238};
239
240static void wl1271_debugfs_delete_files(struct wl1271 *wl)
241{
242 DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow);
243
244 DEBUGFS_FWSTATS_DEL(rx, out_of_mem);
245 DEBUGFS_FWSTATS_DEL(rx, hdr_overflow);
246 DEBUGFS_FWSTATS_DEL(rx, hw_stuck);
247 DEBUGFS_FWSTATS_DEL(rx, dropped);
248 DEBUGFS_FWSTATS_DEL(rx, fcs_err);
249 DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig);
250 DEBUGFS_FWSTATS_DEL(rx, path_reset);
251 DEBUGFS_FWSTATS_DEL(rx, reset_counter);
252
253 DEBUGFS_FWSTATS_DEL(dma, rx_requested);
254 DEBUGFS_FWSTATS_DEL(dma, rx_errors);
255 DEBUGFS_FWSTATS_DEL(dma, tx_requested);
256 DEBUGFS_FWSTATS_DEL(dma, tx_errors);
257
258 DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt);
259 DEBUGFS_FWSTATS_DEL(isr, fiqs);
260 DEBUGFS_FWSTATS_DEL(isr, rx_headers);
261 DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow);
262 DEBUGFS_FWSTATS_DEL(isr, rx_rdys);
263 DEBUGFS_FWSTATS_DEL(isr, irqs);
264 DEBUGFS_FWSTATS_DEL(isr, tx_procs);
265 DEBUGFS_FWSTATS_DEL(isr, decrypt_done);
266 DEBUGFS_FWSTATS_DEL(isr, dma0_done);
267 DEBUGFS_FWSTATS_DEL(isr, dma1_done);
268 DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete);
269 DEBUGFS_FWSTATS_DEL(isr, commands);
270 DEBUGFS_FWSTATS_DEL(isr, rx_procs);
271 DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes);
272 DEBUGFS_FWSTATS_DEL(isr, host_acknowledges);
273 DEBUGFS_FWSTATS_DEL(isr, pci_pm);
274 DEBUGFS_FWSTATS_DEL(isr, wakeups);
275 DEBUGFS_FWSTATS_DEL(isr, low_rssi);
276
277 DEBUGFS_FWSTATS_DEL(wep, addr_key_count);
278 DEBUGFS_FWSTATS_DEL(wep, default_key_count);
279 /* skipping wep.reserved */
280 DEBUGFS_FWSTATS_DEL(wep, key_not_found);
281 DEBUGFS_FWSTATS_DEL(wep, decrypt_fail);
282 DEBUGFS_FWSTATS_DEL(wep, packets);
283 DEBUGFS_FWSTATS_DEL(wep, interrupt);
284
285 DEBUGFS_FWSTATS_DEL(pwr, ps_enter);
286 DEBUGFS_FWSTATS_DEL(pwr, elp_enter);
287 DEBUGFS_FWSTATS_DEL(pwr, missing_bcns);
288 DEBUGFS_FWSTATS_DEL(pwr, wake_on_host);
289 DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp);
290 DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps);
291 DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps);
292 DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons);
293 DEBUGFS_FWSTATS_DEL(pwr, power_save_off);
294 DEBUGFS_FWSTATS_DEL(pwr, enable_ps);
295 DEBUGFS_FWSTATS_DEL(pwr, disable_ps);
296 DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps);
297 /* skipping cont_miss_bcns_spread for now */
298 DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons);
299
300 DEBUGFS_FWSTATS_DEL(mic, rx_pkts);
301 DEBUGFS_FWSTATS_DEL(mic, calc_failure);
302
303 DEBUGFS_FWSTATS_DEL(aes, encrypt_fail);
304 DEBUGFS_FWSTATS_DEL(aes, decrypt_fail);
305 DEBUGFS_FWSTATS_DEL(aes, encrypt_packets);
306 DEBUGFS_FWSTATS_DEL(aes, decrypt_packets);
307 DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt);
308 DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt);
309
310 DEBUGFS_FWSTATS_DEL(event, heart_beat);
311 DEBUGFS_FWSTATS_DEL(event, calibration);
312 DEBUGFS_FWSTATS_DEL(event, rx_mismatch);
313 DEBUGFS_FWSTATS_DEL(event, rx_mem_empty);
314 DEBUGFS_FWSTATS_DEL(event, rx_pool);
315 DEBUGFS_FWSTATS_DEL(event, oom_late);
316 DEBUGFS_FWSTATS_DEL(event, phy_transmit_error);
317 DEBUGFS_FWSTATS_DEL(event, tx_stuck);
318
319 DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts);
320 DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts);
321 DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime);
322 DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn);
323 DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn);
324 DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization);
325 DEBUGFS_FWSTATS_DEL(ps, upsd_utilization);
326
327 DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop);
328 DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data);
329 DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
330 DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data);
331 DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data);
332
333 DEBUGFS_DEL(tx_queue_len);
334 DEBUGFS_DEL(retry_count);
335 DEBUGFS_DEL(excessive_retries);
336}
337
338static int wl1271_debugfs_add_files(struct wl1271 *wl)
339{
340 int ret = 0;
341
342 DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow);
343
344 DEBUGFS_FWSTATS_ADD(rx, out_of_mem);
345 DEBUGFS_FWSTATS_ADD(rx, hdr_overflow);
346 DEBUGFS_FWSTATS_ADD(rx, hw_stuck);
347 DEBUGFS_FWSTATS_ADD(rx, dropped);
348 DEBUGFS_FWSTATS_ADD(rx, fcs_err);
349 DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig);
350 DEBUGFS_FWSTATS_ADD(rx, path_reset);
351 DEBUGFS_FWSTATS_ADD(rx, reset_counter);
352
353 DEBUGFS_FWSTATS_ADD(dma, rx_requested);
354 DEBUGFS_FWSTATS_ADD(dma, rx_errors);
355 DEBUGFS_FWSTATS_ADD(dma, tx_requested);
356 DEBUGFS_FWSTATS_ADD(dma, tx_errors);
357
358 DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt);
359 DEBUGFS_FWSTATS_ADD(isr, fiqs);
360 DEBUGFS_FWSTATS_ADD(isr, rx_headers);
361 DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow);
362 DEBUGFS_FWSTATS_ADD(isr, rx_rdys);
363 DEBUGFS_FWSTATS_ADD(isr, irqs);
364 DEBUGFS_FWSTATS_ADD(isr, tx_procs);
365 DEBUGFS_FWSTATS_ADD(isr, decrypt_done);
366 DEBUGFS_FWSTATS_ADD(isr, dma0_done);
367 DEBUGFS_FWSTATS_ADD(isr, dma1_done);
368 DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete);
369 DEBUGFS_FWSTATS_ADD(isr, commands);
370 DEBUGFS_FWSTATS_ADD(isr, rx_procs);
371 DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes);
372 DEBUGFS_FWSTATS_ADD(isr, host_acknowledges);
373 DEBUGFS_FWSTATS_ADD(isr, pci_pm);
374 DEBUGFS_FWSTATS_ADD(isr, wakeups);
375 DEBUGFS_FWSTATS_ADD(isr, low_rssi);
376
377 DEBUGFS_FWSTATS_ADD(wep, addr_key_count);
378 DEBUGFS_FWSTATS_ADD(wep, default_key_count);
379 /* skipping wep.reserved */
380 DEBUGFS_FWSTATS_ADD(wep, key_not_found);
381 DEBUGFS_FWSTATS_ADD(wep, decrypt_fail);
382 DEBUGFS_FWSTATS_ADD(wep, packets);
383 DEBUGFS_FWSTATS_ADD(wep, interrupt);
384
385 DEBUGFS_FWSTATS_ADD(pwr, ps_enter);
386 DEBUGFS_FWSTATS_ADD(pwr, elp_enter);
387 DEBUGFS_FWSTATS_ADD(pwr, missing_bcns);
388 DEBUGFS_FWSTATS_ADD(pwr, wake_on_host);
389 DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp);
390 DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps);
391 DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps);
392 DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons);
393 DEBUGFS_FWSTATS_ADD(pwr, power_save_off);
394 DEBUGFS_FWSTATS_ADD(pwr, enable_ps);
395 DEBUGFS_FWSTATS_ADD(pwr, disable_ps);
396 DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps);
397 /* skipping cont_miss_bcns_spread for now */
398 DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons);
399
400 DEBUGFS_FWSTATS_ADD(mic, rx_pkts);
401 DEBUGFS_FWSTATS_ADD(mic, calc_failure);
402
403 DEBUGFS_FWSTATS_ADD(aes, encrypt_fail);
404 DEBUGFS_FWSTATS_ADD(aes, decrypt_fail);
405 DEBUGFS_FWSTATS_ADD(aes, encrypt_packets);
406 DEBUGFS_FWSTATS_ADD(aes, decrypt_packets);
407 DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt);
408 DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt);
409
410 DEBUGFS_FWSTATS_ADD(event, heart_beat);
411 DEBUGFS_FWSTATS_ADD(event, calibration);
412 DEBUGFS_FWSTATS_ADD(event, rx_mismatch);
413 DEBUGFS_FWSTATS_ADD(event, rx_mem_empty);
414 DEBUGFS_FWSTATS_ADD(event, rx_pool);
415 DEBUGFS_FWSTATS_ADD(event, oom_late);
416 DEBUGFS_FWSTATS_ADD(event, phy_transmit_error);
417 DEBUGFS_FWSTATS_ADD(event, tx_stuck);
418
419 DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts);
420 DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts);
421 DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime);
422 DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn);
423 DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn);
424 DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization);
425 DEBUGFS_FWSTATS_ADD(ps, upsd_utilization);
426
427 DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop);
428 DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data);
429 DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data);
430 DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
431 DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
432
433 DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir);
434 DEBUGFS_ADD(retry_count, wl->debugfs.rootdir);
435 DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir);
436
437out:
438 if (ret < 0)
439 wl1271_debugfs_delete_files(wl);
440
441 return ret;
442}
443
444void wl1271_debugfs_reset(struct wl1271 *wl)
445{
446 memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
447 wl->stats.retry_count = 0;
448 wl->stats.excessive_retries = 0;
449}
450
451int wl1271_debugfs_init(struct wl1271 *wl)
452{
453 int ret;
454
455 wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
456
457 if (IS_ERR(wl->debugfs.rootdir)) {
458 ret = PTR_ERR(wl->debugfs.rootdir);
459 wl->debugfs.rootdir = NULL;
460 goto err;
461 }
462
463 wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics",
464 wl->debugfs.rootdir);
465
466 if (IS_ERR(wl->debugfs.fw_statistics)) {
467 ret = PTR_ERR(wl->debugfs.fw_statistics);
468 wl->debugfs.fw_statistics = NULL;
469 goto err_root;
470 }
471
472 wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats),
473 GFP_KERNEL);
474
475 if (!wl->stats.fw_stats) {
476 ret = -ENOMEM;
477 goto err_fw;
478 }
479
480 wl->stats.fw_stats_update = jiffies;
481
482 ret = wl1271_debugfs_add_files(wl);
483
484 if (ret < 0)
485 goto err_file;
486
487 return 0;
488
489err_file:
490 kfree(wl->stats.fw_stats);
491 wl->stats.fw_stats = NULL;
492
493err_fw:
494 debugfs_remove(wl->debugfs.fw_statistics);
495 wl->debugfs.fw_statistics = NULL;
496
497err_root:
498 debugfs_remove(wl->debugfs.rootdir);
499 wl->debugfs.rootdir = NULL;
500
501err:
502 return ret;
503}
504
505void wl1271_debugfs_exit(struct wl1271 *wl)
506{
507 wl1271_debugfs_delete_files(wl);
508
509 kfree(wl->stats.fw_stats);
510 wl->stats.fw_stats = NULL;
511
512 debugfs_remove(wl->debugfs.fw_statistics);
513 wl->debugfs.fw_statistics = NULL;
514
515 debugfs_remove(wl->debugfs.rootdir);
516 wl->debugfs.rootdir = NULL;
517
518}
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.h b/drivers/net/wireless/wl12xx/wl1271_debugfs.h
new file mode 100644
index 000000000000..00a45b2669ad
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.h
@@ -0,0 +1,33 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef WL1271_DEBUGFS_H
25#define WL1271_DEBUGFS_H
26
27#include "wl1271.h"
28
29int wl1271_debugfs_init(struct wl1271 *wl);
30void wl1271_debugfs_exit(struct wl1271 *wl);
31void wl1271_debugfs_reset(struct wl1271 *wl);
32
33#endif /* WL1271_DEBUGFS_H */
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
new file mode 100644
index 000000000000..f3afd4a6ff33
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -0,0 +1,125 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1271.h"
25#include "wl1271_reg.h"
26#include "wl1271_spi.h"
27#include "wl1271_event.h"
28#include "wl1271_ps.h"
29
30static int wl1271_event_scan_complete(struct wl1271 *wl,
31 struct event_mailbox *mbox)
32{
33 wl1271_debug(DEBUG_EVENT, "status: 0x%x",
34 mbox->scheduled_scan_status);
35
36 if (wl->scanning) {
37 mutex_unlock(&wl->mutex);
38 ieee80211_scan_completed(wl->hw, false);
39 mutex_lock(&wl->mutex);
40 wl->scanning = false;
41 }
42
43 return 0;
44}
45
46static void wl1271_event_mbox_dump(struct event_mailbox *mbox)
47{
48 wl1271_debug(DEBUG_EVENT, "MBOX DUMP:");
49 wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector);
50 wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask);
51}
52
53static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
54{
55 int ret;
56 u32 vector;
57
58 wl1271_event_mbox_dump(mbox);
59
60 vector = mbox->events_vector & ~(mbox->events_mask);
61 wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector);
62
63 if (vector & SCAN_COMPLETE_EVENT_ID) {
64 ret = wl1271_event_scan_complete(wl, mbox);
65 if (ret < 0)
66 return ret;
67 }
68
69 if (vector & BSS_LOSE_EVENT_ID) {
70 wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
71
72 if (wl->psm_requested && wl->psm) {
73 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
74 if (ret < 0)
75 return ret;
76 }
77 }
78
79 return 0;
80}
81
82int wl1271_event_unmask(struct wl1271 *wl)
83{
84 int ret;
85
86 ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask));
87 if (ret < 0)
88 return ret;
89
90 return 0;
91}
92
93void wl1271_event_mbox_config(struct wl1271 *wl)
94{
95 wl->mbox_ptr[0] = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR);
96 wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox);
97
98 wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x",
99 wl->mbox_ptr[0], wl->mbox_ptr[1]);
100}
101
102int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num)
103{
104 struct event_mailbox mbox;
105 int ret;
106
107 wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num);
108
109 if (mbox_num > 1)
110 return -EINVAL;
111
112 /* first we read the mbox descriptor */
113 wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox,
114 sizeof(struct event_mailbox));
115
116 /* process the descriptor */
117 ret = wl1271_event_process(wl, &mbox);
118 if (ret < 0)
119 return ret;
120
121 /* then we let the firmware know it can go on...*/
122 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK);
123
124 return 0;
125}
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h
new file mode 100644
index 000000000000..2cdce7c34bf0
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_event.h
@@ -0,0 +1,110 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_EVENT_H__
26#define __WL1271_EVENT_H__
27
28/*
29 * Mbox events
30 *
31 * The event mechanism is based on a pair of event buffers (buffers A and
32 * B) at fixed locations in the target's memory. The host processes one
33 * buffer while the other buffer continues to collect events. If the host
34 * is not processing events, an interrupt is issued to signal that a buffer
35 * is ready. Once the host is done with processing events from one buffer,
36 * it signals the target (with an ACK interrupt) that the event buffer is
37 * free.
38 */
39
40enum {
41 MEASUREMENT_START_EVENT_ID = BIT(8),
42 MEASUREMENT_COMPLETE_EVENT_ID = BIT(9),
43 SCAN_COMPLETE_EVENT_ID = BIT(10),
44 SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11),
45 AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12),
46 PS_REPORT_EVENT_ID = BIT(13),
47 PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14),
48 DISCONNECT_EVENT_COMPLETE_ID = BIT(15),
49 JOIN_EVENT_COMPLETE_ID = BIT(16),
50 CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17),
51 BSS_LOSE_EVENT_ID = BIT(18),
52 REGAINED_BSS_EVENT_ID = BIT(19),
53 ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20),
54 SOFT_GEMINI_SENSE_EVENT_ID = BIT(22),
55 SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23),
56 SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24),
57 PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25),
58 DBG_EVENT_ID = BIT(26),
59 HEALTH_CHECK_REPLY_EVENT_ID = BIT(27),
60 PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28),
61 PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29),
62 BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30),
63 EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff,
64};
65
66struct event_debug_report {
67 u8 debug_event_id;
68 u8 num_params;
69 u16 pad;
70 u32 report_1;
71 u32 report_2;
72 u32 report_3;
73} __attribute__ ((packed));
74
75#define NUM_OF_RSSI_SNR_TRIGGERS 8
76
77struct event_mailbox {
78 u32 events_vector;
79 u32 events_mask;
80 u32 reserved_1;
81 u32 reserved_2;
82
83 u8 dbg_event_id;
84 u8 num_relevant_params;
85 u16 reserved_3;
86 u32 event_report_p1;
87 u32 event_report_p2;
88 u32 event_report_p3;
89
90 u8 number_of_scan_results;
91 u8 scan_tag;
92 u8 reserved_4[2];
93 u32 compl_scheduled_scan_status;
94
95 u16 scheduled_scan_attended_channels;
96 u8 soft_gemini_sense_info;
97 u8 soft_gemini_protective_info;
98 s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
99 u8 channel_switch_status;
100 u8 scheduled_scan_status;
101 u8 ps_status;
102
103 u8 reserved_5[29];
104} __attribute__ ((packed));
105
106int wl1271_event_unmask(struct wl1271 *wl);
107void wl1271_event_mbox_config(struct wl1271 *wl);
108int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
109
110#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
new file mode 100644
index 000000000000..490df217605a
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -0,0 +1,397 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26
27#include "wl1271_init.h"
28#include "wl12xx_80211.h"
29#include "wl1271_acx.h"
30#include "wl1271_cmd.h"
31#include "wl1271_reg.h"
32
33static int wl1271_init_hwenc_config(struct wl1271 *wl)
34{
35 int ret;
36
37 ret = wl1271_acx_feature_cfg(wl);
38 if (ret < 0) {
39 wl1271_warning("couldn't set feature config");
40 return ret;
41 }
42
43 ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
44 if (ret < 0) {
45 wl1271_warning("couldn't set default key");
46 return ret;
47 }
48
49 return 0;
50}
51
52static int wl1271_init_templates_config(struct wl1271 *wl)
53{
54 int ret;
55
56 /* send empty templates for fw memory reservation */
57 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
58 sizeof(struct wl12xx_probe_req_template));
59 if (ret < 0)
60 return ret;
61
62 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
63 sizeof(struct wl12xx_null_data_template));
64 if (ret < 0)
65 return ret;
66
67 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
68 sizeof(struct wl12xx_ps_poll_template));
69 if (ret < 0)
70 return ret;
71
72 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
73 sizeof
74 (struct wl12xx_qos_null_data_template));
75 if (ret < 0)
76 return ret;
77
78 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
79 sizeof
80 (struct wl12xx_probe_resp_template));
81 if (ret < 0)
82 return ret;
83
84 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
85 sizeof
86 (struct wl12xx_beacon_template));
87 if (ret < 0)
88 return ret;
89
90 return 0;
91}
92
93static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
94{
95 int ret;
96
97 ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF);
98 if (ret < 0)
99 return ret;
100
101 ret = wl1271_acx_rx_config(wl, config, filter);
102 if (ret < 0)
103 return ret;
104
105 return 0;
106}
107
108static int wl1271_init_phy_config(struct wl1271 *wl)
109{
110 int ret;
111
112 ret = wl1271_acx_pd_threshold(wl);
113 if (ret < 0)
114 return ret;
115
116 ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME);
117 if (ret < 0)
118 return ret;
119
120 ret = wl1271_acx_group_address_tbl(wl);
121 if (ret < 0)
122 return ret;
123
124 ret = wl1271_acx_service_period_timeout(wl);
125 if (ret < 0)
126 return ret;
127
128 ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF);
129 if (ret < 0)
130 return ret;
131
132 return 0;
133}
134
135static int wl1271_init_beacon_filter(struct wl1271 *wl)
136{
137 int ret;
138
139 ret = wl1271_acx_beacon_filter_opt(wl);
140 if (ret < 0)
141 return ret;
142
143 ret = wl1271_acx_beacon_filter_table(wl);
144 if (ret < 0)
145 return ret;
146
147 return 0;
148}
149
150static int wl1271_init_pta(struct wl1271 *wl)
151{
152 int ret;
153
154 ret = wl1271_acx_sg_enable(wl);
155 if (ret < 0)
156 return ret;
157
158 ret = wl1271_acx_sg_cfg(wl);
159 if (ret < 0)
160 return ret;
161
162 return 0;
163}
164
165static int wl1271_init_energy_detection(struct wl1271 *wl)
166{
167 int ret;
168
169 ret = wl1271_acx_cca_threshold(wl);
170 if (ret < 0)
171 return ret;
172
173 return 0;
174}
175
176static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
177{
178 int ret;
179
180 ret = wl1271_acx_bcn_dtim_options(wl);
181 if (ret < 0)
182 return ret;
183
184 return 0;
185}
186
187static int wl1271_init_general_parms(struct wl1271 *wl)
188{
189 struct wl1271_general_parms *gen_parms;
190 int ret;
191
192 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
193 if (!gen_parms)
194 return -ENOMEM;
195
196 gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM;
197
198 gen_parms->ref_clk = REF_CLK_38_4_E;
199 /* FIXME: magic numbers */
200 gen_parms->settling_time = 5;
201 gen_parms->clk_valid_on_wakeup = 0;
202 gen_parms->dc2dcmode = 0;
203 gen_parms->single_dual_band = 0;
204 gen_parms->tx_bip_fem_autodetect = 1;
205 gen_parms->tx_bip_fem_manufacturer = 1;
206 gen_parms->settings = 1;
207
208 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
209 if (ret < 0) {
210 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
211 return ret;
212 }
213
214 kfree(gen_parms);
215 return 0;
216}
217
218static int wl1271_init_radio_parms(struct wl1271 *wl)
219{
220 /*
221 * FIXME: All these magic numbers should be moved to some place where
222 * they can be configured (separate file?)
223 */
224
225 struct wl1271_radio_parms *radio_parms;
226 int ret;
227 u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00,
228 0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 };
229
230 u8 tx_rate_limits_normal[] = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 };
231 u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 };
232
233 u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50,
234 0x50, 0x50, 0x50, 0x50,
235 0x50, 0x50, 0x22, 0x50,
236 0x22, 0x50 };
237
238 u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50,
239 0x50, 0x50, 0x50, 0x50,
240 0x50, 0x50, 0x20, 0x50,
241 0x20, 0x50 };
242
243 u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
244
245 u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 };
246
247 radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
248 if (!radio_parms)
249 return -ENOMEM;
250
251 radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM;
252
253 /* Static radio parameters */
254 radio_parms->rx_trace_loss = 10;
255 radio_parms->tx_trace_loss = 10;
256 memcpy(radio_parms->rx_rssi_and_proc_compens, compensation,
257 sizeof(compensation));
258
259 /* We don't set the 5GHz -- N/A */
260
261 /* Dynamic radio parameters */
262 radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e);
263 radio_parms->tx_ref_power = 0x78;
264 radio_parms->tx_offset_db = 0x0;
265
266 memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal,
267 sizeof(tx_rate_limits_normal));
268 memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded,
269 sizeof(tx_rate_limits_degraded));
270
271 memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b,
272 sizeof(tx_channel_limits_11b));
273 memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm,
274 sizeof(tx_channel_limits_ofdm));
275 memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets,
276 sizeof(tx_pdv_rate_offsets));
277 memcpy(radio_parms->tx_ibias, tx_ibias,
278 sizeof(tx_ibias));
279
280 radio_parms->rx_fem_insertion_loss = 0x14;
281
282 ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
283 if (ret < 0)
284 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
285
286 kfree(radio_parms);
287 return ret;
288}
289
290int wl1271_hw_init(struct wl1271 *wl)
291{
292 int ret;
293
294 ret = wl1271_init_general_parms(wl);
295 if (ret < 0)
296 return ret;
297
298 ret = wl1271_init_radio_parms(wl);
299 if (ret < 0)
300 return ret;
301
302 /* Template settings */
303 ret = wl1271_init_templates_config(wl);
304 if (ret < 0)
305 return ret;
306
307 /* Default memory configuration */
308 ret = wl1271_acx_init_mem_config(wl);
309 if (ret < 0)
310 return ret;
311
312 /* RX config */
313 ret = wl1271_init_rx_config(wl,
314 RX_CFG_PROMISCUOUS | RX_CFG_TSF,
315 RX_FILTER_OPTION_DEF);
316 /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
317 RX_FILTER_OPTION_FILTER_ALL); */
318 if (ret < 0)
319 goto out_free_memmap;
320
321 /* PHY layer config */
322 ret = wl1271_init_phy_config(wl);
323 if (ret < 0)
324 goto out_free_memmap;
325
326 /* Beacon filtering */
327 ret = wl1271_init_beacon_filter(wl);
328 if (ret < 0)
329 goto out_free_memmap;
330
331 /* Configure TX patch complete interrupt behavior */
332 ret = wl1271_acx_tx_config_options(wl);
333 if (ret < 0)
334 goto out_free_memmap;
335
336 /* RX complete interrupt pacing */
337 ret = wl1271_acx_init_rx_interrupt(wl);
338 if (ret < 0)
339 goto out_free_memmap;
340
341 /* Bluetooth WLAN coexistence */
342 ret = wl1271_init_pta(wl);
343 if (ret < 0)
344 goto out_free_memmap;
345
346 /* Energy detection */
347 ret = wl1271_init_energy_detection(wl);
348 if (ret < 0)
349 goto out_free_memmap;
350
351 /* Beacons and boradcast settings */
352 ret = wl1271_init_beacon_broadcast(wl);
353 if (ret < 0)
354 goto out_free_memmap;
355
356 /* Default fragmentation threshold */
357 ret = wl1271_acx_frag_threshold(wl);
358 if (ret < 0)
359 goto out_free_memmap;
360
361 /* Default TID configuration */
362 ret = wl1271_acx_tid_cfg(wl);
363 if (ret < 0)
364 goto out_free_memmap;
365
366 /* Default AC configuration */
367 ret = wl1271_acx_ac_cfg(wl);
368 if (ret < 0)
369 goto out_free_memmap;
370
371 /* Configure TX rate classes */
372 ret = wl1271_acx_rate_policies(wl);
373 if (ret < 0)
374 goto out_free_memmap;
375
376 /* Enable data path */
377 ret = wl1271_cmd_data_path(wl, wl->channel, 1);
378 if (ret < 0)
379 goto out_free_memmap;
380
381 /* Configure for ELP power saving */
382 ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
383 if (ret < 0)
384 goto out_free_memmap;
385
386 /* Configure HW encryption */
387 ret = wl1271_init_hwenc_config(wl);
388 if (ret < 0)
389 goto out_free_memmap;
390
391 return 0;
392
393 out_free_memmap:
394 kfree(wl->target_mem_map);
395
396 return ret;
397}
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h
new file mode 100644
index 000000000000..bd8ff0fa2272
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -0,0 +1,115 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __WL1271_INIT_H__
25#define __WL1271_INIT_H__
26
27#include "wl1271.h"
28
29int wl1271_hw_init_power_auth(struct wl1271 *wl);
30int wl1271_hw_init(struct wl1271 *wl);
31
32/* These are not really a TEST_CMD, but the ref driver uses them as such */
33#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
34#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
35
36struct wl1271_general_parms {
37 u8 id;
38 u8 padding[3];
39
40 u8 ref_clk;
41 u8 settling_time;
42 u8 clk_valid_on_wakeup;
43 u8 dc2dcmode;
44 u8 single_dual_band;
45
46 u8 tx_bip_fem_autodetect;
47 u8 tx_bip_fem_manufacturer;
48 u8 settings;
49} __attribute__ ((packed));
50
51enum ref_clk_enum {
52 REF_CLK_19_2_E,
53 REF_CLK_26_E,
54 REF_CLK_38_4_E,
55 REF_CLK_52_E
56};
57
58#define RSSI_AND_PROCESS_COMPENSATION_SIZE 15
59#define NUMBER_OF_SUB_BANDS_5 7
60#define NUMBER_OF_RATE_GROUPS 6
61#define NUMBER_OF_CHANNELS_2_4 14
62#define NUMBER_OF_CHANNELS_5 35
63
64struct wl1271_radio_parms {
65 u8 id;
66 u8 padding[3];
67
68 /* Static radio parameters */
69 /* 2.4GHz */
70 u8 rx_trace_loss;
71 u8 tx_trace_loss;
72 s8 rx_rssi_and_proc_compens[RSSI_AND_PROCESS_COMPENSATION_SIZE];
73
74 /* 5GHz */
75 u8 rx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
76 u8 tx_trace_loss_5[NUMBER_OF_SUB_BANDS_5];
77 s8 rx_rssi_and_proc_compens_5[RSSI_AND_PROCESS_COMPENSATION_SIZE];
78
79 /* Dynamic radio parameters */
80 /* 2.4GHz */
81 s16 tx_ref_pd_voltage;
82 s8 tx_ref_power;
83 s8 tx_offset_db;
84
85 s8 tx_rate_limits_normal[NUMBER_OF_RATE_GROUPS];
86 s8 tx_rate_limits_degraded[NUMBER_OF_RATE_GROUPS];
87
88 s8 tx_channel_limits_11b[NUMBER_OF_CHANNELS_2_4];
89 s8 tx_channel_limits_ofdm[NUMBER_OF_CHANNELS_2_4];
90 s8 tx_pdv_rate_offsets[NUMBER_OF_RATE_GROUPS];
91
92 u8 tx_ibias[NUMBER_OF_RATE_GROUPS];
93 u8 rx_fem_insertion_loss;
94
95 u8 padding2;
96
97 /* 5GHz */
98 s16 tx_ref_pd_voltage_5[NUMBER_OF_SUB_BANDS_5];
99 s8 tx_ref_power_5[NUMBER_OF_SUB_BANDS_5];
100 s8 tx_offset_db_5[NUMBER_OF_SUB_BANDS_5];
101
102 s8 tx_rate_limits_normal_5[NUMBER_OF_RATE_GROUPS];
103 s8 tx_rate_limits_degraded_5[NUMBER_OF_RATE_GROUPS];
104
105 s8 tx_channel_limits_ofdm_5[NUMBER_OF_CHANNELS_5];
106 s8 tx_pdv_rate_offsets_5[NUMBER_OF_RATE_GROUPS];
107
108 /* FIXME: this is inconsistent with the types for 2.4GHz */
109 s8 tx_ibias_5[NUMBER_OF_RATE_GROUPS];
110 s8 rx_fem_insertion_loss_5[NUMBER_OF_SUB_BANDS_5];
111
112 u8 padding3[2];
113} __attribute__ ((packed));
114
115#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
new file mode 100644
index 000000000000..4102d590b798
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -0,0 +1,1397 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/interrupt.h>
27#include <linux/firmware.h>
28#include <linux/delay.h>
29#include <linux/irq.h>
30#include <linux/spi/spi.h>
31#include <linux/crc32.h>
32#include <linux/etherdevice.h>
33#include <linux/spi/wl12xx.h>
34
35#include "wl1271.h"
36#include "wl12xx_80211.h"
37#include "wl1271_reg.h"
38#include "wl1271_spi.h"
39#include "wl1271_event.h"
40#include "wl1271_tx.h"
41#include "wl1271_rx.h"
42#include "wl1271_ps.h"
43#include "wl1271_init.h"
44#include "wl1271_debugfs.h"
45#include "wl1271_cmd.h"
46#include "wl1271_boot.h"
47
48static int wl1271_plt_init(struct wl1271 *wl)
49{
50 int ret;
51
52 ret = wl1271_acx_init_mem_config(wl);
53 if (ret < 0)
54 return ret;
55
56 ret = wl1271_cmd_data_path(wl, wl->channel, 1);
57 if (ret < 0)
58 return ret;
59
60 return 0;
61}
62
63static void wl1271_disable_interrupts(struct wl1271 *wl)
64{
65 disable_irq(wl->irq);
66}
67
68static void wl1271_power_off(struct wl1271 *wl)
69{
70 wl->set_power(false);
71}
72
73static void wl1271_power_on(struct wl1271 *wl)
74{
75 wl->set_power(true);
76}
77
78static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status)
79{
80 u32 total = 0;
81 int i;
82
83 /*
84 * FIXME: Reading the FW status directly from the registers seems to
85 * be the right thing to do, but it doesn't work. And in the
86 * reference driver, there is a workaround called
87 * USE_SDIO_24M_WORKAROUND, which reads the status from memory
88 * instead, so we do the same here.
89 */
90
91 wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status));
92
93 wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
94 "drv_rx_counter = %d, tx_results_counter = %d)",
95 status->intr,
96 status->fw_rx_counter,
97 status->drv_rx_counter,
98 status->tx_results_counter);
99
100 /* update number of available TX blocks */
101 for (i = 0; i < NUM_TX_QUEUES; i++) {
102 u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i];
103 wl->tx_blocks_freed[i] = status->tx_released_blks[i];
104 wl->tx_blocks_available += cnt;
105 total += cnt;
106 }
107
108 /* if more blocks are available now, schedule some tx work */
109 if (total && !skb_queue_empty(&wl->tx_queue))
110 schedule_work(&wl->tx_work);
111
112 /* update the host-chipset time offset */
113 wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime;
114}
115
116#define WL1271_IRQ_MAX_LOOPS 10
117static void wl1271_irq_work(struct work_struct *work)
118{
119 u32 intr, ctr = WL1271_IRQ_MAX_LOOPS;
120 int ret;
121 struct wl1271 *wl =
122 container_of(work, struct wl1271, irq_work);
123
124 mutex_lock(&wl->mutex);
125
126 wl1271_debug(DEBUG_IRQ, "IRQ work");
127
128 if (wl->state == WL1271_STATE_OFF)
129 goto out;
130
131 ret = wl1271_ps_elp_wakeup(wl, true);
132 if (ret < 0)
133 goto out;
134
135 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL);
136
137 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
138 if (!intr) {
139 wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
140 goto out_sleep;
141 }
142
143 intr &= WL1271_INTR_MASK;
144
145 do {
146 wl1271_fw_status(wl, wl->fw_status);
147
148
149 if (intr & (WL1271_ACX_INTR_EVENT_A |
150 WL1271_ACX_INTR_EVENT_B)) {
151 wl1271_debug(DEBUG_IRQ,
152 "WL1271_ACX_INTR_EVENT (0x%x)", intr);
153 if (intr & WL1271_ACX_INTR_EVENT_A)
154 wl1271_event_handle(wl, 0);
155 else
156 wl1271_event_handle(wl, 1);
157 }
158
159 if (intr & WL1271_ACX_INTR_INIT_COMPLETE)
160 wl1271_debug(DEBUG_IRQ,
161 "WL1271_ACX_INTR_INIT_COMPLETE");
162
163 if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
164 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
165
166 if (intr & WL1271_ACX_INTR_DATA) {
167 u8 tx_res_cnt = wl->fw_status->tx_results_counter -
168 wl->tx_results_count;
169
170 wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
171
172 /* check for tx results */
173 if (tx_res_cnt)
174 wl1271_tx_complete(wl, tx_res_cnt);
175
176 wl1271_rx(wl, wl->fw_status);
177 }
178
179 intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR);
180 intr &= WL1271_INTR_MASK;
181 } while (intr && --ctr);
182
183out_sleep:
184 wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK,
185 WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK));
186 wl1271_ps_elp_sleep(wl);
187
188out:
189 mutex_unlock(&wl->mutex);
190}
191
192static irqreturn_t wl1271_irq(int irq, void *cookie)
193{
194 struct wl1271 *wl;
195 unsigned long flags;
196
197 wl1271_debug(DEBUG_IRQ, "IRQ");
198
199 wl = cookie;
200
201 /* complete the ELP completion */
202 spin_lock_irqsave(&wl->wl_lock, flags);
203 if (wl->elp_compl) {
204 complete(wl->elp_compl);
205 wl->elp_compl = NULL;
206 }
207
208 schedule_work(&wl->irq_work);
209 spin_unlock_irqrestore(&wl->wl_lock, flags);
210
211 return IRQ_HANDLED;
212}
213
214static int wl1271_fetch_firmware(struct wl1271 *wl)
215{
216 const struct firmware *fw;
217 int ret;
218
219 ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev);
220
221 if (ret < 0) {
222 wl1271_error("could not get firmware: %d", ret);
223 return ret;
224 }
225
226 if (fw->size % 4) {
227 wl1271_error("firmware size is not multiple of 32 bits: %zu",
228 fw->size);
229 ret = -EILSEQ;
230 goto out;
231 }
232
233 wl->fw_len = fw->size;
234 wl->fw = kmalloc(wl->fw_len, GFP_KERNEL);
235
236 if (!wl->fw) {
237 wl1271_error("could not allocate memory for the firmware");
238 ret = -ENOMEM;
239 goto out;
240 }
241
242 memcpy(wl->fw, fw->data, wl->fw_len);
243
244 ret = 0;
245
246out:
247 release_firmware(fw);
248
249 return ret;
250}
251
252static int wl1271_fetch_nvs(struct wl1271 *wl)
253{
254 const struct firmware *fw;
255 int ret;
256
257 ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev);
258
259 if (ret < 0) {
260 wl1271_error("could not get nvs file: %d", ret);
261 return ret;
262 }
263
264 if (fw->size % 4) {
265 wl1271_error("nvs size is not multiple of 32 bits: %zu",
266 fw->size);
267 ret = -EILSEQ;
268 goto out;
269 }
270
271 wl->nvs_len = fw->size;
272 wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL);
273
274 if (!wl->nvs) {
275 wl1271_error("could not allocate memory for the nvs file");
276 ret = -ENOMEM;
277 goto out;
278 }
279
280 memcpy(wl->nvs, fw->data, wl->nvs_len);
281
282 ret = 0;
283
284out:
285 release_firmware(fw);
286
287 return ret;
288}
289
290static void wl1271_fw_wakeup(struct wl1271 *wl)
291{
292 u32 elp_reg;
293
294 elp_reg = ELPCTRL_WAKE_UP;
295 wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg);
296}
297
298static int wl1271_setup(struct wl1271 *wl)
299{
300 wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL);
301 if (!wl->fw_status)
302 return -ENOMEM;
303
304 wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL);
305 if (!wl->tx_res_if) {
306 kfree(wl->fw_status);
307 return -ENOMEM;
308 }
309
310 INIT_WORK(&wl->irq_work, wl1271_irq_work);
311 INIT_WORK(&wl->tx_work, wl1271_tx_work);
312 return 0;
313}
314
315static int wl1271_chip_wakeup(struct wl1271 *wl)
316{
317 int ret = 0;
318
319 wl1271_power_on(wl);
320 msleep(WL1271_POWER_ON_SLEEP);
321 wl1271_spi_reset(wl);
322 wl1271_spi_init(wl);
323
324 /* We don't need a real memory partition here, because we only want
325 * to use the registers at this point. */
326 wl1271_set_partition(wl,
327 0x00000000,
328 0x00000000,
329 REGISTERS_BASE,
330 REGISTERS_DOWN_SIZE);
331
332 /* ELP module wake up */
333 wl1271_fw_wakeup(wl);
334
335 /* whal_FwCtrl_BootSm() */
336
337 /* 0. read chip id from CHIP_ID */
338 wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B);
339
340 /* 1. check if chip id is valid */
341
342 switch (wl->chip.id) {
343 case CHIP_ID_1271_PG10:
344 wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete",
345 wl->chip.id);
346
347 ret = wl1271_setup(wl);
348 if (ret < 0)
349 goto out;
350 break;
351 case CHIP_ID_1271_PG20:
352 wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)",
353 wl->chip.id);
354
355 ret = wl1271_setup(wl);
356 if (ret < 0)
357 goto out;
358 break;
359 default:
360 wl1271_error("unsupported chip id: 0x%x", wl->chip.id);
361 ret = -ENODEV;
362 goto out;
363 }
364
365 if (wl->fw == NULL) {
366 ret = wl1271_fetch_firmware(wl);
367 if (ret < 0)
368 goto out;
369 }
370
371 /* No NVS from netlink, try to get it from the filesystem */
372 if (wl->nvs == NULL) {
373 ret = wl1271_fetch_nvs(wl);
374 if (ret < 0)
375 goto out;
376 }
377
378out:
379 return ret;
380}
381
382static void wl1271_filter_work(struct work_struct *work)
383{
384 struct wl1271 *wl =
385 container_of(work, struct wl1271, filter_work);
386 int ret;
387
388 mutex_lock(&wl->mutex);
389
390 if (wl->state == WL1271_STATE_OFF)
391 goto out;
392
393 ret = wl1271_ps_elp_wakeup(wl, false);
394 if (ret < 0)
395 goto out;
396
397 /* FIXME: replace the magic numbers with proper definitions */
398 ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
399 if (ret < 0)
400 goto out_sleep;
401
402out_sleep:
403 wl1271_ps_elp_sleep(wl);
404
405out:
406 mutex_unlock(&wl->mutex);
407}
408
409int wl1271_plt_start(struct wl1271 *wl)
410{
411 int ret;
412
413 mutex_lock(&wl->mutex);
414
415 wl1271_notice("power up");
416
417 if (wl->state != WL1271_STATE_OFF) {
418 wl1271_error("cannot go into PLT state because not "
419 "in off state: %d", wl->state);
420 ret = -EBUSY;
421 goto out;
422 }
423
424 wl->state = WL1271_STATE_PLT;
425
426 ret = wl1271_chip_wakeup(wl);
427 if (ret < 0)
428 goto out;
429
430 ret = wl1271_boot(wl);
431 if (ret < 0)
432 goto out;
433
434 wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver);
435
436 ret = wl1271_plt_init(wl);
437 if (ret < 0)
438 goto out;
439
440out:
441 mutex_unlock(&wl->mutex);
442
443 return ret;
444}
445
446int wl1271_plt_stop(struct wl1271 *wl)
447{
448 int ret = 0;
449
450 mutex_lock(&wl->mutex);
451
452 wl1271_notice("power down");
453
454 if (wl->state != WL1271_STATE_PLT) {
455 wl1271_error("cannot power down because not in PLT "
456 "state: %d", wl->state);
457 ret = -EBUSY;
458 goto out;
459 }
460
461 wl1271_disable_interrupts(wl);
462 wl1271_power_off(wl);
463
464 wl->state = WL1271_STATE_OFF;
465
466out:
467 mutex_unlock(&wl->mutex);
468
469 return ret;
470}
471
472
473static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
474{
475 struct wl1271 *wl = hw->priv;
476
477 skb_queue_tail(&wl->tx_queue, skb);
478
479 /*
480 * The chip specific setup must run before the first TX packet -
481 * before that, the tx_work will not be initialized!
482 */
483
484 schedule_work(&wl->tx_work);
485
486 /*
487 * The workqueue is slow to process the tx_queue and we need stop
488 * the queue here, otherwise the queue will get too long.
489 */
490 if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) {
491 ieee80211_stop_queues(wl->hw);
492
493 /*
494 * FIXME: this is racy, the variable is not properly
495 * protected. Maybe fix this by removing the stupid
496 * variable altogether and checking the real queue state?
497 */
498 wl->tx_queue_stopped = true;
499 }
500
501 return NETDEV_TX_OK;
502}
503
504static int wl1271_op_start(struct ieee80211_hw *hw)
505{
506 struct wl1271 *wl = hw->priv;
507 int ret = 0;
508
509 wl1271_debug(DEBUG_MAC80211, "mac80211 start");
510
511 mutex_lock(&wl->mutex);
512
513 if (wl->state != WL1271_STATE_OFF) {
514 wl1271_error("cannot start because not in off state: %d",
515 wl->state);
516 ret = -EBUSY;
517 goto out;
518 }
519
520 ret = wl1271_chip_wakeup(wl);
521 if (ret < 0)
522 goto out;
523
524 ret = wl1271_boot(wl);
525 if (ret < 0)
526 goto out;
527
528 ret = wl1271_hw_init(wl);
529 if (ret < 0)
530 goto out;
531
532 wl->state = WL1271_STATE_ON;
533
534 wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
535
536out:
537 if (ret < 0)
538 wl1271_power_off(wl);
539
540 mutex_unlock(&wl->mutex);
541
542 return ret;
543}
544
545static void wl1271_op_stop(struct ieee80211_hw *hw)
546{
547 struct wl1271 *wl = hw->priv;
548 int i;
549
550 wl1271_info("down");
551
552 wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
553
554 mutex_lock(&wl->mutex);
555
556 WARN_ON(wl->state != WL1271_STATE_ON);
557
558 if (wl->scanning) {
559 mutex_unlock(&wl->mutex);
560 ieee80211_scan_completed(wl->hw, true);
561 mutex_lock(&wl->mutex);
562 wl->scanning = false;
563 }
564
565 wl->state = WL1271_STATE_OFF;
566
567 wl1271_disable_interrupts(wl);
568
569 mutex_unlock(&wl->mutex);
570
571 cancel_work_sync(&wl->irq_work);
572 cancel_work_sync(&wl->tx_work);
573 cancel_work_sync(&wl->filter_work);
574
575 mutex_lock(&wl->mutex);
576
577 /* let's notify MAC80211 about the remaining pending TX frames */
578 wl1271_tx_flush(wl);
579 wl1271_power_off(wl);
580
581 memset(wl->bssid, 0, ETH_ALEN);
582 memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1);
583 wl->ssid_len = 0;
584 wl->listen_int = 1;
585 wl->bss_type = MAX_BSS_TYPE;
586
587 wl->rx_counter = 0;
588 wl->elp = false;
589 wl->psm = 0;
590 wl->tx_queue_stopped = false;
591 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
592 wl->tx_blocks_available = 0;
593 wl->tx_results_count = 0;
594 wl->tx_packets_count = 0;
595 wl->time_offset = 0;
596 wl->session_counter = 0;
597 for (i = 0; i < NUM_TX_QUEUES; i++)
598 wl->tx_blocks_freed[i] = 0;
599
600 wl1271_debugfs_reset(wl);
601 mutex_unlock(&wl->mutex);
602}
603
604static int wl1271_op_add_interface(struct ieee80211_hw *hw,
605 struct ieee80211_if_init_conf *conf)
606{
607 struct wl1271 *wl = hw->priv;
608 DECLARE_MAC_BUF(mac);
609 int ret = 0;
610
611 wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s",
612 conf->type, print_mac(mac, conf->mac_addr));
613
614 mutex_lock(&wl->mutex);
615
616 switch (conf->type) {
617 case NL80211_IFTYPE_STATION:
618 wl->bss_type = BSS_TYPE_STA_BSS;
619 break;
620 case NL80211_IFTYPE_ADHOC:
621 wl->bss_type = BSS_TYPE_IBSS;
622 break;
623 default:
624 ret = -EOPNOTSUPP;
625 goto out;
626 }
627
628 /* FIXME: what if conf->mac_addr changes? */
629
630out:
631 mutex_unlock(&wl->mutex);
632 return ret;
633}
634
635static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
636 struct ieee80211_if_init_conf *conf)
637{
638 wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
639}
640
641#if 0
642static int wl1271_op_config_interface(struct ieee80211_hw *hw,
643 struct ieee80211_vif *vif,
644 struct ieee80211_if_conf *conf)
645{
646 struct wl1271 *wl = hw->priv;
647 struct sk_buff *beacon;
648 DECLARE_MAC_BUF(mac);
649 int ret;
650
651 wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %s",
652 print_mac(mac, conf->bssid));
653 wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
654 conf->ssid_len);
655
656 mutex_lock(&wl->mutex);
657
658 ret = wl1271_ps_elp_wakeup(wl, false);
659 if (ret < 0)
660 goto out;
661
662 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
663
664 ret = wl1271_cmd_build_null_data(wl);
665 if (ret < 0)
666 goto out_sleep;
667
668 wl->ssid_len = conf->ssid_len;
669 if (wl->ssid_len)
670 memcpy(wl->ssid, conf->ssid, wl->ssid_len);
671
672 if (wl->bss_type != BSS_TYPE_IBSS) {
673 /* FIXME: replace the magic numbers with proper definitions */
674 ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1);
675 if (ret < 0)
676 goto out_sleep;
677 }
678
679 if (conf->changed & IEEE80211_IFCC_BEACON) {
680 beacon = ieee80211_beacon_get(hw, vif);
681 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
682 beacon->data, beacon->len);
683
684 if (ret < 0) {
685 dev_kfree_skb(beacon);
686 goto out_sleep;
687 }
688
689 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
690 beacon->data, beacon->len);
691
692 dev_kfree_skb(beacon);
693
694 if (ret < 0)
695 goto out_sleep;
696
697 /* FIXME: replace the magic numbers with proper definitions */
698 ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
699
700 if (ret < 0)
701 goto out_sleep;
702 }
703
704out_sleep:
705 wl1271_ps_elp_sleep(wl);
706
707out:
708 mutex_unlock(&wl->mutex);
709
710 return ret;
711}
712#endif
713
714static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
715{
716 struct wl1271 *wl = hw->priv;
717 struct ieee80211_conf *conf = &hw->conf;
718 int channel, ret = 0;
719
720 channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
721
722 wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d",
723 channel,
724 conf->flags & IEEE80211_CONF_PS ? "on" : "off",
725 conf->power_level);
726
727 mutex_lock(&wl->mutex);
728
729 ret = wl1271_ps_elp_wakeup(wl, false);
730 if (ret < 0)
731 goto out;
732
733 if (channel != wl->channel) {
734 u8 old_channel = wl->channel;
735 wl->channel = channel;
736
737 /* FIXME: use beacon interval provided by mac80211 */
738 ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0);
739 if (ret < 0) {
740 wl->channel = old_channel;
741 goto out_sleep;
742 }
743 }
744
745 ret = wl1271_cmd_build_null_data(wl);
746 if (ret < 0)
747 goto out_sleep;
748
749 if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) {
750 wl1271_info("psm enabled");
751
752 wl->psm_requested = true;
753
754 /*
755 * We enter PSM only if we're already associated.
756 * If we're not, we'll enter it when joining an SSID,
757 * through the bss_info_changed() hook.
758 */
759 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
760 } else if (!(conf->flags & IEEE80211_CONF_PS) &&
761 wl->psm_requested) {
762 wl1271_info("psm disabled");
763
764 wl->psm_requested = false;
765
766 if (wl->psm)
767 ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE);
768 }
769
770 if (conf->power_level != wl->power_level) {
771 ret = wl1271_acx_tx_power(wl, conf->power_level);
772 if (ret < 0)
773 goto out;
774
775 wl->power_level = conf->power_level;
776 }
777
778out_sleep:
779 wl1271_ps_elp_sleep(wl);
780
781out:
782 mutex_unlock(&wl->mutex);
783
784 return ret;
785}
786
787#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \
788 FIF_ALLMULTI | \
789 FIF_FCSFAIL | \
790 FIF_BCN_PRBRESP_PROMISC | \
791 FIF_CONTROL | \
792 FIF_OTHER_BSS)
793
794static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
795 unsigned int changed,
796 unsigned int *total,
797 int mc_count,
798 struct dev_addr_list *mc_list)
799{
800 struct wl1271 *wl = hw->priv;
801
802 wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
803
804 *total &= WL1271_SUPPORTED_FILTERS;
805 changed &= WL1271_SUPPORTED_FILTERS;
806
807 if (changed == 0)
808 return;
809
810 /* FIXME: wl->rx_config and wl->rx_filter are not protected */
811 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
812 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
813
814 /*
815 * FIXME: workqueues need to be properly cancelled on stop(), for
816 * now let's just disable changing the filter settings. They will
817 * be updated any on config().
818 */
819 /* schedule_work(&wl->filter_work); */
820}
821
822static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
823 struct ieee80211_vif *vif,
824 struct ieee80211_sta *sta,
825 struct ieee80211_key_conf *key_conf)
826{
827 struct wl1271 *wl = hw->priv;
828 const u8 *addr;
829 int ret;
830 u8 key_type;
831
832 static const u8 bcast_addr[ETH_ALEN] =
833 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
834
835 wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
836
837 addr = sta ? sta->addr : bcast_addr;
838
839 wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
840 wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
841 wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
842 key_conf->alg, key_conf->keyidx,
843 key_conf->keylen, key_conf->flags);
844 wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
845
846 if (is_zero_ether_addr(addr)) {
847 /* We dont support TX only encryption */
848 ret = -EOPNOTSUPP;
849 goto out;
850 }
851
852 mutex_lock(&wl->mutex);
853
854 ret = wl1271_ps_elp_wakeup(wl, false);
855 if (ret < 0)
856 goto out_unlock;
857
858 switch (key_conf->alg) {
859 case ALG_WEP:
860 key_type = KEY_WEP;
861
862 key_conf->hw_key_idx = key_conf->keyidx;
863 break;
864 case ALG_TKIP:
865 key_type = KEY_TKIP;
866
867 key_conf->hw_key_idx = key_conf->keyidx;
868 break;
869 case ALG_CCMP:
870 key_type = KEY_AES;
871
872 key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
873 break;
874 default:
875 wl1271_error("Unknown key algo 0x%x", key_conf->alg);
876
877 ret = -EOPNOTSUPP;
878 goto out_sleep;
879 }
880
881 switch (cmd) {
882 case SET_KEY:
883 ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
884 key_conf->keyidx, key_type,
885 key_conf->keylen, key_conf->key,
886 addr);
887 if (ret < 0) {
888 wl1271_error("Could not add or replace key");
889 goto out_sleep;
890 }
891 break;
892
893 case DISABLE_KEY:
894 ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
895 key_conf->keyidx, key_type,
896 key_conf->keylen, key_conf->key,
897 addr);
898 if (ret < 0) {
899 wl1271_error("Could not remove key");
900 goto out_sleep;
901 }
902 break;
903
904 default:
905 wl1271_error("Unsupported key cmd 0x%x", cmd);
906 ret = -EOPNOTSUPP;
907 goto out_sleep;
908
909 break;
910 }
911
912out_sleep:
913 wl1271_ps_elp_sleep(wl);
914
915out_unlock:
916 mutex_unlock(&wl->mutex);
917
918out:
919 return ret;
920}
921
922static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
923 struct cfg80211_scan_request *req)
924{
925 struct wl1271 *wl = hw->priv;
926 int ret;
927 u8 *ssid = NULL;
928 size_t ssid_len = 0;
929
930 wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan");
931
932 if (req->n_ssids) {
933 ssid = req->ssids[0].ssid;
934 ssid_len = req->ssids[0].ssid_len;
935 }
936
937 mutex_lock(&wl->mutex);
938
939 ret = wl1271_ps_elp_wakeup(wl, false);
940 if (ret < 0)
941 goto out;
942
943 ret = wl1271_cmd_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3);
944
945 wl1271_ps_elp_sleep(wl);
946
947out:
948 mutex_unlock(&wl->mutex);
949
950 return ret;
951}
952
953static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
954{
955 struct wl1271 *wl = hw->priv;
956 int ret;
957
958 mutex_lock(&wl->mutex);
959
960 ret = wl1271_ps_elp_wakeup(wl, false);
961 if (ret < 0)
962 goto out;
963
964 ret = wl1271_acx_rts_threshold(wl, (u16) value);
965 if (ret < 0)
966 wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret);
967
968 wl1271_ps_elp_sleep(wl);
969
970out:
971 mutex_unlock(&wl->mutex);
972
973 return ret;
974}
975
976static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
977 struct ieee80211_vif *vif,
978 struct ieee80211_bss_conf *bss_conf,
979 u32 changed)
980{
981 enum wl1271_cmd_ps_mode mode;
982 struct wl1271 *wl = hw->priv;
983 int ret;
984
985 wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
986
987 mutex_lock(&wl->mutex);
988
989 ret = wl1271_ps_elp_wakeup(wl, false);
990 if (ret < 0)
991 goto out;
992
993 if (changed & BSS_CHANGED_ASSOC) {
994 if (bss_conf->assoc) {
995 wl->aid = bss_conf->aid;
996
997 ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
998 if (ret < 0)
999 goto out_sleep;
1000
1001 ret = wl1271_acx_aid(wl, wl->aid);
1002 if (ret < 0)
1003 goto out_sleep;
1004
1005 /* If we want to go in PSM but we're not there yet */
1006 if (wl->psm_requested && !wl->psm) {
1007 mode = STATION_POWER_SAVE_MODE;
1008 ret = wl1271_ps_set_mode(wl, mode);
1009 if (ret < 0)
1010 goto out_sleep;
1011 }
1012 }
1013 }
1014 if (changed & BSS_CHANGED_ERP_SLOT) {
1015 if (bss_conf->use_short_slot)
1016 ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
1017 else
1018 ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
1019 if (ret < 0) {
1020 wl1271_warning("Set slot time failed %d", ret);
1021 goto out_sleep;
1022 }
1023 }
1024
1025 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
1026 if (bss_conf->use_short_preamble)
1027 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
1028 else
1029 wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
1030 }
1031
1032 if (changed & BSS_CHANGED_ERP_CTS_PROT) {
1033 if (bss_conf->use_cts_prot)
1034 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
1035 else
1036 ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
1037 if (ret < 0) {
1038 wl1271_warning("Set ctsprotect failed %d", ret);
1039 goto out_sleep;
1040 }
1041 }
1042
1043out_sleep:
1044 wl1271_ps_elp_sleep(wl);
1045
1046out:
1047 mutex_unlock(&wl->mutex);
1048}
1049
1050
1051/* can't be const, mac80211 writes to this */
1052static struct ieee80211_rate wl1271_rates[] = {
1053 { .bitrate = 10,
1054 .hw_value = 0x1,
1055 .hw_value_short = 0x1, },
1056 { .bitrate = 20,
1057 .hw_value = 0x2,
1058 .hw_value_short = 0x2,
1059 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1060 { .bitrate = 55,
1061 .hw_value = 0x4,
1062 .hw_value_short = 0x4,
1063 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1064 { .bitrate = 110,
1065 .hw_value = 0x20,
1066 .hw_value_short = 0x20,
1067 .flags = IEEE80211_RATE_SHORT_PREAMBLE },
1068 { .bitrate = 60,
1069 .hw_value = 0x8,
1070 .hw_value_short = 0x8, },
1071 { .bitrate = 90,
1072 .hw_value = 0x10,
1073 .hw_value_short = 0x10, },
1074 { .bitrate = 120,
1075 .hw_value = 0x40,
1076 .hw_value_short = 0x40, },
1077 { .bitrate = 180,
1078 .hw_value = 0x80,
1079 .hw_value_short = 0x80, },
1080 { .bitrate = 240,
1081 .hw_value = 0x200,
1082 .hw_value_short = 0x200, },
1083 { .bitrate = 360,
1084 .hw_value = 0x400,
1085 .hw_value_short = 0x400, },
1086 { .bitrate = 480,
1087 .hw_value = 0x800,
1088 .hw_value_short = 0x800, },
1089 { .bitrate = 540,
1090 .hw_value = 0x1000,
1091 .hw_value_short = 0x1000, },
1092};
1093
1094/* can't be const, mac80211 writes to this */
1095static struct ieee80211_channel wl1271_channels[] = {
1096 { .hw_value = 1, .center_freq = 2412},
1097 { .hw_value = 2, .center_freq = 2417},
1098 { .hw_value = 3, .center_freq = 2422},
1099 { .hw_value = 4, .center_freq = 2427},
1100 { .hw_value = 5, .center_freq = 2432},
1101 { .hw_value = 6, .center_freq = 2437},
1102 { .hw_value = 7, .center_freq = 2442},
1103 { .hw_value = 8, .center_freq = 2447},
1104 { .hw_value = 9, .center_freq = 2452},
1105 { .hw_value = 10, .center_freq = 2457},
1106 { .hw_value = 11, .center_freq = 2462},
1107 { .hw_value = 12, .center_freq = 2467},
1108 { .hw_value = 13, .center_freq = 2472},
1109};
1110
1111/* can't be const, mac80211 writes to this */
1112static struct ieee80211_supported_band wl1271_band_2ghz = {
1113 .channels = wl1271_channels,
1114 .n_channels = ARRAY_SIZE(wl1271_channels),
1115 .bitrates = wl1271_rates,
1116 .n_bitrates = ARRAY_SIZE(wl1271_rates),
1117};
1118
1119static const struct ieee80211_ops wl1271_ops = {
1120 .start = wl1271_op_start,
1121 .stop = wl1271_op_stop,
1122 .add_interface = wl1271_op_add_interface,
1123 .remove_interface = wl1271_op_remove_interface,
1124 .config = wl1271_op_config,
1125/* .config_interface = wl1271_op_config_interface, */
1126 .configure_filter = wl1271_op_configure_filter,
1127 .tx = wl1271_op_tx,
1128 .set_key = wl1271_op_set_key,
1129 .hw_scan = wl1271_op_hw_scan,
1130 .bss_info_changed = wl1271_op_bss_info_changed,
1131 .set_rts_threshold = wl1271_op_set_rts_threshold,
1132};
1133
1134static int wl1271_register_hw(struct wl1271 *wl)
1135{
1136 int ret;
1137
1138 if (wl->mac80211_registered)
1139 return 0;
1140
1141 SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
1142
1143 ret = ieee80211_register_hw(wl->hw);
1144 if (ret < 0) {
1145 wl1271_error("unable to register mac80211 hw: %d", ret);
1146 return ret;
1147 }
1148
1149 wl->mac80211_registered = true;
1150
1151 wl1271_notice("loaded");
1152
1153 return 0;
1154}
1155
1156static int wl1271_init_ieee80211(struct wl1271 *wl)
1157{
1158 /*
1159 * The tx descriptor buffer and the TKIP space.
1160 *
1161 * FIXME: add correct 1271 descriptor size
1162 */
1163 wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE;
1164
1165 /* unit us */
1166 /* FIXME: find a proper value */
1167 wl->hw->channel_change_time = 10000;
1168
1169 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1170 IEEE80211_HW_NOISE_DBM;
1171
1172 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1173 wl->hw->wiphy->max_scan_ssids = 1;
1174 wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
1175
1176 SET_IEEE80211_DEV(wl->hw, &wl->spi->dev);
1177
1178 return 0;
1179}
1180
1181static void wl1271_device_release(struct device *dev)
1182{
1183
1184}
1185
1186static struct platform_device wl1271_device = {
1187 .name = "wl1271",
1188 .id = -1,
1189
1190 /* device model insists to have a release function */
1191 .dev = {
1192 .release = wl1271_device_release,
1193 },
1194};
1195
1196#define WL1271_DEFAULT_CHANNEL 0
1197static int __devinit wl1271_probe(struct spi_device *spi)
1198{
1199 struct wl12xx_platform_data *pdata;
1200 struct ieee80211_hw *hw;
1201 struct wl1271 *wl;
1202 int ret, i;
1203 static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
1204
1205 pdata = spi->dev.platform_data;
1206 if (!pdata) {
1207 wl1271_error("no platform data");
1208 return -ENODEV;
1209 }
1210
1211 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
1212 if (!hw) {
1213 wl1271_error("could not alloc ieee80211_hw");
1214 return -ENOMEM;
1215 }
1216
1217 wl = hw->priv;
1218 memset(wl, 0, sizeof(*wl));
1219
1220 wl->hw = hw;
1221 dev_set_drvdata(&spi->dev, wl);
1222 wl->spi = spi;
1223
1224 skb_queue_head_init(&wl->tx_queue);
1225
1226 INIT_WORK(&wl->filter_work, wl1271_filter_work);
1227 wl->channel = WL1271_DEFAULT_CHANNEL;
1228 wl->scanning = false;
1229 wl->default_key = 0;
1230 wl->listen_int = 1;
1231 wl->rx_counter = 0;
1232 wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
1233 wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
1234 wl->elp = false;
1235 wl->psm = 0;
1236 wl->psm_requested = false;
1237 wl->tx_queue_stopped = false;
1238 wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
1239
1240 /* We use the default power on sleep time until we know which chip
1241 * we're using */
1242 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
1243 wl->tx_frames[i] = NULL;
1244
1245 spin_lock_init(&wl->wl_lock);
1246
1247 /*
1248 * In case our MAC address is not correctly set,
1249 * we use a random but Nokia MAC.
1250 */
1251 memcpy(wl->mac_addr, nokia_oui, 3);
1252 get_random_bytes(wl->mac_addr + 3, 3);
1253
1254 wl->state = WL1271_STATE_OFF;
1255 mutex_init(&wl->mutex);
1256
1257 wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL);
1258 if (!wl->rx_descriptor) {
1259 wl1271_error("could not allocate memory for rx descriptor");
1260 ret = -ENOMEM;
1261 goto out_free;
1262 }
1263
1264 /* This is the only SPI value that we need to set here, the rest
1265 * comes from the board-peripherals file */
1266 spi->bits_per_word = 32;
1267
1268 ret = spi_setup(spi);
1269 if (ret < 0) {
1270 wl1271_error("spi_setup failed");
1271 goto out_free;
1272 }
1273
1274 wl->set_power = pdata->set_power;
1275 if (!wl->set_power) {
1276 wl1271_error("set power function missing in platform data");
1277 ret = -ENODEV;
1278 goto out_free;
1279 }
1280
1281 wl->irq = spi->irq;
1282 if (wl->irq < 0) {
1283 wl1271_error("irq missing in platform data");
1284 ret = -ENODEV;
1285 goto out_free;
1286 }
1287
1288 ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
1289 if (ret < 0) {
1290 wl1271_error("request_irq() failed: %d", ret);
1291 goto out_free;
1292 }
1293
1294 set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
1295
1296 disable_irq(wl->irq);
1297
1298 ret = platform_device_register(&wl1271_device);
1299 if (ret) {
1300 wl1271_error("couldn't register platform device");
1301 goto out_irq;
1302 }
1303 dev_set_drvdata(&wl1271_device.dev, wl);
1304
1305 ret = wl1271_init_ieee80211(wl);
1306 if (ret)
1307 goto out_platform;
1308
1309 ret = wl1271_register_hw(wl);
1310 if (ret)
1311 goto out_platform;
1312
1313 wl1271_debugfs_init(wl);
1314
1315 wl1271_notice("initialized");
1316
1317 return 0;
1318
1319 out_platform:
1320 platform_device_unregister(&wl1271_device);
1321
1322 out_irq:
1323 free_irq(wl->irq, wl);
1324
1325 out_free:
1326 kfree(wl->rx_descriptor);
1327 wl->rx_descriptor = NULL;
1328
1329 ieee80211_free_hw(hw);
1330
1331 return ret;
1332}
1333
1334static int __devexit wl1271_remove(struct spi_device *spi)
1335{
1336 struct wl1271 *wl = dev_get_drvdata(&spi->dev);
1337
1338 ieee80211_unregister_hw(wl->hw);
1339
1340 wl1271_debugfs_exit(wl);
1341 platform_device_unregister(&wl1271_device);
1342 free_irq(wl->irq, wl);
1343 kfree(wl->target_mem_map);
1344 kfree(wl->fw);
1345 wl->fw = NULL;
1346 kfree(wl->nvs);
1347 wl->nvs = NULL;
1348
1349 kfree(wl->rx_descriptor);
1350 wl->rx_descriptor = NULL;
1351
1352 kfree(wl->fw_status);
1353 kfree(wl->tx_res_if);
1354
1355 ieee80211_free_hw(wl->hw);
1356
1357 return 0;
1358}
1359
1360
1361static struct spi_driver wl1271_spi_driver = {
1362 .driver = {
1363 .name = "wl1271",
1364 .bus = &spi_bus_type,
1365 .owner = THIS_MODULE,
1366 },
1367
1368 .probe = wl1271_probe,
1369 .remove = __devexit_p(wl1271_remove),
1370};
1371
1372static int __init wl1271_init(void)
1373{
1374 int ret;
1375
1376 ret = spi_register_driver(&wl1271_spi_driver);
1377 if (ret < 0) {
1378 wl1271_error("failed to register spi driver: %d", ret);
1379 goto out;
1380 }
1381
1382out:
1383 return ret;
1384}
1385
1386static void __exit wl1271_exit(void)
1387{
1388 spi_unregister_driver(&wl1271_spi_driver);
1389
1390 wl1271_notice("unloaded");
1391}
1392
1393module_init(wl1271_init);
1394module_exit(wl1271_exit);
1395
1396MODULE_LICENSE("GPL");
1397MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
new file mode 100644
index 000000000000..1dc74b0c7736
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -0,0 +1,142 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1271_reg.h"
25#include "wl1271_ps.h"
26#include "wl1271_spi.h"
27
28#define WL1271_WAKEUP_TIMEOUT 500
29
30/* Routines to toggle sleep mode while in ELP */
31void wl1271_ps_elp_sleep(struct wl1271 *wl)
32{
33 /*
34 * FIXME: due to a problem in the firmware (causing a firmware
35 * crash), ELP entry is prevented below. Remove the "true" to
36 * re-enable ELP entry.
37 */
38 if (true || wl->elp || !wl->psm)
39 return;
40
41 /*
42 * Go to ELP unless there is work already pending - pending work
43 * will immediately wakeup the chipset anyway.
44 */
45 if (!work_pending(&wl->irq_work) && !work_pending(&wl->tx_work)) {
46 wl1271_debug(DEBUG_PSM, "chip to elp");
47 wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP);
48 wl->elp = true;
49 }
50}
51
52int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
53{
54 DECLARE_COMPLETION_ONSTACK(compl);
55 unsigned long flags;
56 int ret;
57 u32 start_time = jiffies;
58 bool pending = false;
59
60 if (!wl->elp)
61 return 0;
62
63 wl1271_debug(DEBUG_PSM, "waking up chip from elp");
64
65 /*
66 * The spinlock is required here to synchronize both the work and
67 * the completion variable in one entity.
68 */
69 spin_lock_irqsave(&wl->wl_lock, flags);
70 if (work_pending(&wl->irq_work) || chip_awake)
71 pending = true;
72 else
73 wl->elp_compl = &compl;
74 spin_unlock_irqrestore(&wl->wl_lock, flags);
75
76 wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP);
77
78 if (!pending) {
79 ret = wait_for_completion_timeout(
80 &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
81 if (ret == 0) {
82 wl1271_error("ELP wakeup timeout!");
83 ret = -ETIMEDOUT;
84 goto err;
85 } else if (ret < 0) {
86 wl1271_error("ELP wakeup completion error.");
87 goto err;
88 }
89 }
90
91 wl->elp = false;
92
93 wl1271_debug(DEBUG_PSM, "wakeup time: %u ms",
94 jiffies_to_msecs(jiffies - start_time));
95 goto out;
96
97err:
98 spin_lock_irqsave(&wl->wl_lock, flags);
99 wl->elp_compl = NULL;
100 spin_unlock_irqrestore(&wl->wl_lock, flags);
101 return ret;
102
103out:
104 return 0;
105}
106
107int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode)
108{
109 int ret;
110
111 switch (mode) {
112 case STATION_POWER_SAVE_MODE:
113 wl1271_debug(DEBUG_PSM, "entering psm");
114 ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
115 if (ret < 0)
116 return ret;
117
118 wl1271_ps_elp_sleep(wl);
119 if (ret < 0)
120 return ret;
121
122 wl->psm = 1;
123 break;
124 case STATION_ACTIVE_MODE:
125 default:
126 wl1271_debug(DEBUG_PSM, "leaving psm");
127 ret = wl1271_ps_elp_wakeup(wl, false);
128 if (ret < 0)
129 return ret;
130
131 ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
132 if (ret < 0)
133 return ret;
134
135 wl->psm = 0;
136 break;
137 }
138
139 return ret;
140}
141
142
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
new file mode 100644
index 000000000000..de2bd3c7dc9c
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -0,0 +1,35 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __WL1271_PS_H__
25#define __WL1271_PS_H__
26
27#include "wl1271.h"
28#include "wl1271_acx.h"
29
30int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode);
31void wl1271_ps_elp_sleep(struct wl1271 *wl);
32int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
33
34
35#endif /* __WL1271_PS_H__ */
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h
index 2de47cc32b8b..f8ed4a4fc691 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/wl1271_reg.h
@@ -1,10 +1,10 @@
1/* 1/*
2 * This file is part of wl12xx 2 * This file is part of wl12xx
3 * 3 *
4 * Copyright (c) 1998-2007 Texas Instruments Incorporated 4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008 Nokia Corporation 5 * Copyright (C) 2009 Nokia Corporation
6 * 6 *
7 * Contact: Kalle Valo <kalle.valo@nokia.com> 7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -34,6 +34,7 @@
34#define REGISTERS_WORK_SIZE 0x0000b000 34#define REGISTERS_WORK_SIZE 0x0000b000
35 35
36#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC 36#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC
37#define STATUS_MEM_ADDRESS 0x40400
37 38
38/* ELP register commands */ 39/* ELP register commands */
39#define ELPCTRL_WAKE_UP 0x1 40#define ELPCTRL_WAKE_UP 0x1
@@ -42,6 +43,25 @@
42/* ELP WLAN_READY bit */ 43/* ELP WLAN_READY bit */
43#define ELPCTRL_WLAN_READY 0x2 44#define ELPCTRL_WLAN_READY 0x2
44 45
46/*===============================================
47 Host Software Reset - 32bit RW
48 ------------------------------------------
49 [31:1] Reserved
50 0 SOFT_RESET Soft Reset - When this bit is set,
51 it holds the Wlan hardware in a soft reset state.
52 This reset disables all MAC and baseband processor
53 clocks except the CardBus/PCI interface clock.
54 It also initializes all MAC state machines except
55 the host interface. It does not reload the
56 contents of the EEPROM. When this bit is cleared
57 (not self-clearing), the Wlan hardware
58 exits the software reset state.
59===============================================*/
60#define ACX_REG_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000)
61
62#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008)
63#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c)
64#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018)
45/* 65/*
46 * Interrupt registers. 66 * Interrupt registers.
47 * 64 bit interrupt sources registers ws ced. 67 * 64 bit interrupt sources registers ws ced.
@@ -95,6 +115,9 @@
95#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) 115#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440)
96#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) 116#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444)
97 117
118#define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474)
119#define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478)
120
98/* Host Interrupts*/ 121/* Host Interrupts*/
99#define HINT_MASK (REGISTERS_BASE + 0x0494) 122#define HINT_MASK (REGISTERS_BASE + 0x0494)
100#define HINT_MASK_SET (REGISTERS_BASE + 0x0498) 123#define HINT_MASK_SET (REGISTERS_BASE + 0x0498)
@@ -106,67 +129,6 @@
106#define HINT_ACK (REGISTERS_BASE + 0x04A8) 129#define HINT_ACK (REGISTERS_BASE + 0x04A8)
107#define HINT_TRIG (REGISTERS_BASE + 0x04AC) 130#define HINT_TRIG (REGISTERS_BASE + 0x04AC)
108 131
109/* Device Configuration registers*/
110#define SOR_CFG (REGISTERS_BASE + 0x0800)
111#define ECPU_CTRL (REGISTERS_BASE + 0x0804)
112#define HI_CFG (REGISTERS_BASE + 0x0808)
113#define EE_START (REGISTERS_BASE + 0x080C)
114
115#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
116
117#define CHIP_ID_1251_PG10 (0x7010101)
118#define CHIP_ID_1251_PG11 (0x7020101)
119#define CHIP_ID_1251_PG12 (0x7030101)
120
121#define ENABLE (REGISTERS_BASE + 0x5450)
122
123/* Power Management registers */
124#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
125#define ELP_CMD (REGISTERS_BASE + 0x5808)
126#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
127#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
128#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
129
130#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
131
132/* Scratch Pad registers*/
133#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
134#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
135#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
136#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
137#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
138#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
139#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
140#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
141#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
142#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
143#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
144#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
145#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
146#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
147
148/* Spare registers*/
149#define SPARE_A1 (REGISTERS_BASE + 0x0994)
150#define SPARE_A2 (REGISTERS_BASE + 0x0998)
151#define SPARE_A3 (REGISTERS_BASE + 0x099C)
152#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
153#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
154#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
155#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
156#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
157#define SPARE_B1 (REGISTERS_BASE + 0x5420)
158#define SPARE_B2 (REGISTERS_BASE + 0x5424)
159#define SPARE_B3 (REGISTERS_BASE + 0x5428)
160#define SPARE_B4 (REGISTERS_BASE + 0x542C)
161#define SPARE_B5 (REGISTERS_BASE + 0x5430)
162#define SPARE_B6 (REGISTERS_BASE + 0x5434)
163#define SPARE_B7 (REGISTERS_BASE + 0x5438)
164#define SPARE_B8 (REGISTERS_BASE + 0x543C)
165
166enum wl12xx_acx_int_reg {
167 ACX_REG_INTERRUPT_TRIG,
168 ACX_REG_INTERRUPT_TRIG_H,
169
170/*============================================= 132/*=============================================
171 Host Interrupt Mask Register - 32bit (RW) 133 Host Interrupt Mask Register - 32bit (RW)
172 ------------------------------------------ 134 ------------------------------------------
@@ -195,7 +157,7 @@ enum wl12xx_acx_int_reg {
195 21- - 157 21- -
196 Default: 0x0001 158 Default: 0x0001
197*==============================================*/ 159*==============================================*/
198 ACX_REG_INTERRUPT_MASK, 160#define ACX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC)
199 161
200/*============================================= 162/*=============================================
201 Host Interrupt Mask Set 16bit, (Write only) 163 Host Interrupt Mask Set 16bit, (Write only)
@@ -205,7 +167,7 @@ enum wl12xx_acx_int_reg {
205 without effecting the mask 167 without effecting the mask
206 state of other bits (0 = no effect). 168 state of other bits (0 = no effect).
207==============================================*/ 169==============================================*/
208 ACX_REG_HINT_MASK_SET, 170#define ACX_REG_HINT_MASK_SET (REGISTERS_BASE + 0x04E0)
209 171
210/*============================================= 172/*=============================================
211 Host Interrupt Mask Clear 16bit,(Write only) 173 Host Interrupt Mask Clear 16bit,(Write only)
@@ -215,7 +177,7 @@ enum wl12xx_acx_int_reg {
215 without effecting the mask 177 without effecting the mask
216 state of other bits (0 = no effect). 178 state of other bits (0 = no effect).
217=============================================*/ 179=============================================*/
218 ACX_REG_HINT_MASK_CLR, 180#define ACX_REG_HINT_MASK_CLR (REGISTERS_BASE + 0x04E4)
219 181
220/*============================================= 182/*=============================================
221 Host Interrupt Status Nondestructive Read 183 Host Interrupt Status Nondestructive Read
@@ -226,7 +188,7 @@ enum wl12xx_acx_int_reg {
226 Reading this register doesn't 188 Reading this register doesn't
227 effect its content. 189 effect its content.
228=============================================*/ 190=============================================*/
229 ACX_REG_INTERRUPT_NO_CLEAR, 191#define ACX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8)
230 192
231/*============================================= 193/*=============================================
232 Host Interrupt Status Clear on Read Register 194 Host Interrupt Status Clear on Read Register
@@ -237,7 +199,7 @@ enum wl12xx_acx_int_reg {
237 Reading this register clears it, 199 Reading this register clears it,
238 thus making all interrupts inactive. 200 thus making all interrupts inactive.
239==============================================*/ 201==============================================*/
240 ACX_REG_INTERRUPT_CLEAR, 202#define ACX_REG_INTERRUPT_CLEAR (REGISTERS_BASE + 0x04F8)
241 203
242/*============================================= 204/*=============================================
243 Host Interrupt Acknowledge Register 205 Host Interrupt Acknowledge Register
@@ -249,40 +211,13 @@ enum wl12xx_acx_int_reg {
249 HINT_STS_ND registers, thus making the 211 HINT_STS_ND registers, thus making the
250 assotiated interrupt inactive. (0-no effect) 212 assotiated interrupt inactive. (0-no effect)
251==============================================*/ 213==============================================*/
252 ACX_REG_INTERRUPT_ACK, 214#define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0)
253 215
254/*=============================================== 216#define RX_DRIVER_DUMMY_WRITE_ADDRESS (REGISTERS_BASE + 0x0534)
255 Host Software Reset - 32bit RW 217#define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538)
256 ------------------------------------------
257 [31:1] Reserved
258 0 SOFT_RESET Soft Reset - When this bit is set,
259 it holds the Wlan hardware in a soft reset state.
260 This reset disables all MAC and baseband processor
261 clocks except the CardBus/PCI interface clock.
262 It also initializes all MAC state machines except
263 the host interface. It does not reload the
264 contents of the EEPROM. When this bit is cleared
265 (not self-clearing), the Wlan hardware
266 exits the software reset state.
267===============================================*/
268 ACX_REG_SLV_SOFT_RESET,
269
270/*===============================================
271 EEPROM Burst Read Start - 32bit RW
272 ------------------------------------------
273 [31:1] Reserved
274 0 ACX_EE_START - EEPROM Burst Read Start 0
275 Setting this bit starts a burst read from
276 the external EEPROM.
277 If this bit is set (after reset) before an EEPROM read/write,
278 the burst read starts at EEPROM address 0.
279 Otherwise, it starts at the address
280 following the address of the previous access.
281 TheWlan hardware hardware clears this bit automatically.
282 218
283 Default: 0x00000000 219/* Device Configuration registers*/
284*================================================*/ 220#define SOR_CFG (REGISTERS_BASE + 0x0800)
285 ACX_REG_EE_START,
286 221
287/* Embedded ARM CPU Control */ 222/* Embedded ARM CPU Control */
288 223
@@ -304,10 +239,89 @@ enum wl12xx_acx_int_reg {
304 1 halt eCPU 239 1 halt eCPU
305 0 enable eCPU 240 0 enable eCPU
306 ===============================================*/ 241 ===============================================*/
307 ACX_REG_ECPU_CONTROL, 242#define ACX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804)
243
244#define HI_CFG (REGISTERS_BASE + 0x0808)
245
246/*===============================================
247 EEPROM Burst Read Start - 32bit RW
248 ------------------------------------------
249 [31:1] Reserved
250 0 ACX_EE_START - EEPROM Burst Read Start 0
251 Setting this bit starts a burst read from
252 the external EEPROM.
253 If this bit is set (after reset) before an EEPROM read/write,
254 the burst read starts at EEPROM address 0.
255 Otherwise, it starts at the address
256 following the address of the previous access.
257 TheWlan hardware hardware clears this bit automatically.
258
259 Default: 0x00000000
260*================================================*/
261#define ACX_REG_EE_START (REGISTERS_BASE + 0x080C)
262
263#define OCP_POR_CTR (REGISTERS_BASE + 0x09B4)
264#define OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8)
265#define OCP_DATA_READ (REGISTERS_BASE + 0x09BC)
266#define OCP_CMD (REGISTERS_BASE + 0x09C0)
267
268#define WL1271_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8)
269
270#define CHIP_ID_B (REGISTERS_BASE + 0x5674)
271
272#define CHIP_ID_1271_PG10 (0x4030101)
273#define CHIP_ID_1271_PG20 (0x4030111)
274
275#define ENABLE (REGISTERS_BASE + 0x5450)
276
277/* Power Management registers */
278#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804)
279#define ELP_CMD (REGISTERS_BASE + 0x5808)
280#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810)
281#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814)
282#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818)
283
284#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820)
285
286/* Scratch Pad registers*/
287#define SCR_PAD0 (REGISTERS_BASE + 0x5608)
288#define SCR_PAD1 (REGISTERS_BASE + 0x560C)
289#define SCR_PAD2 (REGISTERS_BASE + 0x5610)
290#define SCR_PAD3 (REGISTERS_BASE + 0x5614)
291#define SCR_PAD4 (REGISTERS_BASE + 0x5618)
292#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C)
293#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620)
294#define SCR_PAD5 (REGISTERS_BASE + 0x5624)
295#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628)
296#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C)
297#define SCR_PAD6 (REGISTERS_BASE + 0x5630)
298#define SCR_PAD7 (REGISTERS_BASE + 0x5634)
299#define SCR_PAD8 (REGISTERS_BASE + 0x5638)
300#define SCR_PAD9 (REGISTERS_BASE + 0x563C)
301
302/* Spare registers*/
303#define SPARE_A1 (REGISTERS_BASE + 0x0994)
304#define SPARE_A2 (REGISTERS_BASE + 0x0998)
305#define SPARE_A3 (REGISTERS_BASE + 0x099C)
306#define SPARE_A4 (REGISTERS_BASE + 0x09A0)
307#define SPARE_A5 (REGISTERS_BASE + 0x09A4)
308#define SPARE_A6 (REGISTERS_BASE + 0x09A8)
309#define SPARE_A7 (REGISTERS_BASE + 0x09AC)
310#define SPARE_A8 (REGISTERS_BASE + 0x09B0)
311#define SPARE_B1 (REGISTERS_BASE + 0x5420)
312#define SPARE_B2 (REGISTERS_BASE + 0x5424)
313#define SPARE_B3 (REGISTERS_BASE + 0x5428)
314#define SPARE_B4 (REGISTERS_BASE + 0x542C)
315#define SPARE_B5 (REGISTERS_BASE + 0x5430)
316#define SPARE_B6 (REGISTERS_BASE + 0x5434)
317#define SPARE_B7 (REGISTERS_BASE + 0x5438)
318#define SPARE_B8 (REGISTERS_BASE + 0x543C)
319
320#define PLL_PARAMETERS (REGISTERS_BASE + 0x6040)
321#define WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008)
322#define WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100)
323#define DRPW_SCRATCH_START (DRPW_BASE + 0x002C)
308 324
309 ACX_REG_TABLE_LEN
310};
311 325
312#define ACX_SLV_SOFT_RESET_BIT BIT(1) 326#define ACX_SLV_SOFT_RESET_BIT BIT(1)
313#define ACX_REG_EEPROM_START_BIT BIT(1) 327#define ACX_REG_EEPROM_START_BIT BIT(1)
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c
new file mode 100644
index 000000000000..ad8b6904c5eb
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.c
@@ -0,0 +1,200 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include "wl1271.h"
25#include "wl1271_acx.h"
26#include "wl1271_reg.h"
27#include "wl1271_rx.h"
28#include "wl1271_spi.h"
29
30static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
31 u32 drv_rx_counter)
32{
33 return status->rx_pkt_descs[drv_rx_counter] & RX_MEM_BLOCK_MASK;
34}
35
36static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
37 u32 drv_rx_counter)
38{
39 return (status->rx_pkt_descs[drv_rx_counter] & RX_BUF_SIZE_MASK) >>
40 RX_BUF_SIZE_SHIFT_DIV;
41}
42
43/* The values of this table must match the wl1271_rates[] array */
44static u8 wl1271_rx_rate_to_idx[] = {
45 /* MCS rates are used only with 11n */
46 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */
47 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */
48 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */
49 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */
50 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */
51 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */
52 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */
53 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */
54
55 11, /* WL1271_RATE_54 */
56 10, /* WL1271_RATE_48 */
57 9, /* WL1271_RATE_36 */
58 8, /* WL1271_RATE_24 */
59
60 /* TI-specific rate */
61 WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */
62
63 7, /* WL1271_RATE_18 */
64 6, /* WL1271_RATE_12 */
65 3, /* WL1271_RATE_11 */
66 5, /* WL1271_RATE_9 */
67 4, /* WL1271_RATE_6 */
68 2, /* WL1271_RATE_5_5 */
69 1, /* WL1271_RATE_2 */
70 0 /* WL1271_RATE_1 */
71};
72
73static void wl1271_rx_status(struct wl1271 *wl,
74 struct wl1271_rx_descriptor *desc,
75 struct ieee80211_rx_status *status,
76 u8 beacon)
77{
78 memset(status, 0, sizeof(struct ieee80211_rx_status));
79
80 if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG)
81 status->band = IEEE80211_BAND_2GHZ;
82 else
83 wl1271_warning("unsupported band 0x%x",
84 desc->flags & WL1271_RX_DESC_BAND_MASK);
85
86 /*
87 * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the
88 * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we
89 * only need the mactime for monitor mode. For now the mactime is
90 * not valid, so RX_FLAG_TSFT should not be set
91 */
92 status->signal = desc->rssi;
93
94 /* FIXME: Should this be optimized? */
95 status->qual = (desc->rssi - WL1271_RX_MIN_RSSI) * 100 /
96 (WL1271_RX_MAX_RSSI - WL1271_RX_MIN_RSSI);
97 status->qual = min(status->qual, 100);
98 status->qual = max(status->qual, 0);
99
100 /*
101 * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we
102 * need to divide by two for now, but TI has been discussing about
103 * changing it. This needs to be rechecked.
104 */
105 status->noise = desc->rssi - (desc->snr >> 1);
106
107 status->freq = ieee80211_channel_to_frequency(desc->channel);
108
109 if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
110 status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
111
112 if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL)))
113 status->flag |= RX_FLAG_DECRYPTED;
114
115 if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL))
116 status->flag |= RX_FLAG_MMIC_ERROR;
117 }
118
119 status->rate_idx = wl1271_rx_rate_to_idx[desc->rate];
120
121 if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED)
122 wl1271_warning("unsupported rate");
123}
124
125static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length)
126{
127 struct ieee80211_rx_status rx_status;
128 struct wl1271_rx_descriptor *desc;
129 struct sk_buff *skb;
130 u16 *fc;
131 u8 *buf;
132 u8 beacon = 0;
133
134 skb = dev_alloc_skb(length);
135 if (!skb) {
136 wl1271_error("Couldn't allocate RX frame");
137 return;
138 }
139
140 buf = skb_put(skb, length);
141 wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true);
142
143 /* the data read starts with the descriptor */
144 desc = (struct wl1271_rx_descriptor *) buf;
145
146 /* now we pull the descriptor out of the buffer */
147 skb_pull(skb, sizeof(*desc));
148
149 fc = (u16 *)skb->data;
150 if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
151 beacon = 1;
152
153 wl1271_rx_status(wl, desc, &rx_status, beacon);
154
155 wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len,
156 beacon ? "beacon" : "");
157
158 memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
159 ieee80211_rx(wl->hw, skb);
160}
161
162void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
163{
164 struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
165 u32 buf_size;
166 u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
167 u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
168 u32 mem_block;
169
170 while (drv_rx_counter != fw_rx_counter) {
171 mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter);
172 buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter);
173
174 if (buf_size == 0) {
175 wl1271_warning("received empty data");
176 break;
177 }
178
179 wl->rx_mem_pool_addr.addr =
180 (mem_block << 8) + wl_mem_map->packet_memory_pool_start;
181 wl->rx_mem_pool_addr.addr_extra =
182 wl->rx_mem_pool_addr.addr + 4;
183
184 /* Choose the block we want to read */
185 wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA,
186 &wl->rx_mem_pool_addr,
187 sizeof(wl->rx_mem_pool_addr), false);
188
189 wl1271_rx_handle_data(wl, buf_size);
190
191 wl->rx_counter++;
192 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
193 }
194
195 wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
196
197 /* This is a workaround for some problems in the chip */
198 wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1);
199
200}
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h
new file mode 100644
index 000000000000..d1ca60e43a25
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_rx.h
@@ -0,0 +1,121 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_RX_H__
26#define __WL1271_RX_H__
27
28#include <linux/bitops.h>
29
30#define WL1271_RX_MAX_RSSI -30
31#define WL1271_RX_MIN_RSSI -95
32
33#define WL1271_RX_ALIGN_TO 4
34#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \
35 ~(WL1271_RX_ALIGN_TO - 1))
36
37#define SHORT_PREAMBLE_BIT BIT(0)
38#define OFDM_RATE_BIT BIT(6)
39#define PBCC_RATE_BIT BIT(7)
40
41#define PLCP_HEADER_LENGTH 8
42#define RX_DESC_PACKETID_SHIFT 11
43#define RX_MAX_PACKET_ID 3
44
45#define NUM_RX_PKT_DESC_MOD_MASK 7
46#define WL1271_RX_RATE_UNSUPPORTED 0xFF
47
48#define RX_DESC_VALID_FCS 0x0001
49#define RX_DESC_MATCH_RXADDR1 0x0002
50#define RX_DESC_MCAST 0x0004
51#define RX_DESC_STAINTIM 0x0008
52#define RX_DESC_VIRTUAL_BM 0x0010
53#define RX_DESC_BCAST 0x0020
54#define RX_DESC_MATCH_SSID 0x0040
55#define RX_DESC_MATCH_BSSID 0x0080
56#define RX_DESC_ENCRYPTION_MASK 0x0300
57#define RX_DESC_MEASURMENT 0x0400
58#define RX_DESC_SEQNUM_MASK 0x1800
59#define RX_DESC_MIC_FAIL 0x2000
60#define RX_DESC_DECRYPT_FAIL 0x4000
61
62/*
63 * RX Descriptor flags:
64 *
65 * Bits 0-1 - band
66 * Bit 2 - STBC
67 * Bit 3 - A-MPDU
68 * Bit 4 - HT
69 * Bits 5-7 - encryption
70 */
71#define WL1271_RX_DESC_BAND_MASK 0x03
72#define WL1271_RX_DESC_ENCRYPT_MASK 0xE0
73
74#define WL1271_RX_DESC_BAND_BG 0x00
75#define WL1271_RX_DESC_BAND_J 0x01
76#define WL1271_RX_DESC_BAND_A 0x02
77
78#define WL1271_RX_DESC_STBC BIT(2)
79#define WL1271_RX_DESC_A_MPDU BIT(3)
80#define WL1271_RX_DESC_HT BIT(4)
81
82#define WL1271_RX_DESC_ENCRYPT_WEP 0x20
83#define WL1271_RX_DESC_ENCRYPT_TKIP 0x40
84#define WL1271_RX_DESC_ENCRYPT_AES 0x60
85#define WL1271_RX_DESC_ENCRYPT_GEM 0x80
86
87/*
88 * RX Descriptor status
89 *
90 * Bits 0-2 - status
91 * Bits 3-7 - reserved
92 */
93#define WL1271_RX_DESC_STATUS_MASK 0x07
94
95#define WL1271_RX_DESC_SUCCESS 0x00
96#define WL1271_RX_DESC_DECRYPT_FAIL 0x01
97#define WL1271_RX_DESC_MIC_FAIL 0x02
98#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
99
100#define RX_MEM_BLOCK_MASK 0xFF
101#define RX_BUF_SIZE_MASK 0xFFF00
102#define RX_BUF_SIZE_SHIFT_DIV 6
103
104struct wl1271_rx_descriptor {
105 u16 length;
106 u8 status;
107 u8 flags;
108 u8 rate;
109 u8 channel;
110 s8 rssi;
111 u8 snr;
112 u32 timestamp;
113 u8 packet_class;
114 u8 process_id;
115 u8 pad_len;
116 u8 reserved;
117} __attribute__ ((packed));
118
119void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
120
121#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
new file mode 100644
index 000000000000..4a12880c16a8
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -0,0 +1,382 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/platform_device.h>
26#include <linux/crc7.h>
27#include <linux/spi/spi.h>
28
29#include "wl1271.h"
30#include "wl12xx_80211.h"
31#include "wl1271_spi.h"
32
33static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr)
34{
35 return addr - wl->physical_reg_addr + wl->virtual_reg_addr;
36}
37
38static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr)
39{
40 return addr - wl->physical_mem_addr + wl->virtual_mem_addr;
41}
42
43
44void wl1271_spi_reset(struct wl1271 *wl)
45{
46 u8 *cmd;
47 struct spi_transfer t;
48 struct spi_message m;
49
50 cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
51 if (!cmd) {
52 wl1271_error("could not allocate cmd for spi reset");
53 return;
54 }
55
56 memset(&t, 0, sizeof(t));
57 spi_message_init(&m);
58
59 memset(cmd, 0xff, WSPI_INIT_CMD_LEN);
60
61 t.tx_buf = cmd;
62 t.len = WSPI_INIT_CMD_LEN;
63 spi_message_add_tail(&t, &m);
64
65 spi_sync(wl->spi, &m);
66
67 wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
68}
69
70void wl1271_spi_init(struct wl1271 *wl)
71{
72 u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
73 struct spi_transfer t;
74 struct spi_message m;
75
76 cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
77 if (!cmd) {
78 wl1271_error("could not allocate cmd for spi init");
79 return;
80 }
81
82 memset(crc, 0, sizeof(crc));
83 memset(&t, 0, sizeof(t));
84 spi_message_init(&m);
85
86 /*
87 * Set WSPI_INIT_COMMAND
88 * the data is being send from the MSB to LSB
89 */
90 cmd[2] = 0xff;
91 cmd[3] = 0xff;
92 cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
93 cmd[0] = 0;
94 cmd[7] = 0;
95 cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
96 cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
97
98 if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
99 cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
100 else
101 cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
102
103 cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
104 | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
105
106 crc[0] = cmd[1];
107 crc[1] = cmd[0];
108 crc[2] = cmd[7];
109 crc[3] = cmd[6];
110 crc[4] = cmd[5];
111
112 cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
113 cmd[4] |= WSPI_INIT_CMD_END;
114
115 t.tx_buf = cmd;
116 t.len = WSPI_INIT_CMD_LEN;
117 spi_message_add_tail(&t, &m);
118
119 spi_sync(wl->spi, &m);
120
121 wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN);
122}
123
124/* Set the SPI partitions to access the chip addresses
125 *
126 * There are two VIRTUAL (SPI) partitions (the memory partition and the
127 * registers partition), which are mapped to two different areas of the
128 * PHYSICAL (hardware) memory. This function also makes other checks to
129 * ensure that the partitions are not overlapping. In the diagram below, the
130 * memory partition comes before the register partition, but the opposite is
131 * also supported.
132 *
133 * PHYSICAL address
134 * space
135 *
136 * | |
137 * ...+----+--> mem_start
138 * VIRTUAL address ... | |
139 * space ... | | [PART_0]
140 * ... | |
141 * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size
142 * | | ... | |
143 * |MEM | ... | |
144 * | | ... | |
145 * part_size <--+----+... | | {unused area)
146 * | | ... | |
147 * |REG | ... | |
148 * part_size | | ... | |
149 * + <--+----+... ...+----+--> reg_start
150 * reg_size ... | |
151 * ... | | [PART_1]
152 * ... | |
153 * ...+----+--> reg_start + reg_size
154 * | |
155 *
156 */
157int wl1271_set_partition(struct wl1271 *wl,
158 u32 mem_start, u32 mem_size,
159 u32 reg_start, u32 reg_size)
160{
161 struct wl1271_partition *partition;
162 struct spi_transfer t;
163 struct spi_message m;
164 size_t len, cmd_len;
165 u32 *cmd;
166 int addr;
167
168 cmd_len = sizeof(u32) + 2 * sizeof(struct wl1271_partition);
169 cmd = kzalloc(cmd_len, GFP_KERNEL);
170 if (!cmd)
171 return -ENOMEM;
172
173 spi_message_init(&m);
174 memset(&t, 0, sizeof(t));
175
176 partition = (struct wl1271_partition *) (cmd + 1);
177 addr = HW_ACCESS_PART0_SIZE_ADDR;
178 len = 2 * sizeof(struct wl1271_partition);
179
180 *cmd |= WSPI_CMD_WRITE;
181 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
182 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
183
184 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
185 mem_start, mem_size);
186 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
187 reg_start, reg_size);
188
189 /* Make sure that the two partitions together don't exceed the
190 * address range */
191 if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) {
192 wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual"
193 " address range. Truncating partition[0].");
194 mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size;
195 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
196 mem_start, mem_size);
197 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
198 reg_start, reg_size);
199 }
200
201 if ((mem_start < reg_start) &&
202 ((mem_start + mem_size) > reg_start)) {
203 /* Guarantee that the memory partition doesn't overlap the
204 * registers partition */
205 wl1271_debug(DEBUG_SPI, "End of partition[0] is "
206 "overlapping partition[1]. Adjusted.");
207 mem_size = reg_start - mem_start;
208 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
209 mem_start, mem_size);
210 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
211 reg_start, reg_size);
212 } else if ((reg_start < mem_start) &&
213 ((reg_start + reg_size) > mem_start)) {
214 /* Guarantee that the register partition doesn't overlap the
215 * memory partition */
216 wl1271_debug(DEBUG_SPI, "End of partition[1] is"
217 " overlapping partition[0]. Adjusted.");
218 reg_size = mem_start - reg_start;
219 wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X",
220 mem_start, mem_size);
221 wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X",
222 reg_start, reg_size);
223 }
224
225 partition[0].start = mem_start;
226 partition[0].size = mem_size;
227 partition[1].start = reg_start;
228 partition[1].size = reg_size;
229
230 wl->physical_mem_addr = mem_start;
231 wl->physical_reg_addr = reg_start;
232
233 wl->virtual_mem_addr = 0;
234 wl->virtual_reg_addr = mem_size;
235
236 t.tx_buf = cmd;
237 t.len = cmd_len;
238 spi_message_add_tail(&t, &m);
239
240 spi_sync(wl->spi, &m);
241
242 kfree(cmd);
243
244 return 0;
245}
246
247void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
248 size_t len, bool fixed)
249{
250 struct spi_transfer t[3];
251 struct spi_message m;
252 u8 *busy_buf;
253 u32 *cmd;
254
255 cmd = &wl->buffer_cmd;
256 busy_buf = wl->buffer_busyword;
257
258 *cmd = 0;
259 *cmd |= WSPI_CMD_READ;
260 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
261 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
262
263 if (fixed)
264 *cmd |= WSPI_CMD_FIXED;
265
266 spi_message_init(&m);
267 memset(t, 0, sizeof(t));
268
269 t[0].tx_buf = cmd;
270 t[0].len = 4;
271 spi_message_add_tail(&t[0], &m);
272
273 /* Busy and non busy words read */
274 t[1].rx_buf = busy_buf;
275 t[1].len = WL1271_BUSY_WORD_LEN;
276 spi_message_add_tail(&t[1], &m);
277
278 t[2].rx_buf = buf;
279 t[2].len = len;
280 spi_message_add_tail(&t[2], &m);
281
282 spi_sync(wl->spi, &m);
283
284 /* FIXME: check busy words */
285
286 wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd));
287 wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len);
288}
289
290void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
291 size_t len, bool fixed)
292{
293 struct spi_transfer t[2];
294 struct spi_message m;
295 u32 *cmd;
296
297 cmd = &wl->buffer_cmd;
298
299 *cmd = 0;
300 *cmd |= WSPI_CMD_WRITE;
301 *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH;
302 *cmd |= addr & WSPI_CMD_BYTE_ADDR;
303
304 if (fixed)
305 *cmd |= WSPI_CMD_FIXED;
306
307 spi_message_init(&m);
308 memset(t, 0, sizeof(t));
309
310 t[0].tx_buf = cmd;
311 t[0].len = sizeof(*cmd);
312 spi_message_add_tail(&t[0], &m);
313
314 t[1].tx_buf = buf;
315 t[1].len = len;
316 spi_message_add_tail(&t[1], &m);
317
318 spi_sync(wl->spi, &m);
319
320 wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd));
321 wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len);
322}
323
324void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf,
325 size_t len)
326{
327 int physical;
328
329 physical = wl1271_translate_mem_addr(wl, addr);
330
331 wl1271_spi_read(wl, physical, buf, len, false);
332}
333
334void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf,
335 size_t len)
336{
337 int physical;
338
339 physical = wl1271_translate_mem_addr(wl, addr);
340
341 wl1271_spi_write(wl, physical, buf, len, false);
342}
343
344void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
345 bool fixed)
346{
347 int physical;
348
349 physical = wl1271_translate_reg_addr(wl, addr);
350
351 wl1271_spi_read(wl, physical, buf, len, fixed);
352}
353
354void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
355 bool fixed)
356{
357 int physical;
358
359 physical = wl1271_translate_reg_addr(wl, addr);
360
361 wl1271_spi_write(wl, physical, buf, len, fixed);
362}
363
364u32 wl1271_mem_read32(struct wl1271 *wl, int addr)
365{
366 return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr));
367}
368
369void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val)
370{
371 wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val);
372}
373
374u32 wl1271_reg_read32(struct wl1271 *wl, int addr)
375{
376 return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr));
377}
378
379void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val)
380{
381 wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val);
382}
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h
new file mode 100644
index 000000000000..2c9968458646
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.h
@@ -0,0 +1,113 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2008-2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_SPI_H__
26#define __WL1271_SPI_H__
27
28#include "wl1271_reg.h"
29
30#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0
31
32#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0
33#define HW_ACCESS_PART0_START_ADDR 0x1FFC4
34#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8
35#define HW_ACCESS_PART1_START_ADDR 0x1FFCC
36
37#define HW_ACCESS_REGISTER_SIZE 4
38
39#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
40
41#define WSPI_CMD_READ 0x40000000
42#define WSPI_CMD_WRITE 0x00000000
43#define WSPI_CMD_FIXED 0x20000000
44#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000
45#define WSPI_CMD_BYTE_LENGTH_OFFSET 17
46#define WSPI_CMD_BYTE_ADDR 0x0001FFFF
47
48#define WSPI_INIT_CMD_CRC_LEN 5
49
50#define WSPI_INIT_CMD_START 0x00
51#define WSPI_INIT_CMD_TX 0x40
52/* the extra bypass bit is sampled by the TNET as '1' */
53#define WSPI_INIT_CMD_BYPASS_BIT 0x80
54#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07
55#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80
56#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00
57#define WSPI_INIT_CMD_IOD 0x40
58#define WSPI_INIT_CMD_IP 0x20
59#define WSPI_INIT_CMD_CS 0x10
60#define WSPI_INIT_CMD_WS 0x08
61#define WSPI_INIT_CMD_WSPI 0x01
62#define WSPI_INIT_CMD_END 0x01
63
64#define WSPI_INIT_CMD_LEN 8
65
66#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \
67 ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32))
68#define HW_ACCESS_WSPI_INIT_CMD_MASK 0
69
70
71/* Raw target IO, address is not translated */
72void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf,
73 size_t len, bool fixed);
74void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf,
75 size_t len, bool fixed);
76
77/* Memory target IO, address is tranlated to partition 0 */
78void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, size_t len);
79void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, size_t len);
80u32 wl1271_mem_read32(struct wl1271 *wl, int addr);
81void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val);
82
83/* Registers IO */
84void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len,
85 bool fixed);
86void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len,
87 bool fixed);
88u32 wl1271_reg_read32(struct wl1271 *wl, int addr);
89void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val);
90
91/* INIT and RESET words */
92void wl1271_spi_reset(struct wl1271 *wl);
93void wl1271_spi_init(struct wl1271 *wl);
94int wl1271_set_partition(struct wl1271 *wl,
95 u32 part_start, u32 part_size,
96 u32 reg_start, u32 reg_size);
97
98static inline u32 wl1271_read32(struct wl1271 *wl, int addr)
99{
100 wl1271_spi_read(wl, addr, &wl->buffer_32,
101 sizeof(wl->buffer_32), false);
102
103 return wl->buffer_32;
104}
105
106static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
107{
108 wl->buffer_32 = val;
109 wl1271_spi_write(wl, addr, &wl->buffer_32,
110 sizeof(wl->buffer_32), false);
111}
112
113#endif /* __WL1271_SPI_H__ */
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
new file mode 100644
index 000000000000..ff221258b941
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -0,0 +1,378 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 2009 Nokia Corporation
5 *
6 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/module.h>
26
27#include "wl1271.h"
28#include "wl1271_spi.h"
29#include "wl1271_reg.h"
30#include "wl1271_ps.h"
31#include "wl1271_tx.h"
32
33static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb)
34{
35 int i;
36
37 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
38 if (wl->tx_frames[i] == NULL) {
39 wl->tx_frames[i] = skb;
40 return i;
41 }
42
43 return -EBUSY;
44}
45
46static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
47{
48 struct wl1271_tx_hw_descr *desc;
49 u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
50 u32 total_blocks, excluded;
51 int id, ret = -EBUSY;
52
53 /* allocate free identifier for the packet */
54 id = wl1271_tx_id(wl, skb);
55 if (id < 0)
56 return id;
57
58 /* approximate the number of blocks required for this packet
59 in the firmware */
60 /* FIXME: try to figure out what is done here and make it cleaner */
61 total_blocks = (skb->len) >> TX_HW_BLOCK_SHIFT_DIV;
62 excluded = (total_blocks << 2) + (skb->len & 0xff) + 34;
63 total_blocks += (excluded > 252) ? 2 : 1;
64 total_blocks += TX_HW_BLOCK_SPARE;
65
66 if (total_blocks <= wl->tx_blocks_available) {
67 desc = (struct wl1271_tx_hw_descr *)skb_push(
68 skb, total_len - skb->len);
69
70 desc->extra_mem_blocks = TX_HW_BLOCK_SPARE;
71 desc->total_mem_blocks = total_blocks;
72 desc->id = id;
73
74 wl->tx_blocks_available -= total_blocks;
75
76 ret = 0;
77
78 wl1271_debug(DEBUG_TX,
79 "tx_allocate: size: %d, blocks: %d, id: %d",
80 total_len, total_blocks, id);
81 } else
82 wl->tx_frames[id] = NULL;
83
84 return ret;
85}
86
87static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
88 u32 extra, struct ieee80211_tx_info *control)
89{
90 struct wl1271_tx_hw_descr *desc;
91 int pad;
92
93 desc = (struct wl1271_tx_hw_descr *) skb->data;
94
95 /* configure packet life time */
96 desc->start_time = jiffies_to_usecs(jiffies) - wl->time_offset;
97 desc->life_time = TX_HW_MGMT_PKT_LIFETIME_TU;
98
99 /* configure the tx attributes */
100 desc->tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
101 /* FIXME: do we know the packet priority? can we identify mgmt
102 packets, and use max prio for them at least? */
103 desc->tid = 0;
104 desc->aid = TX_HW_DEFAULT_AID;
105 desc->reserved = 0;
106
107 /* align the length (and store in terms of words) */
108 pad = WL1271_TX_ALIGN(skb->len);
109 desc->length = pad >> 2;
110
111 /* calculate number of padding bytes */
112 pad = pad - skb->len;
113 desc->tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
114
115 wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
116 return 0;
117}
118
119static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
120 struct ieee80211_tx_info *control)
121{
122
123 struct wl1271_tx_hw_descr *desc;
124 int len;
125
126 /* FIXME: This is a workaround for getting non-aligned packets.
127 This happens at least with EAPOL packets from the user space.
128 Our DMA requires packets to be aligned on a 4-byte boundary.
129 */
130 if (unlikely((long)skb->data & 0x03)) {
131 int offset = (4 - (long)skb->data) & 0x03;
132 wl1271_debug(DEBUG_TX, "skb offset %d", offset);
133
134 /* check whether the current skb can be used */
135 if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
136 unsigned char *src = skb->data;
137
138 /* align the buffer on a 4-byte boundary */
139 skb_reserve(skb, offset);
140 memmove(skb->data, src, skb->len);
141 } else {
142 wl1271_info("No handler, fixme!");
143 return -EINVAL;
144 }
145 }
146
147 len = WL1271_TX_ALIGN(skb->len);
148
149 /* perform a fixed address block write with the packet */
150 wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true);
151
152 /* write packet new counter into the write access register */
153 wl->tx_packets_count++;
154 wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
155
156 desc = (struct wl1271_tx_hw_descr *) skb->data;
157 wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
158 desc->id, skb, len, desc->length);
159
160 return 0;
161}
162
163/* caller must hold wl->mutex */
164static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
165{
166 struct ieee80211_tx_info *info;
167 u32 extra = 0;
168 int ret = 0;
169 u8 idx;
170
171 if (!skb)
172 return -EINVAL;
173
174 info = IEEE80211_SKB_CB(skb);
175
176 if (info->control.hw_key &&
177 info->control.hw_key->alg == ALG_TKIP)
178 extra = WL1271_TKIP_IV_SPACE;
179
180 if (info->control.hw_key) {
181 idx = info->control.hw_key->hw_key_idx;
182
183 /* FIXME: do we have to do this if we're not using WEP? */
184 if (unlikely(wl->default_key != idx)) {
185 ret = wl1271_cmd_set_default_wep_key(wl, idx);
186 if (ret < 0)
187 return ret;
188 }
189 }
190
191 ret = wl1271_tx_allocate(wl, skb, extra);
192 if (ret < 0)
193 return ret;
194
195 ret = wl1271_tx_fill_hdr(wl, skb, extra, info);
196 if (ret < 0)
197 return ret;
198
199 ret = wl1271_tx_send_packet(wl, skb, info);
200 if (ret < 0)
201 return ret;
202
203 return ret;
204}
205
206void wl1271_tx_work(struct work_struct *work)
207{
208 struct wl1271 *wl = container_of(work, struct wl1271, tx_work);
209 struct sk_buff *skb;
210 bool woken_up = false;
211 int ret;
212
213 mutex_lock(&wl->mutex);
214
215 if (unlikely(wl->state == WL1271_STATE_OFF))
216 goto out;
217
218 while ((skb = skb_dequeue(&wl->tx_queue))) {
219 if (!woken_up) {
220 ret = wl1271_ps_elp_wakeup(wl, false);
221 if (ret < 0)
222 goto out;
223 woken_up = true;
224 }
225
226 ret = wl1271_tx_frame(wl, skb);
227 if (ret == -EBUSY) {
228 /* firmware buffer is full, stop queues */
229 wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
230 "stop queues");
231 ieee80211_stop_queues(wl->hw);
232 wl->tx_queue_stopped = true;
233 skb_queue_head(&wl->tx_queue, skb);
234 goto out;
235 } else if (ret < 0) {
236 dev_kfree_skb(skb);
237 goto out;
238 } else if (wl->tx_queue_stopped) {
239 /* firmware buffer has space, restart queues */
240 wl1271_debug(DEBUG_TX,
241 "complete_packet: waking queues");
242 ieee80211_wake_queues(wl->hw);
243 wl->tx_queue_stopped = false;
244 }
245 }
246
247out:
248 if (woken_up)
249 wl1271_ps_elp_sleep(wl);
250
251 mutex_unlock(&wl->mutex);
252}
253
254static void wl1271_tx_complete_packet(struct wl1271 *wl,
255 struct wl1271_tx_hw_res_descr *result)
256{
257
258 struct ieee80211_tx_info *info;
259 struct sk_buff *skb;
260 u32 header_len;
261 int id = result->id;
262
263 /* check for id legality */
264 if (id >= TX_HW_RESULT_QUEUE_LEN || wl->tx_frames[id] == NULL) {
265 wl1271_warning("TX result illegal id: %d", id);
266 return;
267 }
268
269 skb = wl->tx_frames[id];
270 info = IEEE80211_SKB_CB(skb);
271
272 /* update packet status */
273 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
274 if (result->status == TX_SUCCESS)
275 info->flags |= IEEE80211_TX_STAT_ACK;
276 if (result->status & TX_RETRY_EXCEEDED) {
277 /* FIXME */
278 /* info->status.excessive_retries = 1; */
279 wl->stats.excessive_retries++;
280 }
281 }
282
283 /* FIXME */
284 /* info->status.retry_count = result->ack_failures; */
285 wl->stats.retry_count += result->ack_failures;
286
287 /* get header len */
288 if (info->control.hw_key &&
289 info->control.hw_key->alg == ALG_TKIP)
290 header_len = WL1271_TKIP_IV_SPACE +
291 sizeof(struct wl1271_tx_hw_descr);
292 else
293 header_len = sizeof(struct wl1271_tx_hw_descr);
294
295 wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x"
296 " status 0x%x",
297 result->id, skb, result->ack_failures,
298 result->rate_class_index, result->status);
299
300 /* remove private header from packet */
301 skb_pull(skb, header_len);
302
303 /* return the packet to the stack */
304 ieee80211_tx_status(wl->hw, skb);
305 wl->tx_frames[result->id] = NULL;
306}
307
308/* Called upon reception of a TX complete interrupt */
309void wl1271_tx_complete(struct wl1271 *wl, u32 count)
310{
311 struct wl1271_acx_mem_map *memmap =
312 (struct wl1271_acx_mem_map *)wl->target_mem_map;
313 u32 i;
314
315 wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
316
317 /* read the tx results from the chipset */
318 wl1271_spi_mem_read(wl, memmap->tx_result,
319 wl->tx_res_if, sizeof(*wl->tx_res_if));
320
321 /* verify that the result buffer is not getting overrun */
322 if (count > TX_HW_RESULT_QUEUE_LEN) {
323 wl1271_warning("TX result overflow from chipset: %d", count);
324 count = TX_HW_RESULT_QUEUE_LEN;
325 }
326
327 /* process the results */
328 for (i = 0; i < count; i++) {
329 struct wl1271_tx_hw_res_descr *result;
330 u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK;
331
332 /* process the packet */
333 result = &(wl->tx_res_if->tx_results_queue[offset]);
334 wl1271_tx_complete_packet(wl, result);
335
336 wl->tx_results_count++;
337 }
338
339 /* write host counter to chipset (to ack) */
340 wl1271_mem_write32(wl, memmap->tx_result +
341 offsetof(struct wl1271_tx_hw_res_if,
342 tx_result_host_counter),
343 wl->tx_res_if->tx_result_fw_counter);
344}
345
346/* caller must hold wl->mutex */
347void wl1271_tx_flush(struct wl1271 *wl)
348{
349 int i;
350 struct sk_buff *skb;
351 struct ieee80211_tx_info *info;
352
353 /* TX failure */
354/* control->flags = 0; FIXME */
355
356 while ((skb = skb_dequeue(&wl->tx_queue))) {
357 info = IEEE80211_SKB_CB(skb);
358
359 wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
360
361 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
362 continue;
363
364 ieee80211_tx_status(wl->hw, skb);
365 }
366
367 for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++)
368 if (wl->tx_frames[i] != NULL) {
369 skb = wl->tx_frames[i];
370 info = IEEE80211_SKB_CB(skb);
371
372 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
373 continue;
374
375 ieee80211_tx_status(wl->hw, skb);
376 wl->tx_frames[i] = NULL;
377 }
378}
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
new file mode 100644
index 000000000000..4a614067ddba
--- /dev/null
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -0,0 +1,130 @@
1/*
2 * This file is part of wl1271
3 *
4 * Copyright (C) 1998-2009 Texas Instruments. All rights reserved.
5 * Copyright (C) 2009 Nokia Corporation
6 *
7 * Contact: Luciano Coelho <luciano.coelho@nokia.com>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * version 2 as published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301 USA
22 *
23 */
24
25#ifndef __WL1271_TX_H__
26#define __WL1271_TX_H__
27
28#define TX_HW_BLOCK_SPARE 2
29#define TX_HW_BLOCK_SHIFT_DIV 8
30
31#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
32/* The chipset reference driver states, that the "aid" value 1
33 * is for infra-BSS, but is still always used */
34#define TX_HW_DEFAULT_AID 1
35
36#define TX_HW_ATTR_SAVE_RETRIES BIT(0)
37#define TX_HW_ATTR_HEADER_PAD BIT(1)
38#define TX_HW_ATTR_SESSION_COUNTER (BIT(2) | BIT(3) | BIT(4))
39#define TX_HW_ATTR_RATE_POLICY (BIT(5) | BIT(6) | BIT(7) | \
40 BIT(8) | BIT(9))
41#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11))
42#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12)
43
44#define TX_HW_ATTR_OFST_SAVE_RETRIES 0
45#define TX_HW_ATTR_OFST_HEADER_PAD 1
46#define TX_HW_ATTR_OFST_SESSION_COUNTER 2
47#define TX_HW_ATTR_OFST_RATE_POLICY 5
48#define TX_HW_ATTR_OFST_LAST_WORD_PAD 10
49#define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12
50
51#define TX_HW_RESULT_QUEUE_LEN 16
52#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf
53
54#define WL1271_TX_ALIGN_TO 4
55#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \
56 ~(WL1271_TX_ALIGN_TO - 1))
57#define WL1271_TKIP_IV_SPACE 4
58
59struct wl1271_tx_hw_descr {
60 /* Length of packet in words, including descriptor+header+data */
61 u16 length;
62 /* Number of extra memory blocks to allocate for this packet in
63 addition to the number of blocks derived from the packet length */
64 u8 extra_mem_blocks;
65 /* Total number of memory blocks allocated by the host for this packet.
66 Must be equal or greater than the actual blocks number allocated by
67 HW!! */
68 u8 total_mem_blocks;
69 /* Device time (in us) when the packet arrived to the driver */
70 u32 start_time;
71 /* Max delay in TUs until transmission. The last device time the
72 packet can be transmitted is: startTime+(1024*LifeTime) */
73 u16 life_time;
74 /* Bitwise fields - see TX_ATTR... definitions above. */
75 u16 tx_attr;
76 /* Packet identifier used also in the Tx-Result. */
77 u8 id;
78 /* The packet TID value (as User-Priority) */
79 u8 tid;
80 /* Identifier of the remote STA in IBSS, 1 in infra-BSS */
81 u8 aid;
82 u8 reserved;
83} __attribute__ ((packed));
84
85enum wl1271_tx_hw_res_status {
86 TX_SUCCESS = 0,
87 TX_HW_ERROR = 1,
88 TX_DISABLED = 2,
89 TX_RETRY_EXCEEDED = 3,
90 TX_TIMEOUT = 4,
91 TX_KEY_NOT_FOUND = 5,
92 TX_PEER_NOT_FOUND = 6,
93 TX_SESSION_MISMATCH = 7
94};
95
96struct wl1271_tx_hw_res_descr {
97 /* Packet Identifier - same value used in the Tx descriptor.*/
98 u8 id;
99 /* The status of the transmission, indicating success or one of
100 several possible reasons for failure. */
101 u8 status;
102 /* Total air access duration including all retrys and overheads.*/
103 u16 medium_usage;
104 /* The time passed from host xfer to Tx-complete.*/
105 u32 fw_handling_time;
106 /* Total media delay
107 (from 1st EDCA AIFS counter until TX Complete). */
108 u32 medium_delay;
109 /* LS-byte of last TKIP seq-num (saved per AC for recovery). */
110 u8 lsb_security_sequence_number;
111 /* Retry count - number of transmissions without successful ACK.*/
112 u8 ack_failures;
113 /* The rate that succeeded getting ACK
114 (Valid only if status=SUCCESS). */
115 u8 rate_class_index;
116 /* for 4-byte alignment. */
117 u8 spare;
118} __attribute__ ((packed));
119
120struct wl1271_tx_hw_res_if {
121 u32 tx_result_fw_counter;
122 u32 tx_result_host_counter;
123 struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN];
124} __attribute__ ((packed));
125
126void wl1271_tx_work(struct work_struct *work);
127void wl1271_tx_complete(struct wl1271 *wl, u32 count);
128void wl1271_tx_flush(struct wl1271 *wl);
129
130#endif
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 2c813d87092c..5e110a2328ae 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -1278,11 +1278,11 @@ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
1278 other_led = chip->link_led == LED1 ? LED2 : LED1; 1278 other_led = chip->link_led == LED1 ? LED2 : LED1;
1279 1279
1280 switch (status) { 1280 switch (status) {
1281 case LED_OFF: 1281 case ZD_LED_OFF:
1282 ioreqs[0].value = FW_LINK_OFF; 1282 ioreqs[0].value = FW_LINK_OFF;
1283 ioreqs[1].value = v[1] & ~(LED1|LED2); 1283 ioreqs[1].value = v[1] & ~(LED1|LED2);
1284 break; 1284 break;
1285 case LED_SCANNING: 1285 case ZD_LED_SCANNING:
1286 ioreqs[0].value = FW_LINK_OFF; 1286 ioreqs[0].value = FW_LINK_OFF;
1287 ioreqs[1].value = v[1] & ~other_led; 1287 ioreqs[1].value = v[1] & ~other_led;
1288 if (get_seconds() % 3 == 0) { 1288 if (get_seconds() % 3 == 0) {
@@ -1291,7 +1291,7 @@ int zd_chip_control_leds(struct zd_chip *chip, enum led_status status)
1291 ioreqs[1].value |= chip->link_led; 1291 ioreqs[1].value |= chip->link_led;
1292 } 1292 }
1293 break; 1293 break;
1294 case LED_ASSOCIATED: 1294 case ZD_LED_ASSOCIATED:
1295 ioreqs[0].value = FW_LINK_TX; 1295 ioreqs[0].value = FW_LINK_TX;
1296 ioreqs[1].value = v[1] & ~other_led; 1296 ioreqs[1].value = v[1] & ~other_led;
1297 ioreqs[1].value |= chip->link_led; 1297 ioreqs[1].value |= chip->link_led;
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h
index ee42751d5cb0..678c139a840c 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.h
+++ b/drivers/net/wireless/zd1211rw/zd_chip.h
@@ -897,9 +897,9 @@ int zd_chip_lock_phy_regs(struct zd_chip *chip);
897int zd_chip_unlock_phy_regs(struct zd_chip *chip); 897int zd_chip_unlock_phy_regs(struct zd_chip *chip);
898 898
899enum led_status { 899enum led_status {
900 LED_OFF = 0, 900 ZD_LED_OFF = 0,
901 LED_SCANNING = 1, 901 ZD_LED_SCANNING = 1,
902 LED_ASSOCIATED = 2, 902 ZD_LED_ASSOCIATED = 2,
903}; 903};
904 904
905int zd_chip_control_leds(struct zd_chip *chip, enum led_status status); 905int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 54abdd0c0045..55b7fbdc85dc 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -1013,7 +1013,7 @@ static void link_led_handler(struct work_struct *work)
1013 spin_unlock_irq(&mac->lock); 1013 spin_unlock_irq(&mac->lock);
1014 1014
1015 r = zd_chip_control_leds(chip, 1015 r = zd_chip_control_leds(chip,
1016 is_associated ? LED_ASSOCIATED : LED_SCANNING); 1016 is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING);
1017 if (r) 1017 if (r)
1018 dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r); 1018 dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
1019 1019
@@ -1038,5 +1038,5 @@ static void housekeeping_disable(struct zd_mac *mac)
1038 dev_dbg_f(zd_mac_dev(mac), "\n"); 1038 dev_dbg_f(zd_mac_dev(mac), "\n");
1039 cancel_rearming_delayed_workqueue(zd_workqueue, 1039 cancel_rearming_delayed_workqueue(zd_workqueue,
1040 &mac->housekeeping.link_led_work); 1040 &mac->housekeeping.link_led_work);
1041 zd_chip_control_leds(&mac->chip, LED_OFF); 1041 zd_chip_control_leds(&mac->chip, ZD_LED_OFF);
1042} 1042}
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 40ea41762247..593fc618a2ea 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -169,8 +169,14 @@ err_pci:
169/* Get the word-offset for a SSB_SPROM_XXX define. */ 169/* Get the word-offset for a SSB_SPROM_XXX define. */
170#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16)) 170#define SPOFF(offset) (((offset) - SSB_SPROM_BASE) / sizeof(u16))
171/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */ 171/* Helper to extract some _offset, which is one of the SSB_SPROM_XXX defines. */
172#define SPEX(_outvar, _offset, _mask, _shift) \ 172#define SPEX16(_outvar, _offset, _mask, _shift) \
173 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift)) 173 out->_outvar = ((in[SPOFF(_offset)] & (_mask)) >> (_shift))
174#define SPEX32(_outvar, _offset, _mask, _shift) \
175 out->_outvar = ((((u32)in[SPOFF((_offset)+2)] << 16 | \
176 in[SPOFF(_offset)]) & (_mask)) >> (_shift))
177#define SPEX(_outvar, _offset, _mask, _shift) \
178 SPEX16(_outvar, _offset, _mask, _shift)
179
174 180
175static inline u8 ssb_crc8(u8 crc, u8 data) 181static inline u8 ssb_crc8(u8 crc, u8 data)
176{ 182{
@@ -480,6 +486,8 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
480 SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); 486 SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0);
481 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); 487 SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0);
482 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); 488 SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0);
489 SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0);
490 SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, 0xFFFF, 0);
483 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, 491 SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A,
484 SSB_SPROM8_ANTAVAIL_A_SHIFT); 492 SSB_SPROM8_ANTAVAIL_A_SHIFT);
485 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, 493 SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG,
@@ -490,12 +498,55 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in)
490 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); 498 SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0);
491 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, 499 SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A,
492 SSB_SPROM8_ITSSI_A_SHIFT); 500 SSB_SPROM8_ITSSI_A_SHIFT);
501 SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0);
502 SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK,
503 SSB_SPROM8_MAXP_AL_SHIFT);
493 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); 504 SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0);
494 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, 505 SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1,
495 SSB_SPROM8_GPIOA_P1_SHIFT); 506 SSB_SPROM8_GPIOA_P1_SHIFT);
496 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); 507 SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0);
497 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, 508 SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3,
498 SSB_SPROM8_GPIOB_P3_SHIFT); 509 SSB_SPROM8_GPIOB_P3_SHIFT);
510 SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0);
511 SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G,
512 SSB_SPROM8_TRI5G_SHIFT);
513 SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0);
514 SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH,
515 SSB_SPROM8_TRI5GH_SHIFT);
516 SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, 0);
517 SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G,
518 SSB_SPROM8_RXPO5G_SHIFT);
519 SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0);
520 SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G,
521 SSB_SPROM8_RSSISMC2G_SHIFT);
522 SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G,
523 SSB_SPROM8_RSSISAV2G_SHIFT);
524 SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G,
525 SSB_SPROM8_BXA2G_SHIFT);
526 SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0);
527 SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G,
528 SSB_SPROM8_RSSISMC5G_SHIFT);
529 SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G,
530 SSB_SPROM8_RSSISAV5G_SHIFT);
531 SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G,
532 SSB_SPROM8_BXA5G_SHIFT);
533 SPEX(pa0b0, SSB_SPROM8_PA0B0, 0xFFFF, 0);
534 SPEX(pa0b1, SSB_SPROM8_PA0B1, 0xFFFF, 0);
535 SPEX(pa0b2, SSB_SPROM8_PA0B2, 0xFFFF, 0);
536 SPEX(pa1b0, SSB_SPROM8_PA1B0, 0xFFFF, 0);
537 SPEX(pa1b1, SSB_SPROM8_PA1B1, 0xFFFF, 0);
538 SPEX(pa1b2, SSB_SPROM8_PA1B2, 0xFFFF, 0);
539 SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, 0xFFFF, 0);
540 SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, 0xFFFF, 0);
541 SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, 0xFFFF, 0);
542 SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, 0xFFFF, 0);
543 SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, 0xFFFF, 0);
544 SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, 0xFFFF, 0);
545 SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, 0xFFFF, 0);
546 SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, 0xFFFFFFFF, 0);
547 SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, 0xFFFFFFFF, 0);
548 SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, 0xFFFFFFFF, 0);
549 SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, 0xFFFFFFFF, 0);
499 550
500 /* Extract the antenna gain values. */ 551 /* Extract the antenna gain values. */
501 SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01, 552 SPEX(antenna_gain.ghz24.a0, SSB_SPROM8_AGAIN01,
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index cb3dc6027fd9..a8d71ed43a0e 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -480,10 +480,6 @@ enum nl80211_commands {
480 * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) 480 * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz)
481 * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive 481 * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive
482 * scanning and include a zero-length SSID (wildcard) for wildcard scan 482 * scanning and include a zero-length SSID (wildcard) for wildcard scan
483 * @NL80211_ATTR_SCAN_GENERATION: the scan generation increases whenever the
484 * scan result list changes (BSS expired or added) so that applications
485 * can verify that they got a single, consistent snapshot (when all dump
486 * messages carried the same generation number)
487 * @NL80211_ATTR_BSS: scan result BSS 483 * @NL80211_ATTR_BSS: scan result BSS
488 * 484 *
489 * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain 485 * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain
@@ -580,6 +576,14 @@ enum nl80211_commands {
580 * 576 *
581 * @NL80211_ATTR_PID: Process ID of a network namespace. 577 * @NL80211_ATTR_PID: Process ID of a network namespace.
582 * 578 *
579 * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for
580 * dumps. This number increases whenever the object list being
581 * dumped changes, and as such userspace can verify that it has
582 * obtained a complete and consistent snapshot by verifying that
583 * all dump messages contain the same generation number. If it
584 * changed then the list changed and the dump should be repeated
585 * completely from scratch.
586 *
583 * @NL80211_ATTR_MAX: highest attribute number currently defined 587 * @NL80211_ATTR_MAX: highest attribute number currently defined
584 * @__NL80211_ATTR_AFTER_LAST: internal use 588 * @__NL80211_ATTR_AFTER_LAST: internal use
585 */ 589 */
@@ -651,7 +655,7 @@ enum nl80211_attrs {
651 655
652 NL80211_ATTR_SCAN_FREQUENCIES, 656 NL80211_ATTR_SCAN_FREQUENCIES,
653 NL80211_ATTR_SCAN_SSIDS, 657 NL80211_ATTR_SCAN_SSIDS,
654 NL80211_ATTR_SCAN_GENERATION, 658 NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */
655 NL80211_ATTR_BSS, 659 NL80211_ATTR_BSS,
656 660
657 NL80211_ATTR_REG_INITIATOR, 661 NL80211_ATTR_REG_INITIATOR,
@@ -716,6 +720,9 @@ enum nl80211_attrs {
716 NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 720 NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
717}; 721};
718 722
723/* source-level API compatibility */
724#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
725
719/* 726/*
720 * Allow user space programs to use #ifdef on new attributes by defining them 727 * Allow user space programs to use #ifdef on new attributes by defining them
721 * here 728 * here
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 5ae8fa22d331..17ffc1f84d76 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -27,24 +27,54 @@ struct ssb_sprom {
27 u8 et1mdcport; /* MDIO for enet1 */ 27 u8 et1mdcport; /* MDIO for enet1 */
28 u8 board_rev; /* Board revision number from SPROM. */ 28 u8 board_rev; /* Board revision number from SPROM. */
29 u8 country_code; /* Country Code */ 29 u8 country_code; /* Country Code */
30 u8 ant_available_a; /* A-PHY antenna available bits (up to 4) */ 30 u8 ant_available_a; /* 2GHz antenna available bits (up to 4) */
31 u8 ant_available_bg; /* B/G-PHY antenna available bits (up to 4) */ 31 u8 ant_available_bg; /* 5GHz antenna available bits (up to 4) */
32 u16 pa0b0; 32 u16 pa0b0;
33 u16 pa0b1; 33 u16 pa0b1;
34 u16 pa0b2; 34 u16 pa0b2;
35 u16 pa1b0; 35 u16 pa1b0;
36 u16 pa1b1; 36 u16 pa1b1;
37 u16 pa1b2; 37 u16 pa1b2;
38 u16 pa1lob0;
39 u16 pa1lob1;
40 u16 pa1lob2;
41 u16 pa1hib0;
42 u16 pa1hib1;
43 u16 pa1hib2;
38 u8 gpio0; /* GPIO pin 0 */ 44 u8 gpio0; /* GPIO pin 0 */
39 u8 gpio1; /* GPIO pin 1 */ 45 u8 gpio1; /* GPIO pin 1 */
40 u8 gpio2; /* GPIO pin 2 */ 46 u8 gpio2; /* GPIO pin 2 */
41 u8 gpio3; /* GPIO pin 3 */ 47 u8 gpio3; /* GPIO pin 3 */
42 u16 maxpwr_a; /* A-PHY Amplifier Max Power (in dBm Q5.2) */ 48 u16 maxpwr_bg; /* 2.4GHz Amplifier Max Power (in dBm Q5.2) */
43 u16 maxpwr_bg; /* B/G-PHY Amplifier Max Power (in dBm Q5.2) */ 49 u16 maxpwr_al; /* 5.2GHz Amplifier Max Power (in dBm Q5.2) */
50 u16 maxpwr_a; /* 5.3GHz Amplifier Max Power (in dBm Q5.2) */
51 u16 maxpwr_ah; /* 5.8GHz Amplifier Max Power (in dBm Q5.2) */
44 u8 itssi_a; /* Idle TSSI Target for A-PHY */ 52 u8 itssi_a; /* Idle TSSI Target for A-PHY */
45 u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */ 53 u8 itssi_bg; /* Idle TSSI Target for B/G-PHY */
46 u16 boardflags_lo; /* Boardflags (low 16 bits) */ 54 u8 tri2g; /* 2.4GHz TX isolation */
47 u16 boardflags_hi; /* Boardflags (high 16 bits) */ 55 u8 tri5gl; /* 5.2GHz TX isolation */
56 u8 tri5g; /* 5.3GHz TX isolation */
57 u8 tri5gh; /* 5.8GHz TX isolation */
58 u8 rxpo2g; /* 2GHz RX power offset */
59 u8 rxpo5g; /* 5GHz RX power offset */
60 u8 rssisav2g; /* 2GHz RSSI params */
61 u8 rssismc2g;
62 u8 rssismf2g;
63 u8 bxa2g; /* 2GHz BX arch */
64 u8 rssisav5g; /* 5GHz RSSI params */
65 u8 rssismc5g;
66 u8 rssismf5g;
67 u8 bxa5g; /* 5GHz BX arch */
68 u16 cck2gpo; /* CCK power offset */
69 u32 ofdm2gpo; /* 2.4GHz OFDM power offset */
70 u32 ofdm5glpo; /* 5.2GHz OFDM power offset */
71 u32 ofdm5gpo; /* 5.3GHz OFDM power offset */
72 u32 ofdm5ghpo; /* 5.8GHz OFDM power offset */
73 u16 boardflags_lo; /* Board flags (bits 0-15) */
74 u16 boardflags_hi; /* Board flags (bits 16-31) */
75 u16 boardflags2_lo; /* Board flags (bits 32-47) */
76 u16 boardflags2_hi; /* Board flags (bits 48-63) */
77 /* TODO store board flags in a single u64 */
48 78
49 /* Antenna gain values for up to 4 antennas 79 /* Antenna gain values for up to 4 antennas
50 * on each band. Values in dBm/4 (Q5.2). Negative gain means the 80 * on each band. Values in dBm/4 (Q5.2). Negative gain means the
@@ -58,7 +88,7 @@ struct ssb_sprom {
58 } ghz5; /* 5GHz band */ 88 } ghz5; /* 5GHz band */
59 } antenna_gain; 89 } antenna_gain;
60 90
61 /* TODO - add any parameters needed from rev 2, 3, or 4 SPROMs */ 91 /* TODO - add any parameters needed from rev 2, 3, 4, 5 or 8 SPROMs */
62}; 92};
63 93
64/* Information about the PCB the circuitry is soldered on. */ 94/* Information about the PCB the circuitry is soldered on. */
diff --git a/include/linux/ssb/ssb_regs.h b/include/linux/ssb/ssb_regs.h
index a01b982b5783..9ae9082eaeb4 100644
--- a/include/linux/ssb/ssb_regs.h
+++ b/include/linux/ssb/ssb_regs.h
@@ -162,7 +162,7 @@
162 162
163/* SPROM shadow area. If not otherwise noted, fields are 163/* SPROM shadow area. If not otherwise noted, fields are
164 * two bytes wide. Note that the SPROM can _only_ be read 164 * two bytes wide. Note that the SPROM can _only_ be read
165 * in two-byte quantinies. 165 * in two-byte quantities.
166 */ 166 */
167#define SSB_SPROMSIZE_WORDS 64 167#define SSB_SPROMSIZE_WORDS 64
168#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16)) 168#define SSB_SPROMSIZE_BYTES (SSB_SPROMSIZE_WORDS * sizeof(u16))
@@ -327,8 +327,11 @@
327#define SSB_SPROM5_GPIOB_P3_SHIFT 8 327#define SSB_SPROM5_GPIOB_P3_SHIFT 8
328 328
329/* SPROM Revision 8 */ 329/* SPROM Revision 8 */
330#define SSB_SPROM8_BFLLO 0x1084 /* Boardflags (low 16 bits) */ 330#define SSB_SPROM8_BOARDREV 0x1082 /* Board revision */
331#define SSB_SPROM8_BFLHI 0x1086 /* Boardflags Hi */ 331#define SSB_SPROM8_BFLLO 0x1084 /* Board flags (bits 0-15) */
332#define SSB_SPROM8_BFLHI 0x1086 /* Board flags (bits 16-31) */
333#define SSB_SPROM8_BFL2LO 0x1088 /* Board flags (bits 32-47) */
334#define SSB_SPROM8_BFL2HI 0x108A /* Board flags (bits 48-63) */
332#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */ 335#define SSB_SPROM8_IL0MAC 0x108C /* 6 byte MAC address */
333#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */ 336#define SSB_SPROM8_CCODE 0x1092 /* 2 byte country code */
334#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/ 337#define SSB_SPROM8_ANTAVAIL 0x109C /* Antenna available bitfields*/
@@ -354,14 +357,63 @@
354#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */ 357#define SSB_SPROM8_GPIOB_P2 0x00FF /* Pin 2 */
355#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */ 358#define SSB_SPROM8_GPIOB_P3 0xFF00 /* Pin 3 */
356#define SSB_SPROM8_GPIOB_P3_SHIFT 8 359#define SSB_SPROM8_GPIOB_P3_SHIFT 8
357#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power BG in path 1 */ 360#define SSB_SPROM8_RSSIPARM2G 0x10A4 /* RSSI params for 2GHz */
358#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power BG */ 361#define SSB_SPROM8_RSSISMF2G 0x000F
362#define SSB_SPROM8_RSSISMC2G 0x00F0
363#define SSB_SPROM8_RSSISMC2G_SHIFT 4
364#define SSB_SPROM8_RSSISAV2G 0x0700
365#define SSB_SPROM8_RSSISAV2G_SHIFT 8
366#define SSB_SPROM8_BXA2G 0x1800
367#define SSB_SPROM8_BXA2G_SHIFT 11
368#define SSB_SPROM8_RSSIPARM5G 0x10A6 /* RSSI params for 5GHz */
369#define SSB_SPROM8_RSSISMF5G 0x000F
370#define SSB_SPROM8_RSSISMC5G 0x00F0
371#define SSB_SPROM8_RSSISMC5G_SHIFT 4
372#define SSB_SPROM8_RSSISAV5G 0x0700
373#define SSB_SPROM8_RSSISAV5G_SHIFT 8
374#define SSB_SPROM8_BXA5G 0x1800
375#define SSB_SPROM8_BXA5G_SHIFT 11
376#define SSB_SPROM8_TRI25G 0x10A8 /* TX isolation 2.4&5.3GHz */
377#define SSB_SPROM8_TRI2G 0x00FF /* TX isolation 2.4GHz */
378#define SSB_SPROM8_TRI5G 0xFF00 /* TX isolation 5.3GHz */
379#define SSB_SPROM8_TRI5G_SHIFT 8
380#define SSB_SPROM8_TRI5GHL 0x10AA /* TX isolation 5.2/5.8GHz */
381#define SSB_SPROM8_TRI5GL 0x00FF /* TX isolation 5.2GHz */
382#define SSB_SPROM8_TRI5GH 0xFF00 /* TX isolation 5.8GHz */
383#define SSB_SPROM8_TRI5GH_SHIFT 8
384#define SSB_SPROM8_RXPO 0x10AC /* RX power offsets */
385#define SSB_SPROM8_RXPO2G 0x00FF /* 2GHz RX power offset */
386#define SSB_SPROM8_RXPO5G 0xFF00 /* 5GHz RX power offset */
387#define SSB_SPROM8_RXPO5G_SHIFT 8
388#define SSB_SPROM8_MAXP_BG 0x10C0 /* Max Power 2GHz in path 1 */
389#define SSB_SPROM8_MAXP_BG_MASK 0x00FF /* Mask for Max Power 2GHz */
359#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */ 390#define SSB_SPROM8_ITSSI_BG 0xFF00 /* Mask for path 1 itssi_bg */
360#define SSB_SPROM8_ITSSI_BG_SHIFT 8 391#define SSB_SPROM8_ITSSI_BG_SHIFT 8
361#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power A in path 1 */ 392#define SSB_SPROM8_PA0B0 0x10C2 /* 2GHz power amp settings */
362#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power A */ 393#define SSB_SPROM8_PA0B1 0x10C4
394#define SSB_SPROM8_PA0B2 0x10C6
395#define SSB_SPROM8_MAXP_A 0x10C8 /* Max Power 5.3GHz */
396#define SSB_SPROM8_MAXP_A_MASK 0x00FF /* Mask for Max Power 5.3GHz */
363#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */ 397#define SSB_SPROM8_ITSSI_A 0xFF00 /* Mask for path 1 itssi_a */
364#define SSB_SPROM8_ITSSI_A_SHIFT 8 398#define SSB_SPROM8_ITSSI_A_SHIFT 8
399#define SSB_SPROM8_MAXP_AHL 0x10CA /* Max Power 5.2/5.8GHz */
400#define SSB_SPROM8_MAXP_AH_MASK 0x00FF /* Mask for Max Power 5.8GHz */
401#define SSB_SPROM8_MAXP_AL_MASK 0xFF00 /* Mask for Max Power 5.2GHz */
402#define SSB_SPROM8_MAXP_AL_SHIFT 8
403#define SSB_SPROM8_PA1B0 0x10CC /* 5.3GHz power amp settings */
404#define SSB_SPROM8_PA1B1 0x10CE
405#define SSB_SPROM8_PA1B2 0x10D0
406#define SSB_SPROM8_PA1LOB0 0x10D2 /* 5.2GHz power amp settings */
407#define SSB_SPROM8_PA1LOB1 0x10D4
408#define SSB_SPROM8_PA1LOB2 0x10D6
409#define SSB_SPROM8_PA1HIB0 0x10D8 /* 5.8GHz power amp settings */
410#define SSB_SPROM8_PA1HIB1 0x10DA
411#define SSB_SPROM8_PA1HIB2 0x10DC
412#define SSB_SPROM8_CCK2GPO 0x1140 /* CCK power offset */
413#define SSB_SPROM8_OFDM2GPO 0x1142 /* 2.4GHz OFDM power offset */
414#define SSB_SPROM8_OFDM5GPO 0x1146 /* 5.3GHz OFDM power offset */
415#define SSB_SPROM8_OFDM5GLPO 0x114A /* 5.2GHz OFDM power offset */
416#define SSB_SPROM8_OFDM5GHPO 0x114E /* 5.8GHz OFDM power offset */
365 417
366/* Values for SSB_SPROM1_BINF_CCODE */ 418/* Values for SSB_SPROM1_BINF_CCODE */
367enum { 419enum {
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index de8b4b18961b..09514252d84e 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -53,6 +53,7 @@ struct usbnet {
53 struct sk_buff_head rxq; 53 struct sk_buff_head rxq;
54 struct sk_buff_head txq; 54 struct sk_buff_head txq;
55 struct sk_buff_head done; 55 struct sk_buff_head done;
56 struct sk_buff_head rxq_pause;
56 struct urb *interrupt; 57 struct urb *interrupt;
57 struct tasklet_struct bh; 58 struct tasklet_struct bh;
58 59
@@ -63,6 +64,7 @@ struct usbnet {
63# define EVENT_RX_MEMORY 2 64# define EVENT_RX_MEMORY 2
64# define EVENT_STS_SPLIT 3 65# define EVENT_STS_SPLIT 3
65# define EVENT_LINK_RESET 4 66# define EVENT_LINK_RESET 4
67# define EVENT_RX_PAUSED 5
66}; 68};
67 69
68static inline struct usb_driver *driver_of(struct usb_interface *intf) 70static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -190,6 +192,10 @@ extern void usbnet_defer_kevent (struct usbnet *, int);
190extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); 192extern void usbnet_skb_return (struct usbnet *, struct sk_buff *);
191extern void usbnet_unlink_rx_urbs(struct usbnet *); 193extern void usbnet_unlink_rx_urbs(struct usbnet *);
192 194
195extern void usbnet_pause_rx(struct usbnet *);
196extern void usbnet_resume_rx(struct usbnet *);
197extern void usbnet_purge_paused_rxq(struct usbnet *);
198
193extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd); 199extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd);
194extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd); 200extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd);
195extern u32 usbnet_get_link (struct net_device *net); 201extern u32 usbnet_get_link (struct net_device *net);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 64df51d9a89f..0b146bb2dd14 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -80,7 +80,6 @@ enum ieee80211_channel_flags {
80 * with cfg80211. 80 * with cfg80211.
81 * 81 *
82 * @center_freq: center frequency in MHz 82 * @center_freq: center frequency in MHz
83 * @max_bandwidth: maximum allowed bandwidth for this channel, in MHz
84 * @hw_value: hardware-specific value for the channel 83 * @hw_value: hardware-specific value for the channel
85 * @flags: channel flags from &enum ieee80211_channel_flags. 84 * @flags: channel flags from &enum ieee80211_channel_flags.
86 * @orig_flags: channel flags at registration time, used by regulatory 85 * @orig_flags: channel flags at registration time, used by regulatory
@@ -97,7 +96,6 @@ enum ieee80211_channel_flags {
97struct ieee80211_channel { 96struct ieee80211_channel {
98 enum ieee80211_band band; 97 enum ieee80211_band band;
99 u16 center_freq; 98 u16 center_freq;
100 u8 max_bandwidth;
101 u16 hw_value; 99 u16 hw_value;
102 u32 flags; 100 u32 flags;
103 int max_antenna_gain; 101 int max_antenna_gain;
@@ -372,6 +370,10 @@ struct rate_info {
372 * @txrate: current unicast bitrate to this station 370 * @txrate: current unicast bitrate to this station
373 * @rx_packets: packets received from this station 371 * @rx_packets: packets received from this station
374 * @tx_packets: packets transmitted to this station 372 * @tx_packets: packets transmitted to this station
373 * @generation: generation number for nl80211 dumps.
374 * This number should increase every time the list of stations
375 * changes, i.e. when a station is added or removed, so that
376 * userspace can tell whether it got a consistent snapshot.
375 */ 377 */
376struct station_info { 378struct station_info {
377 u32 filled; 379 u32 filled;
@@ -385,6 +387,8 @@ struct station_info {
385 struct rate_info txrate; 387 struct rate_info txrate;
386 u32 rx_packets; 388 u32 rx_packets;
387 u32 tx_packets; 389 u32 tx_packets;
390
391 int generation;
388}; 392};
389 393
390/** 394/**
@@ -444,6 +448,10 @@ enum mpath_info_flags {
444 * @flags: mesh path flags 448 * @flags: mesh path flags
445 * @discovery_timeout: total mesh path discovery timeout, in msecs 449 * @discovery_timeout: total mesh path discovery timeout, in msecs
446 * @discovery_retries: mesh path discovery retries 450 * @discovery_retries: mesh path discovery retries
451 * @generation: generation number for nl80211 dumps.
452 * This number should increase every time the list of mesh paths
453 * changes, i.e. when a station is added or removed, so that
454 * userspace can tell whether it got a consistent snapshot.
447 */ 455 */
448struct mpath_info { 456struct mpath_info {
449 u32 filled; 457 u32 filled;
@@ -454,6 +462,8 @@ struct mpath_info {
454 u32 discovery_timeout; 462 u32 discovery_timeout;
455 u8 discovery_retries; 463 u8 discovery_retries;
456 u8 flags; 464 u8 flags;
465
466 int generation;
457}; 467};
458 468
459/** 469/**
@@ -547,7 +557,6 @@ struct cfg80211_ssid {
547struct cfg80211_scan_request { 557struct cfg80211_scan_request {
548 struct cfg80211_ssid *ssids; 558 struct cfg80211_ssid *ssids;
549 int n_ssids; 559 int n_ssids;
550 struct ieee80211_channel **channels;
551 u32 n_channels; 560 u32 n_channels;
552 const u8 *ie; 561 const u8 *ie;
553 size_t ie_len; 562 size_t ie_len;
@@ -556,6 +565,9 @@ struct cfg80211_scan_request {
556 struct wiphy *wiphy; 565 struct wiphy *wiphy;
557 struct net_device *dev; 566 struct net_device *dev;
558 bool aborted; 567 bool aborted;
568
569 /* keep last */
570 struct ieee80211_channel *channels[0];
559}; 571};
560 572
561/** 573/**
@@ -1096,6 +1108,9 @@ struct cfg80211_ops {
1096 * @net: the network namespace this wiphy currently lives in 1108 * @net: the network namespace this wiphy currently lives in
1097 * @netnsok: if set to false, do not allow changing the netns of this 1109 * @netnsok: if set to false, do not allow changing the netns of this
1098 * wiphy at all 1110 * wiphy at all
1111 * @ps_default: default for powersave, will be set depending on the
1112 * kernel's default on wiphy_new(), but can be changed by the
1113 * driver if it has a good reason to override the default
1099 */ 1114 */
1100struct wiphy { 1115struct wiphy {
1101 /* assign these fields before you register the wiphy */ 1116 /* assign these fields before you register the wiphy */
@@ -1111,6 +1126,7 @@ struct wiphy {
1111 bool disable_beacon_hints; 1126 bool disable_beacon_hints;
1112 1127
1113 bool netnsok; 1128 bool netnsok;
1129 bool ps_default;
1114 1130
1115 enum cfg80211_signal_type signal_type; 1131 enum cfg80211_signal_type signal_type;
1116 1132
@@ -1335,10 +1351,10 @@ struct wireless_dev {
1335 struct cfg80211_cached_keys *keys; 1351 struct cfg80211_cached_keys *keys;
1336 u8 *ie; 1352 u8 *ie;
1337 size_t ie_len; 1353 size_t ie_len;
1338 u8 bssid[ETH_ALEN]; 1354 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
1339 u8 ssid[IEEE80211_MAX_SSID_LEN]; 1355 u8 ssid[IEEE80211_MAX_SSID_LEN];
1340 s8 default_key, default_mgmt_key; 1356 s8 default_key, default_mgmt_key;
1341 bool ps; 1357 bool ps, prev_bssid_valid;
1342 int ps_timeout; 1358 int ps_timeout;
1343 } wext; 1359 } wext;
1344#endif 1360#endif
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index e2fb5767e1fa..76d43e12cc29 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -239,7 +239,14 @@ struct ieee80211_bss_conf {
239 * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU 239 * @IEEE80211_TX_CTL_AMPDU: this frame should be sent as part of an A-MPDU
240 * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211. 240 * @IEEE80211_TX_CTL_INJECTED: Frame was injected, internal to mac80211.
241 * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted 241 * @IEEE80211_TX_STAT_TX_FILTERED: The frame was not transmitted
242 * because the destination STA was in powersave mode. 242 * because the destination STA was in powersave mode. Note that to
243 * avoid race conditions, the filter must be set by the hardware or
244 * firmware upon receiving a frame that indicates that the station
245 * went to sleep (must be done on device to filter frames already on
246 * the queue) and may only be unset after mac80211 gives the OK for
247 * that by setting the IEEE80211_TX_CTL_CLEAR_PS_FILT (see above),
248 * since only then is it guaranteed that no more frames are in the
249 * hardware queue.
243 * @IEEE80211_TX_STAT_ACK: Frame was acknowledged 250 * @IEEE80211_TX_STAT_ACK: Frame was acknowledged
244 * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status 251 * @IEEE80211_TX_STAT_AMPDU: The frame was aggregated, so status
245 * is for the whole aggregation. 252 * is for the whole aggregation.
@@ -261,6 +268,10 @@ struct ieee80211_bss_conf {
261 * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?) 268 * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?)
262 * This frame is a response to a PS-poll frame and should be sent 269 * This frame is a response to a PS-poll frame and should be sent
263 * although the station is in powersave mode. 270 * although the station is in powersave mode.
271 * @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the
272 * transmit function after the current frame, this can be used
273 * by drivers to kick the DMA queue only if unset or when the
274 * queue gets full.
264 */ 275 */
265enum mac80211_tx_control_flags { 276enum mac80211_tx_control_flags {
266 IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0), 277 IEEE80211_TX_CTL_REQ_TX_STATUS = BIT(0),
@@ -281,6 +292,7 @@ enum mac80211_tx_control_flags {
281 IEEE80211_TX_INTFL_RETRIED = BIT(15), 292 IEEE80211_TX_INTFL_RETRIED = BIT(15),
282 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16), 293 IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
283 IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17), 294 IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
295 IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
284}; 296};
285 297
286/** 298/**
@@ -338,6 +350,21 @@ enum mac80211_rate_control_flags {
338 * 350 *
339 * When used for transmit status reporting, the driver should 351 * When used for transmit status reporting, the driver should
340 * always report the rate along with the flags it used. 352 * always report the rate along with the flags it used.
353 *
354 * &struct ieee80211_tx_info contains an array of these structs
355 * in the control information, and it will be filled by the rate
356 * control algorithm according to what should be sent. For example,
357 * if this array contains, in the format { <idx>, <count> } the
358 * information
359 * { 3, 2 }, { 2, 2 }, { 1, 4 }, { -1, 0 }, { -1, 0 }
360 * then this means that the frame should be transmitted
361 * up to twice at rate 3, up to twice at rate 2, and up to four
362 * times at rate 1 if it doesn't get acknowledged. Say it gets
363 * acknowledged by the peer after the fifth attempt, the status
364 * information should then contain
365 * { 3, 2 }, { 2, 2 }, { 1, 1 }, { -1, 0 } ...
366 * since it was transmitted twice at rate 3, twice at rate 2
367 * and once at rate 1 after which we received an acknowledgement.
341 */ 368 */
342struct ieee80211_tx_rate { 369struct ieee80211_tx_rate {
343 s8 idx; 370 s8 idx;
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 7dd77b6d4c9a..9db4ff836a3d 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -66,12 +66,12 @@ endmenu
66config MAC80211_MESH 66config MAC80211_MESH
67 bool "Enable mac80211 mesh networking (pre-802.11s) support" 67 bool "Enable mac80211 mesh networking (pre-802.11s) support"
68 depends on MAC80211 && EXPERIMENTAL 68 depends on MAC80211 && EXPERIMENTAL
69 depends on BROKEN
70 ---help--- 69 ---help---
71 This options enables support of Draft 802.11s mesh networking. 70 This options enables support of Draft 802.11s mesh networking.
72 The implementation is based on Draft 1.08 of the Mesh Networking 71 The implementation is based on Draft 2.08 of the Mesh Networking
73 amendment. For more information visit http://o11s.org/. 72 amendment. However, no compliance with that draft is claimed or even
74 73 possible, as drafts leave a number of identifiers to be defined after
74 ratification. For more information visit http://o11s.org/.
75 75
76config MAC80211_LEDS 76config MAC80211_LEDS
77 bool "Enable LED triggers" 77 bool "Enable LED triggers"
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4bbf5007799b..5608f6c68413 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -323,6 +323,8 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
323{ 323{
324 struct ieee80211_sub_if_data *sdata = sta->sdata; 324 struct ieee80211_sub_if_data *sdata = sta->sdata;
325 325
326 sinfo->generation = sdata->local->sta_generation;
327
326 sinfo->filled = STATION_INFO_INACTIVE_TIME | 328 sinfo->filled = STATION_INFO_INACTIVE_TIME |
327 STATION_INFO_RX_BYTES | 329 STATION_INFO_RX_BYTES |
328 STATION_INFO_TX_BYTES | 330 STATION_INFO_TX_BYTES |
@@ -909,6 +911,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
909 else 911 else
910 memset(next_hop, 0, ETH_ALEN); 912 memset(next_hop, 0, ETH_ALEN);
911 913
914 pinfo->generation = mesh_paths_generation;
915
912 pinfo->filled = MPATH_INFO_FRAME_QLEN | 916 pinfo->filled = MPATH_INFO_FRAME_QLEN |
913 MPATH_INFO_DSN | 917 MPATH_INFO_DSN |
914 MPATH_INFO_METRIC | 918 MPATH_INFO_METRIC |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 630a438180fd..a6abc7dfd903 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -284,6 +284,7 @@ struct ieee80211_if_managed {
284 284
285 struct mutex mtx; 285 struct mutex mtx;
286 struct ieee80211_bss *associated; 286 struct ieee80211_bss *associated;
287 struct ieee80211_mgd_work *old_associate_work;
287 struct list_head work_list; 288 struct list_head work_list;
288 289
289 u8 bssid[ETH_ALEN]; 290 u8 bssid[ETH_ALEN];
@@ -354,7 +355,7 @@ struct ieee80211_if_mesh {
354 355
355 unsigned long timers_running; 356 unsigned long timers_running;
356 357
357 bool housekeeping; 358 unsigned long wrkq_flags;
358 359
359 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; 360 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
360 size_t mesh_id_len; 361 size_t mesh_id_len;
@@ -677,6 +678,7 @@ struct ieee80211_local {
677 struct list_head sta_list; 678 struct list_head sta_list;
678 struct sta_info *sta_hash[STA_HASH_SIZE]; 679 struct sta_info *sta_hash[STA_HASH_SIZE];
679 struct timer_list sta_cleanup; 680 struct timer_list sta_cleanup;
681 int sta_generation;
680 682
681 struct sk_buff_head pending[IEEE80211_MAX_QUEUES]; 683 struct sk_buff_head pending[IEEE80211_MAX_QUEUES];
682 struct tasklet_struct tx_pending_tasklet; 684 struct tasklet_struct tx_pending_tasklet;
@@ -713,7 +715,7 @@ struct ieee80211_local {
713 struct mutex scan_mtx; 715 struct mutex scan_mtx;
714 unsigned long scanning; 716 unsigned long scanning;
715 struct cfg80211_ssid scan_ssid; 717 struct cfg80211_ssid scan_ssid;
716 struct cfg80211_scan_request int_scan_req; 718 struct cfg80211_scan_request *int_scan_req;
717 struct cfg80211_scan_request *scan_req; 719 struct cfg80211_scan_request *scan_req;
718 struct ieee80211_channel *scan_channel; 720 struct ieee80211_channel *scan_channel;
719 const u8 *orig_ies; 721 const u8 *orig_ies;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 0c4f8e122ed6..b03fd84777fa 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -765,9 +765,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
765 supp_ht = supp_ht || sband->ht_cap.ht_supported; 765 supp_ht = supp_ht || sband->ht_cap.ht_supported;
766 } 766 }
767 767
768 local->int_scan_req.n_channels = channels; 768 local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
769 local->int_scan_req.channels = kzalloc(sizeof(void *) * channels, GFP_KERNEL); 769 sizeof(void *) * channels, GFP_KERNEL);
770 if (!local->int_scan_req.channels) 770 if (!local->int_scan_req)
771 return -ENOMEM; 771 return -ENOMEM;
772 772
773 /* if low-level driver supports AP, we also support VLAN */ 773 /* if low-level driver supports AP, we also support VLAN */
@@ -882,13 +882,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
882 882
883 /* alloc internal scan request */ 883 /* alloc internal scan request */
884 i = 0; 884 i = 0;
885 local->int_scan_req.ssids = &local->scan_ssid; 885 local->int_scan_req->ssids = &local->scan_ssid;
886 local->int_scan_req.n_ssids = 1; 886 local->int_scan_req->n_ssids = 1;
887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 887 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
888 if (!hw->wiphy->bands[band]) 888 if (!hw->wiphy->bands[band])
889 continue; 889 continue;
890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) { 890 for (j = 0; j < hw->wiphy->bands[band]->n_channels; j++) {
891 local->int_scan_req.channels[i] = 891 local->int_scan_req->channels[i] =
892 &hw->wiphy->bands[band]->channels[j]; 892 &hw->wiphy->bands[band]->channels[j];
893 i++; 893 i++;
894 } 894 }
@@ -920,7 +920,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
920 fail_workqueue: 920 fail_workqueue:
921 wiphy_unregister(local->hw.wiphy); 921 wiphy_unregister(local->hw.wiphy);
922 fail_wiphy_register: 922 fail_wiphy_register:
923 kfree(local->int_scan_req.channels); 923 kfree(local->int_scan_req->channels);
924 return result; 924 return result;
925} 925}
926EXPORT_SYMBOL(ieee80211_register_hw); 926EXPORT_SYMBOL(ieee80211_register_hw);
@@ -962,7 +962,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
962 wiphy_unregister(local->hw.wiphy); 962 wiphy_unregister(local->hw.wiphy);
963 ieee80211_wep_free(local); 963 ieee80211_wep_free(local);
964 ieee80211_led_exit(local); 964 ieee80211_led_exit(local);
965 kfree(local->int_scan_req.channels); 965 kfree(local->int_scan_req);
966} 966}
967EXPORT_SYMBOL(ieee80211_unregister_hw); 967EXPORT_SYMBOL(ieee80211_unregister_hw);
968 968
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2f4f518ab45c..3185e18c8214 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -47,14 +47,14 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
47 struct ieee80211_local *local = sdata->local; 47 struct ieee80211_local *local = sdata->local;
48 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 48 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
49 49
50 ifmsh->housekeeping = true; 50 ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
51 51
52 if (local->quiescing) { 52 if (local->quiescing) {
53 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running); 53 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
54 return; 54 return;
55 } 55 }
56 56
57 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 57 ieee80211_queue_work(&local->hw, &ifmsh->work);
58} 58}
59 59
60/** 60/**
@@ -320,30 +320,6 @@ struct mesh_table *mesh_table_alloc(int size_order)
320 return newtbl; 320 return newtbl;
321} 321}
322 322
323static void __mesh_table_free(struct mesh_table *tbl)
324{
325 kfree(tbl->hash_buckets);
326 kfree(tbl->hashwlock);
327 kfree(tbl);
328}
329
330void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
331{
332 struct hlist_head *mesh_hash;
333 struct hlist_node *p, *q;
334 int i;
335
336 mesh_hash = tbl->hash_buckets;
337 for (i = 0; i <= tbl->hash_mask; i++) {
338 spin_lock(&tbl->hashwlock[i]);
339 hlist_for_each_safe(p, q, &mesh_hash[i]) {
340 tbl->free_node(p, free_leafs);
341 atomic_dec(&tbl->entries);
342 }
343 spin_unlock(&tbl->hashwlock[i]);
344 }
345 __mesh_table_free(tbl);
346}
347 323
348static void ieee80211_mesh_path_timer(unsigned long data) 324static void ieee80211_mesh_path_timer(unsigned long data)
349{ 325{
@@ -357,63 +333,79 @@ static void ieee80211_mesh_path_timer(unsigned long data)
357 return; 333 return;
358 } 334 }
359 335
360 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 336 ieee80211_queue_work(&local->hw, &ifmsh->work);
361} 337}
362 338
363struct mesh_table *mesh_table_grow(struct mesh_table *tbl) 339/**
364{ 340 * ieee80211_fill_mesh_addresses - fill addresses of a locally originated mesh frame
365 struct mesh_table *newtbl; 341 * @hdr: 802.11 frame header
366 struct hlist_head *oldhash; 342 * @fc: frame control field
367 struct hlist_node *p, *q; 343 * @meshda: destination address in the mesh
368 int i; 344 * @meshsa: source address address in the mesh. Same as TA, as frame is
369 345 * locally originated.
370 if (atomic_read(&tbl->entries) 346 *
371 < tbl->mean_chain_len * (tbl->hash_mask + 1)) 347 * Return the length of the 802.11 (does not include a mesh control header)
372 goto endgrow; 348 */
373 349int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char
374 newtbl = mesh_table_alloc(tbl->size_order + 1); 350 *meshda, char *meshsa) {
375 if (!newtbl) 351 if (is_multicast_ether_addr(meshda)) {
376 goto endgrow; 352 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
377 353 /* DA TA SA */
378 newtbl->free_node = tbl->free_node; 354 memcpy(hdr->addr1, meshda, ETH_ALEN);
379 newtbl->mean_chain_len = tbl->mean_chain_len; 355 memcpy(hdr->addr2, meshsa, ETH_ALEN);
380 newtbl->copy_node = tbl->copy_node; 356 memcpy(hdr->addr3, meshsa, ETH_ALEN);
381 atomic_set(&newtbl->entries, atomic_read(&tbl->entries)); 357 return 24;
382 358 } else {
383 oldhash = tbl->hash_buckets; 359 *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
384 for (i = 0; i <= tbl->hash_mask; i++) 360 IEEE80211_FCTL_TODS);
385 hlist_for_each(p, &oldhash[i]) 361 /* RA TA DA SA */
386 if (tbl->copy_node(p, newtbl) < 0) 362 memset(hdr->addr1, 0, ETH_ALEN); /* RA is resolved later */
387 goto errcopy; 363 memcpy(hdr->addr2, meshsa, ETH_ALEN);
388 364 memcpy(hdr->addr3, meshda, ETH_ALEN);
389 return newtbl; 365 memcpy(hdr->addr4, meshsa, ETH_ALEN);
390 366 return 30;
391errcopy:
392 for (i = 0; i <= newtbl->hash_mask; i++) {
393 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
394 tbl->free_node(p, 0);
395 } 367 }
396 __mesh_table_free(newtbl);
397endgrow:
398 return NULL;
399} 368}
400 369
401/** 370/**
402 * ieee80211_new_mesh_header - create a new mesh header 371 * ieee80211_new_mesh_header - create a new mesh header
403 * @meshhdr: uninitialized mesh header 372 * @meshhdr: uninitialized mesh header
404 * @sdata: mesh interface to be used 373 * @sdata: mesh interface to be used
374 * @addr4: addr4 of the mesh frame (1st in ae header)
375 * may be NULL
376 * @addr5: addr5 of the mesh frame (1st or 2nd in ae header)
377 * may be NULL unless addr6 is present
378 * @addr6: addr6 of the mesh frame (2nd or 3rd in ae header)
379 * may be NULL unless addr5 is present
405 * 380 *
406 * Return the header length. 381 * Return the header length.
407 */ 382 */
408int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 383int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
409 struct ieee80211_sub_if_data *sdata) 384 struct ieee80211_sub_if_data *sdata, char *addr4,
385 char *addr5, char *addr6)
410{ 386{
411 meshhdr->flags = 0; 387 int aelen = 0;
388 memset(meshhdr, 0, sizeof(meshhdr));
412 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL; 389 meshhdr->ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
413 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum); 390 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &meshhdr->seqnum);
414 sdata->u.mesh.mesh_seqnum++; 391 sdata->u.mesh.mesh_seqnum++;
415 392 if (addr4) {
416 return 6; 393 meshhdr->flags |= MESH_FLAGS_AE_A4;
394 aelen += ETH_ALEN;
395 memcpy(meshhdr->eaddr1, addr4, ETH_ALEN);
396 }
397 if (addr5 && addr6) {
398 meshhdr->flags |= MESH_FLAGS_AE_A5_A6;
399 aelen += 2 * ETH_ALEN;
400 if (!addr4) {
401 memcpy(meshhdr->eaddr1, addr5, ETH_ALEN);
402 memcpy(meshhdr->eaddr2, addr6, ETH_ALEN);
403 } else {
404 memcpy(meshhdr->eaddr2, addr5, ETH_ALEN);
405 memcpy(meshhdr->eaddr3, addr6, ETH_ALEN);
406 }
407 }
408 return 6 + aelen;
417} 409}
418 410
419static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, 411static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
@@ -433,7 +425,6 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
433 if (free_plinks != sdata->u.mesh.accepting_plinks) 425 if (free_plinks != sdata->u.mesh.accepting_plinks)
434 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); 426 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
435 427
436 ifmsh->housekeeping = false;
437 mod_timer(&ifmsh->housekeeping_timer, 428 mod_timer(&ifmsh->housekeeping_timer,
438 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); 429 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
439} 430}
@@ -470,10 +461,12 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
470 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 461 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
471 struct ieee80211_local *local = sdata->local; 462 struct ieee80211_local *local = sdata->local;
472 463
473 ifmsh->housekeeping = true; 464 ifmsh->wrkq_flags |= MESH_WORK_HOUSEKEEPING;
474 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 465 ieee80211_queue_work(&local->hw, &ifmsh->work);
466 sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
475 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | 467 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
476 BSS_CHANGED_BEACON_ENABLED); 468 BSS_CHANGED_BEACON_ENABLED |
469 BSS_CHANGED_BEACON_INT);
477} 470}
478 471
479void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 472void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
@@ -608,7 +601,13 @@ static void ieee80211_mesh_work(struct work_struct *work)
608 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval))) 601 ifmsh->last_preq + msecs_to_jiffies(ifmsh->mshcfg.dot11MeshHWMPpreqMinInterval)))
609 mesh_path_start_discovery(sdata); 602 mesh_path_start_discovery(sdata);
610 603
611 if (ifmsh->housekeeping) 604 if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
605 mesh_mpath_table_grow();
606
607 if (test_and_clear_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags))
608 mesh_mpp_table_grow();
609
610 if (test_and_clear_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags))
612 ieee80211_mesh_housekeeping(sdata, ifmsh); 611 ieee80211_mesh_housekeeping(sdata, ifmsh);
613} 612}
614 613
@@ -619,7 +618,7 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
619 rcu_read_lock(); 618 rcu_read_lock();
620 list_for_each_entry_rcu(sdata, &local->interfaces, list) 619 list_for_each_entry_rcu(sdata, &local->interfaces, list)
621 if (ieee80211_vif_is_mesh(&sdata->vif)) 620 if (ieee80211_vif_is_mesh(&sdata->vif))
622 ieee80211_queue_work(local->hw.workqueue, &sdata->u.mesh.work); 621 ieee80211_queue_work(&local->hw, &sdata->u.mesh.work);
623 rcu_read_unlock(); 622 rcu_read_unlock();
624} 623}
625 624
@@ -692,7 +691,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
692 case IEEE80211_STYPE_PROBE_RESP: 691 case IEEE80211_STYPE_PROBE_RESP:
693 case IEEE80211_STYPE_BEACON: 692 case IEEE80211_STYPE_BEACON:
694 skb_queue_tail(&ifmsh->skb_queue, skb); 693 skb_queue_tail(&ifmsh->skb_queue, skb);
695 ieee80211_queue_work(local->hw.workqueue, &ifmsh->work); 694 ieee80211_queue_work(&local->hw, &ifmsh->work);
696 return RX_QUEUED; 695 return RX_QUEUED;
697 } 696 }
698 697
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 2a2ed182cb7e..eb23fc639b2b 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -44,6 +44,23 @@ enum mesh_path_flags {
44}; 44};
45 45
46/** 46/**
47 * enum mesh_deferred_task_flags - mac80211 mesh deferred tasks
48 *
49 *
50 *
51 * @MESH_WORK_HOUSEKEEPING: run the periodic mesh housekeeping tasks
52 * @MESH_WORK_GROW_MPATH_TABLE: the mesh path table is full and needs
53 * to grow.
54 * @MESH_WORK_GROW_MPP_TABLE: the mesh portals table is full and needs to
55 * grow
56 */
57enum mesh_deferred_task_flags {
58 MESH_WORK_HOUSEKEEPING,
59 MESH_WORK_GROW_MPATH_TABLE,
60 MESH_WORK_GROW_MPP_TABLE,
61};
62
63/**
47 * struct mesh_path - mac80211 mesh path structure 64 * struct mesh_path - mac80211 mesh path structure
48 * 65 *
49 * @dst: mesh path destination mac address 66 * @dst: mesh path destination mac address
@@ -61,7 +78,7 @@ enum mesh_path_flags {
61 * retry 78 * retry
62 * @discovery_retries: number of discovery retries 79 * @discovery_retries: number of discovery retries
63 * @flags: mesh path flags, as specified on &enum mesh_path_flags 80 * @flags: mesh path flags, as specified on &enum mesh_path_flags
64 * @state_lock: mesh pat state lock 81 * @state_lock: mesh path state lock
65 * 82 *
66 * 83 *
67 * The combination of dst and sdata is unique in the mesh path table. Since the 84 * The combination of dst and sdata is unique in the mesh path table. Since the
@@ -174,6 +191,7 @@ struct mesh_rmc {
174 */ 191 */
175#define MESH_PATH_REFRESH_TIME 1000 192#define MESH_PATH_REFRESH_TIME 1000
176#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME) 193#define MESH_MIN_DISCOVERY_TIMEOUT (2 * MESH_DIAM_TRAVERSAL_TIME)
194#define MESH_DEFAULT_BEACON_INTERVAL 1000 /* in 1024 us units */
177 195
178#define MESH_MAX_PREQ_RETRIES 4 196#define MESH_MAX_PREQ_RETRIES 4
179#define MESH_PATH_EXPIRE (600 * HZ) 197#define MESH_PATH_EXPIRE (600 * HZ)
@@ -193,8 +211,11 @@ struct mesh_rmc {
193 211
194/* Public interfaces */ 212/* Public interfaces */
195/* Various */ 213/* Various */
214int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
215 char *da, char *sa);
196int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 216int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
197 struct ieee80211_sub_if_data *sdata); 217 struct ieee80211_sub_if_data *sdata, char *addr4,
218 char *addr5, char *addr6);
198int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, 219int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
199 struct ieee80211_sub_if_data *sdata); 220 struct ieee80211_sub_if_data *sdata);
200bool mesh_matches_local(struct ieee802_11_elems *ie, 221bool mesh_matches_local(struct ieee802_11_elems *ie,
@@ -246,7 +267,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
246/* Mesh tables */ 267/* Mesh tables */
247struct mesh_table *mesh_table_alloc(int size_order); 268struct mesh_table *mesh_table_alloc(int size_order);
248void mesh_table_free(struct mesh_table *tbl, bool free_leafs); 269void mesh_table_free(struct mesh_table *tbl, bool free_leafs);
249struct mesh_table *mesh_table_grow(struct mesh_table *tbl); 270void mesh_mpath_table_grow(void);
271void mesh_mpp_table_grow(void);
250u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, 272u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata,
251 struct mesh_table *tbl); 273 struct mesh_table *tbl);
252/* Mesh paths */ 274/* Mesh paths */
@@ -265,6 +287,8 @@ void mesh_path_discard_frame(struct sk_buff *skb,
265void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata); 287void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
266void mesh_path_restart(struct ieee80211_sub_if_data *sdata); 288void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
267 289
290extern int mesh_paths_generation;
291
268#ifdef CONFIG_MAC80211_MESH 292#ifdef CONFIG_MAC80211_MESH
269extern int mesh_allocated; 293extern int mesh_allocated;
270 294
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 11ab71a68ff9..ef1efd362691 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -397,7 +397,8 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
397 397
398static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, 398static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
399 struct ieee80211_mgmt *mgmt, 399 struct ieee80211_mgmt *mgmt,
400 u8 *preq_elem, u32 metric) { 400 u8 *preq_elem, u32 metric)
401{
401 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 402 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
402 struct mesh_path *mpath; 403 struct mesh_path *mpath;
403 u8 *dst_addr, *orig_addr; 404 u8 *dst_addr, *orig_addr;
@@ -430,7 +431,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
430 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) || 431 if ((!(mpath->flags & MESH_PATH_DSN_VALID)) ||
431 DSN_LT(mpath->dsn, dst_dsn)) { 432 DSN_LT(mpath->dsn, dst_dsn)) {
432 mpath->dsn = dst_dsn; 433 mpath->dsn = dst_dsn;
433 mpath->flags &= MESH_PATH_DSN_VALID; 434 mpath->flags |= MESH_PATH_DSN_VALID;
434 } else if ((!(dst_flags & MP_F_DO)) && 435 } else if ((!(dst_flags & MP_F_DO)) &&
435 (mpath->flags & MESH_PATH_ACTIVE)) { 436 (mpath->flags & MESH_PATH_ACTIVE)) {
436 reply = true; 437 reply = true;
@@ -660,14 +661,14 @@ static void mesh_queue_preq(struct mesh_path *mpath, u8 flags)
660 spin_unlock(&ifmsh->mesh_preq_queue_lock); 661 spin_unlock(&ifmsh->mesh_preq_queue_lock);
661 662
662 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata))) 663 if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
663 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); 664 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
664 665
665 else if (time_before(jiffies, ifmsh->last_preq)) { 666 else if (time_before(jiffies, ifmsh->last_preq)) {
666 /* avoid long wait if did not send preqs for a long time 667 /* avoid long wait if did not send preqs for a long time
667 * and jiffies wrapped around 668 * and jiffies wrapped around
668 */ 669 */
669 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1; 670 ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
670 ieee80211_queue_work(sdata->local->hw.workqueue, &ifmsh->work); 671 ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
671 } else 672 } else
672 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq + 673 mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
673 min_preq_int_jiff(sdata)); 674 min_preq_int_jiff(sdata));
@@ -791,7 +792,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
791 } 792 }
792 793
793 if (mpath->flags & MESH_PATH_ACTIVE) { 794 if (mpath->flags & MESH_PATH_ACTIVE) {
794 if (time_after(jiffies, mpath->exp_time - 795 if (time_after(jiffies, mpath->exp_time +
795 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time)) 796 msecs_to_jiffies(sdata->u.mesh.mshcfg.path_refresh_time))
796 && !memcmp(sdata->dev->dev_addr, hdr->addr4, 797 && !memcmp(sdata->dev->dev_addr, hdr->addr4,
797 ETH_ALEN) 798 ETH_ALEN)
@@ -810,10 +811,8 @@ int mesh_nexthop_lookup(struct sk_buff *skb,
810 } 811 }
811 812
812 if (skb_queue_len(&mpath->frame_queue) >= 813 if (skb_queue_len(&mpath->frame_queue) >=
813 MESH_FRAME_QUEUE_LEN) { 814 MESH_FRAME_QUEUE_LEN)
814 skb_to_free = mpath->frame_queue.next; 815 skb_to_free = skb_dequeue(&mpath->frame_queue);
815 skb_unlink(skb_to_free, &mpath->frame_queue);
816 }
817 816
818 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 817 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
819 skb_queue_tail(&mpath->frame_queue, skb); 818 skb_queue_tail(&mpath->frame_queue, skb);
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 04b9e4d61b8e..751c4d0e2b36 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -38,6 +38,71 @@ struct mpath_node {
38static struct mesh_table *mesh_paths; 38static struct mesh_table *mesh_paths;
39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ 39static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */
40 40
41int mesh_paths_generation;
42static void __mesh_table_free(struct mesh_table *tbl)
43{
44 kfree(tbl->hash_buckets);
45 kfree(tbl->hashwlock);
46 kfree(tbl);
47}
48
49void mesh_table_free(struct mesh_table *tbl, bool free_leafs)
50{
51 struct hlist_head *mesh_hash;
52 struct hlist_node *p, *q;
53 int i;
54
55 mesh_hash = tbl->hash_buckets;
56 for (i = 0; i <= tbl->hash_mask; i++) {
57 spin_lock(&tbl->hashwlock[i]);
58 hlist_for_each_safe(p, q, &mesh_hash[i]) {
59 tbl->free_node(p, free_leafs);
60 atomic_dec(&tbl->entries);
61 }
62 spin_unlock(&tbl->hashwlock[i]);
63 }
64 __mesh_table_free(tbl);
65}
66
67static struct mesh_table *mesh_table_grow(struct mesh_table *tbl)
68{
69 struct mesh_table *newtbl;
70 struct hlist_head *oldhash;
71 struct hlist_node *p, *q;
72 int i;
73
74 if (atomic_read(&tbl->entries)
75 < tbl->mean_chain_len * (tbl->hash_mask + 1))
76 goto endgrow;
77
78 newtbl = mesh_table_alloc(tbl->size_order + 1);
79 if (!newtbl)
80 goto endgrow;
81
82 newtbl->free_node = tbl->free_node;
83 newtbl->mean_chain_len = tbl->mean_chain_len;
84 newtbl->copy_node = tbl->copy_node;
85 atomic_set(&newtbl->entries, atomic_read(&tbl->entries));
86
87 oldhash = tbl->hash_buckets;
88 for (i = 0; i <= tbl->hash_mask; i++)
89 hlist_for_each(p, &oldhash[i])
90 if (tbl->copy_node(p, newtbl) < 0)
91 goto errcopy;
92
93 return newtbl;
94
95errcopy:
96 for (i = 0; i <= newtbl->hash_mask; i++) {
97 hlist_for_each_safe(p, q, &newtbl->hash_buckets[i])
98 tbl->free_node(p, 0);
99 }
100 __mesh_table_free(newtbl);
101endgrow:
102 return NULL;
103}
104
105
41/* This lock will have the grow table function as writer and add / delete nodes 106/* This lock will have the grow table function as writer and add / delete nodes
42 * as readers. When reading the table (i.e. doing lookups) we are well protected 107 * as readers. When reading the table (i.e. doing lookups) we are well protected
43 * by RCU 108 * by RCU
@@ -185,6 +250,8 @@ struct mesh_path *mesh_path_lookup_by_idx(int idx, struct ieee80211_sub_if_data
185 */ 250 */
186int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) 251int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
187{ 252{
253 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
254 struct ieee80211_local *local = sdata->local;
188 struct mesh_path *mpath, *new_mpath; 255 struct mesh_path *mpath, *new_mpath;
189 struct mpath_node *node, *new_node; 256 struct mpath_node *node, *new_node;
190 struct hlist_head *bucket; 257 struct hlist_head *bucket;
@@ -193,8 +260,6 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
193 int err = 0; 260 int err = 0;
194 u32 hash_idx; 261 u32 hash_idx;
195 262
196 might_sleep();
197
198 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 263 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
199 /* never add ourselves as neighbours */ 264 /* never add ourselves as neighbours */
200 return -ENOTSUPP; 265 return -ENOTSUPP;
@@ -206,11 +271,11 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
206 return -ENOSPC; 271 return -ENOSPC;
207 272
208 err = -ENOMEM; 273 err = -ENOMEM;
209 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 274 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
210 if (!new_mpath) 275 if (!new_mpath)
211 goto err_path_alloc; 276 goto err_path_alloc;
212 277
213 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 278 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
214 if (!new_node) 279 if (!new_node)
215 goto err_node_alloc; 280 goto err_node_alloc;
216 281
@@ -243,23 +308,13 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata)
243 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1)) 308 mesh_paths->mean_chain_len * (mesh_paths->hash_mask + 1))
244 grow = 1; 309 grow = 1;
245 310
311 mesh_paths_generation++;
312
246 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 313 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
247 read_unlock(&pathtbl_resize_lock); 314 read_unlock(&pathtbl_resize_lock);
248 if (grow) { 315 if (grow) {
249 struct mesh_table *oldtbl, *newtbl; 316 set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags);
250 317 ieee80211_queue_work(&local->hw, &ifmsh->work);
251 write_lock(&pathtbl_resize_lock);
252 oldtbl = mesh_paths;
253 newtbl = mesh_table_grow(mesh_paths);
254 if (!newtbl) {
255 write_unlock(&pathtbl_resize_lock);
256 return 0;
257 }
258 rcu_assign_pointer(mesh_paths, newtbl);
259 write_unlock(&pathtbl_resize_lock);
260
261 synchronize_rcu();
262 mesh_table_free(oldtbl, false);
263 } 318 }
264 return 0; 319 return 0;
265 320
@@ -274,9 +329,46 @@ err_path_alloc:
274 return err; 329 return err;
275} 330}
276 331
332void mesh_mpath_table_grow(void)
333{
334 struct mesh_table *oldtbl, *newtbl;
335
336 write_lock(&pathtbl_resize_lock);
337 oldtbl = mesh_paths;
338 newtbl = mesh_table_grow(mesh_paths);
339 if (!newtbl) {
340 write_unlock(&pathtbl_resize_lock);
341 return;
342 }
343 rcu_assign_pointer(mesh_paths, newtbl);
344 write_unlock(&pathtbl_resize_lock);
345
346 synchronize_rcu();
347 mesh_table_free(oldtbl, false);
348}
349
350void mesh_mpp_table_grow(void)
351{
352 struct mesh_table *oldtbl, *newtbl;
353
354 write_lock(&pathtbl_resize_lock);
355 oldtbl = mpp_paths;
356 newtbl = mesh_table_grow(mpp_paths);
357 if (!newtbl) {
358 write_unlock(&pathtbl_resize_lock);
359 return;
360 }
361 rcu_assign_pointer(mpp_paths, newtbl);
362 write_unlock(&pathtbl_resize_lock);
363
364 synchronize_rcu();
365 mesh_table_free(oldtbl, false);
366}
277 367
278int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) 368int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
279{ 369{
370 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
371 struct ieee80211_local *local = sdata->local;
280 struct mesh_path *mpath, *new_mpath; 372 struct mesh_path *mpath, *new_mpath;
281 struct mpath_node *node, *new_node; 373 struct mpath_node *node, *new_node;
282 struct hlist_head *bucket; 374 struct hlist_head *bucket;
@@ -285,8 +377,6 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
285 int err = 0; 377 int err = 0;
286 u32 hash_idx; 378 u32 hash_idx;
287 379
288 might_sleep();
289
290 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0) 380 if (memcmp(dst, sdata->dev->dev_addr, ETH_ALEN) == 0)
291 /* never add ourselves as neighbours */ 381 /* never add ourselves as neighbours */
292 return -ENOTSUPP; 382 return -ENOTSUPP;
@@ -295,11 +385,11 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
295 return -ENOTSUPP; 385 return -ENOTSUPP;
296 386
297 err = -ENOMEM; 387 err = -ENOMEM;
298 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); 388 new_mpath = kzalloc(sizeof(struct mesh_path), GFP_ATOMIC);
299 if (!new_mpath) 389 if (!new_mpath)
300 goto err_path_alloc; 390 goto err_path_alloc;
301 391
302 new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); 392 new_node = kmalloc(sizeof(struct mpath_node), GFP_ATOMIC);
303 if (!new_node) 393 if (!new_node)
304 goto err_node_alloc; 394 goto err_node_alloc;
305 395
@@ -333,20 +423,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata)
333 spin_unlock(&mpp_paths->hashwlock[hash_idx]); 423 spin_unlock(&mpp_paths->hashwlock[hash_idx]);
334 read_unlock(&pathtbl_resize_lock); 424 read_unlock(&pathtbl_resize_lock);
335 if (grow) { 425 if (grow) {
336 struct mesh_table *oldtbl, *newtbl; 426 set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
337 427 ieee80211_queue_work(&local->hw, &ifmsh->work);
338 write_lock(&pathtbl_resize_lock);
339 oldtbl = mpp_paths;
340 newtbl = mesh_table_grow(mpp_paths);
341 if (!newtbl) {
342 write_unlock(&pathtbl_resize_lock);
343 return 0;
344 }
345 rcu_assign_pointer(mpp_paths, newtbl);
346 write_unlock(&pathtbl_resize_lock);
347
348 synchronize_rcu();
349 mesh_table_free(oldtbl, false);
350 } 428 }
351 return 0; 429 return 0;
352 430
@@ -484,6 +562,7 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata)
484 562
485 err = -ENXIO; 563 err = -ENXIO;
486enddel: 564enddel:
565 mesh_paths_generation++;
487 spin_unlock(&mesh_paths->hashwlock[hash_idx]); 566 spin_unlock(&mesh_paths->hashwlock[hash_idx]);
488 read_unlock(&pathtbl_resize_lock); 567 read_unlock(&pathtbl_resize_lock);
489 return err; 568 return err;
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index cb14253587f1..ffcbad75e09b 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -409,7 +409,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
409 baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; 409 baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt;
410 if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { 410 if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) {
411 baseaddr += 4; 411 baseaddr += 4;
412 baselen -= 4; 412 baselen += 4;
413 } 413 }
414 ieee802_11_parse_elems(baseaddr, len - baselen, &elems); 414 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
415 if (!elems.peer_link) { 415 if (!elems.peer_link) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 6d5a1ee0445f..c374d2d73fa4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -880,10 +880,11 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,
880} 880}
881 881
882static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 882static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
883 struct ieee80211_bss *bss, 883 struct ieee80211_mgd_work *wk,
884 u32 bss_info_changed) 884 u32 bss_info_changed)
885{ 885{
886 struct ieee80211_local *local = sdata->local; 886 struct ieee80211_local *local = sdata->local;
887 struct ieee80211_bss *bss = wk->bss;
887 888
888 bss_info_changed |= BSS_CHANGED_ASSOC; 889 bss_info_changed |= BSS_CHANGED_ASSOC;
889 /* set timing information */ 890 /* set timing information */
@@ -896,6 +897,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
896 bss->cbss.capability, bss->has_erp_value, bss->erp_value); 897 bss->cbss.capability, bss->has_erp_value, bss->erp_value);
897 898
898 sdata->u.mgd.associated = bss; 899 sdata->u.mgd.associated = bss;
900 sdata->u.mgd.old_associate_work = wk;
899 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); 901 memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN);
900 902
901 /* just to be sure */ 903 /* just to be sure */
@@ -1010,7 +1012,8 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata,
1010 return RX_MGMT_NONE; 1012 return RX_MGMT_NONE;
1011} 1013}
1012 1014
1013static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) 1015static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1016 bool deauth)
1014{ 1017{
1015 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1018 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1016 struct ieee80211_local *local = sdata->local; 1019 struct ieee80211_local *local = sdata->local;
@@ -1028,6 +1031,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata)
1028 ifmgd->associated = NULL; 1031 ifmgd->associated = NULL;
1029 memset(ifmgd->bssid, 0, ETH_ALEN); 1032 memset(ifmgd->bssid, 0, ETH_ALEN);
1030 1033
1034 if (deauth) {
1035 kfree(ifmgd->old_associate_work);
1036 ifmgd->old_associate_work = NULL;
1037 } else {
1038 struct ieee80211_mgd_work *wk = ifmgd->old_associate_work;
1039
1040 wk->state = IEEE80211_MGD_STATE_IDLE;
1041 list_add(&wk->list, &ifmgd->work_list);
1042 }
1043
1031 /* 1044 /*
1032 * we need to commit the associated = NULL change because the 1045 * we need to commit the associated = NULL change because the
1033 * scan code uses that to determine whether this iface should 1046 * scan code uses that to determine whether this iface should
@@ -1345,7 +1358,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1345 sdata->dev->name, bssid, reason_code); 1358 sdata->dev->name, bssid, reason_code);
1346 1359
1347 if (!wk) { 1360 if (!wk) {
1348 ieee80211_set_disassoc(sdata); 1361 ieee80211_set_disassoc(sdata, true);
1349 } else { 1362 } else {
1350 list_del(&wk->list); 1363 list_del(&wk->list);
1351 kfree(wk); 1364 kfree(wk);
@@ -1378,7 +1391,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1378 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", 1391 printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n",
1379 sdata->dev->name, reason_code); 1392 sdata->dev->name, reason_code);
1380 1393
1381 ieee80211_set_disassoc(sdata); 1394 ieee80211_set_disassoc(sdata, false);
1382 return RX_MGMT_CFG80211_DISASSOC; 1395 return RX_MGMT_CFG80211_DISASSOC;
1383} 1396}
1384 1397
@@ -1581,7 +1594,8 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1581 * ieee80211_set_associated() will tell the driver */ 1594 * ieee80211_set_associated() will tell the driver */
1582 bss_conf->aid = aid; 1595 bss_conf->aid = aid;
1583 bss_conf->assoc_capability = capab_info; 1596 bss_conf->assoc_capability = capab_info;
1584 ieee80211_set_associated(sdata, wk->bss, changed); 1597 /* this will take ownership of wk */
1598 ieee80211_set_associated(sdata, wk, changed);
1585 1599
1586 /* 1600 /*
1587 * Start timer to probe the connection to the AP now. 1601 * Start timer to probe the connection to the AP now.
@@ -1590,7 +1604,6 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
1590 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); 1604 ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt);
1591 mod_beacon_timer(sdata); 1605 mod_beacon_timer(sdata);
1592 1606
1593 kfree(wk);
1594 return RX_MGMT_CFG80211_ASSOC; 1607 return RX_MGMT_CFG80211_ASSOC;
1595} 1608}
1596 1609
@@ -2096,7 +2109,7 @@ static void ieee80211_sta_work(struct work_struct *work)
2096 printk(KERN_DEBUG "No probe response from AP %pM" 2109 printk(KERN_DEBUG "No probe response from AP %pM"
2097 " after %dms, disconnecting.\n", 2110 " after %dms, disconnecting.\n",
2098 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 2111 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
2099 ieee80211_set_disassoc(sdata); 2112 ieee80211_set_disassoc(sdata, true);
2100 mutex_unlock(&ifmgd->mtx); 2113 mutex_unlock(&ifmgd->mtx);
2101 /* 2114 /*
2102 * must be outside lock due to cfg80211, 2115 * must be outside lock due to cfg80211,
@@ -2500,7 +2513,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2500 2513
2501 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { 2514 if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) {
2502 bssid = req->bss->bssid; 2515 bssid = req->bss->bssid;
2503 ieee80211_set_disassoc(sdata); 2516 ieee80211_set_disassoc(sdata, true);
2504 } else list_for_each_entry(wk, &ifmgd->work_list, list) { 2517 } else list_for_each_entry(wk, &ifmgd->work_list, list) {
2505 if (&wk->bss->cbss == req->bss) { 2518 if (&wk->bss->cbss == req->bss) {
2506 bssid = req->bss->bssid; 2519 bssid = req->bss->bssid;
@@ -2552,7 +2565,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2552 return -ENOLINK; 2565 return -ENOLINK;
2553 } 2566 }
2554 2567
2555 ieee80211_set_disassoc(sdata); 2568 ieee80211_set_disassoc(sdata, false);
2556 2569
2557 mutex_unlock(&ifmgd->mtx); 2570 mutex_unlock(&ifmgd->mtx);
2558 2571
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 7c5142988bbb..007164919e02 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -51,6 +51,7 @@
51#include <linux/random.h> 51#include <linux/random.h>
52#include <linux/ieee80211.h> 52#include <linux/ieee80211.h>
53#include <net/mac80211.h> 53#include <net/mac80211.h>
54#include "mesh.h"
54#include "rate.h" 55#include "rate.h"
55#include "rc80211_minstrel.h" 56#include "rc80211_minstrel.h"
56 57
@@ -155,12 +156,16 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
155 struct sk_buff *skb) 156 struct sk_buff *skb)
156{ 157{
157 struct minstrel_sta_info *mi = priv_sta; 158 struct minstrel_sta_info *mi = priv_sta;
159 struct minstrel_priv *mp = (struct minstrel_priv *)priv;
158 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 160 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
159 struct ieee80211_tx_rate *ar = info->status.rates; 161 struct ieee80211_tx_rate *ar = info->status.rates;
162 struct ieee80211_local *local = hw_to_local(mp->hw);
163 struct sta_info *si;
160 int i, ndx; 164 int i, ndx;
161 int success; 165 int success;
162 166
163 success = !!(info->flags & IEEE80211_TX_STAT_ACK); 167 success = !!(info->flags & IEEE80211_TX_STAT_ACK);
168 si = sta_info_get(local, sta->addr);
164 169
165 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 170 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
166 if (ar[i].idx < 0) 171 if (ar[i].idx < 0)
@@ -172,8 +177,17 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
172 177
173 mi->r[ndx].attempts += ar[i].count; 178 mi->r[ndx].attempts += ar[i].count;
174 179
175 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) 180 if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) {
176 mi->r[ndx].success += success; 181 mi->r[ndx].success += success;
182 if (si) {
183 si->fail_avg = (18050 - mi->r[ndx].probability)
184 / 180;
185 WARN_ON(si->fail_avg > 100);
186 if (si->fail_avg == 100 &&
187 ieee80211_vif_is_mesh(&si->sdata->vif))
188 mesh_plink_broken(si);
189 }
190 }
177 } 191 }
178 192
179 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) 193 if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0))
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 25a669c86e14..4cd9e45b1443 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -489,12 +489,21 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
489{ 489{
490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; 490 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); 491 unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control);
492 char *dev_addr = rx->dev->dev_addr;
492 493
493 if (ieee80211_is_data(hdr->frame_control)) { 494 if (ieee80211_is_data(hdr->frame_control)) {
494 if (!ieee80211_has_a4(hdr->frame_control)) 495 if (is_multicast_ether_addr(hdr->addr1)) {
495 return RX_DROP_MONITOR; 496 if (ieee80211_has_tods(hdr->frame_control) ||
496 if (memcmp(hdr->addr4, rx->dev->dev_addr, ETH_ALEN) == 0) 497 !ieee80211_has_fromds(hdr->frame_control))
497 return RX_DROP_MONITOR; 498 return RX_DROP_MONITOR;
499 if (memcmp(hdr->addr3, dev_addr, ETH_ALEN) == 0)
500 return RX_DROP_MONITOR;
501 } else {
502 if (!ieee80211_has_a4(hdr->frame_control))
503 return RX_DROP_MONITOR;
504 if (memcmp(hdr->addr4, dev_addr, ETH_ALEN) == 0)
505 return RX_DROP_MONITOR;
506 }
498 } 507 }
499 508
500 /* If there is not an established peer link and this is not a peer link 509 /* If there is not an established peer link and this is not a peer link
@@ -527,7 +536,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
527 536
528 if (ieee80211_is_data(hdr->frame_control) && 537 if (ieee80211_is_data(hdr->frame_control) &&
529 is_multicast_ether_addr(hdr->addr1) && 538 is_multicast_ether_addr(hdr->addr1) &&
530 mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata)) 539 mesh_rmc_check(hdr->addr3, msh_h_get(hdr, hdrlen), rx->sdata))
531 return RX_DROP_MONITOR; 540 return RX_DROP_MONITOR;
532#undef msh_h_get 541#undef msh_h_get
533 542
@@ -1495,7 +1504,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1495 /* illegal frame */ 1504 /* illegal frame */
1496 return RX_DROP_MONITOR; 1505 return RX_DROP_MONITOR;
1497 1506
1498 if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){ 1507 if (!is_multicast_ether_addr(hdr->addr1) &&
1508 (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6)) {
1499 struct mesh_path *mppath; 1509 struct mesh_path *mppath;
1500 1510
1501 rcu_read_lock(); 1511 rcu_read_lock();
@@ -1512,7 +1522,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1512 rcu_read_unlock(); 1522 rcu_read_unlock();
1513 } 1523 }
1514 1524
1515 if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) 1525 /* Frame has reached destination. Don't forward */
1526 if (!is_multicast_ether_addr(hdr->addr1) &&
1527 compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
1516 return RX_CONTINUE; 1528 return RX_CONTINUE;
1517 1529
1518 mesh_hdr->ttl--; 1530 mesh_hdr->ttl--;
@@ -1532,22 +1544,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1532 rx->dev->name); 1544 rx->dev->name);
1533 1545
1534 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; 1546 fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
1535 /*
1536 * Save TA to addr1 to send TA a path error if a
1537 * suitable next hop is not found
1538 */
1539 memcpy(fwd_hdr->addr1, fwd_hdr->addr2, ETH_ALEN);
1540 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); 1547 memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN);
1541 info = IEEE80211_SKB_CB(fwd_skb); 1548 info = IEEE80211_SKB_CB(fwd_skb);
1542 memset(info, 0, sizeof(*info)); 1549 memset(info, 0, sizeof(*info));
1543 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; 1550 info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
1544 info->control.vif = &rx->sdata->vif; 1551 info->control.vif = &rx->sdata->vif;
1545 ieee80211_select_queue(local, fwd_skb); 1552 ieee80211_select_queue(local, fwd_skb);
1546 if (is_multicast_ether_addr(fwd_hdr->addr3)) 1553 if (!is_multicast_ether_addr(fwd_hdr->addr1)) {
1547 memcpy(fwd_hdr->addr1, fwd_hdr->addr3, 1554 int err;
1555 /*
1556 * Save TA to addr1 to send TA a path error if a
1557 * suitable next hop is not found
1558 */
1559 memcpy(fwd_hdr->addr1, fwd_hdr->addr2,
1548 ETH_ALEN); 1560 ETH_ALEN);
1549 else { 1561 err = mesh_nexthop_lookup(fwd_skb, sdata);
1550 int err = mesh_nexthop_lookup(fwd_skb, sdata);
1551 /* Failed to immediately resolve next hop: 1562 /* Failed to immediately resolve next hop:
1552 * fwded frame was dropped or will be added 1563 * fwded frame was dropped or will be added
1553 * later to the pending skb queue. */ 1564 * later to the pending skb queue. */
@@ -1560,7 +1571,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
1560 } 1571 }
1561 } 1572 }
1562 1573
1563 if (is_multicast_ether_addr(hdr->addr3) || 1574 if (is_multicast_ether_addr(hdr->addr1) ||
1564 rx->dev->flags & IFF_PROMISC) 1575 rx->dev->flags & IFF_PROMISC)
1565 return RX_CONTINUE; 1576 return RX_CONTINUE;
1566 else 1577 else
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 244f53f3c8b4..e091cbc3434f 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -277,7 +277,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
277 if (test_bit(SCAN_HW_SCANNING, &local->scanning)) 277 if (test_bit(SCAN_HW_SCANNING, &local->scanning))
278 ieee80211_restore_scan_ies(local); 278 ieee80211_restore_scan_ies(local);
279 279
280 if (local->scan_req != &local->int_scan_req) 280 if (local->scan_req != local->int_scan_req)
281 cfg80211_scan_done(local->scan_req, aborted); 281 cfg80211_scan_done(local->scan_req, aborted);
282 local->scan_req = NULL; 282 local->scan_req = NULL;
283 283
@@ -423,7 +423,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
423 local->scan_req = req; 423 local->scan_req = req;
424 local->scan_sdata = sdata; 424 local->scan_sdata = sdata;
425 425
426 if (req != &local->int_scan_req && 426 if (req != local->int_scan_req &&
427 sdata->vif.type == NL80211_IFTYPE_STATION && 427 sdata->vif.type == NL80211_IFTYPE_STATION &&
428 !list_empty(&ifmgd->work_list)) { 428 !list_empty(&ifmgd->work_list)) {
429 /* actually wait for the work it's doing to finish/time out */ 429 /* actually wait for the work it's doing to finish/time out */
@@ -743,10 +743,10 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
743 if (local->scan_req) 743 if (local->scan_req)
744 goto unlock; 744 goto unlock;
745 745
746 memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); 746 memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
747 local->int_scan_req.ssids[0].ssid_len = ssid_len; 747 local->int_scan_req->ssids[0].ssid_len = ssid_len;
748 748
749 ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); 749 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
750 unlock: 750 unlock:
751 mutex_unlock(&local->scan_mtx); 751 mutex_unlock(&local->scan_mtx);
752 return ret; 752 return ret;
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a360bceeba59..eec001491e66 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -349,6 +349,7 @@ int sta_info_insert(struct sta_info *sta)
349 goto out_free; 349 goto out_free;
350 } 350 }
351 list_add(&sta->list, &local->sta_list); 351 list_add(&sta->list, &local->sta_list);
352 local->sta_generation++;
352 local->num_sta++; 353 local->num_sta++;
353 sta_info_hash_add(local, sta); 354 sta_info_hash_add(local, sta);
354 355
@@ -485,6 +486,7 @@ static void __sta_info_unlink(struct sta_info **sta)
485 } 486 }
486 487
487 local->num_sta--; 488 local->num_sta--;
489 local->sta_generation++;
488 490
489 if (local->ops->sta_notify) { 491 if (local->ops->sta_notify) {
490 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 492 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7cffaa046b33..0c08d1e60cb5 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -317,30 +317,30 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
317 if (!atomic_read(&tx->sdata->bss->num_sta_ps)) 317 if (!atomic_read(&tx->sdata->bss->num_sta_ps))
318 return TX_CONTINUE; 318 return TX_CONTINUE;
319 319
320 /* buffered in hardware */
321 if (!(tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)) {
322 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
323
324 return TX_CONTINUE;
325 }
326
320 /* buffered in mac80211 */ 327 /* buffered in mac80211 */
321 if (tx->local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING) { 328 if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER)
322 if (tx->local->total_ps_buffered >= TOTAL_MAX_TX_BUFFER) 329 purge_old_ps_buffers(tx->local);
323 purge_old_ps_buffers(tx->local); 330
324 if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= 331 if (skb_queue_len(&tx->sdata->bss->ps_bc_buf) >= AP_MAX_BC_BUFFER) {
325 AP_MAX_BC_BUFFER) {
326#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG 332#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
327 if (net_ratelimit()) { 333 if (net_ratelimit())
328 printk(KERN_DEBUG "%s: BC TX buffer full - " 334 printk(KERN_DEBUG "%s: BC TX buffer full - dropping the oldest frame\n",
329 "dropping the oldest frame\n", 335 tx->dev->name);
330 tx->dev->name);
331 }
332#endif 336#endif
333 dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf)); 337 dev_kfree_skb(skb_dequeue(&tx->sdata->bss->ps_bc_buf));
334 } else 338 } else
335 tx->local->total_ps_buffered++; 339 tx->local->total_ps_buffered++;
336 skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
337 return TX_QUEUED;
338 }
339 340
340 /* buffered in hardware */ 341 skb_queue_tail(&tx->sdata->bss->ps_bc_buf, tx->skb);
341 info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM;
342 342
343 return TX_CONTINUE; 343 return TX_QUEUED;
344} 344}
345 345
346static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, 346static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta,
@@ -700,7 +700,6 @@ ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
700 /* for pure STA mode without beacons, we can do it */ 700 /* for pure STA mode without beacons, we can do it */
701 hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number); 701 hdr->seq_ctrl = cpu_to_le16(tx->sdata->sequence_number);
702 tx->sdata->sequence_number += 0x10; 702 tx->sdata->sequence_number += 0x10;
703 tx->sdata->sequence_number &= IEEE80211_SCTL_SEQ;
704 return TX_CONTINUE; 703 return TX_CONTINUE;
705 } 704 }
706 705
@@ -844,6 +843,23 @@ ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
844} 843}
845 844
846static ieee80211_tx_result debug_noinline 845static ieee80211_tx_result debug_noinline
846ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
847{
848 struct sk_buff *skb = tx->skb;
849
850 if (!tx->sta)
851 return TX_CONTINUE;
852
853 tx->sta->tx_packets++;
854 do {
855 tx->sta->tx_fragments++;
856 tx->sta->tx_bytes += skb->len;
857 } while ((skb = skb->next));
858
859 return TX_CONTINUE;
860}
861
862static ieee80211_tx_result debug_noinline
847ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx) 863ieee80211_tx_h_encrypt(struct ieee80211_tx_data *tx)
848{ 864{
849 if (!tx->key) 865 if (!tx->key)
@@ -887,23 +903,6 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
887 return TX_CONTINUE; 903 return TX_CONTINUE;
888} 904}
889 905
890static ieee80211_tx_result debug_noinline
891ieee80211_tx_h_stats(struct ieee80211_tx_data *tx)
892{
893 struct sk_buff *skb = tx->skb;
894
895 if (!tx->sta)
896 return TX_CONTINUE;
897
898 tx->sta->tx_packets++;
899 do {
900 tx->sta->tx_fragments++;
901 tx->sta->tx_bytes += skb->len;
902 } while ((skb = skb->next));
903
904 return TX_CONTINUE;
905}
906
907/* actual transmit path */ 906/* actual transmit path */
908 907
909/* 908/*
@@ -1154,6 +1153,9 @@ static int __ieee80211_tx(struct ieee80211_local *local,
1154 next = skb->next; 1153 next = skb->next;
1155 len = skb->len; 1154 len = skb->len;
1156 1155
1156 if (next)
1157 info->flags |= IEEE80211_TX_CTL_MORE_FRAMES;
1158
1157 sdata = vif_to_sdata(info->control.vif); 1159 sdata = vif_to_sdata(info->control.vif);
1158 1160
1159 switch (sdata->vif.type) { 1161 switch (sdata->vif.type) {
@@ -1210,9 +1212,9 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
1210 CALL_TXH(ieee80211_tx_h_sequence) 1212 CALL_TXH(ieee80211_tx_h_sequence)
1211 CALL_TXH(ieee80211_tx_h_fragment) 1213 CALL_TXH(ieee80211_tx_h_fragment)
1212 /* handlers after fragment must be aware of tx info fragmentation! */ 1214 /* handlers after fragment must be aware of tx info fragmentation! */
1215 CALL_TXH(ieee80211_tx_h_stats)
1213 CALL_TXH(ieee80211_tx_h_encrypt) 1216 CALL_TXH(ieee80211_tx_h_encrypt)
1214 CALL_TXH(ieee80211_tx_h_calculate_duration) 1217 CALL_TXH(ieee80211_tx_h_calculate_duration)
1215 CALL_TXH(ieee80211_tx_h_stats)
1216#undef CALL_TXH 1218#undef CALL_TXH
1217 1219
1218 txh_done: 1220 txh_done:
@@ -1410,16 +1412,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1410 1412
1411 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; 1413 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS;
1412 1414
1413 if (ieee80211_vif_is_mesh(&sdata->vif) && 1415 if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1414 ieee80211_is_data(hdr->frame_control)) {
1415 if (is_multicast_ether_addr(hdr->addr3))
1416 memcpy(hdr->addr1, hdr->addr3, ETH_ALEN);
1417 else
1418 if (mesh_nexthop_lookup(skb, sdata)) {
1419 dev_put(sdata->dev);
1420 return;
1421 }
1422 } else if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) {
1423 int hdrlen; 1416 int hdrlen;
1424 u16 len_rthdr; 1417 u16 len_rthdr;
1425 1418
@@ -1476,6 +1469,15 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
1476 1469
1477 info->control.vif = &sdata->vif; 1470 info->control.vif = &sdata->vif;
1478 1471
1472 if (ieee80211_vif_is_mesh(&sdata->vif) &&
1473 ieee80211_is_data(hdr->frame_control) &&
1474 !is_multicast_ether_addr(hdr->addr1))
1475 if (mesh_nexthop_lookup(skb, sdata)) {
1476 /* skb queued: don't free */
1477 dev_put(sdata->dev);
1478 return;
1479 }
1480
1479 ieee80211_select_queue(local, skb); 1481 ieee80211_select_queue(local, skb);
1480 ieee80211_tx(sdata, skb, false); 1482 ieee80211_tx(sdata, skb, false);
1481 dev_put(sdata->dev); 1483 dev_put(sdata->dev);
@@ -1617,52 +1619,58 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb,
1617 break; 1619 break;
1618#ifdef CONFIG_MAC80211_MESH 1620#ifdef CONFIG_MAC80211_MESH
1619 case NL80211_IFTYPE_MESH_POINT: 1621 case NL80211_IFTYPE_MESH_POINT:
1620 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
1621 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { 1622 if (!sdata->u.mesh.mshcfg.dot11MeshTTL) {
1622 /* Do not send frames with mesh_ttl == 0 */ 1623 /* Do not send frames with mesh_ttl == 0 */
1623 sdata->u.mesh.mshstats.dropped_frames_ttl++; 1624 sdata->u.mesh.mshstats.dropped_frames_ttl++;
1624 ret = NETDEV_TX_OK; 1625 ret = NETDEV_TX_OK;
1625 goto fail; 1626 goto fail;
1626 } 1627 }
1627 memset(&mesh_hdr, 0, sizeof(mesh_hdr));
1628 1628
1629 if (compare_ether_addr(dev->dev_addr, 1629 if (compare_ether_addr(dev->dev_addr,
1630 skb->data + ETH_ALEN) == 0) { 1630 skb->data + ETH_ALEN) == 0) {
1631 /* RA TA DA SA */ 1631 hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
1632 memset(hdr.addr1, 0, ETH_ALEN); 1632 skb->data, skb->data + ETH_ALEN);
1633 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); 1633 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
1634 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1634 sdata, NULL, NULL, NULL);
1635 memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
1636 meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, sdata);
1637 } else { 1635 } else {
1638 /* packet from other interface */ 1636 /* packet from other interface */
1639 struct mesh_path *mppath; 1637 struct mesh_path *mppath;
1638 int is_mesh_mcast = 1;
1639 char *mesh_da;
1640 1640
1641 memset(hdr.addr1, 0, ETH_ALEN); 1641 rcu_read_lock();
1642 memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN);
1643 memcpy(hdr.addr4, dev->dev_addr, ETH_ALEN);
1644
1645 if (is_multicast_ether_addr(skb->data)) 1642 if (is_multicast_ether_addr(skb->data))
1646 memcpy(hdr.addr3, skb->data, ETH_ALEN); 1643 /* DA TA mSA AE:SA */
1644 mesh_da = skb->data;
1647 else { 1645 else {
1648 rcu_read_lock();
1649 mppath = mpp_path_lookup(skb->data, sdata); 1646 mppath = mpp_path_lookup(skb->data, sdata);
1650 if (mppath) 1647 if (mppath) {
1651 memcpy(hdr.addr3, mppath->mpp, ETH_ALEN); 1648 /* RA TA mDA mSA AE:DA SA */
1652 else 1649 mesh_da = mppath->mpp;
1653 memset(hdr.addr3, 0xff, ETH_ALEN); 1650 is_mesh_mcast = 0;
1654 rcu_read_unlock(); 1651 } else
1652 /* DA TA mSA AE:SA */
1653 mesh_da = dev->broadcast;
1655 } 1654 }
1655 hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
1656 mesh_da, dev->dev_addr);
1657 rcu_read_unlock();
1658 if (is_mesh_mcast)
1659 meshhdrlen =
1660 ieee80211_new_mesh_header(&mesh_hdr,
1661 sdata,
1662 skb->data + ETH_ALEN,
1663 NULL,
1664 NULL);
1665 else
1666 meshhdrlen =
1667 ieee80211_new_mesh_header(&mesh_hdr,
1668 sdata,
1669 NULL,
1670 skb->data,
1671 skb->data + ETH_ALEN);
1656 1672
1657 mesh_hdr.flags |= MESH_FLAGS_AE_A5_A6;
1658 mesh_hdr.ttl = sdata->u.mesh.mshcfg.dot11MeshTTL;
1659 put_unaligned(cpu_to_le32(sdata->u.mesh.mesh_seqnum), &mesh_hdr.seqnum);
1660 memcpy(mesh_hdr.eaddr1, skb->data, ETH_ALEN);
1661 memcpy(mesh_hdr.eaddr2, skb->data + ETH_ALEN, ETH_ALEN);
1662 sdata->u.mesh.mesh_seqnum++;
1663 meshhdrlen = 18;
1664 } 1673 }
1665 hdrlen = 30;
1666 break; 1674 break;
1667#endif 1675#endif
1668 case NL80211_IFTYPE_STATION: 1676 case NL80211_IFTYPE_STATION:
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index d74cc77fa57a..3ecaa9179977 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -5,7 +5,8 @@ obj-$(CONFIG_LIB80211_CRYPT_WEP) += lib80211_crypt_wep.o
5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o 5obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o sme.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
9cfg80211-y += mlme.o ibss.o sme.o chan.o
9cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o 10cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
10cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o 11cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o wext-sme.o
11 12
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
new file mode 100644
index 000000000000..a46ac6c9b365
--- /dev/null
+++ b/net/wireless/chan.c
@@ -0,0 +1,89 @@
1/*
2 * This file contains helper code to handle channel
3 * settings and keeping track of what is possible at
4 * any point in time.
5 *
6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
7 */
8
9#include <net/cfg80211.h>
10#include "core.h"
11
12struct ieee80211_channel *
13rdev_fixed_channel(struct cfg80211_registered_device *rdev,
14 struct wireless_dev *for_wdev)
15{
16 struct wireless_dev *wdev;
17 struct ieee80211_channel *result = NULL;
18
19 WARN_ON(!mutex_is_locked(&rdev->devlist_mtx));
20
21 list_for_each_entry(wdev, &rdev->netdev_list, list) {
22 if (wdev == for_wdev)
23 continue;
24
25 /*
26 * Lock manually to tell lockdep about allowed
27 * nesting here if for_wdev->mtx is held already.
28 * This is ok as it's all under the rdev devlist
29 * mutex and as such can only be done once at any
30 * given time.
31 */
32 mutex_lock_nested(&wdev->mtx, SINGLE_DEPTH_NESTING);
33 if (wdev->current_bss)
34 result = wdev->current_bss->pub.channel;
35 wdev_unlock(wdev);
36
37 if (result)
38 break;
39 }
40
41 return result;
42}
43
44int rdev_set_freq(struct cfg80211_registered_device *rdev,
45 struct wireless_dev *for_wdev,
46 int freq, enum nl80211_channel_type channel_type)
47{
48 struct ieee80211_channel *chan;
49 struct ieee80211_sta_ht_cap *ht_cap;
50 int result;
51
52 if (rdev_fixed_channel(rdev, for_wdev))
53 return -EBUSY;
54
55 if (!rdev->ops->set_channel)
56 return -EOPNOTSUPP;
57
58 chan = ieee80211_get_channel(&rdev->wiphy, freq);
59
60 /* Primary channel not allowed */
61 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
62 return -EINVAL;
63
64 if (channel_type == NL80211_CHAN_HT40MINUS &&
65 chan->flags & IEEE80211_CHAN_NO_HT40MINUS)
66 return -EINVAL;
67 else if (channel_type == NL80211_CHAN_HT40PLUS &&
68 chan->flags & IEEE80211_CHAN_NO_HT40PLUS)
69 return -EINVAL;
70
71 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
72
73 if (channel_type != NL80211_CHAN_NO_HT) {
74 if (!ht_cap->ht_supported)
75 return -EINVAL;
76
77 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
78 ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)
79 return -EINVAL;
80 }
81
82 result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type);
83 if (result)
84 return result;
85
86 rdev->channel = chan;
87
88 return 0;
89}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 1e189306560d..bc99e4ec7463 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -32,6 +32,7 @@ MODULE_DESCRIPTION("wireless configuration support");
32 * only read the list, and that can happen quite 32 * only read the list, and that can happen quite
33 * often because we need to do it for each command */ 33 * often because we need to do it for each command */
34LIST_HEAD(cfg80211_rdev_list); 34LIST_HEAD(cfg80211_rdev_list);
35int cfg80211_rdev_list_generation;
35 36
36/* 37/*
37 * This is used to protect the cfg80211_rdev_list 38 * This is used to protect the cfg80211_rdev_list
@@ -411,6 +412,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
411 rdev->wiphy.dev.class = &ieee80211_class; 412 rdev->wiphy.dev.class = &ieee80211_class;
412 rdev->wiphy.dev.platform_data = rdev; 413 rdev->wiphy.dev.platform_data = rdev;
413 414
415 rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE;
416
414 wiphy_net_set(&rdev->wiphy, &init_net); 417 wiphy_net_set(&rdev->wiphy, &init_net);
415 418
416 rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block; 419 rdev->rfkill_ops.set_block = cfg80211_rfkill_set_block;
@@ -511,6 +514,7 @@ int wiphy_register(struct wiphy *wiphy)
511 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 514 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
512 515
513 list_add(&rdev->list, &cfg80211_rdev_list); 516 list_add(&rdev->list, &cfg80211_rdev_list);
517 cfg80211_rdev_list_generation++;
514 518
515 mutex_unlock(&cfg80211_mutex); 519 mutex_unlock(&cfg80211_mutex);
516 520
@@ -593,13 +597,14 @@ void wiphy_unregister(struct wiphy *wiphy)
593 reg_device_remove(wiphy); 597 reg_device_remove(wiphy);
594 598
595 list_del(&rdev->list); 599 list_del(&rdev->list);
600 cfg80211_rdev_list_generation++;
596 device_del(&rdev->wiphy.dev); 601 device_del(&rdev->wiphy.dev);
597 debugfs_remove(rdev->wiphy.debugfsdir); 602 debugfs_remove(rdev->wiphy.debugfsdir);
598 603
599 mutex_unlock(&cfg80211_mutex); 604 mutex_unlock(&cfg80211_mutex);
600 605
606 flush_work(&rdev->scan_done_wk);
601 cancel_work_sync(&rdev->conn_work); 607 cancel_work_sync(&rdev->conn_work);
602 cancel_work_sync(&rdev->scan_done_wk);
603 kfree(rdev->scan_req); 608 kfree(rdev->scan_req);
604 flush_work(&rdev->event_work); 609 flush_work(&rdev->event_work);
605} 610}
@@ -653,6 +658,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
653 spin_lock_init(&wdev->event_lock); 658 spin_lock_init(&wdev->event_lock);
654 mutex_lock(&rdev->devlist_mtx); 659 mutex_lock(&rdev->devlist_mtx);
655 list_add(&wdev->list, &rdev->netdev_list); 660 list_add(&wdev->list, &rdev->netdev_list);
661 rdev->devlist_generation++;
656 /* can only change netns with wiphy */ 662 /* can only change netns with wiphy */
657 dev->features |= NETIF_F_NETNS_LOCAL; 663 dev->features |= NETIF_F_NETNS_LOCAL;
658 664
@@ -670,7 +676,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
670 wdev->wext.default_key = -1; 676 wdev->wext.default_key = -1;
671 wdev->wext.default_mgmt_key = -1; 677 wdev->wext.default_mgmt_key = -1;
672 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; 678 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
673 wdev->wext.ps = CONFIG_CFG80211_DEFAULT_PS_VALUE; 679 wdev->wext.ps = wdev->wiphy->ps_default;
674 wdev->wext.ps_timeout = 100; 680 wdev->wext.ps_timeout = 100;
675 if (rdev->ops->set_power_mgmt) 681 if (rdev->ops->set_power_mgmt)
676 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, 682 if (rdev->ops->set_power_mgmt(wdev->wiphy, dev,
@@ -706,6 +712,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
706 case NETDEV_UP: 712 case NETDEV_UP:
707#ifdef CONFIG_WIRELESS_EXT 713#ifdef CONFIG_WIRELESS_EXT
708 cfg80211_lock_rdev(rdev); 714 cfg80211_lock_rdev(rdev);
715 mutex_lock(&rdev->devlist_mtx);
709 wdev_lock(wdev); 716 wdev_lock(wdev);
710 switch (wdev->iftype) { 717 switch (wdev->iftype) {
711 case NL80211_IFTYPE_ADHOC: 718 case NL80211_IFTYPE_ADHOC:
@@ -718,10 +725,18 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
718 break; 725 break;
719 } 726 }
720 wdev_unlock(wdev); 727 wdev_unlock(wdev);
728 mutex_unlock(&rdev->devlist_mtx);
721 cfg80211_unlock_rdev(rdev); 729 cfg80211_unlock_rdev(rdev);
722#endif 730#endif
723 break; 731 break;
724 case NETDEV_UNREGISTER: 732 case NETDEV_UNREGISTER:
733 cfg80211_lock_rdev(rdev);
734
735 if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) {
736 rdev->scan_req->aborted = true;
737 ___cfg80211_scan_done(rdev);
738 }
739
725 mutex_lock(&rdev->devlist_mtx); 740 mutex_lock(&rdev->devlist_mtx);
726 /* 741 /*
727 * It is possible to get NETDEV_UNREGISTER 742 * It is possible to get NETDEV_UNREGISTER
@@ -733,12 +748,14 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
733 if (!list_empty(&wdev->list)) { 748 if (!list_empty(&wdev->list)) {
734 sysfs_remove_link(&dev->dev.kobj, "phy80211"); 749 sysfs_remove_link(&dev->dev.kobj, "phy80211");
735 list_del_init(&wdev->list); 750 list_del_init(&wdev->list);
751 rdev->devlist_generation++;
736 mutex_destroy(&wdev->mtx); 752 mutex_destroy(&wdev->mtx);
737#ifdef CONFIG_WIRELESS_EXT 753#ifdef CONFIG_WIRELESS_EXT
738 kfree(wdev->wext.keys); 754 kfree(wdev->wext.keys);
739#endif 755#endif
740 } 756 }
741 mutex_unlock(&rdev->devlist_mtx); 757 mutex_unlock(&rdev->devlist_mtx);
758 cfg80211_unlock_rdev(rdev);
742 break; 759 break;
743 case NETDEV_PRE_UP: 760 case NETDEV_PRE_UP:
744 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) 761 if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 325c17e6198c..c603f5286326 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -49,6 +49,7 @@ struct cfg80211_registered_device {
49 /* associate netdev list */ 49 /* associate netdev list */
50 struct mutex devlist_mtx; 50 struct mutex devlist_mtx;
51 struct list_head netdev_list; 51 struct list_head netdev_list;
52 int devlist_generation;
52 53
53 /* BSSes/scanning */ 54 /* BSSes/scanning */
54 spinlock_t bss_lock; 55 spinlock_t bss_lock;
@@ -101,6 +102,7 @@ bool wiphy_idx_valid(int wiphy_idx)
101 102
102extern struct mutex cfg80211_mutex; 103extern struct mutex cfg80211_mutex;
103extern struct list_head cfg80211_rdev_list; 104extern struct list_head cfg80211_rdev_list;
105extern int cfg80211_rdev_list_generation;
104 106
105#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex)) 107#define assert_cfg80211_lock() WARN_ON(!mutex_is_locked(&cfg80211_mutex))
106 108
@@ -335,7 +337,8 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
335int __cfg80211_connect(struct cfg80211_registered_device *rdev, 337int __cfg80211_connect(struct cfg80211_registered_device *rdev,
336 struct net_device *dev, 338 struct net_device *dev,
337 struct cfg80211_connect_params *connect, 339 struct cfg80211_connect_params *connect,
338 struct cfg80211_cached_keys *connkeys); 340 struct cfg80211_cached_keys *connkeys,
341 const u8 *prev_bssid);
339int cfg80211_connect(struct cfg80211_registered_device *rdev, 342int cfg80211_connect(struct cfg80211_registered_device *rdev,
340 struct net_device *dev, 343 struct net_device *dev,
341 struct cfg80211_connect_params *connect, 344 struct cfg80211_connect_params *connect,
@@ -353,6 +356,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
353 struct wireless_dev *wdev); 356 struct wireless_dev *wdev);
354 357
355void cfg80211_conn_work(struct work_struct *work); 358void cfg80211_conn_work(struct work_struct *work);
359bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev);
356 360
357/* internal helpers */ 361/* internal helpers */
358int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 362int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
@@ -364,6 +368,14 @@ void cfg80211_sme_scan_done(struct net_device *dev);
364void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); 368void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
365void cfg80211_sme_disassoc(struct net_device *dev, int idx); 369void cfg80211_sme_disassoc(struct net_device *dev, int idx);
366void __cfg80211_scan_done(struct work_struct *wk); 370void __cfg80211_scan_done(struct work_struct *wk);
371void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev);
367void cfg80211_upload_connect_keys(struct wireless_dev *wdev); 372void cfg80211_upload_connect_keys(struct wireless_dev *wdev);
368 373
374struct ieee80211_channel *
375rdev_fixed_channel(struct cfg80211_registered_device *rdev,
376 struct wireless_dev *for_wdev);
377int rdev_set_freq(struct cfg80211_registered_device *rdev,
378 struct wireless_dev *for_wdev,
379 int freq, enum nl80211_channel_type channel_type);
380
369#endif /* __NET_WIRELESS_CORE_H */ 381#endif /* __NET_WIRELESS_CORE_H */
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 4d7a084b35e2..42840a01be74 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -78,10 +78,15 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
78 struct cfg80211_cached_keys *connkeys) 78 struct cfg80211_cached_keys *connkeys)
79{ 79{
80 struct wireless_dev *wdev = dev->ieee80211_ptr; 80 struct wireless_dev *wdev = dev->ieee80211_ptr;
81 struct ieee80211_channel *chan;
81 int err; 82 int err;
82 83
83 ASSERT_WDEV_LOCK(wdev); 84 ASSERT_WDEV_LOCK(wdev);
84 85
86 chan = rdev_fixed_channel(rdev, wdev);
87 if (chan && chan != params->channel)
88 return -EBUSY;
89
85 if (wdev->ssid_len) 90 if (wdev->ssid_len)
86 return -EALREADY; 91 return -EALREADY;
87 92
@@ -112,9 +117,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
112 struct wireless_dev *wdev = dev->ieee80211_ptr; 117 struct wireless_dev *wdev = dev->ieee80211_ptr;
113 int err; 118 int err;
114 119
120 mutex_lock(&rdev->devlist_mtx);
115 wdev_lock(wdev); 121 wdev_lock(wdev);
116 err = __cfg80211_join_ibss(rdev, dev, params, connkeys); 122 err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
117 wdev_unlock(wdev); 123 wdev_unlock(wdev);
124 mutex_unlock(&rdev->devlist_mtx);
118 125
119 return err; 126 return err;
120} 127}
@@ -264,27 +271,32 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
264 271
265int cfg80211_ibss_wext_siwfreq(struct net_device *dev, 272int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
266 struct iw_request_info *info, 273 struct iw_request_info *info,
267 struct iw_freq *freq, char *extra) 274 struct iw_freq *wextfreq, char *extra)
268{ 275{
269 struct wireless_dev *wdev = dev->ieee80211_ptr; 276 struct wireless_dev *wdev = dev->ieee80211_ptr;
270 struct ieee80211_channel *chan; 277 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
271 int err; 278 struct ieee80211_channel *chan = NULL;
279 int err, freq;
272 280
273 /* call only for ibss! */ 281 /* call only for ibss! */
274 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 282 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
275 return -EINVAL; 283 return -EINVAL;
276 284
277 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 285 if (!rdev->ops->join_ibss)
278 return -EOPNOTSUPP; 286 return -EOPNOTSUPP;
279 287
280 chan = cfg80211_wext_freq(wdev->wiphy, freq); 288 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
281 if (chan && IS_ERR(chan)) 289 if (freq < 0)
282 return PTR_ERR(chan); 290 return freq;
283 291
284 if (chan && 292 if (freq) {
285 (chan->flags & IEEE80211_CHAN_NO_IBSS || 293 chan = ieee80211_get_channel(wdev->wiphy, freq);
286 chan->flags & IEEE80211_CHAN_DISABLED)) 294 if (!chan)
287 return -EINVAL; 295 return -EINVAL;
296 if (chan->flags & IEEE80211_CHAN_NO_IBSS ||
297 chan->flags & IEEE80211_CHAN_DISABLED)
298 return -EINVAL;
299 }
288 300
289 if (wdev->wext.ibss.channel == chan) 301 if (wdev->wext.ibss.channel == chan)
290 return 0; 302 return 0;
@@ -292,8 +304,7 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
292 wdev_lock(wdev); 304 wdev_lock(wdev);
293 err = 0; 305 err = 0;
294 if (wdev->ssid_len) 306 if (wdev->ssid_len)
295 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 307 err = __cfg80211_leave_ibss(rdev, dev, true);
296 dev, true);
297 wdev_unlock(wdev); 308 wdev_unlock(wdev);
298 309
299 if (err) 310 if (err)
@@ -307,9 +318,11 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
307 wdev->wext.ibss.channel_fixed = false; 318 wdev->wext.ibss.channel_fixed = false;
308 } 319 }
309 320
321 mutex_lock(&rdev->devlist_mtx);
310 wdev_lock(wdev); 322 wdev_lock(wdev);
311 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 323 err = cfg80211_ibss_wext_join(rdev, wdev);
312 wdev_unlock(wdev); 324 wdev_unlock(wdev);
325 mutex_unlock(&rdev->devlist_mtx);
313 326
314 return err; 327 return err;
315} 328}
@@ -347,6 +360,7 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
347 struct iw_point *data, char *ssid) 360 struct iw_point *data, char *ssid)
348{ 361{
349 struct wireless_dev *wdev = dev->ieee80211_ptr; 362 struct wireless_dev *wdev = dev->ieee80211_ptr;
363 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
350 size_t len = data->length; 364 size_t len = data->length;
351 int err; 365 int err;
352 366
@@ -354,14 +368,13 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
354 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 368 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
355 return -EINVAL; 369 return -EINVAL;
356 370
357 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 371 if (!rdev->ops->join_ibss)
358 return -EOPNOTSUPP; 372 return -EOPNOTSUPP;
359 373
360 wdev_lock(wdev); 374 wdev_lock(wdev);
361 err = 0; 375 err = 0;
362 if (wdev->ssid_len) 376 if (wdev->ssid_len)
363 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 377 err = __cfg80211_leave_ibss(rdev, dev, true);
364 dev, true);
365 wdev_unlock(wdev); 378 wdev_unlock(wdev);
366 379
367 if (err) 380 if (err)
@@ -375,9 +388,11 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
375 memcpy(wdev->wext.ibss.ssid, ssid, len); 388 memcpy(wdev->wext.ibss.ssid, ssid, len);
376 wdev->wext.ibss.ssid_len = len; 389 wdev->wext.ibss.ssid_len = len;
377 390
391 mutex_lock(&rdev->devlist_mtx);
378 wdev_lock(wdev); 392 wdev_lock(wdev);
379 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 393 err = cfg80211_ibss_wext_join(rdev, wdev);
380 wdev_unlock(wdev); 394 wdev_unlock(wdev);
395 mutex_unlock(&rdev->devlist_mtx);
381 396
382 return err; 397 return err;
383} 398}
@@ -414,6 +429,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
414 struct sockaddr *ap_addr, char *extra) 429 struct sockaddr *ap_addr, char *extra)
415{ 430{
416 struct wireless_dev *wdev = dev->ieee80211_ptr; 431 struct wireless_dev *wdev = dev->ieee80211_ptr;
432 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
417 u8 *bssid = ap_addr->sa_data; 433 u8 *bssid = ap_addr->sa_data;
418 int err; 434 int err;
419 435
@@ -421,7 +437,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
421 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) 437 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC))
422 return -EINVAL; 438 return -EINVAL;
423 439
424 if (!wiphy_to_dev(wdev->wiphy)->ops->join_ibss) 440 if (!rdev->ops->join_ibss)
425 return -EOPNOTSUPP; 441 return -EOPNOTSUPP;
426 442
427 if (ap_addr->sa_family != ARPHRD_ETHER) 443 if (ap_addr->sa_family != ARPHRD_ETHER)
@@ -443,8 +459,7 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
443 wdev_lock(wdev); 459 wdev_lock(wdev);
444 err = 0; 460 err = 0;
445 if (wdev->ssid_len) 461 if (wdev->ssid_len)
446 err = __cfg80211_leave_ibss(wiphy_to_dev(wdev->wiphy), 462 err = __cfg80211_leave_ibss(rdev, dev, true);
447 dev, true);
448 wdev_unlock(wdev); 463 wdev_unlock(wdev);
449 464
450 if (err) 465 if (err)
@@ -456,9 +471,11 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
456 } else 471 } else
457 wdev->wext.ibss.bssid = NULL; 472 wdev->wext.ibss.bssid = NULL;
458 473
474 mutex_lock(&rdev->devlist_mtx);
459 wdev_lock(wdev); 475 wdev_lock(wdev);
460 err = cfg80211_ibss_wext_join(wiphy_to_dev(wdev->wiphy), wdev); 476 err = cfg80211_ibss_wext_join(rdev, wdev);
461 wdev_unlock(wdev); 477 wdev_unlock(wdev);
478 mutex_unlock(&rdev->devlist_mtx);
462 479
463 return err; 480 return err;
464} 481}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 525e8e247b30..da64071ceb84 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -67,6 +67,16 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
67 67
68 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); 68 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
69 69
70 /*
71 * This is a bit of a hack, we don't notify userspace of
72 * a (re-)association reply if we tried to send a reassoc
73 * and got a reject -- we only try again with an assoc
74 * frame instead of reassoc.
75 */
76 if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
77 cfg80211_sme_failed_reassoc(wdev))
78 goto out;
79
70 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); 80 nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
71 81
72 if (status_code == WLAN_STATUS_SUCCESS) { 82 if (status_code == WLAN_STATUS_SUCCESS) {
@@ -97,6 +107,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len)
97 cfg80211_put_bss(&bss->pub); 107 cfg80211_put_bss(&bss->pub);
98 } 108 }
99 109
110 out:
100 wdev_unlock(wdev); 111 wdev_unlock(wdev);
101} 112}
102EXPORT_SYMBOL(cfg80211_send_rx_assoc); 113EXPORT_SYMBOL(cfg80211_send_rx_assoc);
@@ -149,7 +160,7 @@ static void __cfg80211_send_deauth(struct net_device *dev,
149 160
150 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); 161 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
151 162
152 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 163 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
153 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 164 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
154 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) { 165 } else if (wdev->sme_state == CFG80211_SME_CONNECTING) {
155 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0, 166 __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, NULL, 0,
@@ -198,7 +209,7 @@ static void __cfg80211_send_disassoc(struct net_device *dev,
198 return; 209 return;
199 210
200 if (wdev->current_bss && 211 if (wdev->current_bss &&
201 memcmp(wdev->current_bss, bssid, ETH_ALEN) == 0) { 212 memcmp(wdev->current_bss->pub.bssid, bssid, ETH_ALEN) == 0) {
202 for (i = 0; i < MAX_AUTH_BSSES; i++) { 213 for (i = 0; i < MAX_AUTH_BSSES; i++) {
203 if (wdev->authtry_bsses[i] || wdev->auth_bsses[i]) 214 if (wdev->authtry_bsses[i] || wdev->auth_bsses[i])
204 continue; 215 continue;
@@ -215,7 +226,7 @@ static void __cfg80211_send_disassoc(struct net_device *dev,
215 226
216 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); 227 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
217 228
218 from_ap = memcmp(mgmt->da, dev->dev_addr, ETH_ALEN) == 0; 229 from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
219 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); 230 __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
220} 231}
221 232
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 0cd548267d4a..a8aaadeb6773 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -408,6 +408,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
408 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx); 408 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
409 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 409 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
410 410
411 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
412 cfg80211_rdev_list_generation);
413
411 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT, 414 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_SHORT,
412 dev->wiphy.retry_short); 415 dev->wiphy.retry_short);
413 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG, 416 NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_RETRY_LONG,
@@ -701,15 +704,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
701 704
702 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { 705 if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
703 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 706 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
704 struct ieee80211_channel *chan;
705 struct ieee80211_sta_ht_cap *ht_cap;
706 u32 freq; 707 u32 freq;
707 708
708 if (!rdev->ops->set_channel) {
709 result = -EOPNOTSUPP;
710 goto bad_res;
711 }
712
713 result = -EINVAL; 709 result = -EINVAL;
714 710
715 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { 711 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
@@ -723,42 +719,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
723 } 719 }
724 720
725 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); 721 freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]);
726 chan = ieee80211_get_channel(&rdev->wiphy, freq);
727
728 /* Primary channel not allowed */
729 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
730 goto bad_res;
731
732 if (channel_type == NL80211_CHAN_HT40MINUS &&
733 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
734 goto bad_res;
735 else if (channel_type == NL80211_CHAN_HT40PLUS &&
736 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
737 goto bad_res;
738
739 /*
740 * At this point we know if that if HT40 was requested
741 * we are allowed to use it and the extension channel
742 * exists.
743 */
744
745 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
746
747 /* no HT capabilities or intolerant */
748 if (channel_type != NL80211_CHAN_NO_HT) {
749 if (!ht_cap->ht_supported)
750 goto bad_res;
751 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
752 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
753 goto bad_res;
754 }
755 722
756 result = rdev->ops->set_channel(&rdev->wiphy, chan, 723 mutex_lock(&rdev->devlist_mtx);
757 channel_type); 724 result = rdev_set_freq(rdev, NULL, freq, channel_type);
725 mutex_unlock(&rdev->devlist_mtx);
758 if (result) 726 if (result)
759 goto bad_res; 727 goto bad_res;
760
761 rdev->channel = chan;
762 } 728 }
763 729
764 changed = 0; 730 changed = 0;
@@ -862,6 +828,11 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags,
862 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); 828 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
863 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name); 829 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, dev->name);
864 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype); 830 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, dev->ieee80211_ptr->iftype);
831
832 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION,
833 rdev->devlist_generation ^
834 (cfg80211_rdev_list_generation << 2));
835
865 return genlmsg_end(msg, hdr); 836 return genlmsg_end(msg, hdr);
866 837
867 nla_put_failure: 838 nla_put_failure:
@@ -875,12 +846,12 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
875 int if_idx = 0; 846 int if_idx = 0;
876 int wp_start = cb->args[0]; 847 int wp_start = cb->args[0];
877 int if_start = cb->args[1]; 848 int if_start = cb->args[1];
878 struct cfg80211_registered_device *dev; 849 struct cfg80211_registered_device *rdev;
879 struct wireless_dev *wdev; 850 struct wireless_dev *wdev;
880 851
881 mutex_lock(&cfg80211_mutex); 852 mutex_lock(&cfg80211_mutex);
882 list_for_each_entry(dev, &cfg80211_rdev_list, list) { 853 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
883 if (!net_eq(wiphy_net(&dev->wiphy), sock_net(skb->sk))) 854 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
884 continue; 855 continue;
885 if (wp_idx < wp_start) { 856 if (wp_idx < wp_start) {
886 wp_idx++; 857 wp_idx++;
@@ -888,21 +859,21 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
888 } 859 }
889 if_idx = 0; 860 if_idx = 0;
890 861
891 mutex_lock(&dev->devlist_mtx); 862 mutex_lock(&rdev->devlist_mtx);
892 list_for_each_entry(wdev, &dev->netdev_list, list) { 863 list_for_each_entry(wdev, &rdev->netdev_list, list) {
893 if (if_idx < if_start) { 864 if (if_idx < if_start) {
894 if_idx++; 865 if_idx++;
895 continue; 866 continue;
896 } 867 }
897 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid, 868 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).pid,
898 cb->nlh->nlmsg_seq, NLM_F_MULTI, 869 cb->nlh->nlmsg_seq, NLM_F_MULTI,
899 dev, wdev->netdev) < 0) { 870 rdev, wdev->netdev) < 0) {
900 mutex_unlock(&dev->devlist_mtx); 871 mutex_unlock(&rdev->devlist_mtx);
901 goto out; 872 goto out;
902 } 873 }
903 if_idx++; 874 if_idx++;
904 } 875 }
905 mutex_unlock(&dev->devlist_mtx); 876 mutex_unlock(&rdev->devlist_mtx);
906 877
907 wp_idx++; 878 wp_idx++;
908 } 879 }
@@ -1653,6 +1624,8 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1653 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex); 1624 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
1654 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); 1625 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr);
1655 1626
1627 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, sinfo->generation);
1628
1656 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO); 1629 sinfoattr = nla_nest_start(msg, NL80211_ATTR_STA_INFO);
1657 if (!sinfoattr) 1630 if (!sinfoattr)
1658 goto nla_put_failure; 1631 goto nla_put_failure;
@@ -2138,6 +2111,8 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
2138 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst); 2111 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
2139 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop); 2112 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
2140 2113
2114 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, pinfo->generation);
2115
2141 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO); 2116 pinfoattr = nla_nest_start(msg, NL80211_ATTR_MPATH_INFO);
2142 if (!pinfoattr) 2117 if (!pinfoattr)
2143 goto nla_put_failure; 2118 goto nla_put_failure;
@@ -3027,10 +3002,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
3027 goto out; 3002 goto out;
3028 } 3003 }
3029 3004
3030 request->channels = (void *)((char *)request + sizeof(*request));
3031 request->n_channels = n_channels; 3005 request->n_channels = n_channels;
3032 if (n_ssids) 3006 if (n_ssids)
3033 request->ssids = (void *)(request->channels + n_channels); 3007 request->ssids = (void *)&request->channels[n_channels];
3034 request->n_ssids = n_ssids; 3008 request->n_ssids = n_ssids;
3035 if (ie_len) { 3009 if (ie_len) {
3036 if (request->ssids) 3010 if (request->ssids)
@@ -3127,8 +3101,7 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
3127 if (!hdr) 3101 if (!hdr)
3128 return -1; 3102 return -1;
3129 3103
3130 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION, 3104 NLA_PUT_U32(msg, NL80211_ATTR_GENERATION, rdev->bss_generation);
3131 rdev->bss_generation);
3132 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex); 3105 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex);
3133 3106
3134 bss = nla_nest_start(msg, NL80211_ATTR_BSS); 3107 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
@@ -3453,7 +3426,7 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3453 struct cfg80211_registered_device *rdev; 3426 struct cfg80211_registered_device *rdev;
3454 struct net_device *dev; 3427 struct net_device *dev;
3455 struct cfg80211_crypto_settings crypto; 3428 struct cfg80211_crypto_settings crypto;
3456 struct ieee80211_channel *chan; 3429 struct ieee80211_channel *chan, *fixedchan;
3457 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL; 3430 const u8 *bssid, *ssid, *ie = NULL, *prev_bssid = NULL;
3458 int err, ssid_len, ie_len = 0; 3431 int err, ssid_len, ie_len = 0;
3459 bool use_mfp = false; 3432 bool use_mfp = false;
@@ -3496,6 +3469,15 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
3496 goto out; 3469 goto out;
3497 } 3470 }
3498 3471
3472 mutex_lock(&rdev->devlist_mtx);
3473 fixedchan = rdev_fixed_channel(rdev, NULL);
3474 if (fixedchan && chan != fixedchan) {
3475 err = -EBUSY;
3476 mutex_unlock(&rdev->devlist_mtx);
3477 goto out;
3478 }
3479 mutex_unlock(&rdev->devlist_mtx);
3480
3499 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); 3481 ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
3500 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); 3482 ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
3501 3483
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0f61ae613f3b..f256dfffbf46 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1018,7 +1018,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1018 map_regdom_flags(reg_rule->flags) | bw_flags; 1018 map_regdom_flags(reg_rule->flags) | bw_flags;
1019 chan->max_antenna_gain = chan->orig_mag = 1019 chan->max_antenna_gain = chan->orig_mag =
1020 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1020 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1021 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1022 chan->max_power = chan->orig_mpwr = 1021 chan->max_power = chan->orig_mpwr =
1023 (int) MBM_TO_DBM(power_rule->max_eirp); 1022 (int) MBM_TO_DBM(power_rule->max_eirp);
1024 return; 1023 return;
@@ -1027,7 +1026,6 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
1027 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); 1026 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
1028 chan->max_antenna_gain = min(chan->orig_mag, 1027 chan->max_antenna_gain = min(chan->orig_mag,
1029 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1028 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
1030 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1031 if (chan->orig_mpwr) 1029 if (chan->orig_mpwr)
1032 chan->max_power = min(chan->orig_mpwr, 1030 chan->max_power = min(chan->orig_mpwr,
1033 (int) MBM_TO_DBM(power_rule->max_eirp)); 1031 (int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1329,7 +1327,6 @@ static void handle_channel_custom(struct wiphy *wiphy,
1329 1327
1330 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; 1328 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1331 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1329 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1332 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1333 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1330 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1334} 1331}
1335 1332
@@ -1427,7 +1424,7 @@ static int ignore_request(struct wiphy *wiphy,
1427 if (last_wiphy != wiphy) { 1424 if (last_wiphy != wiphy) {
1428 /* 1425 /*
1429 * Two cards with two APs claiming different 1426 * Two cards with two APs claiming different
1430 * different Country IE alpha2s. We could 1427 * Country IE alpha2s. We could
1431 * intersect them, but that seems unlikely 1428 * intersect them, but that seems unlikely
1432 * to be correct. Reject second one for now. 1429 * to be correct. Reject second one for now.
1433 */ 1430 */
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 0ccf3a07dc02..fe575a24c95c 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -18,19 +18,14 @@
18 18
19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) 19#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
20 20
21void __cfg80211_scan_done(struct work_struct *wk) 21void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev)
22{ 22{
23 struct cfg80211_registered_device *rdev;
24 struct cfg80211_scan_request *request; 23 struct cfg80211_scan_request *request;
25 struct net_device *dev; 24 struct net_device *dev;
26#ifdef CONFIG_WIRELESS_EXT 25#ifdef CONFIG_WIRELESS_EXT
27 union iwreq_data wrqu; 26 union iwreq_data wrqu;
28#endif 27#endif
29 28
30 rdev = container_of(wk, struct cfg80211_registered_device,
31 scan_done_wk);
32
33 mutex_lock(&rdev->mtx);
34 request = rdev->scan_req; 29 request = rdev->scan_req;
35 30
36 dev = request->dev; 31 dev = request->dev;
@@ -43,9 +38,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
43 cfg80211_sme_scan_done(dev); 38 cfg80211_sme_scan_done(dev);
44 39
45 if (request->aborted) 40 if (request->aborted)
46 nl80211_send_scan_aborted(wiphy_to_dev(request->wiphy), dev); 41 nl80211_send_scan_aborted(rdev, dev);
47 else 42 else
48 nl80211_send_scan_done(wiphy_to_dev(request->wiphy), dev); 43 nl80211_send_scan_done(rdev, dev);
49 44
50#ifdef CONFIG_WIRELESS_EXT 45#ifdef CONFIG_WIRELESS_EXT
51 if (!request->aborted) { 46 if (!request->aborted) {
@@ -57,11 +52,22 @@ void __cfg80211_scan_done(struct work_struct *wk)
57 52
58 dev_put(dev); 53 dev_put(dev);
59 54
60 cfg80211_unlock_rdev(rdev); 55 rdev->scan_req = NULL;
61 wiphy_to_dev(request->wiphy)->scan_req = NULL;
62 kfree(request); 56 kfree(request);
63} 57}
64 58
59void __cfg80211_scan_done(struct work_struct *wk)
60{
61 struct cfg80211_registered_device *rdev;
62
63 rdev = container_of(wk, struct cfg80211_registered_device,
64 scan_done_wk);
65
66 cfg80211_lock_rdev(rdev);
67 ___cfg80211_scan_done(rdev);
68 cfg80211_unlock_rdev(rdev);
69}
70
65void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) 71void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
66{ 72{
67 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 73 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
@@ -562,6 +568,7 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
562 spin_lock_bh(&dev->bss_lock); 568 spin_lock_bh(&dev->bss_lock);
563 569
564 list_del(&bss->list); 570 list_del(&bss->list);
571 dev->bss_generation++;
565 rb_erase(&bss->rbn, &dev->bss_tree); 572 rb_erase(&bss->rbn, &dev->bss_tree);
566 573
567 spin_unlock_bh(&dev->bss_lock); 574 spin_unlock_bh(&dev->bss_lock);
@@ -611,8 +618,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
611 618
612 creq->wiphy = wiphy; 619 creq->wiphy = wiphy;
613 creq->dev = dev; 620 creq->dev = dev;
614 creq->ssids = (void *)(creq + 1); 621 /* SSIDs come after channels */
615 creq->channels = (void *)(creq->ssids + 1); 622 creq->ssids = (void *)&creq->channels[n_channels];
616 creq->n_channels = n_channels; 623 creq->n_channels = n_channels;
617 creq->n_ssids = 1; 624 creq->n_ssids = 1;
618 625
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 8a7dcbf90602..8e2ef54ea714 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -27,10 +27,10 @@ struct cfg80211_conn {
27 CFG80211_CONN_ASSOCIATE_NEXT, 27 CFG80211_CONN_ASSOCIATE_NEXT,
28 CFG80211_CONN_ASSOCIATING, 28 CFG80211_CONN_ASSOCIATING,
29 } state; 29 } state;
30 u8 bssid[ETH_ALEN]; 30 u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
31 u8 *ie; 31 u8 *ie;
32 size_t ie_len; 32 size_t ie_len;
33 bool auto_auth; 33 bool auto_auth, prev_bssid_valid;
34}; 34};
35 35
36 36
@@ -65,7 +65,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
65 if (!request) 65 if (!request)
66 return -ENOMEM; 66 return -ENOMEM;
67 67
68 request->channels = (void *)((char *)request + sizeof(*request));
69 if (wdev->conn->params.channel) 68 if (wdev->conn->params.channel)
70 request->channels[0] = wdev->conn->params.channel; 69 request->channels[0] = wdev->conn->params.channel;
71 else { 70 else {
@@ -82,7 +81,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
82 } 81 }
83 } 82 }
84 request->n_channels = n_channels; 83 request->n_channels = n_channels;
85 request->ssids = (void *)(request->channels + n_channels); 84 request->ssids = (void *)&request->channels[n_channels];
86 request->n_ssids = 1; 85 request->n_ssids = 1;
87 86
88 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid, 87 memcpy(request->ssids[0].ssid, wdev->conn->params.ssid,
@@ -110,6 +109,7 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
110{ 109{
111 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 110 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
112 struct cfg80211_connect_params *params; 111 struct cfg80211_connect_params *params;
112 const u8 *prev_bssid = NULL;
113 int err; 113 int err;
114 114
115 ASSERT_WDEV_LOCK(wdev); 115 ASSERT_WDEV_LOCK(wdev);
@@ -135,15 +135,11 @@ static int cfg80211_conn_do_work(struct wireless_dev *wdev)
135 case CFG80211_CONN_ASSOCIATE_NEXT: 135 case CFG80211_CONN_ASSOCIATE_NEXT:
136 BUG_ON(!rdev->ops->assoc); 136 BUG_ON(!rdev->ops->assoc);
137 wdev->conn->state = CFG80211_CONN_ASSOCIATING; 137 wdev->conn->state = CFG80211_CONN_ASSOCIATING;
138 /* 138 if (wdev->conn->prev_bssid_valid)
139 * We could, later, implement roaming here and then actually 139 prev_bssid = wdev->conn->prev_bssid;
140 * set prev_bssid to non-NULL. But then we need to be aware
141 * that some APs don't like that -- so we'd need to retry
142 * the association.
143 */
144 err = __cfg80211_mlme_assoc(rdev, wdev->netdev, 140 err = __cfg80211_mlme_assoc(rdev, wdev->netdev,
145 params->channel, params->bssid, 141 params->channel, params->bssid,
146 NULL, 142 prev_bssid,
147 params->ssid, params->ssid_len, 143 params->ssid, params->ssid_len,
148 params->ie, params->ie_len, 144 params->ie, params->ie_len,
149 false, &params->crypto); 145 false, &params->crypto);
@@ -256,9 +252,11 @@ void cfg80211_sme_scan_done(struct net_device *dev)
256{ 252{
257 struct wireless_dev *wdev = dev->ieee80211_ptr; 253 struct wireless_dev *wdev = dev->ieee80211_ptr;
258 254
255 mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
259 wdev_lock(wdev); 256 wdev_lock(wdev);
260 __cfg80211_sme_scan_done(dev); 257 __cfg80211_sme_scan_done(dev);
261 wdev_unlock(wdev); 258 wdev_unlock(wdev);
259 mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
262} 260}
263 261
264void cfg80211_sme_rx_auth(struct net_device *dev, 262void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -314,6 +312,28 @@ void cfg80211_sme_rx_auth(struct net_device *dev,
314 } 312 }
315} 313}
316 314
315bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev)
316{
317 struct wiphy *wiphy = wdev->wiphy;
318 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
319
320 if (WARN_ON(!wdev->conn))
321 return false;
322
323 if (!wdev->conn->prev_bssid_valid)
324 return false;
325
326 /*
327 * Some stupid APs don't accept reassoc, so we
328 * need to fall back to trying regular assoc.
329 */
330 wdev->conn->prev_bssid_valid = false;
331 wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT;
332 schedule_work(&rdev->conn_work);
333
334 return true;
335}
336
317void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, 337void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
318 const u8 *req_ie, size_t req_ie_len, 338 const u8 *req_ie, size_t req_ie_len,
319 const u8 *resp_ie, size_t resp_ie_len, 339 const u8 *resp_ie, size_t resp_ie_len,
@@ -357,8 +377,11 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
357 377
358 memset(&wrqu, 0, sizeof(wrqu)); 378 memset(&wrqu, 0, sizeof(wrqu));
359 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 379 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
360 if (bssid && status == WLAN_STATUS_SUCCESS) 380 if (bssid && status == WLAN_STATUS_SUCCESS) {
361 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 381 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
382 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
383 wdev->wext.prev_bssid_valid = true;
384 }
362 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); 385 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
363 } 386 }
364#endif 387#endif
@@ -509,6 +532,8 @@ void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid,
509 memset(&wrqu, 0, sizeof(wrqu)); 532 memset(&wrqu, 0, sizeof(wrqu));
510 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 533 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
511 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); 534 memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN);
535 memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN);
536 wdev->wext.prev_bssid_valid = true;
512 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL); 537 wireless_send_event(wdev->netdev, SIOCGIWAP, &wrqu, NULL);
513#endif 538#endif
514} 539}
@@ -570,10 +595,30 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
570 wdev->ssid_len = 0; 595 wdev->ssid_len = 0;
571 596
572 if (wdev->conn) { 597 if (wdev->conn) {
598 const u8 *bssid;
599 int ret;
600
573 kfree(wdev->conn->ie); 601 kfree(wdev->conn->ie);
574 wdev->conn->ie = NULL; 602 wdev->conn->ie = NULL;
575 kfree(wdev->conn); 603 kfree(wdev->conn);
576 wdev->conn = NULL; 604 wdev->conn = NULL;
605
606 /*
607 * If this disconnect was due to a disassoc, we
608 * we might still have an auth BSS around. For
609 * the userspace SME that's currently expected,
610 * but for the kernel SME (nl80211 CONNECT or
611 * wireless extensions) we want to clear up all
612 * state.
613 */
614 for (i = 0; i < MAX_AUTH_BSSES; i++) {
615 if (!wdev->auth_bsses[i])
616 continue;
617 bssid = wdev->auth_bsses[i]->pub.bssid;
618 ret = __cfg80211_mlme_deauth(rdev, dev, bssid, NULL, 0,
619 WLAN_REASON_DEAUTH_LEAVING);
620 WARN(ret, "deauth failed: %d\n", ret);
621 }
577 } 622 }
578 623
579 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap); 624 nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
@@ -621,9 +666,11 @@ EXPORT_SYMBOL(cfg80211_disconnected);
621int __cfg80211_connect(struct cfg80211_registered_device *rdev, 666int __cfg80211_connect(struct cfg80211_registered_device *rdev,
622 struct net_device *dev, 667 struct net_device *dev,
623 struct cfg80211_connect_params *connect, 668 struct cfg80211_connect_params *connect,
624 struct cfg80211_cached_keys *connkeys) 669 struct cfg80211_cached_keys *connkeys,
670 const u8 *prev_bssid)
625{ 671{
626 struct wireless_dev *wdev = dev->ieee80211_ptr; 672 struct wireless_dev *wdev = dev->ieee80211_ptr;
673 struct ieee80211_channel *chan;
627 int err; 674 int err;
628 675
629 ASSERT_WDEV_LOCK(wdev); 676 ASSERT_WDEV_LOCK(wdev);
@@ -631,6 +678,10 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
631 if (wdev->sme_state != CFG80211_SME_IDLE) 678 if (wdev->sme_state != CFG80211_SME_IDLE)
632 return -EALREADY; 679 return -EALREADY;
633 680
681 chan = rdev_fixed_channel(rdev, wdev);
682 if (chan && chan != connect->channel)
683 return -EBUSY;
684
634 if (WARN_ON(wdev->connect_keys)) { 685 if (WARN_ON(wdev->connect_keys)) {
635 kfree(wdev->connect_keys); 686 kfree(wdev->connect_keys);
636 wdev->connect_keys = NULL; 687 wdev->connect_keys = NULL;
@@ -638,14 +689,28 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
638 689
639 if (connkeys && connkeys->def >= 0) { 690 if (connkeys && connkeys->def >= 0) {
640 int idx; 691 int idx;
692 u32 cipher;
641 693
642 idx = connkeys->def; 694 idx = connkeys->def;
695 cipher = connkeys->params[idx].cipher;
643 /* If given a WEP key we may need it for shared key auth */ 696 /* If given a WEP key we may need it for shared key auth */
644 if (connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP40 || 697 if (cipher == WLAN_CIPHER_SUITE_WEP40 ||
645 connkeys->params[idx].cipher == WLAN_CIPHER_SUITE_WEP104) { 698 cipher == WLAN_CIPHER_SUITE_WEP104) {
646 connect->key_idx = idx; 699 connect->key_idx = idx;
647 connect->key = connkeys->params[idx].key; 700 connect->key = connkeys->params[idx].key;
648 connect->key_len = connkeys->params[idx].key_len; 701 connect->key_len = connkeys->params[idx].key_len;
702
703 /*
704 * If ciphers are not set (e.g. when going through
705 * iwconfig), we have to set them appropriately here.
706 */
707 if (connect->crypto.cipher_group == 0)
708 connect->crypto.cipher_group = cipher;
709
710 if (connect->crypto.n_ciphers_pairwise == 0) {
711 connect->crypto.n_ciphers_pairwise = 1;
712 connect->crypto.ciphers_pairwise[0] = cipher;
713 }
649 } 714 }
650 } 715 }
651 716
@@ -701,6 +766,11 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev,
701 wdev->sme_state = CFG80211_SME_CONNECTING; 766 wdev->sme_state = CFG80211_SME_CONNECTING;
702 wdev->connect_keys = connkeys; 767 wdev->connect_keys = connkeys;
703 768
769 if (prev_bssid) {
770 memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
771 wdev->conn->prev_bssid_valid = true;
772 }
773
704 /* we're good if we have both BSSID and channel */ 774 /* we're good if we have both BSSID and channel */
705 if (wdev->conn->params.bssid && wdev->conn->params.channel) { 775 if (wdev->conn->params.bssid && wdev->conn->params.channel) {
706 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; 776 wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
@@ -751,9 +821,11 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
751{ 821{
752 int err; 822 int err;
753 823
824 mutex_lock(&rdev->devlist_mtx);
754 wdev_lock(dev->ieee80211_ptr); 825 wdev_lock(dev->ieee80211_ptr);
755 err = __cfg80211_connect(rdev, dev, connect, connkeys); 826 err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
756 wdev_unlock(dev->ieee80211_ptr); 827 wdev_unlock(dev->ieee80211_ptr);
828 mutex_unlock(&rdev->devlist_mtx);
757 829
758 return err; 830 return err;
759} 831}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index ba387d85dcfd..693275a16a26 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -274,11 +274,11 @@ static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
274 switch (ae) { 274 switch (ae) {
275 case 0: 275 case 0:
276 return 6; 276 return 6;
277 case 1: 277 case MESH_FLAGS_AE_A4:
278 return 12; 278 return 12;
279 case 2: 279 case MESH_FLAGS_AE_A5_A6:
280 return 18; 280 return 18;
281 case 3: 281 case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6):
282 return 24; 282 return 24;
283 default: 283 default:
284 return 6; 284 return 6;
@@ -333,10 +333,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
333 } 333 }
334 break; 334 break;
335 case cpu_to_le16(IEEE80211_FCTL_FROMDS): 335 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
336 if (iftype != NL80211_IFTYPE_STATION || 336 if ((iftype != NL80211_IFTYPE_STATION &&
337 iftype != NL80211_IFTYPE_MESH_POINT) ||
337 (is_multicast_ether_addr(dst) && 338 (is_multicast_ether_addr(dst) &&
338 !compare_ether_addr(src, addr))) 339 !compare_ether_addr(src, addr)))
339 return -1; 340 return -1;
341 if (iftype == NL80211_IFTYPE_MESH_POINT) {
342 struct ieee80211s_hdr *meshdr =
343 (struct ieee80211s_hdr *) (skb->data + hdrlen);
344 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
345 if (meshdr->flags & MESH_FLAGS_AE_A4)
346 memcpy(src, meshdr->eaddr1, ETH_ALEN);
347 }
340 break; 348 break;
341 case cpu_to_le16(0): 349 case cpu_to_le16(0):
342 if (iftype != NL80211_IFTYPE_ADHOC) 350 if (iftype != NL80211_IFTYPE_ADHOC)
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index e4e90e249bab..c44917492210 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -267,39 +267,26 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwrange);
267 * @wiphy: the wiphy 267 * @wiphy: the wiphy
268 * @freq: the wext freq encoding 268 * @freq: the wext freq encoding
269 * 269 *
270 * Returns a channel, %NULL for auto, or an ERR_PTR for errors! 270 * Returns a frequency, or a negative error code, or 0 for auto.
271 */ 271 */
272struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 272int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq)
273 struct iw_freq *freq)
274{ 273{
275 struct ieee80211_channel *chan;
276 int f;
277
278 /* 274 /*
279 * Parse frequency - return NULL for auto and 275 * Parse frequency - return 0 for auto and
280 * -EINVAL for impossible things. 276 * -EINVAL for impossible things.
281 */ 277 */
282 if (freq->e == 0) { 278 if (freq->e == 0) {
283 if (freq->m < 0) 279 if (freq->m < 0)
284 return NULL; 280 return 0;
285 f = ieee80211_channel_to_frequency(freq->m); 281 return ieee80211_channel_to_frequency(freq->m);
286 } else { 282 } else {
287 int i, div = 1000000; 283 int i, div = 1000000;
288 for (i = 0; i < freq->e; i++) 284 for (i = 0; i < freq->e; i++)
289 div /= 10; 285 div /= 10;
290 if (div <= 0) 286 if (div <= 0)
291 return ERR_PTR(-EINVAL); 287 return -EINVAL;
292 f = freq->m / div; 288 return freq->m / div;
293 } 289 }
294
295 /*
296 * Look up channel struct and return -EINVAL when
297 * it cannot be found.
298 */
299 chan = ieee80211_get_channel(wiphy, f);
300 if (!chan)
301 return ERR_PTR(-EINVAL);
302 return chan;
303} 290}
304 291
305int cfg80211_wext_siwrts(struct net_device *dev, 292int cfg80211_wext_siwrts(struct net_device *dev,
@@ -761,33 +748,29 @@ EXPORT_SYMBOL_GPL(cfg80211_wext_giwencode);
761 748
762int cfg80211_wext_siwfreq(struct net_device *dev, 749int cfg80211_wext_siwfreq(struct net_device *dev,
763 struct iw_request_info *info, 750 struct iw_request_info *info,
764 struct iw_freq *freq, char *extra) 751 struct iw_freq *wextfreq, char *extra)
765{ 752{
766 struct wireless_dev *wdev = dev->ieee80211_ptr; 753 struct wireless_dev *wdev = dev->ieee80211_ptr;
767 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 754 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
768 struct ieee80211_channel *chan; 755 int freq, err;
769 int err;
770 756
771 switch (wdev->iftype) { 757 switch (wdev->iftype) {
772 case NL80211_IFTYPE_STATION: 758 case NL80211_IFTYPE_STATION:
773 return cfg80211_mgd_wext_siwfreq(dev, info, freq, extra); 759 return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
774 case NL80211_IFTYPE_ADHOC: 760 case NL80211_IFTYPE_ADHOC:
775 return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra); 761 return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
776 default: 762 default:
777 chan = cfg80211_wext_freq(wdev->wiphy, freq); 763 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
778 if (!chan) 764 if (freq < 0)
765 return freq;
766 if (freq == 0)
779 return -EINVAL; 767 return -EINVAL;
780 if (IS_ERR(chan)) 768 mutex_lock(&rdev->devlist_mtx);
781 return PTR_ERR(chan); 769 err = rdev_set_freq(rdev, NULL, freq, NL80211_CHAN_NO_HT);
782 err = rdev->ops->set_channel(wdev->wiphy, chan, 770 mutex_unlock(&rdev->devlist_mtx);
783 NL80211_CHAN_NO_HT); 771 return err;
784 if (err)
785 return err;
786 rdev->channel = chan;
787 return 0;
788 } 772 }
789} 773}
790EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq);
791 774
792int cfg80211_wext_giwfreq(struct net_device *dev, 775int cfg80211_wext_giwfreq(struct net_device *dev,
793 struct iw_request_info *info, 776 struct iw_request_info *info,
diff --git a/net/wireless/wext-compat.h b/net/wireless/wext-compat.h
index 9a3774749589..20b3daef6964 100644
--- a/net/wireless/wext-compat.h
+++ b/net/wireless/wext-compat.h
@@ -42,8 +42,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
42 struct iw_request_info *info, 42 struct iw_request_info *info,
43 struct iw_point *data, char *ssid); 43 struct iw_point *data, char *ssid);
44 44
45struct ieee80211_channel *cfg80211_wext_freq(struct wiphy *wiphy, 45int cfg80211_wext_freq(struct wiphy *wiphy, struct iw_freq *freq);
46 struct iw_freq *freq);
47 46
48 47
49extern const struct iw_handler_def cfg80211_wext_handler; 48extern const struct iw_handler_def cfg80211_wext_handler;
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 7bacbd1c2af6..d16cd9ea4d00 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -15,6 +15,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
15 struct wireless_dev *wdev) 15 struct wireless_dev *wdev)
16{ 16{
17 struct cfg80211_cached_keys *ck = NULL; 17 struct cfg80211_cached_keys *ck = NULL;
18 const u8 *prev_bssid = NULL;
18 int err, i; 19 int err, i;
19 20
20 ASSERT_RDEV_LOCK(rdev); 21 ASSERT_RDEV_LOCK(rdev);
@@ -42,8 +43,12 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
42 for (i = 0; i < 6; i++) 43 for (i = 0; i < 6; i++)
43 ck->params[i].key = ck->data[i]; 44 ck->params[i].key = ck->data[i];
44 } 45 }
46
47 if (wdev->wext.prev_bssid_valid)
48 prev_bssid = wdev->wext.prev_bssid;
49
45 err = __cfg80211_connect(rdev, wdev->netdev, 50 err = __cfg80211_connect(rdev, wdev->netdev,
46 &wdev->wext.connect, ck); 51 &wdev->wext.connect, ck, prev_bssid);
47 if (err) 52 if (err)
48 kfree(ck); 53 kfree(ck);
49 54
@@ -52,25 +57,31 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
52 57
53int cfg80211_mgd_wext_siwfreq(struct net_device *dev, 58int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
54 struct iw_request_info *info, 59 struct iw_request_info *info,
55 struct iw_freq *freq, char *extra) 60 struct iw_freq *wextfreq, char *extra)
56{ 61{
57 struct wireless_dev *wdev = dev->ieee80211_ptr; 62 struct wireless_dev *wdev = dev->ieee80211_ptr;
58 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 63 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
59 struct ieee80211_channel *chan; 64 struct ieee80211_channel *chan = NULL;
60 int err; 65 int err, freq;
61 66
62 /* call only for station! */ 67 /* call only for station! */
63 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) 68 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
64 return -EINVAL; 69 return -EINVAL;
65 70
66 chan = cfg80211_wext_freq(wdev->wiphy, freq); 71 freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
67 if (chan && IS_ERR(chan)) 72 if (freq < 0)
68 return PTR_ERR(chan); 73 return freq;
69 74
70 if (chan && (chan->flags & IEEE80211_CHAN_DISABLED)) 75 if (freq) {
71 return -EINVAL; 76 chan = ieee80211_get_channel(wdev->wiphy, freq);
77 if (!chan)
78 return -EINVAL;
79 if (chan->flags & IEEE80211_CHAN_DISABLED)
80 return -EINVAL;
81 }
72 82
73 cfg80211_lock_rdev(rdev); 83 cfg80211_lock_rdev(rdev);
84 mutex_lock(&rdev->devlist_mtx);
74 wdev_lock(wdev); 85 wdev_lock(wdev);
75 86
76 if (wdev->sme_state != CFG80211_SME_IDLE) { 87 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -84,9 +95,8 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
84 /* if SSID set, we'll try right again, avoid event */ 95 /* if SSID set, we'll try right again, avoid event */
85 if (wdev->wext.connect.ssid_len) 96 if (wdev->wext.connect.ssid_len)
86 event = false; 97 event = false;
87 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 98 err = __cfg80211_disconnect(rdev, dev,
88 dev, WLAN_REASON_DEAUTH_LEAVING, 99 WLAN_REASON_DEAUTH_LEAVING, event);
89 event);
90 if (err) 100 if (err)
91 goto out; 101 goto out;
92 } 102 }
@@ -95,17 +105,15 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
95 wdev->wext.connect.channel = chan; 105 wdev->wext.connect.channel = chan;
96 106
97 /* SSID is not set, we just want to switch channel */ 107 /* SSID is not set, we just want to switch channel */
98 if (wdev->wext.connect.ssid_len && chan) { 108 if (chan && !wdev->wext.connect.ssid_len) {
99 err = -EOPNOTSUPP; 109 err = rdev_set_freq(rdev, wdev, freq, NL80211_CHAN_NO_HT);
100 if (rdev->ops->set_channel)
101 err = rdev->ops->set_channel(wdev->wiphy, chan,
102 NL80211_CHAN_NO_HT);
103 goto out; 110 goto out;
104 } 111 }
105 112
106 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 113 err = cfg80211_mgd_wext_connect(rdev, wdev);
107 out: 114 out:
108 wdev_unlock(wdev); 115 wdev_unlock(wdev);
116 mutex_unlock(&rdev->devlist_mtx);
109 cfg80211_unlock_rdev(rdev); 117 cfg80211_unlock_rdev(rdev);
110 return err; 118 return err;
111} 119}
@@ -143,6 +151,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
143 struct iw_point *data, char *ssid) 151 struct iw_point *data, char *ssid)
144{ 152{
145 struct wireless_dev *wdev = dev->ieee80211_ptr; 153 struct wireless_dev *wdev = dev->ieee80211_ptr;
154 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
146 size_t len = data->length; 155 size_t len = data->length;
147 int err; 156 int err;
148 157
@@ -157,7 +166,8 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
157 if (len > 0 && ssid[len - 1] == '\0') 166 if (len > 0 && ssid[len - 1] == '\0')
158 len--; 167 len--;
159 168
160 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); 169 cfg80211_lock_rdev(rdev);
170 mutex_lock(&rdev->devlist_mtx);
161 wdev_lock(wdev); 171 wdev_lock(wdev);
162 172
163 err = 0; 173 err = 0;
@@ -173,23 +183,24 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
173 /* if SSID set now, we'll try to connect, avoid event */ 183 /* if SSID set now, we'll try to connect, avoid event */
174 if (len) 184 if (len)
175 event = false; 185 event = false;
176 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 186 err = __cfg80211_disconnect(rdev, dev,
177 dev, WLAN_REASON_DEAUTH_LEAVING, 187 WLAN_REASON_DEAUTH_LEAVING, event);
178 event);
179 if (err) 188 if (err)
180 goto out; 189 goto out;
181 } 190 }
182 191
192 wdev->wext.prev_bssid_valid = false;
183 wdev->wext.connect.ssid = wdev->wext.ssid; 193 wdev->wext.connect.ssid = wdev->wext.ssid;
184 memcpy(wdev->wext.ssid, ssid, len); 194 memcpy(wdev->wext.ssid, ssid, len);
185 wdev->wext.connect.ssid_len = len; 195 wdev->wext.connect.ssid_len = len;
186 196
187 wdev->wext.connect.crypto.control_port = false; 197 wdev->wext.connect.crypto.control_port = false;
188 198
189 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 199 err = cfg80211_mgd_wext_connect(rdev, wdev);
190 out: 200 out:
191 wdev_unlock(wdev); 201 wdev_unlock(wdev);
192 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); 202 mutex_unlock(&rdev->devlist_mtx);
203 cfg80211_unlock_rdev(rdev);
193 return err; 204 return err;
194} 205}
195 206
@@ -206,7 +217,15 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
206 data->flags = 0; 217 data->flags = 0;
207 218
208 wdev_lock(wdev); 219 wdev_lock(wdev);
209 if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { 220 if (wdev->current_bss) {
221 const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
222 WLAN_EID_SSID);
223 if (ie) {
224 data->flags = 1;
225 data->length = ie[1];
226 memcpy(ssid, ie + 2, data->length);
227 }
228 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
210 data->flags = 1; 229 data->flags = 1;
211 data->length = wdev->wext.connect.ssid_len; 230 data->length = wdev->wext.connect.ssid_len;
212 memcpy(ssid, wdev->wext.connect.ssid, data->length); 231 memcpy(ssid, wdev->wext.connect.ssid, data->length);
@@ -222,6 +241,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
222 struct sockaddr *ap_addr, char *extra) 241 struct sockaddr *ap_addr, char *extra)
223{ 242{
224 struct wireless_dev *wdev = dev->ieee80211_ptr; 243 struct wireless_dev *wdev = dev->ieee80211_ptr;
244 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
225 u8 *bssid = ap_addr->sa_data; 245 u8 *bssid = ap_addr->sa_data;
226 int err; 246 int err;
227 247
@@ -236,7 +256,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
236 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) 256 if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
237 bssid = NULL; 257 bssid = NULL;
238 258
239 cfg80211_lock_rdev(wiphy_to_dev(wdev->wiphy)); 259 cfg80211_lock_rdev(rdev);
260 mutex_lock(&rdev->devlist_mtx);
240 wdev_lock(wdev); 261 wdev_lock(wdev);
241 262
242 if (wdev->sme_state != CFG80211_SME_IDLE) { 263 if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -250,9 +271,8 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
250 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0) 271 compare_ether_addr(bssid, wdev->wext.connect.bssid) == 0)
251 goto out; 272 goto out;
252 273
253 err = __cfg80211_disconnect(wiphy_to_dev(wdev->wiphy), 274 err = __cfg80211_disconnect(rdev, dev,
254 dev, WLAN_REASON_DEAUTH_LEAVING, 275 WLAN_REASON_DEAUTH_LEAVING, false);
255 false);
256 if (err) 276 if (err)
257 goto out; 277 goto out;
258 } 278 }
@@ -263,10 +283,11 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
263 } else 283 } else
264 wdev->wext.connect.bssid = NULL; 284 wdev->wext.connect.bssid = NULL;
265 285
266 err = cfg80211_mgd_wext_connect(wiphy_to_dev(wdev->wiphy), wdev); 286 err = cfg80211_mgd_wext_connect(rdev, wdev);
267 out: 287 out:
268 wdev_unlock(wdev); 288 wdev_unlock(wdev);
269 cfg80211_unlock_rdev(wiphy_to_dev(wdev->wiphy)); 289 mutex_unlock(&rdev->devlist_mtx);
290 cfg80211_unlock_rdev(rdev);
270 return err; 291 return err;
271} 292}
272 293