Przeglądaj źródła

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

Conflicts:
	net/mac80211/pm.c
David S. Miller 16 lat temu
rodzic
commit
495a1b4eff
100 zmienionych plików z 2243 dodań i 1880 usunięć
  1. 6 22
      Documentation/networking/mac80211-injection.txt
  2. 6 10
      Documentation/rfkill.txt
  3. 8 2
      MAINTAINERS
  4. 2 2
      arch/arm/mach-pxa/tosa-bt.c
  5. 2 2
      drivers/net/usb/hso.c
  6. 11 5
      drivers/net/wireless/Kconfig
  7. 1 3
      drivers/net/wireless/Makefile
  8. 1 0
      drivers/net/wireless/at76c50x-usb.c
  9. 8 0
      drivers/net/wireless/ath/Kconfig
  10. 6 0
      drivers/net/wireless/ath/Makefile
  11. 1 0
      drivers/net/wireless/ath/ar9170/Kconfig
  12. 0 0
      drivers/net/wireless/ath/ar9170/Makefile
  13. 31 1
      drivers/net/wireless/ath/ar9170/ar9170.h
  14. 0 0
      drivers/net/wireless/ath/ar9170/cmd.c
  15. 0 0
      drivers/net/wireless/ath/ar9170/cmd.h
  16. 0 0
      drivers/net/wireless/ath/ar9170/eeprom.h
  17. 9 6
      drivers/net/wireless/ath/ar9170/hw.h
  18. 0 0
      drivers/net/wireless/ath/ar9170/led.c
  19. 0 0
      drivers/net/wireless/ath/ar9170/mac.c
  20. 470 143
      drivers/net/wireless/ath/ar9170/main.c
  21. 0 0
      drivers/net/wireless/ath/ar9170/phy.c
  22. 0 0
      drivers/net/wireless/ath/ar9170/usb.c
  23. 1 1
      drivers/net/wireless/ath/ar9170/usb.h
  24. 1 0
      drivers/net/wireless/ath/ath5k/Kconfig
  25. 0 0
      drivers/net/wireless/ath/ath5k/Makefile
  26. 3 2
      drivers/net/wireless/ath/ath5k/ath5k.h
  27. 0 0
      drivers/net/wireless/ath/ath5k/attach.c
  28. 49 25
      drivers/net/wireless/ath/ath5k/base.c
  29. 0 1
      drivers/net/wireless/ath/ath5k/base.h
  30. 0 0
      drivers/net/wireless/ath/ath5k/caps.c
  31. 0 0
      drivers/net/wireless/ath/ath5k/debug.c
  32. 0 0
      drivers/net/wireless/ath/ath5k/debug.h
  33. 0 0
      drivers/net/wireless/ath/ath5k/desc.c
  34. 0 0
      drivers/net/wireless/ath/ath5k/desc.h
  35. 0 2
      drivers/net/wireless/ath/ath5k/dma.c
  36. 0 0
      drivers/net/wireless/ath/ath5k/eeprom.c
  37. 0 0
      drivers/net/wireless/ath/ath5k/eeprom.h
  38. 0 0
      drivers/net/wireless/ath/ath5k/gpio.c
  39. 3 5
      drivers/net/wireless/ath/ath5k/initvals.c
  40. 3 1
      drivers/net/wireless/ath/ath5k/led.c
  41. 0 0
      drivers/net/wireless/ath/ath5k/pcu.c
  42. 28 21
      drivers/net/wireless/ath/ath5k/phy.c
  43. 0 0
      drivers/net/wireless/ath/ath5k/qcu.c
  44. 0 0
      drivers/net/wireless/ath/ath5k/reg.h
  45. 1 1
      drivers/net/wireless/ath/ath5k/reset.c
  46. 0 0
      drivers/net/wireless/ath/ath5k/rfbuffer.h
  47. 0 0
      drivers/net/wireless/ath/ath5k/rfgain.h
  48. 1 0
      drivers/net/wireless/ath/ath9k/Kconfig
  49. 0 1
      drivers/net/wireless/ath/ath9k/Makefile
  50. 0 0
      drivers/net/wireless/ath/ath9k/ahb.c
  51. 3 5
      drivers/net/wireless/ath/ath9k/ani.c
  52. 0 0
      drivers/net/wireless/ath/ath9k/ani.h
  53. 21 44
      drivers/net/wireless/ath/ath9k/ath9k.h
  54. 7 10
      drivers/net/wireless/ath/ath9k/beacon.c
  55. 51 72
      drivers/net/wireless/ath/ath9k/calib.c
  56. 16 17
      drivers/net/wireless/ath/ath9k/calib.h
  57. 3 0
      drivers/net/wireless/ath/ath9k/debug.c
  58. 10 14
      drivers/net/wireless/ath/ath9k/debug.h
  59. 12 12
      drivers/net/wireless/ath/ath9k/eeprom.c
  60. 2 0
      drivers/net/wireless/ath/ath9k/eeprom.h
  61. 72 107
      drivers/net/wireless/ath/ath9k/hw.c
  62. 31 59
      drivers/net/wireless/ath/ath9k/hw.h
  63. 0 0
      drivers/net/wireless/ath/ath9k/initvals.h
  64. 37 26
      drivers/net/wireless/ath/ath9k/mac.c
  65. 0 0
      drivers/net/wireless/ath/ath9k/mac.h
  66. 174 200
      drivers/net/wireless/ath/ath9k/main.c
  67. 0 0
      drivers/net/wireless/ath/ath9k/pci.c
  68. 2 2
      drivers/net/wireless/ath/ath9k/phy.c
  69. 0 3
      drivers/net/wireless/ath/ath9k/phy.h
  70. 11 15
      drivers/net/wireless/ath/ath9k/rc.c
  71. 0 4
      drivers/net/wireless/ath/ath9k/rc.h
  72. 40 45
      drivers/net/wireless/ath/ath9k/recv.c
  73. 0 0
      drivers/net/wireless/ath/ath9k/reg.h
  74. 0 0
      drivers/net/wireless/ath/ath9k/virtual.c
  75. 29 35
      drivers/net/wireless/ath/ath9k/xmit.c
  76. 22 0
      drivers/net/wireless/ath/main.c
  77. 137 104
      drivers/net/wireless/ath/regd.c
  78. 29 11
      drivers/net/wireless/ath/regd.h
  79. 0 0
      drivers/net/wireless/ath/regd_common.h
  80. 7 1
      drivers/net/wireless/b43/Kconfig
  81. 5 3
      drivers/net/wireless/b43/b43.h
  82. 26 43
      drivers/net/wireless/b43/main.c
  83. 0 1
      drivers/net/wireless/b43/rfkill.c
  84. 7 1
      drivers/net/wireless/b43legacy/Kconfig
  85. 6 2
      drivers/net/wireless/b43legacy/b43legacy.h
  86. 150 43
      drivers/net/wireless/b43legacy/main.c
  87. 0 1
      drivers/net/wireless/b43legacy/rfkill.c
  88. 1 1
      drivers/net/wireless/b43legacy/xmit.c
  89. 3 1
      drivers/net/wireless/b43legacy/xmit.h
  90. 1 1
      drivers/net/wireless/hostap/hostap_plx.c
  91. 1 1
      drivers/net/wireless/iwlwifi/iwl-3945-rs.c
  92. 206 0
      drivers/net/wireless/iwlwifi/iwl-3945.c
  93. 4 2
      drivers/net/wireless/iwlwifi/iwl-3945.h
  94. 11 2
      drivers/net/wireless/iwlwifi/iwl-4965.c
  95. 13 4
      drivers/net/wireless/iwlwifi/iwl-5000.c
  96. 1 0
      drivers/net/wireless/iwlwifi/iwl-6000.c
  97. 360 50
      drivers/net/wireless/iwlwifi/iwl-agn-rs.c
  98. 25 0
      drivers/net/wireless/iwlwifi/iwl-agn-rs.h
  99. 51 679
      drivers/net/wireless/iwlwifi/iwl-agn.c
  100. 4 3
      drivers/net/wireless/iwlwifi/iwl-commands.h

+ 6 - 22
Documentation/networking/mac80211-injection.txt

@@ -12,38 +12,22 @@ following format:
 The radiotap format is discussed in
 ./Documentation/networking/radiotap-headers.txt.
 
-Despite 13 radiotap argument types are currently defined, most only make sense
+Despite many radiotap parameters being currently defined, most only make sense
 to appear on received packets.  The following information is parsed from the
 radiotap headers and used to control injection:
 
- * IEEE80211_RADIOTAP_RATE
-
-   rate in 500kbps units, automatic if invalid or not present
-
-
- * IEEE80211_RADIOTAP_ANTENNA
-
-   antenna to use, automatic if not present
-
-
- * IEEE80211_RADIOTAP_DBM_TX_POWER
-
-   transmit power in dBm, automatic if not present
-
-
  * IEEE80211_RADIOTAP_FLAGS
 
    IEEE80211_RADIOTAP_F_FCS: FCS will be removed and recalculated
    IEEE80211_RADIOTAP_F_WEP: frame will be encrypted if key available
    IEEE80211_RADIOTAP_F_FRAG: frame will be fragmented if longer than the
-			      current fragmentation threshold. Note that
-			      this flag is only reliable when software
-			      fragmentation is enabled)
+			      current fragmentation threshold.
+
 
 The injection code can also skip all other currently defined radiotap fields
 facilitating replay of captured radiotap headers directly.
 
-Here is an example valid radiotap header defining these three parameters
+Here is an example valid radiotap header defining some parameters
 
 	0x00, 0x00, // <-- radiotap version
 	0x0b, 0x00, // <- radiotap header length
@@ -72,8 +56,8 @@ interface), along the following lines:
 ...
 	r = pcap_inject(ppcap, u8aSendBuffer, nLength);
 
-You can also find sources for a complete inject test applet here:
+You can also find a link to a complete inject application here:
 
-http://penumbra.warmcat.com/_twk/tiki-index.php?page=packetspammer
+http://wireless.kernel.org/en/users/Documentation/packetspammer
 
 Andy Green <andy@warmcat.com>

+ 6 - 10
Documentation/rfkill.txt

@@ -521,16 +521,12 @@ status of the system.
 Input devices may issue events that are related to rfkill.  These are the
 various KEY_* events and SW_* events supported by rfkill-input.c.
 
-******IMPORTANT******
-When rfkill-input is ACTIVE, userspace is NOT TO CHANGE THE STATE OF AN RFKILL
-SWITCH IN RESPONSE TO AN INPUT EVENT also handled by rfkill-input, unless it
-has set to true the user_claim attribute for that particular switch.  This rule
-is *absolute*; do NOT violate it.
-******IMPORTANT******
-
-Userspace must not assume it is the only source of control for rfkill switches.
-Their state CAN and WILL change due to firmware actions, direct user actions,
-and the rfkill-input EPO override for *_RFKILL_ALL.
+Userspace may not change the state of an rfkill switch in response to an
+input event, it should refrain from changing states entirely.
+
+Userspace cannot assume it is the only source of control for rfkill switches.
+Their state can change due to firmware actions, direct user actions, and the
+rfkill-input EPO override for *_RFKILL_ALL.
 
 When rfkill-input is not active, userspace must initiate a rfkill status
 change by writing to the "state" attribute in order for anything to happen.

+ 8 - 2
MAINTAINERS

@@ -888,6 +888,12 @@ P:	Luis R. Rodriguez
 M:	lrodriguez@atheros.com
 P:	Jouni Malinen
 M:	jmalinen@atheros.com
+P:	Sujith Manoharan
+M:	Sujith.Manoharan@atheros.com
+P:	Vasanthakumar Thiagarajan
+M:	vasanth@atheros.com
+P:	Senthil Balasubramanian
+M:	senthilkumar@atheros.com
 L:	linux-wireless@vger.kernel.org
 L:	ath9k-devel@lists.ath9k.org
 S:	Supported
@@ -4421,8 +4427,8 @@ S:	Maintained
 F:	drivers/ata/sata_promise.*
 
 PS3 NETWORK SUPPORT
-P:	Masakazu Mokuno
-M:	mokuno@sm.sony.co.jp
+P:	Geoff Levand
+M:	geoffrey.levand@am.sony.com
 L:	netdev@vger.kernel.org
 L:	cbe-oss-dev@ozlabs.org
 S:	Supported

+ 2 - 2
arch/arm/mach-pxa/tosa-bt.c

@@ -38,9 +38,9 @@ static void tosa_bt_off(struct tosa_bt_data *data)
 static int tosa_bt_toggle_radio(void *data, enum rfkill_state state)
 {
 	pr_info("BT_RADIO going: %s\n",
-			state == RFKILL_STATE_ON ? "on" : "off");
+			state == RFKILL_STATE_UNBLOCKED ? "on" : "off");
 
-	if (state == RFKILL_STATE_ON) {
+	if (state == RFKILL_STATE_UNBLOCKED) {
 		pr_info("TOSA_BT: going ON\n");
 		tosa_bt_on(data);
 	} else {

+ 2 - 2
drivers/net/usb/hso.c

@@ -2484,7 +2484,7 @@ static int add_net_device(struct hso_device *hso_dev)
 static int hso_radio_toggle(void *data, enum rfkill_state state)
 {
 	struct hso_device *hso_dev = data;
-	int enabled = (state == RFKILL_STATE_ON);
+	int enabled = (state == RFKILL_STATE_UNBLOCKED);
 	int rv;
 
 	mutex_lock(&hso_dev->mutex);
@@ -2522,7 +2522,7 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
 	snprintf(rfkn, 20, "hso-%d",
 		 interface->altsetting->desc.bInterfaceNumber);
 	hso_net->rfkill->name = rfkn;
-	hso_net->rfkill->state = RFKILL_STATE_ON;
+	hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED;
 	hso_net->rfkill->data = hso_dev;
 	hso_net->rfkill->toggle_radio = hso_radio_toggle;
 	if (rfkill_register(hso_net->rfkill) < 0) {

+ 11 - 5
drivers/net/wireless/Kconfig

@@ -146,10 +146,10 @@ config LIBERTAS_CS
 	  A driver for Marvell Libertas 8385 CompactFlash devices.
 
 config LIBERTAS_SDIO
-	tristate "Marvell Libertas 8385 and 8686 SDIO 802.11b/g cards"
+	tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
 	depends on LIBERTAS && MMC
 	---help---
-	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
+	  A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
 
 config LIBERTAS_SPI
 	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
@@ -337,6 +337,7 @@ config USB_NET_RNDIS_WLAN
 	select USB_NET_CDCETHER
 	select USB_NET_RNDIS_HOST
 	select WIRELESS_EXT
+	select CFG80211
 	---help---
 	  This is a driver for wireless RNDIS devices.
 	  These are USB based adapters found in devices such as:
@@ -433,6 +434,13 @@ config RTL8187
 
 	  Thanks to Realtek for their support!
 
+# If possible, automatically enable LEDs for RTL8187.
+
+config RTL8187_LEDS
+	bool
+	depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187)
+	default y
+
 config ADM8211
 	tristate "ADMtek ADM8211 support"
 	depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
@@ -483,9 +491,7 @@ config MWL8K
 	  will be called mwl8k.  If unsure, say N.
 
 source "drivers/net/wireless/p54/Kconfig"
-source "drivers/net/wireless/ath5k/Kconfig"
-source "drivers/net/wireless/ath9k/Kconfig"
-source "drivers/net/wireless/ar9170/Kconfig"
+source "drivers/net/wireless/ath/Kconfig"
 source "drivers/net/wireless/ipw2x00/Kconfig"
 source "drivers/net/wireless/iwlwifi/Kconfig"
 source "drivers/net/wireless/hostap/Kconfig"

+ 1 - 3
drivers/net/wireless/Makefile

@@ -55,8 +55,6 @@ obj-$(CONFIG_RT2X00)	+= rt2x00/
 
 obj-$(CONFIG_P54_COMMON)	+= p54/
 
-obj-$(CONFIG_ATH5K)	+= ath5k/
-obj-$(CONFIG_ATH9K)	+= ath9k/
-obj-$(CONFIG_AR9170_USB)	+= ar9170/
+obj-$(CONFIG_ATH_COMMON)	+= ath/
 
 obj-$(CONFIG_MAC80211_HWSIM)	+= mac80211_hwsim.o

+ 1 - 0
drivers/net/wireless/at76c50x-usb.c

@@ -2250,6 +2250,7 @@ static int at76_init_new_device(struct at76_priv *priv,
 
 	/* mac80211 initialisation */
 	priv->hw->wiphy->max_scan_ssids = 1;
+	priv->hw->wiphy->max_scan_ie_len = 0;
 	priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
 	priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band;
 	priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |

+ 8 - 0
drivers/net/wireless/ath/Kconfig

@@ -0,0 +1,8 @@
+config ATH_COMMON
+	tristate "Atheros Wireless Cards"
+	depends on ATH5K || ATH9K || AR9170_USB
+
+source "drivers/net/wireless/ath/ath5k/Kconfig"
+source "drivers/net/wireless/ath/ath9k/Kconfig"
+source "drivers/net/wireless/ath/ar9170/Kconfig"
+

+ 6 - 0
drivers/net/wireless/ath/Makefile

@@ -0,0 +1,6 @@
+obj-$(CONFIG_ATH5K)		+= ath5k/
+obj-$(CONFIG_ATH9K)		+= ath9k/
+obj-$(CONFIG_AR9170_USB)        += ar9170/
+
+obj-$(CONFIG_ATH_COMMON)	+= ath.o
+ath-objs 		:= main.o regd.o

+ 1 - 0
drivers/net/wireless/ar9170/Kconfig → drivers/net/wireless/ath/ar9170/Kconfig

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

+ 0 - 0
drivers/net/wireless/ar9170/Makefile → drivers/net/wireless/ath/ar9170/Makefile


+ 31 - 1
drivers/net/wireless/ar9170/ar9170.h → drivers/net/wireless/ath/ar9170/ar9170.h

@@ -40,7 +40,7 @@
 
 #include <linux/completion.h>
 #include <linux/spinlock.h>
-#include <net/wireless.h>
+#include <net/cfg80211.h>
 #include <net/mac80211.h>
 #ifdef CONFIG_AR9170_LEDS
 #include <linux/leds.h>
@@ -48,6 +48,8 @@
 #include "eeprom.h"
 #include "hw.h"
 
+#include "../regd.h"
+
 #define PAYLOAD_MAX	(AR9170_MAX_CMD_LEN/4 - 1)
 
 enum ar9170_bw {
@@ -58,6 +60,21 @@ enum ar9170_bw {
 	__AR9170_NUM_BW,
 };
 
+static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type)
+{
+	switch (type) {
+	case NL80211_CHAN_NO_HT:
+	case NL80211_CHAN_HT20:
+		return AR9170_BW_20;
+	case NL80211_CHAN_HT40MINUS:
+		return AR9170_BW_40_BELOW;
+	case NL80211_CHAN_HT40PLUS:
+		return AR9170_BW_40_ABOVE;
+	default:
+		BUG();
+	}
+}
+
 enum ar9170_rf_init_mode {
 	AR9170_RFI_NONE,
 	AR9170_RFI_WARM,
@@ -87,10 +104,16 @@ enum ar9170_device_state {
 	AR9170_ASSOCIATED,
 };
 
+struct ar9170_rxstream_mpdu_merge {
+	struct ar9170_rx_head plcp;
+	bool has_plcp;
+};
+
 struct ar9170 {
 	struct ieee80211_hw *hw;
 	struct mutex mutex;
 	enum ar9170_device_state state;
+	unsigned long bad_hw_nagger;
 
 	int (*open)(struct ar9170 *);
 	void (*stop)(struct ar9170 *);
@@ -118,6 +141,7 @@ struct ar9170 {
 	u64 cur_mc_hash, want_mc_hash;
 	u32 cur_filter, want_filter;
 	unsigned int filter_changed;
+	unsigned int filter_state;
 	bool sniffer_enabled;
 
 	/* PHY */
@@ -151,11 +175,17 @@ struct ar9170 {
 
 	/* EEPROM */
 	struct ar9170_eeprom eeprom;
+	struct ath_regulatory regulatory;
 
 	/* global tx status for unregistered Stations. */
 	struct sk_buff_head global_tx_status;
 	struct sk_buff_head global_tx_status_waste;
 	struct delayed_work tx_status_janitor;
+
+	/* rxstream mpdu merge */
+	struct ar9170_rxstream_mpdu_merge rx_mpdu;
+	struct sk_buff *rx_failover;
+	int rx_failover_missing;
 };
 
 struct ar9170_sta_info {

+ 0 - 0
drivers/net/wireless/ar9170/cmd.c → drivers/net/wireless/ath/ar9170/cmd.c


+ 0 - 0
drivers/net/wireless/ar9170/cmd.h → drivers/net/wireless/ath/ar9170/cmd.h


+ 0 - 0
drivers/net/wireless/ar9170/eeprom.h → drivers/net/wireless/ath/ar9170/eeprom.h


+ 9 - 6
drivers/net/wireless/ar9170/hw.h → drivers/net/wireless/ath/ar9170/hw.h

@@ -312,7 +312,7 @@ struct ar9170_rx_head {
 	u8 plcp[12];
 } __packed;
 
-struct ar9170_rx_tail {
+struct ar9170_rx_phystatus {
 	union {
 		struct {
 			u8 rssi_ant0, rssi_ant1, rssi_ant2,
@@ -324,6 +324,9 @@ struct ar9170_rx_tail {
 
 	u8 evm_stream0[6], evm_stream1[6];
 	u8 phy_err;
+} __packed;
+
+struct ar9170_rx_macstatus {
 	u8 SAidx, DAidx;
 	u8 error;
 	u8 status;
@@ -339,7 +342,7 @@ struct ar9170_rx_tail {
 
 #define AR9170_RX_ENC_SOFTWARE			0x8
 
-static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
+static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t)
 {
 	return (t->SAidx & 0xc0) >> 4 |
 	       (t->DAidx & 0xc0) >> 6;
@@ -357,10 +360,9 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
 
 #define AR9170_RX_STATUS_MPDU_MASK		0x30
 #define AR9170_RX_STATUS_MPDU_SINGLE		0x00
-#define AR9170_RX_STATUS_MPDU_FIRST		0x10
-#define AR9170_RX_STATUS_MPDU_MIDDLE		0x20
-#define AR9170_RX_STATUS_MPDU_LAST		0x30
-
+#define AR9170_RX_STATUS_MPDU_FIRST		0x20
+#define AR9170_RX_STATUS_MPDU_MIDDLE		0x30
+#define AR9170_RX_STATUS_MPDU_LAST		0x10
 
 #define AR9170_RX_ERROR_RXTO			0x01
 #define AR9170_RX_ERROR_OVERRUN			0x02
@@ -369,6 +371,7 @@ static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_tail *t)
 #define AR9170_RX_ERROR_WRONG_RA		0x10
 #define AR9170_RX_ERROR_PLCP			0x20
 #define AR9170_RX_ERROR_MMIC			0x40
+#define AR9170_RX_ERROR_FATAL			0x80
 
 struct ar9170_cmd_tx_status {
 	__le16 unkn;

+ 0 - 0
drivers/net/wireless/ar9170/led.c → drivers/net/wireless/ath/ar9170/led.c


+ 0 - 0
drivers/net/wireless/ar9170/mac.c → drivers/net/wireless/ath/ar9170/mac.c


+ 470 - 143
drivers/net/wireless/ar9170/main.c → drivers/net/wireless/ath/ar9170/main.c

@@ -142,11 +142,36 @@ static struct ieee80211_channel ar9170_5ghz_chantable[] = {
 };
 #undef CHAN
 
+#define AR9170_HT_CAP							\
+{									\
+	.ht_supported	= true,						\
+	.cap		= IEEE80211_HT_CAP_MAX_AMSDU |			\
+			  IEEE80211_HT_CAP_SM_PS |			\
+			  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |		\
+			  IEEE80211_HT_CAP_SGI_40 |			\
+			  IEEE80211_HT_CAP_DSSSCCK40 |			\
+			  IEEE80211_HT_CAP_SM_PS,			\
+	.ampdu_factor	= 3, /* ?? */					\
+	.ampdu_density	= 7, /* ?? */					\
+	.mcs		= {						\
+		.rx_mask = { 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, },	\
+	},								\
+}
+
 static struct ieee80211_supported_band ar9170_band_2GHz = {
 	.channels	= ar9170_2ghz_chantable,
 	.n_channels	= ARRAY_SIZE(ar9170_2ghz_chantable),
 	.bitrates	= ar9170_g_ratetable,
 	.n_bitrates	= ar9170_g_ratetable_size,
+	.ht_cap		= AR9170_HT_CAP,
+};
+
+static struct ieee80211_supported_band ar9170_band_5GHz = {
+	.channels	= ar9170_5ghz_chantable,
+	.n_channels	= ARRAY_SIZE(ar9170_5ghz_chantable),
+	.bitrates	= ar9170_a_ratetable,
+	.n_bitrates	= ar9170_a_ratetable_size,
+	.ht_cap		= AR9170_HT_CAP,
 };
 
 #ifdef AR9170_QUEUE_DEBUG
@@ -190,13 +215,6 @@ static void ar9170_dump_station_tx_status_queue(struct ar9170 *ar,
 }
 #endif /* AR9170_QUEUE_DEBUG */
 
-static struct ieee80211_supported_band ar9170_band_5GHz = {
-	.channels	= ar9170_5ghz_chantable,
-	.n_channels	= ARRAY_SIZE(ar9170_5ghz_chantable),
-	.bitrates	= ar9170_a_ratetable,
-	.n_bitrates	= ar9170_a_ratetable_size,
-};
-
 void ar9170_handle_tx_status(struct ar9170 *ar, struct sk_buff *skb,
 			     bool valid_status, u16 tx_status)
 {
@@ -436,214 +454,430 @@ static void ar9170_handle_command_response(struct ar9170 *ar,
 	}
 }
 
-/*
- * If the frame alignment is right (or the kernel has
- * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
- * is only a single MPDU in the USB frame, then we can
- * submit to mac80211 the SKB directly. However, since
- * there may be multiple packets in one SKB in stream
- * mode, and we need to observe the proper ordering,
- * this is non-trivial.
- */
-static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar)
 {
-	struct sk_buff *skb;
-	struct ar9170_rx_head *head = (void *)buf;
-	struct ar9170_rx_tail *tail;
-	struct ieee80211_rx_status status;
-	int mpdu_len, i;
-	u8 error, antennas = 0, decrypt;
-	__le16 fc;
-	int reserved;
+	memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head));
+	ar->rx_mpdu.has_plcp = false;
+}
 
-	if (unlikely(!IS_STARTED(ar)))
-		return ;
+static int ar9170_nag_limiter(struct ar9170 *ar)
+{
+	bool print_message;
+
+	/*
+	 * we expect all sorts of errors in promiscuous mode.
+	 * don't bother with it, it's OK!
+	 */
+	if (ar->sniffer_enabled)
+		return false;
+
+	/*
+	 * only go for frequent errors! The hardware tends to
+	 * do some stupid thing once in a while under load, in
+	 * noisy environments or just for fun!
+	 */
+	if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit())
+		print_message = true;
+	else
+		print_message = false;
+
+	/* reset threshold for "once in a while" */
+	ar->bad_hw_nagger = jiffies + HZ / 4;
+	return print_message;
+}
+
+static int ar9170_rx_mac_status(struct ar9170 *ar,
+				struct ar9170_rx_head *head,
+				struct ar9170_rx_macstatus *mac,
+				struct ieee80211_rx_status *status)
+{
+	u8 error, decrypt;
 
-	/* Received MPDU */
-	mpdu_len = len;
-	mpdu_len -= sizeof(struct ar9170_rx_head);
-	mpdu_len -= sizeof(struct ar9170_rx_tail);
 	BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
-	BUILD_BUG_ON(sizeof(struct ar9170_rx_tail) != 24);
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
 
-	if (mpdu_len <= FCS_LEN)
-		return;
+	error = mac->error;
+	if (error & AR9170_RX_ERROR_MMIC) {
+		status->flag |= RX_FLAG_MMIC_ERROR;
+		error &= ~AR9170_RX_ERROR_MMIC;
+	}
 
-	tail = (void *)(buf + sizeof(struct ar9170_rx_head) + mpdu_len);
+	if (error & AR9170_RX_ERROR_PLCP) {
+		status->flag |= RX_FLAG_FAILED_PLCP_CRC;
+		error &= ~AR9170_RX_ERROR_PLCP;
 
-	for (i = 0; i < 3; i++)
-		if (tail->rssi[i] != 0x80)
-			antennas |= BIT(i);
+		if (!(ar->filter_state & FIF_PLCPFAIL))
+			return -EINVAL;
+	}
 
-	/* post-process RSSI */
-	for (i = 0; i < 7; i++)
-		if (tail->rssi[i] & 0x80)
-			tail->rssi[i] = ((tail->rssi[i] & 0x7f) + 1) & 0x7f;
+	if (error & AR9170_RX_ERROR_FCS) {
+		status->flag |= RX_FLAG_FAILED_FCS_CRC;
+		error &= ~AR9170_RX_ERROR_FCS;
 
-	memset(&status, 0, sizeof(status));
+		if (!(ar->filter_state & FIF_FCSFAIL))
+			return -EINVAL;
+	}
+
+	decrypt = ar9170_get_decrypt_type(mac);
+	if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
+	    decrypt != AR9170_ENC_ALG_NONE)
+		status->flag |= RX_FLAG_DECRYPTED;
 
-	status.band = ar->channel->band;
-	status.freq = ar->channel->center_freq;
-	status.signal = ar->noise[0] + tail->rssi_combined;
-	status.noise = ar->noise[0];
-	status.antenna = antennas;
+	/* ignore wrong RA errors */
+	error &= ~AR9170_RX_ERROR_WRONG_RA;
+
+	if (error & AR9170_RX_ERROR_DECRYPT) {
+		error &= ~AR9170_RX_ERROR_DECRYPT;
+		/*
+		 * Rx decryption is done in place,
+		 * the original data is lost anyway.
+		 */
+
+		return -EINVAL;
+	}
+
+	/* drop any other error frames */
+	if (unlikely(error)) {
+		/* TODO: update netdevice's RX dropped/errors statistics */
+
+		if (ar9170_nag_limiter(ar))
+			printk(KERN_DEBUG "%s: received frame with "
+			       "suspicious error code (%#x).\n",
+			       wiphy_name(ar->hw->wiphy), error);
+
+		return -EINVAL;
+	}
+
+	status->band = ar->channel->band;
+	status->freq = ar->channel->center_freq;
 
-	switch (tail->status & AR9170_RX_STATUS_MODULATION_MASK) {
+	switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) {
 	case AR9170_RX_STATUS_MODULATION_CCK:
-		if (tail->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
-			status.flag |= RX_FLAG_SHORTPRE;
+		if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
+			status->flag |= RX_FLAG_SHORTPRE;
 		switch (head->plcp[0]) {
 		case 0x0a:
-			status.rate_idx = 0;
+			status->rate_idx = 0;
 			break;
 		case 0x14:
-			status.rate_idx = 1;
+			status->rate_idx = 1;
 			break;
 		case 0x37:
-			status.rate_idx = 2;
+			status->rate_idx = 2;
 			break;
 		case 0x6e:
-			status.rate_idx = 3;
+			status->rate_idx = 3;
 			break;
 		default:
-			if ((!ar->sniffer_enabled) && (net_ratelimit()))
+			if (ar9170_nag_limiter(ar))
 				printk(KERN_ERR "%s: invalid plcp cck rate "
 				       "(%x).\n", wiphy_name(ar->hw->wiphy),
 				       head->plcp[0]);
-			return;
+			return -EINVAL;
 		}
 		break;
+
 	case AR9170_RX_STATUS_MODULATION_OFDM:
-		switch (head->plcp[0] & 0xF) {
-		case 0xB:
-			status.rate_idx = 0;
+		switch (head->plcp[0] & 0xf) {
+		case 0xb:
+			status->rate_idx = 0;
 			break;
-		case 0xF:
-			status.rate_idx = 1;
+		case 0xf:
+			status->rate_idx = 1;
 			break;
-		case 0xA:
-			status.rate_idx = 2;
+		case 0xa:
+			status->rate_idx = 2;
 			break;
-		case 0xE:
-			status.rate_idx = 3;
+		case 0xe:
+			status->rate_idx = 3;
 			break;
 		case 0x9:
-			status.rate_idx = 4;
+			status->rate_idx = 4;
 			break;
-		case 0xD:
-			status.rate_idx = 5;
+		case 0xd:
+			status->rate_idx = 5;
 			break;
 		case 0x8:
-			status.rate_idx = 6;
+			status->rate_idx = 6;
 			break;
-		case 0xC:
-			status.rate_idx = 7;
+		case 0xc:
+			status->rate_idx = 7;
 			break;
 		default:
-			if ((!ar->sniffer_enabled) && (net_ratelimit()))
+			if (ar9170_nag_limiter(ar))
 				printk(KERN_ERR "%s: invalid plcp ofdm rate "
 				       "(%x).\n", wiphy_name(ar->hw->wiphy),
 				       head->plcp[0]);
-			return;
+			return -EINVAL;
 		}
-		if (status.band == IEEE80211_BAND_2GHZ)
-			status.rate_idx += 4;
+		if (status->band == IEEE80211_BAND_2GHZ)
+			status->rate_idx += 4;
 		break;
+
 	case AR9170_RX_STATUS_MODULATION_HT:
+		if (head->plcp[3] & 0x80)
+			status->flag |= RX_FLAG_40MHZ;
+		if (head->plcp[6] & 0x80)
+			status->flag |= RX_FLAG_SHORT_GI;
+
+		status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f);
+		status->flag |= RX_FLAG_HT;
+		break;
+
 	case AR9170_RX_STATUS_MODULATION_DUPOFDM:
 		/* XXX */
-
-		if (net_ratelimit())
+		if (ar9170_nag_limiter(ar))
 			printk(KERN_ERR "%s: invalid modulation\n",
 			       wiphy_name(ar->hw->wiphy));
-		return;
+		return -EINVAL;
 	}
 
-	error = tail->error;
+	return 0;
+}
 
-	if (error & AR9170_RX_ERROR_MMIC) {
-		status.flag |= RX_FLAG_MMIC_ERROR;
-		error &= ~AR9170_RX_ERROR_MMIC;
-	}
+static void ar9170_rx_phy_status(struct ar9170 *ar,
+				 struct ar9170_rx_phystatus *phy,
+				 struct ieee80211_rx_status *status)
+{
+	int i;
 
-	if (error & AR9170_RX_ERROR_PLCP) {
-		status.flag |= RX_FLAG_FAILED_PLCP_CRC;
-		error &= ~AR9170_RX_ERROR_PLCP;
+	BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
+
+	for (i = 0; i < 3; i++)
+		if (phy->rssi[i] != 0x80)
+			status->antenna |= BIT(i);
+
+	/* post-process RSSI */
+	for (i = 0; i < 7; i++)
+		if (phy->rssi[i] & 0x80)
+			phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
+
+	/* TODO: we could do something with phy_errors */
+	status->signal = ar->noise[0] + phy->rssi_combined;
+	status->noise = ar->noise[0];
+}
+
+static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
+{
+	struct sk_buff *skb;
+	int reserved = 0;
+	struct ieee80211_hdr *hdr = (void *) buf;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		reserved += NET_IP_ALIGN;
+
+		if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
+			reserved += NET_IP_ALIGN;
 	}
 
-	if (error & AR9170_RX_ERROR_FCS) {
-		status.flag |= RX_FLAG_FAILED_FCS_CRC;
-		error &= ~AR9170_RX_ERROR_FCS;
+	if (ieee80211_has_a4(hdr->frame_control))
+		reserved += NET_IP_ALIGN;
+
+	reserved = 32 + (reserved & NET_IP_ALIGN);
+
+	skb = dev_alloc_skb(len + reserved);
+	if (likely(skb)) {
+		skb_reserve(skb, reserved);
+		memcpy(skb_put(skb, len), buf, len);
 	}
 
-	decrypt = ar9170_get_decrypt_type(tail);
-	if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
-	    decrypt != AR9170_ENC_ALG_NONE)
-		status.flag |= RX_FLAG_DECRYPTED;
+	return skb;
+}
 
-	/* ignore wrong RA errors */
-	error &= ~AR9170_RX_ERROR_WRONG_RA;
+/*
+ * If the frame alignment is right (or the kernel has
+ * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
+ * is only a single MPDU in the USB frame, then we could
+ * submit to mac80211 the SKB directly. However, since
+ * there may be multiple packets in one SKB in stream
+ * mode, and we need to observe the proper ordering,
+ * this is non-trivial.
+ */
 
-	if (error & AR9170_RX_ERROR_DECRYPT) {
-		error &= ~AR9170_RX_ERROR_DECRYPT;
+static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
+{
+	struct ar9170_rx_head *head;
+	struct ar9170_rx_macstatus *mac;
+	struct ar9170_rx_phystatus *phy = NULL;
+	struct ieee80211_rx_status status;
+	struct sk_buff *skb;
+	int mpdu_len;
+
+	if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac))))
+		return ;
+
+	/* Received MPDU */
+	mpdu_len = len - sizeof(*mac);
+
+	mac = (void *)(buf + mpdu_len);
+	if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) {
+		/* this frame is too damaged and can't be used - drop it */
 
-		/*
-		 * Rx decryption is done in place,
-		 * the original data is lost anyway.
-		 */
 		return ;
 	}
 
-	/* drop any other error frames */
-	if ((error) && (net_ratelimit())) {
-		printk(KERN_DEBUG "%s: errors: %#x\n",
-		       wiphy_name(ar->hw->wiphy), error);
-		return;
+	switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) {
+	case AR9170_RX_STATUS_MPDU_FIRST:
+		/* first mpdu packet has the plcp header */
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
+			head = (void *) buf;
+			memcpy(&ar->rx_mpdu.plcp, (void *) buf,
+			       sizeof(struct ar9170_rx_head));
+
+			mpdu_len -= sizeof(struct ar9170_rx_head);
+			buf += sizeof(struct ar9170_rx_head);
+			ar->rx_mpdu.has_plcp = true;
+		} else {
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: plcp info is clipped.\n",
+				       wiphy_name(ar->hw->wiphy));
+			return ;
+		}
+		break;
+
+	case AR9170_RX_STATUS_MPDU_LAST:
+		/* last mpdu has a extra tail with phy status information */
+
+		if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
+			mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+			phy = (void *)(buf + mpdu_len);
+		} else {
+			if (ar9170_nag_limiter(ar))
+				printk(KERN_ERR "%s: frame tail is clipped.\n",
+				       wiphy_name(ar->hw->wiphy));
+			return ;
+		}
+
+	case AR9170_RX_STATUS_MPDU_MIDDLE:
+		/* middle mpdus are just data */
+		if (unlikely(!ar->rx_mpdu.has_plcp)) {
+			if (!ar9170_nag_limiter(ar))
+				return ;
+
+			printk(KERN_ERR "%s: rx stream did not start "
+					"with a first_mpdu frame tag.\n",
+			       wiphy_name(ar->hw->wiphy));
+
+			return ;
+		}
+
+		head = &ar->rx_mpdu.plcp;
+		break;
+
+	case AR9170_RX_STATUS_MPDU_SINGLE:
+		/* single mpdu - has plcp (head) and phy status (tail) */
+		head = (void *) buf;
+
+		mpdu_len -= sizeof(struct ar9170_rx_head);
+		mpdu_len -= sizeof(struct ar9170_rx_phystatus);
+
+		buf += sizeof(struct ar9170_rx_head);
+		phy = (void *)(buf + mpdu_len);
+		break;
+
+	default:
+		BUG_ON(1);
+		break;
 	}
 
-	buf += sizeof(struct ar9170_rx_head);
-	fc = *(__le16 *)buf;
+	if (unlikely(mpdu_len < FCS_LEN))
+		return ;
 
-	if (ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc))
-		reserved = 32 + 2;
-	else
-		reserved = 32;
+	memset(&status, 0, sizeof(status));
+	if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status)))
+		return ;
 
-	skb = dev_alloc_skb(mpdu_len + reserved);
-	if (!skb)
-		return;
+	if (phy)
+		ar9170_rx_phy_status(ar, phy, &status);
 
-	skb_reserve(skb, reserved);
-	memcpy(skb_put(skb, mpdu_len), buf, mpdu_len);
-	ieee80211_rx_irqsafe(ar->hw, skb, &status);
+	skb = ar9170_rx_copy_data(buf, mpdu_len);
+	if (likely(skb))
+		ieee80211_rx_irqsafe(ar->hw, skb, &status);
 }
 
 void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
 {
-	unsigned int i, tlen, resplen;
+	unsigned int i, tlen, resplen, wlen = 0, clen = 0;
 	u8 *tbuf, *respbuf;
 
 	tbuf = skb->data;
 	tlen = skb->len;
 
 	while (tlen >= 4) {
-		int clen = tbuf[1] << 8 | tbuf[0];
-		int wlen = (clen + 3) & ~3;
+		clen = tbuf[1] << 8 | tbuf[0];
+		wlen = ALIGN(clen, 4);
 
-		/*
-		 * parse stream (if any)
-		 */
+		/* check if this is stream has a valid tag.*/
 		if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
-			printk(KERN_ERR "%s: missing tag!\n",
-			       wiphy_name(ar->hw->wiphy));
+			/*
+			 * TODO: handle the highly unlikely event that the
+			 * corrupted stream has the TAG at the right position.
+			 */
+
+			/* check if the frame can be repaired. */
+			if (!ar->rx_failover_missing) {
+				/* this is no "short read". */
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: missing tag!\n",
+					       wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			if (ar->rx_failover_missing > tlen) {
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: possible multi "
+					       "stream corruption!\n",
+					       wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing -= tlen;
+
+			if (ar->rx_failover_missing <= 0) {
+				/*
+				 * nested ar9170_rx call!
+				 * termination is guranteed, even when the
+				 * combined frame also have a element with
+				 * a bad tag.
+				 */
+
+				ar->rx_failover_missing = 0;
+				ar9170_rx(ar, ar->rx_failover);
+
+				skb_reset_tail_pointer(ar->rx_failover);
+				skb_trim(ar->rx_failover, 0);
+			}
+
 			return ;
 		}
+
+		/* check if stream is clipped */
 		if (wlen > tlen - 4) {
-			printk(KERN_ERR "%s: invalid RX (%d, %d, %d)\n",
-			       wiphy_name(ar->hw->wiphy), clen, wlen, tlen);
-			print_hex_dump(KERN_DEBUG, "data: ",
-				       DUMP_PREFIX_OFFSET,
-				       16, 1, tbuf, tlen, true);
+			if (ar->rx_failover_missing) {
+				/* TODO: handle double stream corruption. */
+				if (ar9170_nag_limiter(ar)) {
+					printk(KERN_ERR "%s: double rx stream "
+					       "corruption!\n",
+						wiphy_name(ar->hw->wiphy));
+					goto err_telluser;
+				} else
+					goto err_silent;
+			}
+
+			/*
+			 * save incomplete data set.
+			 * the firmware will resend the missing bits when
+			 * the rx - descriptor comes round again.
+			 */
+
+			memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
+			ar->rx_failover_missing = clen - tlen;
 			return ;
 		}
 		resplen = clen;
@@ -668,12 +902,44 @@ void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
 		if (i == 12)
 			ar9170_handle_command_response(ar, respbuf, resplen);
 		else
-			ar9170_handle_mpdu(ar, respbuf, resplen);
+			ar9170_handle_mpdu(ar, respbuf, clen);
 	}
 
-	if (tlen)
-		printk(KERN_ERR "%s: buffer remains!\n",
-		       wiphy_name(ar->hw->wiphy));
+	if (tlen) {
+		if (net_ratelimit())
+			printk(KERN_ERR "%s: %d bytes of unprocessed "
+					"data left in rx stream!\n",
+			       wiphy_name(ar->hw->wiphy), tlen);
+
+		goto err_telluser;
+	}
+
+	return ;
+
+err_telluser:
+	printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
+			"data:%d, rx:%d, pending:%d ]\n",
+	       wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
+	       ar->rx_failover_missing);
+
+	if (ar->rx_failover_missing)
+		print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
+				     ar->rx_failover->data,
+				     ar->rx_failover->len);
+
+	print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
+			     skb->data, skb->len);
+
+	printk(KERN_ERR "%s: please check your hardware and cables, if "
+			"you see this message frequently.\n",
+	       wiphy_name(ar->hw->wiphy));
+
+err_silent:
+	if (ar->rx_failover_missing) {
+		skb_reset_tail_pointer(ar->rx_failover);
+		skb_trim(ar->rx_failover, 0);
+		ar->rx_failover_missing = 0;
+	}
 }
 
 #define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop)		\
@@ -703,6 +969,8 @@ static int ar9170_op_start(struct ieee80211_hw *hw)
 	AR9170_FILL_QUEUE(ar->edcf[3], 2, 3,     7, 47); /* VOICE */
 	AR9170_FILL_QUEUE(ar->edcf[4], 2, 3,     7,  0); /* SPECIAL */
 
+	ar->bad_hw_nagger = jiffies;
+
 	err = ar->open(ar);
 	if (err)
 		goto out;
@@ -742,8 +1010,9 @@ static void ar9170_op_stop(struct ieee80211_hw *hw)
 	if (IS_STARTED(ar))
 		ar->state = AR9170_IDLE;
 
-	mutex_lock(&ar->mutex);
+	flush_workqueue(ar->hw->workqueue);
 
+	mutex_lock(&ar->mutex);
 	cancel_delayed_work_sync(&ar->tx_status_janitor);
 	cancel_work_sync(&ar->filter_config_work);
 	cancel_work_sync(&ar->beacon_work);
@@ -1076,7 +1345,8 @@ static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		err = ar9170_set_channel(ar, hw->conf.channel,
-					 AR9170_RFI_NONE, AR9170_BW_20);
+				AR9170_RFI_NONE,
+				nl80211_to_ar9170(hw->conf.channel_type));
 		if (err)
 			goto out;
 		/* adjust slot time for 5 GHz */
@@ -1123,10 +1393,10 @@ static void ar9170_set_filters(struct work_struct *work)
 					 filter_config_work);
 	int err;
 
-	mutex_lock(&ar->mutex);
 	if (unlikely(!IS_STARTED(ar)))
-		goto unlock;
+		return ;
 
+	mutex_lock(&ar->mutex);
 	if (ar->filter_changed & AR9170_FILTER_CHANGED_PROMISC) {
 		err = ar9170_set_operating_mode(ar);
 		if (err)
@@ -1155,8 +1425,8 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
 
 	/* mask supported flags */
 	*new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
-		      FIF_PROMISC_IN_BSS;
-
+		      FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
+	ar->filter_state = *new_flags;
 	/*
 	 * We can support more by setting the sniffer bit and
 	 * then checking the error flags, later.
@@ -1498,6 +1768,24 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	return ret;
 }
 
+static int ar9170_ampdu_action(struct ieee80211_hw *hw,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+{
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/*
+		 * Something goes wrong -- RX locks up
+		 * after a while of receiving aggregated
+		 * frames -- not enabling for now.
+		 */
+		return -EOPNOTSUPP;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static const struct ieee80211_ops ar9170_ops = {
 	.start			= ar9170_op_start,
 	.stop			= ar9170_op_stop,
@@ -1514,26 +1802,40 @@ static const struct ieee80211_ops ar9170_ops = {
 	.sta_notify		= ar9170_sta_notify,
 	.get_stats		= ar9170_get_stats,
 	.get_tx_stats		= ar9170_get_tx_stats,
+	.ampdu_action		= ar9170_ampdu_action,
 };
 
 void *ar9170_alloc(size_t priv_size)
 {
 	struct ieee80211_hw *hw;
 	struct ar9170 *ar;
+	struct sk_buff *skb;
 	int i;
 
+	/*
+	 * this buffer is used for rx stream reconstruction.
+	 * Under heavy load this device (or the transport layer?)
+	 * tends to split the streams into seperate rx descriptors.
+	 */
+
+	skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
+	if (!skb)
+		goto err_nomem;
+
 	hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
 	if (!hw)
-		return ERR_PTR(-ENOMEM);
+		goto err_nomem;
 
 	ar = hw->priv;
 	ar->hw = hw;
+	ar->rx_failover = skb;
 
 	mutex_init(&ar->mutex);
 	spin_lock_init(&ar->cmdlock);
 	spin_lock_init(&ar->tx_stats_lock);
 	skb_queue_head_init(&ar->global_tx_status);
 	skb_queue_head_init(&ar->global_tx_status_waste);
+	ar9170_rx_reset_rx_mpdu(ar);
 	INIT_WORK(&ar->filter_config_work, ar9170_set_filters);
 	INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
 	INIT_DELAYED_WORK(&ar->tx_status_janitor, ar9170_tx_status_janitor);
@@ -1561,6 +1863,10 @@ void *ar9170_alloc(size_t priv_size)
 		ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
 
 	return ar;
+
+err_nomem:
+	kfree_skb(skb);
+	return ERR_PTR(-ENOMEM);
 }
 
 static int ar9170_read_eeprom(struct ar9170 *ar)
@@ -1619,12 +1925,24 @@ static int ar9170_read_eeprom(struct ar9170 *ar)
 	else
 		ar->hw->channel_change_time = 80 * 1000;
 
+	ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
+	ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
+
 	/* second part of wiphy init */
 	SET_IEEE80211_PERM_ADDR(ar->hw, addr);
 
 	return bands ? 0 : -EINVAL;
 }
 
+static int ar9170_reg_notifier(struct wiphy *wiphy,
+			struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ar9170 *ar = hw->priv;
+
+	return ath_reg_notifier_apply(wiphy, request, &ar->regulatory);
+}
+
 int ar9170_register(struct ar9170 *ar, struct device *pdev)
 {
 	int err;
@@ -1634,10 +1952,18 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev)
 	if (err)
 		goto err_out;
 
+	err = ath_regd_init(&ar->regulatory, ar->hw->wiphy,
+			    ar9170_reg_notifier);
+	if (err)
+		goto err_out;
+
 	err = ieee80211_register_hw(ar->hw);
 	if (err)
 		goto err_out;
 
+	if (!ath_is_world_regd(&ar->regulatory))
+		regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2);
+
 	err = ar9170_init_leds(ar);
 	if (err)
 		goto err_unreg;
@@ -1666,6 +1992,7 @@ void ar9170_unregister(struct ar9170 *ar)
 	ar9170_unregister_leds(ar);
 #endif /* CONFIG_AR9170_LEDS */
 
+	kfree_skb(ar->rx_failover);
 	ieee80211_unregister_hw(ar->hw);
 	mutex_destroy(&ar->mutex);
 }

+ 0 - 0
drivers/net/wireless/ar9170/phy.c → drivers/net/wireless/ath/ar9170/phy.c


+ 0 - 0
drivers/net/wireless/ar9170/usb.c → drivers/net/wireless/ath/ar9170/usb.c


+ 1 - 1
drivers/net/wireless/ar9170/usb.h → drivers/net/wireless/ath/ar9170/usb.h

@@ -43,7 +43,7 @@
 #include <linux/completion.h>
 #include <linux/spinlock.h>
 #include <linux/leds.h>
-#include <net/wireless.h>
+#include <net/cfg80211.h>
 #include <net/mac80211.h>
 #include <linux/firmware.h>
 #include "eeprom.h"

+ 1 - 0
drivers/net/wireless/ath5k/Kconfig → drivers/net/wireless/ath/ath5k/Kconfig

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

+ 0 - 0
drivers/net/wireless/ath5k/Makefile → drivers/net/wireless/ath/ath5k/Makefile


+ 3 - 2
drivers/net/wireless/ath5k/ath5k.h → drivers/net/wireless/ath/ath5k/ath5k.h

@@ -27,6 +27,8 @@
 #include <linux/types.h>
 #include <net/mac80211.h>
 
+#include "../regd.h"
+
 /* RX/TX descriptor hw structs
  * TODO: Driver part should only see sw structs */
 #include "desc.h"
@@ -1039,8 +1041,6 @@ struct ath5k_hw {
 	bool			ah_5ghz;
 	bool			ah_2ghz;
 
-#define ah_regdomain		ah_capabilities.cap_regdomain.reg_current
-#define ah_regdomain_hw		ah_capabilities.cap_regdomain.reg_hw
 #define ah_modes		ah_capabilities.cap_mode
 #define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
 
@@ -1065,6 +1065,7 @@ struct ath5k_hw {
 	u32			ah_gpio[AR5K_MAX_GPIO];
 	int			ah_gpio_npins;
 
+	struct ath_regulatory	ah_regulatory;
 	struct ath5k_capabilities ah_capabilities;
 
 	struct ath5k_txq_info	ah_txq[AR5K_NUM_TX_QUEUES];

+ 0 - 0
drivers/net/wireless/ath5k/attach.c → drivers/net/wireless/ath/ath5k/attach.c


+ 49 - 25
drivers/net/wireless/ath5k/base.c → drivers/net/wireless/ath/ath5k/base.c

@@ -61,9 +61,13 @@
 
 static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
 static int modparam_nohwcrypt;
-module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
+static int modparam_all_channels;
+module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
+MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
+
 
 /******************\
 * Internal defines *
@@ -705,6 +709,15 @@ err_no_irq:
 * Driver Initialization *
 \***********************/
 
+static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ath5k_softc *sc = hw->priv;
+	struct ath_regulatory *reg = &sc->ah->ah_regulatory;
+
+	return ath_reg_notifier_apply(wiphy, request, reg);
+}
+
 static int
 ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 {
@@ -793,12 +806,23 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
 	memset(sc->bssidmask, 0xff, ETH_ALEN);
 	ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
 
+	ah->ah_regulatory.current_rd =
+		ah->ah_capabilities.cap_eeprom.ee_regdomain;
+	ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier);
+	if (ret) {
+		ATH5K_ERR(sc, "can't initialize regulatory system\n");
+		goto err_queues;
+	}
+
 	ret = ieee80211_register_hw(hw);
 	if (ret) {
 		ATH5K_ERR(sc, "can't register ieee80211 hw\n");
 		goto err_queues;
 	}
 
+	if (!ath_is_world_regd(&sc->ah->ah_regulatory))
+		regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2);
+
 	ath5k_init_leds(sc);
 
 	return 0;
@@ -862,6 +886,20 @@ ath5k_ieee2mhz(short chan)
 		return 2212 + chan * 20;
 }
 
+/*
+ * Returns true for the channel numbers used without all_channels modparam.
+ */
+static bool ath5k_is_standard_channel(short chan)
+{
+	return ((chan <= 14) ||
+		/* UNII 1,2 */
+		((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
+		/* midband */
+		((chan & 3) == 0 && chan >= 100 && chan <= 140) ||
+		/* UNII-3 */
+		((chan & 3) == 1 && chan >= 149 && chan <= 165));
+}
+
 static unsigned int
 ath5k_copy_channels(struct ath5k_hw *ah,
 		struct ieee80211_channel *channels,
@@ -899,6 +937,9 @@ ath5k_copy_channels(struct ath5k_hw *ah,
 		if (!ath5k_channel_ok(ah, freq, chfreq))
 			continue;
 
+		if (!modparam_all_channels && !ath5k_is_standard_channel(ch))
+			continue;
+
 		/* Write channel info and increment counter */
 		channels[count].center_freq = freq;
 		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
@@ -1577,9 +1618,8 @@ ath5k_rx_start(struct ath5k_softc *sc)
 	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
 		sc->cachelsz, sc->rxbufsize);
 
-	sc->rxlink = NULL;
-
 	spin_lock_bh(&sc->rxbuflock);
+	sc->rxlink = NULL;
 	list_for_each_entry(bf, &sc->rxbuf, list) {
 		ret = ath5k_rxbuf_setup(sc, bf);
 		if (ret != 0) {
@@ -1588,9 +1628,9 @@ ath5k_rx_start(struct ath5k_softc *sc)
 		}
 	}
 	bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
+	ath5k_hw_set_rxdp(ah, bf->daddr);
 	spin_unlock_bh(&sc->rxbuflock);
 
-	ath5k_hw_set_rxdp(ah, bf->daddr);
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
 	ath5k_mode_setup(sc);		/* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
@@ -1739,7 +1779,7 @@ ath5k_tasklet_rx(unsigned long data)
 	struct sk_buff *skb, *next_skb;
 	dma_addr_t next_skb_addr;
 	struct ath5k_softc *sc = (void *)data;
-	struct ath5k_buf *bf, *bf_last;
+	struct ath5k_buf *bf;
 	struct ath5k_desc *ds;
 	int ret;
 	int hdrlen;
@@ -1750,7 +1790,6 @@ ath5k_tasklet_rx(unsigned long data)
 		ATH5K_WARN(sc, "empty rx buf pool\n");
 		goto unlock;
 	}
-	bf_last = list_entry(sc->rxbuf.prev, struct ath5k_buf, list);
 	do {
 		rxs.flag = 0;
 
@@ -1759,24 +1798,9 @@ ath5k_tasklet_rx(unsigned long data)
 		skb = bf->skb;
 		ds = bf->desc;
 
-		/*
-		 * last buffer must not be freed to ensure proper hardware
-		 * function. When the hardware finishes also a packet next to
-		 * it, we are sure, it doesn't use it anymore and we can go on.
-		 */
-		if (bf_last == bf)
-			bf->flags |= 1;
-		if (bf->flags) {
-			struct ath5k_buf *bf_next = list_entry(bf->list.next,
-					struct ath5k_buf, list);
-			ret = sc->ah->ah_proc_rx_desc(sc->ah, bf_next->desc,
-					&rs);
-			if (ret)
-				break;
-			bf->flags &= ~1;
-			/* skip the overwritten one (even status is martian) */
-			goto next;
-		}
+		/* bail if HW is still using self-linked descriptor */
+		if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr)
+			break;
 
 		ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs);
 		if (unlikely(ret == -EINPROGRESS))
@@ -2455,7 +2479,7 @@ ath5k_intr(int irq, void *dev_id)
 			tasklet_schedule(&sc->restq);
 		} else {
 			if (status & AR5K_INT_SWBA) {
-				tasklet_schedule(&sc->beacontq);
+				tasklet_hi_schedule(&sc->beacontq);
 			}
 			if (status & AR5K_INT_RXEOL) {
 				/*

+ 0 - 1
drivers/net/wireless/ath5k/base.h → drivers/net/wireless/ath/ath5k/base.h

@@ -56,7 +56,6 @@
 
 struct ath5k_buf {
 	struct list_head	list;
-	unsigned int		flags;	/* rx descriptor flags */
 	struct ath5k_desc	*desc;	/* virtual addr of desc */
 	dma_addr_t		daddr;	/* physical addr of desc */
 	struct sk_buff		*skb;	/* skbuff for buf */

+ 0 - 0
drivers/net/wireless/ath5k/caps.c → drivers/net/wireless/ath/ath5k/caps.c


+ 0 - 0
drivers/net/wireless/ath5k/debug.c → drivers/net/wireless/ath/ath5k/debug.c


+ 0 - 0
drivers/net/wireless/ath5k/debug.h → drivers/net/wireless/ath/ath5k/debug.h


+ 0 - 0
drivers/net/wireless/ath5k/desc.c → drivers/net/wireless/ath/ath5k/desc.c


+ 0 - 0
drivers/net/wireless/ath5k/desc.h → drivers/net/wireless/ath/ath5k/desc.h


+ 0 - 2
drivers/net/wireless/ath5k/dma.c → drivers/net/wireless/ath/ath5k/dma.c

@@ -80,8 +80,6 @@ int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
  * ath5k_hw_get_rxdp - Get RX Descriptor's address
  *
  * @ah: The &struct ath5k_hw
- *
- * XXX: Is RXDP read and clear ?
  */
 u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
 {

+ 0 - 0
drivers/net/wireless/ath5k/eeprom.c → drivers/net/wireless/ath/ath5k/eeprom.c


+ 0 - 0
drivers/net/wireless/ath5k/eeprom.h → drivers/net/wireless/ath/ath5k/eeprom.h


+ 0 - 0
drivers/net/wireless/ath5k/gpio.c → drivers/net/wireless/ath/ath5k/gpio.c


+ 3 - 5
drivers/net/wireless/ath5k/initvals.c → drivers/net/wireless/ath/ath5k/initvals.c

@@ -537,8 +537,6 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
 	{ AR5K_DCU_TX_FILTER_1(15), 0x00000000 },
 	{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
 	{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_CLR, 0x00000000 },
-	{ AR5K_DCU_TX_FILTER_SET, 0x00000000 },
 	{ AR5K_STA_ID1,		0x00000000 },
 	{ AR5K_BSS_ID0,		0x00000000 },
 	{ AR5K_BSS_ID1,		0x00000000 },
@@ -669,7 +667,7 @@ static const struct ath5k_ini ar5212_ini_common_start[] = {
 	/*{ AR5K_PHY(650), 0x000001b5 },*/
 	{ AR5K_PHY(651),	0x00000000 },
 	{ AR5K_PHY_TXPOWER_RATE3, 0x20202020 },
-	{ AR5K_PHY_TXPOWER_RATE2, 0x20202020 },
+	{ AR5K_PHY_TXPOWER_RATE4, 0x20202020 },
 	/*{ AR5K_PHY(655), 0x13c889af },*/
 	{ AR5K_PHY(656),	0x38490a20 },
 	{ AR5K_PHY(657),	0x00007bb6 },
@@ -718,7 +716,7 @@ static const struct ath5k_ini_mode ar5212_ini_mode_start[] = {
 	{ AR5K_PHY_SETTLING,
 	   { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } },
 	{ AR5K_PHY_AGCCTL,
-	   { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d18 } },
+	   { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } },
 	{ AR5K_PHY_NF,
 	   { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } },
 	{ AR5K_PHY_WEAK_OFDM_HIGH_THR,
@@ -799,7 +797,7 @@ static const struct ath5k_ini_mode rf5112_ini_mode_end[] = {
 	{ AR5K_PHY_DESIRED_SIZE,
 	   { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } },
 	{ AR5K_PHY_SIG,
-	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7ee80d2e } },
+	   { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } },
 	{ AR5K_PHY_AGCCOARSE,
 	   { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } },
 	{ AR5K_PHY_WEAK_OFDM_LOW_THR,

+ 3 - 1
drivers/net/wireless/ath5k/led.c → drivers/net/wireless/ath/ath5k/led.c

@@ -67,6 +67,8 @@ static const struct pci_device_id ath5k_led_devices[] = {
 	{ ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) },
 	/* Acer Extensa 5620z (nekoreeve@gmail.com) */
 	{ ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) },
+	/* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */
+	{ ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) },
 	{ }
 };
 
@@ -78,7 +80,7 @@ void ath5k_led_enable(struct ath5k_softc *sc)
 	}
 }
 
-void ath5k_led_on(struct ath5k_softc *sc)
+static void ath5k_led_on(struct ath5k_softc *sc)
 {
 	if (!test_bit(ATH_STAT_LEDSOFT, sc->status))
 		return;

+ 0 - 0
drivers/net/wireless/ath5k/pcu.c → drivers/net/wireless/ath/ath5k/pcu.c


+ 28 - 21
drivers/net/wireless/ath5k/phy.c → drivers/net/wireless/ath/ath5k/phy.c

@@ -1487,28 +1487,35 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
 {
 	s8 tmp;
 	s16 min_pwrL, min_pwrR;
-	s16 pwr_i = pwrL[0];
-
-	do {
-		pwr_i--;
-		tmp = (s8) ath5k_get_interpolated_value(pwr_i,
-						pwrL[0], pwrL[1],
-						stepL[0], stepL[1]);
-
-	} while (tmp > 1);
-
-	min_pwrL = pwr_i;
-
-	pwr_i = pwrR[0];
-	do {
-		pwr_i--;
-		tmp = (s8) ath5k_get_interpolated_value(pwr_i,
-						pwrR[0], pwrR[1],
-						stepR[0], stepR[1]);
-
-	} while (tmp > 1);
+	s16 pwr_i;
+
+	if (pwrL[0] == pwrL[1])
+		min_pwrL = pwrL[0];
+	else {
+		pwr_i = pwrL[0];
+		do {
+			pwr_i--;
+			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+							pwrL[0], pwrL[1],
+							stepL[0], stepL[1]);
+		} while (tmp > 1);
+
+		min_pwrL = pwr_i;
+	}
 
-	min_pwrR = pwr_i;
+	if (pwrR[0] == pwrR[1])
+		min_pwrR = pwrR[0];
+	else {
+		pwr_i = pwrR[0];
+		do {
+			pwr_i--;
+			tmp = (s8) ath5k_get_interpolated_value(pwr_i,
+							pwrR[0], pwrR[1],
+							stepR[0], stepR[1]);
+		} while (tmp > 1);
+
+		min_pwrR = pwr_i;
+	}
 
 	/* Keep the right boundary so that it works for both curves */
 	return max(min_pwrL, min_pwrR);

+ 0 - 0
drivers/net/wireless/ath5k/qcu.c → drivers/net/wireless/ath/ath5k/qcu.c


+ 0 - 0
drivers/net/wireless/ath5k/reg.h → drivers/net/wireless/ath/ath5k/reg.h


+ 1 - 1
drivers/net/wireless/ath5k/reset.c → drivers/net/wireless/ath/ath5k/reset.c

@@ -358,7 +358,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
 			mode |= AR5K_PHY_MODE_FREQ_5GHZ;
 
 			if (ah->ah_radio == AR5K_RF5413)
-				clock |= AR5K_PHY_PLL_40MHZ_5413;
+				clock = AR5K_PHY_PLL_40MHZ_5413;
 			else
 				clock |= AR5K_PHY_PLL_40MHZ;
 

+ 0 - 0
drivers/net/wireless/ath5k/rfbuffer.h → drivers/net/wireless/ath/ath5k/rfbuffer.h


+ 0 - 0
drivers/net/wireless/ath5k/rfgain.h → drivers/net/wireless/ath/ath5k/rfgain.h


+ 1 - 0
drivers/net/wireless/ath9k/Kconfig → drivers/net/wireless/ath/ath9k/Kconfig

@@ -2,6 +2,7 @@ config ATH9K
 	tristate "Atheros 802.11n wireless cards support"
 	depends on PCI && MAC80211 && WLAN_80211
 	depends on RFKILL || RFKILL=n
+	select ATH_COMMON
 	select MAC80211_LEDS
 	select LEDS_CLASS
 	select NEW_LEDS

+ 0 - 1
drivers/net/wireless/ath9k/Makefile → drivers/net/wireless/ath/ath9k/Makefile

@@ -4,7 +4,6 @@ ath9k-y +=	hw.o \
 		calib.o \
 		ani.o \
 		phy.o \
-		regd.o \
 		beacon.o \
 		main.o \
 		recv.o \

+ 0 - 0
drivers/net/wireless/ath9k/ahb.c → drivers/net/wireless/ath/ath9k/ahb.c


+ 3 - 5
drivers/net/wireless/ath9k/ani.c → drivers/net/wireless/ath/ath9k/ani.c

@@ -569,8 +569,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
 				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
 					"phyCnt1 0x%x, resetting "
 					"counter value to 0x%x\n",
-					phyCnt1,
-					aniState->ofdmPhyErrBase);
+					phyCnt1, aniState->ofdmPhyErrBase);
 				REG_WRITE(ah, AR_PHY_ERR_1,
 					  aniState->ofdmPhyErrBase);
 				REG_WRITE(ah, AR_PHY_ERR_MASK_1,
@@ -580,8 +579,7 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah,
 				DPRINTF(ah->ah_sc, ATH_DBG_ANI,
 					"phyCnt2 0x%x, resetting "
 					"counter value to 0x%x\n",
-					phyCnt2,
-					aniState->cckPhyErrBase);
+					phyCnt2, aniState->cckPhyErrBase);
 				REG_WRITE(ah, AR_PHY_ERR_2,
 					  aniState->cckPhyErrBase);
 				REG_WRITE(ah, AR_PHY_ERR_MASK_2,
@@ -667,7 +665,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah,
 	u32 cc = REG_READ(ah, AR_CCCNT);
 
 	if (cycles == 0 || cycles > cc) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+		DPRINTF(ah->ah_sc, ATH_DBG_ANI,
 			"cycle counter wrap. ExtBusy = 0\n");
 		good = 0;
 	} else {

+ 0 - 0
drivers/net/wireless/ath9k/ani.h → drivers/net/wireless/ath/ath9k/ani.h


+ 21 - 44
drivers/net/wireless/ath9k/ath9k.h → drivers/net/wireless/ath/ath9k/ath9k.h

@@ -66,7 +66,6 @@ struct ath_config {
 	u32 ath_aggr_prot;
 	u16 txpowlimit;
 	u8 cabqReadytime;
-	u8 swBeaconProcess;
 };
 
 /*************************/
@@ -74,13 +73,17 @@ struct ath_config {
 /*************************/
 
 #define ATH_TXBUF_RESET(_bf) do {				\
-		(_bf)->bf_status = 0;				\
+		(_bf)->bf_stale = false;			\
 		(_bf)->bf_lastbf = NULL;			\
 		(_bf)->bf_next = NULL;				\
 		memset(&((_bf)->bf_state), 0,			\
 		       sizeof(struct ath_buf_state));		\
 	} while (0)
 
+#define ATH_RXBUF_RESET(_bf) do {		\
+		(_bf)->bf_stale = false;	\
+	} while (0)
+
 /**
  * enum buffer_type - Buffer type flags
  *
@@ -106,7 +109,7 @@ struct ath_buf_state {
 	int bfs_seqno;
 	int bfs_tidno;
 	int bfs_retries;
-	u32 bf_type;
+	u8 bf_type;
 	u32 bfs_keyix;
 	enum ath9k_key_type bfs_keytype;
 };
@@ -130,26 +133,21 @@ struct ath_buf {
 	struct ath_buf *bf_lastbf;	/* last buf of this unit (a frame or
 					   an aggregate) */
 	struct ath_buf *bf_next;	/* next subframe in the aggregate */
-	void *bf_mpdu;			/* enclosing frame structure */
+	struct sk_buff *bf_mpdu;	/* enclosing frame structure */
 	struct ath_desc *bf_desc;	/* virtual addr of desc */
 	dma_addr_t bf_daddr;		/* physical addr of desc */
 	dma_addr_t bf_buf_addr;		/* physical addr of data buffer */
-	u32 bf_status;
+	bool bf_stale;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
 	dma_addr_t bf_dmacontext;
 };
 
-#define ATH_RXBUF_RESET(_bf)    ((_bf)->bf_status = 0)
-#define ATH_BUFSTATUS_STALE     0x00000002
-
 struct ath_descdma {
-	const char *dd_name;
 	struct ath_desc *dd_desc;
 	dma_addr_t dd_desc_paddr;
 	u32 dd_desc_len;
 	struct ath_buf *dd_bufptr;
-	dma_addr_t dd_dmacontext;
 };
 
 int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
@@ -295,26 +293,6 @@ struct ath_tx_control {
 #define ATH_TX_XRETRY       0x02
 #define ATH_TX_BAR          0x04
 
-/* All RSSI values are noise floor adjusted */
-struct ath_tx_stat {
-	int rssi;
-	int rssictl[ATH_MAX_ANTENNA];
-	int rssiextn[ATH_MAX_ANTENNA];
-	int rateieee;
-	int rateKbps;
-	int ratecode;
-	int flags;
-	u32 airtime;	/* time on air per final tx rate */
-};
-
-struct aggr_rifs_param {
-	int param_max_frames;
-	int param_max_len;
-	int param_rl;
-	int param_al;
-	struct ath_rc_series *param_rcs;
-};
-
 struct ath_node {
 	struct ath_softc *an_sc;
 	struct ath_atx_tid tid[WME_NUM_TID];
@@ -362,7 +340,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
 void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
 int ath_tx_init(struct ath_softc *sc, int nbufs);
-int ath_tx_cleanup(struct ath_softc *sc);
+void ath_tx_cleanup(struct ath_softc *sc);
 struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
 int ath_txq_update(struct ath_softc *sc, int qnum,
 		   struct ath9k_tx_queue_info *q);
@@ -525,19 +503,18 @@ struct ath_rfkill {
 #define SC_OP_BEACONS           BIT(1)
 #define SC_OP_RXAGGR            BIT(2)
 #define SC_OP_TXAGGR            BIT(3)
-#define SC_OP_CHAINMASK_UPDATE  BIT(4)
-#define SC_OP_FULL_RESET        BIT(5)
-#define SC_OP_PREAMBLE_SHORT    BIT(6)
-#define SC_OP_PROTECT_ENABLE    BIT(7)
-#define SC_OP_RXFLUSH           BIT(8)
-#define SC_OP_LED_ASSOCIATED    BIT(9)
-#define SC_OP_RFKILL_REGISTERED BIT(10)
-#define SC_OP_RFKILL_SW_BLOCKED BIT(11)
-#define SC_OP_RFKILL_HW_BLOCKED BIT(12)
-#define SC_OP_WAIT_FOR_BEACON   BIT(13)
-#define SC_OP_LED_ON            BIT(14)
-#define SC_OP_SCANNING          BIT(15)
-#define SC_OP_TSF_RESET         BIT(16)
+#define SC_OP_FULL_RESET        BIT(4)
+#define SC_OP_PREAMBLE_SHORT    BIT(5)
+#define SC_OP_PROTECT_ENABLE    BIT(6)
+#define SC_OP_RXFLUSH           BIT(7)
+#define SC_OP_LED_ASSOCIATED    BIT(8)
+#define SC_OP_RFKILL_REGISTERED BIT(9)
+#define SC_OP_RFKILL_SW_BLOCKED BIT(10)
+#define SC_OP_RFKILL_HW_BLOCKED BIT(11)
+#define SC_OP_WAIT_FOR_BEACON   BIT(12)
+#define SC_OP_LED_ON            BIT(13)
+#define SC_OP_SCANNING          BIT(14)
+#define SC_OP_TSF_RESET         BIT(15)
 
 struct ath_bus_ops {
 	void		(*read_cachesize)(struct ath_softc *sc, int *csz);

+ 7 - 10
drivers/net/wireless/ath9k/beacon.c → drivers/net/wireless/ath/ath9k/beacon.c

@@ -43,7 +43,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
 
 	if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
 		DPRINTF(sc, ATH_DBG_FATAL,
-			"unable to update h/w beacon queue parameters\n");
+			"Unable to update h/w beacon queue parameters\n");
 		return 0;
 	} else {
 		ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
@@ -59,7 +59,7 @@ static int ath_beaconq_config(struct ath_softc *sc)
 static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
 			     struct ath_buf *bf)
 {
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+	struct sk_buff *skb = bf->bf_mpdu;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_desc *ds;
 	struct ath9k_11n_rate_series series[4];
@@ -132,16 +132,13 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 	avp = (void *)vif->drv_priv;
 	cabq = sc->beacon.cabq;
 
-	if (avp->av_bcbuf == NULL) {
-		DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
-			avp, avp->av_bcbuf);
+	if (avp->av_bcbuf == NULL)
 		return NULL;
-	}
 
 	/* Release the old beacon first */
 
 	bf = avp->av_bcbuf;
-	skb = (struct sk_buff *)bf->bf_mpdu;
+	skb = bf->bf_mpdu;
 	if (skb) {
 		dma_unmap_single(sc->dev, bf->bf_dmacontext,
 				 skb->len, DMA_TO_DEVICE);
@@ -229,7 +226,7 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc,
 		return;
 
 	bf = avp->av_bcbuf;
-	skb = (struct sk_buff *) bf->bf_mpdu;
+	skb = bf->bf_mpdu;
 
 	ath_beacon_setup(sc, avp, bf);
 
@@ -302,7 +299,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 	/* release the previous beacon frame, if it already exists. */
 	bf = avp->av_bcbuf;
 	if (bf->bf_mpdu != NULL) {
-		skb = (struct sk_buff *)bf->bf_mpdu;
+		skb = bf->bf_mpdu;
 		dma_unmap_single(sc->dev, bf->bf_dmacontext,
 				 skb->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
@@ -374,7 +371,7 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
 
 		bf = avp->av_bcbuf;
 		if (bf->bf_mpdu != NULL) {
-			struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+			struct sk_buff *skb = bf->bf_mpdu;
 			dma_unmap_single(sc->dev, bf->bf_dmacontext,
 					 skb->len, DMA_TO_DEVICE);
 			dev_kfree_skb_any(skb);

+ 51 - 72
drivers/net/wireless/ath9k/calib.c → drivers/net/wireless/ath/ath9k/calib.c

@@ -186,7 +186,7 @@ static bool getNoiseFloorThresh(struct ath_hw *ah,
 }
 
 static void ath9k_hw_setup_calibration(struct ath_hw *ah,
-				       struct hal_cal_list *currCal)
+				       struct ath9k_cal_list *currCal)
 {
 	REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
 		      AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
@@ -220,7 +220,7 @@ static void ath9k_hw_setup_calibration(struct ath_hw *ah,
 }
 
 static void ath9k_hw_reset_calibration(struct ath_hw *ah,
-				       struct hal_cal_list *currCal)
+				       struct ath9k_cal_list *currCal)
 {
 	int i;
 
@@ -238,13 +238,12 @@ static void ath9k_hw_reset_calibration(struct ath_hw *ah,
 	ah->cal_samples = 0;
 }
 
-static void ath9k_hw_per_calibration(struct ath_hw *ah,
+static bool ath9k_hw_per_calibration(struct ath_hw *ah,
 				     struct ath9k_channel *ichan,
 				     u8 rxchainmask,
-				     struct hal_cal_list *currCal,
-				     bool *isCalDone)
+				     struct ath9k_cal_list *currCal)
 {
-	*isCalDone = false;
+	bool iscaldone = false;
 
 	if (currCal->calState == CAL_RUNNING) {
 		if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
@@ -263,7 +262,7 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah,
 				currCal->calData->calPostProc(ah, numChains);
 				ichan->CalValid |= currCal->calData->calType;
 				currCal->calState = CAL_DONE;
-				*isCalDone = true;
+				iscaldone = true;
 			} else {
 				ath9k_hw_setup_calibration(ah, currCal);
 			}
@@ -271,11 +270,13 @@ static void ath9k_hw_per_calibration(struct ath_hw *ah,
 	} else if (!(ichan->CalValid & currCal->calData->calType)) {
 		ath9k_hw_reset_calibration(ah, currCal);
 	}
+
+	return iscaldone;
 }
 
 /* Assumes you are talking about the currently configured channel */
 static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
-				     enum hal_cal_types calType)
+				     enum ath9k_cal_types calType)
 {
 	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
 
@@ -284,8 +285,8 @@ static bool ath9k_hw_iscal_supported(struct ath_hw *ah,
 		return true;
 	case ADC_GAIN_CAL:
 	case ADC_DC_CAL:
-		if (conf->channel->band == IEEE80211_BAND_5GHZ &&
-		  conf_is_ht20(conf))
+		if (!(conf->channel->band == IEEE80211_BAND_2GHZ &&
+		      conf_is_ht20(conf)))
 			return true;
 		break;
 	}
@@ -498,7 +499,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
 {
 	u32 iOddMeasOffset, iEvenMeasOffset, val, i;
 	int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
-	const struct hal_percal_data *calData =
+	const struct ath9k_percal_data *calData =
 		ah->cal_list_curr->calData;
 	u32 numSamples =
 		(1 << (calData->calCountMax + 5)) * calData->calNumSamples;
@@ -555,7 +556,7 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains)
 bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
 {
 	struct ieee80211_conf *conf = &ah->ah_sc->hw->conf;
-	struct hal_cal_list *currCal = ah->cal_list_curr;
+	struct ath9k_cal_list *currCal = ah->cal_list_curr;
 
 	if (!ah->curchan)
 		return true;
@@ -841,23 +842,21 @@ static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah)
 }
 
 bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			u8 rxchainmask, bool longcal,
-			bool *isCalDone)
+			u8 rxchainmask, bool longcal)
 {
-	struct hal_cal_list *currCal = ah->cal_list_curr;
-
-	*isCalDone = true;
+	bool iscaldone = true;
+	struct ath9k_cal_list *currCal = ah->cal_list_curr;
 
 	if (currCal &&
 	    (currCal->calState == CAL_RUNNING ||
 	     currCal->calState == CAL_WAITING)) {
-		ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal,
-					 isCalDone);
-		if (*isCalDone) {
+		iscaldone = ath9k_hw_per_calibration(ah, chan,
+						     rxchainmask, currCal);
+		if (iscaldone) {
 			ah->cal_list_curr = currCal = currCal->calNext;
 
 			if (currCal->calState == CAL_WAITING) {
-				*isCalDone = false;
+				iscaldone = false;
 				ath9k_hw_reset_calibration(ah, currCal);
 			}
 		}
@@ -872,18 +871,15 @@ bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
 		ath9k_hw_getnf(ah, chan);
 		ath9k_hw_loadnf(ah, ah->curchan);
 		ath9k_hw_start_nfcal(ah);
-
-		if (chan->channelFlags & CHANNEL_CW_INT)
-			chan->channelFlags &= ~CHANNEL_CW_INT;
 	}
 
-	return true;
+	return iscaldone;
 }
 
 static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	if (chan->channelFlags & CHANNEL_HT20) {
+	if (IS_CHAN_HT20(chan)) {
 		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE);
 		REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN);
 		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
@@ -919,83 +915,66 @@ static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan)
 	return true;
 }
 
-bool ath9k_hw_init_cal(struct ath_hw *ah,
-		       struct ath9k_channel *chan)
+bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
 {
 	if (AR_SREV_9285(ah) && AR_SREV_9285_12_OR_LATER(ah)) {
 		if (!ar9285_clc(ah, chan))
 			return false;
-	} else if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-		REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
+	} else {
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+			REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+		}
 
-		/* Kick off the cal */
+		/* Calibrate the AGC */
 		REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-				REG_READ(ah, AR_PHY_AGC_CONTROL) |
-				AR_PHY_AGC_CONTROL_CAL);
+			  REG_READ(ah, AR_PHY_AGC_CONTROL) |
+			  AR_PHY_AGC_CONTROL_CAL);
 
-		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
-					AR_PHY_AGC_CONTROL_CAL, 0,
-					AH_WAIT_TIMEOUT)) {
+		/* Poll for offset calibration complete */
+		if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
+				   0, AH_WAIT_TIMEOUT)) {
 			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
 				"offset calibration failed to complete in 1ms; "
 				"noisy environment?\n");
 			return false;
 		}
 
-		REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
-		REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE);
-	}
-
-	/* Calibrate the AGC */
-	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-			REG_READ(ah, AR_PHY_AGC_CONTROL) |
-			AR_PHY_AGC_CONTROL_CAL);
-
-	if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL,
-				0, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-			"offset calibration failed to complete in 1ms; "
-			"noisy environment?\n");
-		return false;
-	}
-
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
-		REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+		if (AR_SREV_9280_10_OR_LATER(ah)) {
+			REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC);
+			REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL);
+		}
 	}
 
 	/* Do PA Calibration */
 	if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
 		ath9k_hw_9285_pa_cal(ah);
 
-	/* Do NF Calibration */
+	/* Do NF Calibration after DC offset and other calibrations */
 	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
-			REG_READ(ah, AR_PHY_AGC_CONTROL) |
-			AR_PHY_AGC_CONTROL_NF);
+		  REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
 
 	ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
 
+	/* Enable IQ, ADC Gain and ADC DC offset CALs */
 	if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
 		if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) {
 			INIT_CAL(&ah->adcgain_caldata);
 			INSERT_CAL(ah, &ah->adcgain_caldata);
 			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling ADC Gain Calibration.\n");
+				"enabling ADC Gain Calibration.\n");
 		}
 		if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) {
 			INIT_CAL(&ah->adcdc_caldata);
 			INSERT_CAL(ah, &ah->adcdc_caldata);
 			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling ADC DC Calibration.\n");
+				"enabling ADC DC Calibration.\n");
 		}
 		if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) {
 			INIT_CAL(&ah->iq_caldata);
 			INSERT_CAL(ah, &ah->iq_caldata);
 			DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
-					"enabling IQ Calibration.\n");
+				"enabling IQ Calibration.\n");
 		}
 
 		ah->cal_list_curr = ah->cal_list;
@@ -1009,49 +988,49 @@ bool ath9k_hw_init_cal(struct ath_hw *ah,
 	return true;
 }
 
-const struct hal_percal_data iq_cal_multi_sample = {
+const struct ath9k_percal_data iq_cal_multi_sample = {
 	IQ_MISMATCH_CAL,
 	MAX_CAL_SAMPLES,
 	PER_MIN_LOG_COUNT,
 	ath9k_hw_iqcal_collect,
 	ath9k_hw_iqcalibrate
 };
-const struct hal_percal_data iq_cal_single_sample = {
+const struct ath9k_percal_data iq_cal_single_sample = {
 	IQ_MISMATCH_CAL,
 	MIN_CAL_SAMPLES,
 	PER_MAX_LOG_COUNT,
 	ath9k_hw_iqcal_collect,
 	ath9k_hw_iqcalibrate
 };
-const struct hal_percal_data adc_gain_cal_multi_sample = {
+const struct ath9k_percal_data adc_gain_cal_multi_sample = {
 	ADC_GAIN_CAL,
 	MAX_CAL_SAMPLES,
 	PER_MIN_LOG_COUNT,
 	ath9k_hw_adc_gaincal_collect,
 	ath9k_hw_adc_gaincal_calibrate
 };
-const struct hal_percal_data adc_gain_cal_single_sample = {
+const struct ath9k_percal_data adc_gain_cal_single_sample = {
 	ADC_GAIN_CAL,
 	MIN_CAL_SAMPLES,
 	PER_MAX_LOG_COUNT,
 	ath9k_hw_adc_gaincal_collect,
 	ath9k_hw_adc_gaincal_calibrate
 };
-const struct hal_percal_data adc_dc_cal_multi_sample = {
+const struct ath9k_percal_data adc_dc_cal_multi_sample = {
 	ADC_DC_CAL,
 	MAX_CAL_SAMPLES,
 	PER_MIN_LOG_COUNT,
 	ath9k_hw_adc_dccal_collect,
 	ath9k_hw_adc_dccal_calibrate
 };
-const struct hal_percal_data adc_dc_cal_single_sample = {
+const struct ath9k_percal_data adc_dc_cal_single_sample = {
 	ADC_DC_CAL,
 	MIN_CAL_SAMPLES,
 	PER_MAX_LOG_COUNT,
 	ath9k_hw_adc_dccal_collect,
 	ath9k_hw_adc_dccal_calibrate
 };
-const struct hal_percal_data adc_init_dc_cal = {
+const struct ath9k_percal_data adc_init_dc_cal = {
 	ADC_DC_INIT_CAL,
 	MIN_CAL_SAMPLES,
 	INIT_LOG_COUNT,

+ 16 - 17
drivers/net/wireless/ath9k/calib.h → drivers/net/wireless/ath/ath9k/calib.h

@@ -17,13 +17,13 @@
 #ifndef CALIB_H
 #define CALIB_H
 
-extern const struct hal_percal_data iq_cal_multi_sample;
-extern const struct hal_percal_data iq_cal_single_sample;
-extern const struct hal_percal_data adc_gain_cal_multi_sample;
-extern const struct hal_percal_data adc_gain_cal_single_sample;
-extern const struct hal_percal_data adc_dc_cal_multi_sample;
-extern const struct hal_percal_data adc_dc_cal_single_sample;
-extern const struct hal_percal_data adc_init_dc_cal;
+extern const struct ath9k_percal_data iq_cal_multi_sample;
+extern const struct ath9k_percal_data iq_cal_single_sample;
+extern const struct ath9k_percal_data adc_gain_cal_multi_sample;
+extern const struct ath9k_percal_data adc_gain_cal_single_sample;
+extern const struct ath9k_percal_data adc_dc_cal_multi_sample;
+extern const struct ath9k_percal_data adc_dc_cal_single_sample;
+extern const struct ath9k_percal_data adc_init_dc_cal;
 
 #define AR_PHY_CCA_MAX_GOOD_VALUE      		-85
 #define AR_PHY_CCA_MAX_HIGH_VALUE      		-62
@@ -67,14 +67,14 @@ struct ar5416IniArray {
 		}							\
 	} while (0)
 
-enum hal_cal_types {
+enum ath9k_cal_types {
 	ADC_DC_INIT_CAL = 0x1,
 	ADC_GAIN_CAL = 0x2,
 	ADC_DC_CAL = 0x4,
 	IQ_MISMATCH_CAL = 0x8
 };
 
-enum hal_cal_state {
+enum ath9k_cal_state {
 	CAL_INACTIVE,
 	CAL_WAITING,
 	CAL_RUNNING,
@@ -87,18 +87,18 @@ enum hal_cal_state {
 #define PER_MIN_LOG_COUNT   2
 #define PER_MAX_LOG_COUNT  10
 
-struct hal_percal_data {
-	enum hal_cal_types calType;
+struct ath9k_percal_data {
+	enum ath9k_cal_types calType;
 	u32 calNumSamples;
 	u32 calCountMax;
 	void (*calCollect) (struct ath_hw *);
 	void (*calPostProc) (struct ath_hw *, u8);
 };
 
-struct hal_cal_list {
-	const struct hal_percal_data *calData;
-	enum hal_cal_state calState;
-	struct hal_cal_list *calNext;
+struct ath9k_cal_list {
+	const struct ath9k_percal_data *calData;
+	enum ath9k_cal_state calState;
+	struct ath9k_cal_list *calNext;
 };
 
 struct ath9k_nfcal_hist {
@@ -116,8 +116,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
 void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah);
 s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
 bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
-			u8 rxchainmask, bool longcal,
-			bool *isCalDone);
+			u8 rxchainmask, bool longcal);
 bool ath9k_hw_init_cal(struct ath_hw *ah,
 		       struct ath9k_channel *chan);
 

+ 3 - 0
drivers/net/wireless/ath9k/debug.c → drivers/net/wireless/ath/ath9k/debug.c

@@ -498,6 +498,9 @@ int ath9k_init_debug(struct ath_softc *sc)
 {
 	sc->debug.debug_mask = ath9k_debug;
 
+	if (!ath9k_debugfs_root)
+		return -ENOENT;
+
 	sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
 						      ath9k_debugfs_root);
 	if (!sc->debug.debugfs_phy)

+ 10 - 14
drivers/net/wireless/ath9k/debug.h → drivers/net/wireless/ath/ath9k/debug.h

@@ -19,20 +19,16 @@
 
 enum ATH_DEBUG {
 	ATH_DBG_RESET		= 0x00000001,
-	ATH_DBG_REG_IO		= 0x00000002,
-	ATH_DBG_QUEUE		= 0x00000004,
-	ATH_DBG_EEPROM		= 0x00000008,
-	ATH_DBG_CALIBRATE	= 0x00000010,
-	ATH_DBG_CHANNEL		= 0x00000020,
-	ATH_DBG_INTERRUPT	= 0x00000040,
-	ATH_DBG_REGULATORY	= 0x00000080,
-	ATH_DBG_ANI		= 0x00000100,
-	ATH_DBG_POWER_MGMT	= 0x00000200,
-	ATH_DBG_XMIT		= 0x00000400,
-	ATH_DBG_BEACON		= 0x00001000,
-	ATH_DBG_CONFIG		= 0x00002000,
-	ATH_DBG_KEYCACHE	= 0x00004000,
-	ATH_DBG_FATAL		= 0x00008000,
+	ATH_DBG_QUEUE		= 0x00000002,
+	ATH_DBG_EEPROM		= 0x00000004,
+	ATH_DBG_CALIBRATE	= 0x00000008,
+	ATH_DBG_INTERRUPT	= 0x00000010,
+	ATH_DBG_REGULATORY	= 0x00000020,
+	ATH_DBG_ANI		= 0x00000040,
+	ATH_DBG_XMIT		= 0x00000080,
+	ATH_DBG_BEACON		= 0x00000100,
+	ATH_DBG_CONFIG		= 0x00000200,
+	ATH_DBG_FATAL		= 0x00000400,
 	ATH_DBG_ANY		= 0xffffffff
 };
 

+ 12 - 12
drivers/net/wireless/ath9k/eeprom.c → drivers/net/wireless/ath/ath9k/eeprom.c

@@ -783,11 +783,11 @@ static bool ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
 					((pdadcValues[4 * j + 3] & 0xFF) << 24);
 				REG_WRITE(ah, regOffset, reg32);
 
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PDADC (%d,%4x): %4.4x %8.8x\n",
 					i, regChainOffset, regOffset,
 					reg32);
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PDADC: Chain %d | "
 					"PDADC %3d Value %3d | "
 					"PDADC %3d Value %3d | "
@@ -910,7 +910,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
 			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
 
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
 			"EXT_ADDITIVE %d\n",
 			ctlMode, numCtlModes, isHt40CtlMode,
@@ -918,7 +918,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 
 		for (i = 0; (i < AR5416_NUM_CTLS) &&
 				pEepData->ctlIndex[i]; i++) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
 				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
 				"chan %d\n",
@@ -941,7 +941,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 				IS_CHAN_2GHZ(chan),
 				AR5416_EEP4K_NUM_BAND_EDGES);
 
-				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"    MATCH-EE_IDX %d: ch %d is2 %d "
 					"2xMinEdge %d chainmask %d chains %d\n",
 					i, freq, IS_CHAN_2GHZ(chan),
@@ -961,7 +961,7 @@ static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
 
 		minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
 
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 			"    SEL-Min ctlMode %d pCtlMode %d "
 			"2xMaxEdge %d sP %d minCtlPwr %d\n",
 			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
@@ -2234,11 +2234,11 @@ static bool ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
 					((pdadcValues[4 * j + 3] & 0xFF) << 24);
 				REG_WRITE(ah, regOffset, reg32);
 
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PDADC (%d,%4x): %4.4x %8.8x\n",
 					i, regChainOffset, regOffset,
 					reg32);
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PDADC: Chain %d | PDADC %3d "
 					"Value %3d | PDADC %3d Value %3d | "
 					"PDADC %3d Value %3d | PDADC %3d "
@@ -2415,14 +2415,14 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 		    ah->eep_ops->get_eeprom_rev(ah) <= 2)
 			twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
 
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 			"LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
 			"EXT_ADDITIVE %d\n",
 			ctlMode, numCtlModes, isHt40CtlMode,
 			(pCtlMode[ctlMode] & EXT_ADDITIVE));
 
 		for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 				"  LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
 				"pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
 				"chan %d\n",
@@ -2441,7 +2441,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 				rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
 				IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
 
-				DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"    MATCH-EE_IDX %d: ch %d is2 %d "
 					"2xMinEdge %d chainmask %d chains %d\n",
 					i, freq, IS_CHAN_2GHZ(chan),
@@ -2460,7 +2460,7 @@ static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah,
 
 		minCtlPower = min(twiceMaxEdgePower, scaledPower);
 
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 			"    SEL-Min ctlMode %d pCtlMode %d "
 			"2xMaxEdge %d sP %d minCtlPwr %d\n",
 			ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,

+ 2 - 0
drivers/net/wireless/ath9k/eeprom.h → drivers/net/wireless/ath/ath9k/eeprom.h

@@ -17,6 +17,8 @@
 #ifndef EEPROM_H
 #define EEPROM_H
 
+#include <net/cfg80211.h>
+
 #define AH_USE_EEPROM   0x1
 
 #ifdef __BIG_ENDIAN

+ 72 - 107
drivers/net/wireless/ath9k/hw.c → drivers/net/wireless/ath/ath9k/hw.c

@@ -97,7 +97,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout)
 		udelay(AH_TIME_QUANTUM);
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+	DPRINTF(ah->ah_sc, ATH_DBG_ANY,
 		"timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
 		timeout, reg, REG_READ(ah, reg), mask, val);
 
@@ -181,7 +181,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
 		}
 		break;
 	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"Unknown phy %u (rate ix %u)\n",
 			rates->info[rateix].phy, rateix);
 		txTime = 0;
@@ -306,7 +306,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
 			REG_WRITE(ah, addr, wrData);
 			rdData = REG_READ(ah, addr);
 			if (rdData != wrData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 					"address test failed "
 					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
 					addr, wrData, rdData);
@@ -318,7 +318,7 @@ static bool ath9k_hw_chip_test(struct ath_hw *ah)
 			REG_WRITE(ah, addr, wrData);
 			rdData = REG_READ(ah, addr);
 			if (wrData != rdData) {
-				DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+				DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 					"address test failed "
 					"addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
 					addr, wrData, rdData);
@@ -363,10 +363,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
 	ah->config.ack_6mb = 0x0;
 	ah->config.cwm_ignore_extcca = 0;
 	ah->config.pcie_powersave_enable = 0;
-	ah->config.pcie_l1skp_enable = 0;
 	ah->config.pcie_clock_req = 0;
-	ah->config.pcie_power_reset = 0x100;
-	ah->config.pcie_restore = 0;
 	ah->config.pcie_waen = 0;
 	ah->config.analog_shiftreg = 1;
 	ah->config.ht_enable = 1;
@@ -375,13 +372,6 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
 	ah->config.cck_trig_high = 200;
 	ah->config.cck_trig_low = 100;
 	ah->config.enable_ani = 1;
-	ah->config.noise_immunity_level = 4;
-	ah->config.ofdm_weaksignal_det = 1;
-	ah->config.cck_weaksignal_thr = 0;
-	ah->config.spur_immunity_level = 2;
-	ah->config.firstep_level = 0;
-	ah->config.rssi_thr_high = 40;
-	ah->config.rssi_thr_low = 7;
 	ah->config.diversity_control = 0;
 	ah->config.antenna_switch_swap = 0;
 
@@ -390,7 +380,7 @@ static void ath9k_hw_set_defaults(struct ath_hw *ah)
 		ah->config.spurchans[i][1] = AR_NO_SPUR;
 	}
 
-	ah->config.intr_mitigation = 1;
+	ah->config.intr_mitigation = true;
 
 	/*
 	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
@@ -463,8 +453,8 @@ static int ath9k_hw_rfattach(struct ath_hw *ah)
 
 	rfStatus = ath9k_hw_init_rf(ah, &ecode);
 	if (!rfStatus) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET,
-			"RF setup failed, status %u\n", ecode);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"RF setup failed, status: %u\n", ecode);
 		return ecode;
 	}
 
@@ -488,10 +478,9 @@ static int ath9k_hw_rf_claim(struct ath_hw *ah)
 	case AR_RAD2122_SREV_MAJOR:
 		break;
 	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-			"5G Radio Chip Rev 0x%02X is not "
-			"supported by this driver\n",
-			ah->hw_version.analog5GhzRev);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Radio Chip Rev 0x%02X not supported\n",
+			val & AR_RADIO_SREV_MAJOR);
 		return -EOPNOTSUPP;
 	}
 
@@ -513,12 +502,8 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah)
 		ah->macaddr[2 * i] = eeval >> 8;
 		ah->macaddr[2 * i + 1] = eeval & 0xff;
 	}
-	if (sum == 0 || sum == 0xffff * 3) {
-		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"mac address read failed: %pM\n",
-			ah->macaddr);
+	if (sum == 0 || sum == 0xffff * 3)
 		return -EADDRNOTAVAIL;
-	}
 
 	return 0;
 }
@@ -575,11 +560,8 @@ static int ath9k_hw_post_attach(struct ath_hw *ah)
 {
 	int ecode;
 
-	if (!ath9k_hw_chip_test(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
-			"hardware self-test failed\n");
+	if (!ath9k_hw_chip_test(ah))
 		return -ENODEV;
-	}
 
 	ecode = ath9k_hw_rf_claim(ah);
 	if (ecode != 0)
@@ -617,17 +599,14 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
 
 	ath9k_hw_set_defaults(ah);
 
-	if (ah->config.intr_mitigation != 0)
-		ah->intr_mitigation = true;
-
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
-		DPRINTF(sc, ATH_DBG_RESET, "Couldn't reset chip\n");
+		DPRINTF(sc, ATH_DBG_FATAL, "Couldn't reset chip\n");
 		ecode = -EIO;
 		goto bad;
 	}
 
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
-		DPRINTF(sc, ATH_DBG_RESET, "Couldn't wakeup chip\n");
+		DPRINTF(sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n");
 		ecode = -EIO;
 		goto bad;
 	}
@@ -650,7 +629,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
 	    (ah->hw_version.macVersion != AR_SREV_VERSION_5416_PCIE) &&
 	    (ah->hw_version.macVersion != AR_SREV_VERSION_9160) &&
 	    (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
-		DPRINTF(sc, ATH_DBG_RESET,
+		DPRINTF(sc, ATH_DBG_FATAL,
 			"Mac Chip Rev 0x%02x.%x is not supported by "
 			"this driver\n", ah->hw_version.macVersion,
 			ah->hw_version.macRev);
@@ -690,10 +669,6 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
 	if (AR_SREV_9280_10_OR_LATER(ah))
 		ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
 
-	DPRINTF(sc, ATH_DBG_RESET,
-		"This Mac Chip Rev 0x%02x.%x is \n",
-		ah->hw_version.macVersion, ah->hw_version.macRev);
-
 	if (AR_SREV_9285_12_OR_LATER(ah)) {
 
 		INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
@@ -859,11 +834,7 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
 	if (AR_SREV_9280_20(ah))
 		ath9k_hw_init_txgain_ini(ah);
 
-	if (!ath9k_hw_fill_cap_info(ah)) {
-		DPRINTF(sc, ATH_DBG_RESET, "failed ath9k_hw_fill_cap_info\n");
-		ecode = -EINVAL;
-		goto bad;
-	}
+	ath9k_hw_fill_cap_info(ah);
 
 	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
 	    test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) {
@@ -885,8 +856,8 @@ static struct ath_hw *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
 
 	ecode = ath9k_hw_init_macaddr(ah);
 	if (ecode != 0) {
-		DPRINTF(sc, ATH_DBG_RESET,
-			"failed initializing mac address\n");
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to initialize MAC address\n");
 		goto bad;
 	}
 
@@ -1054,7 +1025,7 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
 		AR_IMR_RXORN |
 		AR_IMR_BCNMISC;
 
-	if (ah->intr_mitigation)
+	if (ah->config.intr_mitigation)
 		ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
 	else
 		ah->mask_reg |= AR_IMR_RXOK;
@@ -1203,23 +1174,23 @@ static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah,
 	switch (ah->hw_version.devid) {
 	case AR9280_DEVID_PCI:
 		if (reg == 0x7894) {
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 				"ini VAL: %x  EEPROM: %x\n", value,
 				(pBase->version & 0xff));
 
 			if ((pBase->version & 0xff) > 0x0a) {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PWDCLKIND: %d\n",
 					pBase->pwdclkind);
 				value &= ~AR_AN_TOP2_PWDCLKIND;
 				value |= AR_AN_TOP2_PWDCLKIND &
 					(pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
 			} else {
-				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+				DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 					"PWDCLKIND Earlier Rev\n");
 			}
 
-			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+			DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
 				"final ini VAL: %x\n", value);
 		}
 		break;
@@ -1249,6 +1220,21 @@ static void ath9k_olc_init(struct ath_hw *ah)
 	ah->PDADCdelta = 0;
 }
 
+static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg,
+			      struct ath9k_channel *chan)
+{
+	u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band);
+
+	if (IS_CHAN_B(chan))
+		ctl |= CTL_11B;
+	else if (IS_CHAN_G(chan))
+		ctl |= CTL_11G;
+	else
+		ctl |= CTL_11A;
+
+	return ctl;
+}
+
 static int ath9k_hw_process_ini(struct ath_hw *ah,
 				struct ath9k_channel *chan,
 				enum ath9k_ht_macmode macmode)
@@ -1360,19 +1346,19 @@ static int ath9k_hw_process_ini(struct ath_hw *ah,
 		ath9k_olc_init(ah);
 
 	status = ah->eep_ops->set_txpower(ah, chan,
-				  ath9k_regd_get_ctl(ah, chan),
+				  ath9k_regd_get_ctl(&ah->regulatory, chan),
 				  channel->max_antenna_gain * 2,
 				  channel->max_power * 2,
 				  min((u32) MAX_RATE_POWER,
 				      (u32) ah->regulatory.power_limit));
 	if (status != 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
-			"error init'ing transmit power\n");
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"Error initializing transmit power\n");
 		return -EIO;
 	}
 
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"ar5416SetRfRegs failed\n");
 		return -EIO;
 	}
@@ -1678,7 +1664,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
 	if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
 			   AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"Could not kill baseband RX\n");
 		return false;
 	}
@@ -1687,26 +1673,26 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 
 	if (AR_SREV_9280_10_OR_LATER(ah)) {
 		if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				"failed to set channel\n");
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Failed to set channel\n");
 			return false;
 		}
 	} else {
 		if (!(ath9k_hw_set_channel(ah, chan))) {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
-				"failed to set channel\n");
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"Failed to set channel\n");
 			return false;
 		}
 	}
 
 	if (ah->eep_ops->set_txpower(ah, chan,
-			     ath9k_regd_get_ctl(ah, chan),
+			     ath9k_regd_get_ctl(&ah->regulatory, chan),
 			     channel->max_antenna_gain * 2,
 			     channel->max_power * 2,
 			     min((u32) MAX_RATE_POWER,
 				 (u32) ah->regulatory.power_limit)) != 0) {
 		DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
-			"error init'ing transmit power\n");
+			"Error initializing transmit power\n");
 		return false;
 	}
 
@@ -2199,14 +2185,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	ah->txchainmask = sc->tx_chainmask;
 	ah->rxchainmask = sc->rx_chainmask;
 
-	if (AR_SREV_9285(ah)) {
-		ah->txchainmask &= 0x1;
-		ah->rxchainmask &= 0x1;
-	} else if (AR_SREV_9280(ah)) {
-		ah->txchainmask &= 0x3;
-		ah->rxchainmask &= 0x3;
-	}
-
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 
@@ -2242,7 +2220,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	ath9k_hw_mark_phy_inactive(ah);
 
 	if (!ath9k_hw_chip_reset(ah, chan)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n");
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n");
 		return -EINVAL;
 	}
 
@@ -2335,8 +2313,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 
 	REG_WRITE(ah, AR_OBS, 8);
 
-	if (ah->intr_mitigation) {
-
+	if (ah->config.intr_mitigation) {
 		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500);
 		REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000);
 	}
@@ -2385,8 +2362,8 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
 	u32 keyType;
 
 	if (entry >= ah->caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keychache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -2422,8 +2399,8 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
 	u32 macHi, macLo;
 
 	if (entry >= ah->caps.keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keychache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -2454,8 +2431,8 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 	u32 keyType;
 
 	if (entry >= pCap->keycache_size) {
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
-			"entry %u out of range\n", entry);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"keycache entry %u out of range\n", entry);
 		return false;
 	}
 
@@ -2465,7 +2442,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 		break;
 	case ATH9K_CIPHER_AES_CCM:
 		if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
 				"AES-CCM not supported by mac rev 0x%x\n",
 				ah->hw_version.macRev);
 			return false;
@@ -2476,14 +2453,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 		keyType = AR_KEYTABLE_TYPE_TKIP;
 		if (ATH9K_IS_MIC_ENABLED(ah)
 		    && entry + 64 >= pCap->keycache_size) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
 				"entry %u inappropriate for TKIP\n", entry);
 			return false;
 		}
 		break;
 	case ATH9K_CIPHER_WEP:
 		if (k->kv_len < LEN_WEP40) {
-			DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+			DPRINTF(ah->ah_sc, ATH_DBG_ANY,
 				"WEP key length %u too small\n", k->kv_len);
 			return false;
 		}
@@ -2498,7 +2475,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 		keyType = AR_KEYTABLE_TYPE_CLR;
 		break;
 	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"cipher %u not supported\n", k->kv_type);
 		return false;
 	}
@@ -2716,7 +2693,7 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
 				    AR_RTC_FORCE_WAKE_EN);
 		}
 		if (i == 0) {
-			DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 				"Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
 			return false;
 		}
@@ -2737,9 +2714,8 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
 		"UNDEFINED"
 	};
 
-	DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n",
-		modes[ah->power_mode], modes[mode],
-		setChip ? "set chip " : "");
+	DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n",
+		modes[ah->power_mode], modes[mode]);
 
 	switch (mode) {
 	case ATH9K_PM_AWAKE:
@@ -2753,7 +2729,7 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
 		ath9k_set_power_network_sleep(ah, setChip);
 		break;
 	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"Unknown power mode %u\n", mode);
 		return false;
 	}
@@ -2943,7 +2919,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
 
 		*masked = isr & ATH9K_INT_COMMON;
 
-		if (ah->intr_mitigation) {
+		if (ah->config.intr_mitigation) {
 			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
 				*masked |= ATH9K_INT_RX;
 		}
@@ -3000,6 +2976,7 @@ bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked)
 				DPRINTF(ah->ah_sc, ATH_DBG_ANY,
 					"received PCI PERR interrupt\n");
 			}
+			*masked |= ATH9K_INT_FATAL;
 		}
 		if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
 			DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
@@ -3061,7 +3038,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
 	}
 	if (ints & ATH9K_INT_RX) {
 		mask |= AR_IMR_RXERR;
-		if (ah->intr_mitigation)
+		if (ah->config.intr_mitigation)
 			mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM;
 		else
 			mask |= AR_IMR_RXOK | AR_IMR_RXDESC;
@@ -3259,7 +3236,7 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
 /* HW Capabilities */
 /*******************/
 
-bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
+void ath9k_hw_fill_cap_info(struct ath_hw *ah)
 {
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	u16 capField = 0, eeval;
@@ -3343,8 +3320,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
 	pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
 
-	pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
-
 	if (ah->config.ht_enable)
 		pCap->hw_caps |= ATH9K_HW_CAP_HT;
 	else
@@ -3368,7 +3343,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		pCap->keycache_size = AR_KEYTABLE_SIZE;
 
 	pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-	pCap->num_mr_retries = 4;
 	pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
 
 	if (AR_SREV_9285_10_OR_LATER(ah))
@@ -3378,14 +3352,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	else
 		pCap->num_gpio_pins = AR_NUM_GPIO;
 
-	if (AR_SREV_9280_10_OR_LATER(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW;
-		pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	} else {
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
-		pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
-	}
-
 	if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
 		pCap->hw_caps |= ATH9K_HW_CAP_CST;
 		pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
@@ -3411,7 +3377,8 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	    (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) ||
 	    (ah->hw_version.macVersion == AR_SREV_VERSION_9160) ||
 	    (ah->hw_version.macVersion == AR_SREV_VERSION_9100) ||
-	    (ah->hw_version.macVersion == AR_SREV_VERSION_9280))
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9280) ||
+	    (ah->hw_version.macVersion == AR_SREV_VERSION_9285))
 		pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
 	else
 		pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
@@ -3445,8 +3412,6 @@ bool ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		ah->btactive_gpio = 6;
 		ah->wlanactive_gpio = 5;
 	}
-
-	return true;
 }
 
 bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
@@ -3762,7 +3727,7 @@ bool ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
 	ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER);
 
 	if (ah->eep_ops->set_txpower(ah, chan,
-			     ath9k_regd_get_ctl(ah, chan),
+			     ath9k_regd_get_ctl(&ah->regulatory, chan),
 			     channel->max_antenna_gain * 2,
 			     channel->max_power * 2,
 			     min((u32) MAX_RATE_POWER,

+ 31 - 59
drivers/net/wireless/ath9k/hw.h → drivers/net/wireless/ath/ath9k/hw.h

@@ -25,10 +25,11 @@
 #include "ani.h"
 #include "eeprom.h"
 #include "calib.h"
-#include "regd.h"
 #include "reg.h"
 #include "phy.h"
 
+#include "../regd.h"
+
 #define ATHEROS_VENDOR_ID	0x168c
 #define AR5416_DEVID_PCI	0x0023
 #define AR5416_DEVID_PCIE	0x0024
@@ -124,29 +125,24 @@ enum wireless_mode {
 };
 
 enum ath9k_hw_caps {
-	ATH9K_HW_CAP_CHAN_SPREAD		= BIT(0),
-	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(1),
-	ATH9K_HW_CAP_MIC_CKIP                   = BIT(2),
-	ATH9K_HW_CAP_MIC_TKIP                   = BIT(3),
-	ATH9K_HW_CAP_CIPHER_AESCCM              = BIT(4),
-	ATH9K_HW_CAP_CIPHER_CKIP                = BIT(5),
-	ATH9K_HW_CAP_CIPHER_TKIP                = BIT(6),
-	ATH9K_HW_CAP_VEOL                       = BIT(7),
-	ATH9K_HW_CAP_BSSIDMASK                  = BIT(8),
-	ATH9K_HW_CAP_MCAST_KEYSEARCH            = BIT(9),
-	ATH9K_HW_CAP_CHAN_HALFRATE              = BIT(10),
-	ATH9K_HW_CAP_CHAN_QUARTERRATE           = BIT(11),
-	ATH9K_HW_CAP_HT                         = BIT(12),
-	ATH9K_HW_CAP_GTT                        = BIT(13),
-	ATH9K_HW_CAP_FASTCC                     = BIT(14),
-	ATH9K_HW_CAP_RFSILENT                   = BIT(15),
-	ATH9K_HW_CAP_WOW                        = BIT(16),
-	ATH9K_HW_CAP_CST                        = BIT(17),
-	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(18),
-	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(19),
-	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(20),
-	ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT     = BIT(21),
-	ATH9K_HW_CAP_BT_COEX			= BIT(22)
+	ATH9K_HW_CAP_MIC_AESCCM                 = BIT(0),
+	ATH9K_HW_CAP_MIC_CKIP                   = BIT(1),
+	ATH9K_HW_CAP_MIC_TKIP                   = BIT(2),
+	ATH9K_HW_CAP_CIPHER_AESCCM              = BIT(3),
+	ATH9K_HW_CAP_CIPHER_CKIP                = BIT(4),
+	ATH9K_HW_CAP_CIPHER_TKIP                = BIT(5),
+	ATH9K_HW_CAP_VEOL                       = BIT(6),
+	ATH9K_HW_CAP_BSSIDMASK                  = BIT(7),
+	ATH9K_HW_CAP_MCAST_KEYSEARCH            = BIT(8),
+	ATH9K_HW_CAP_HT                         = BIT(9),
+	ATH9K_HW_CAP_GTT                        = BIT(10),
+	ATH9K_HW_CAP_FASTCC                     = BIT(11),
+	ATH9K_HW_CAP_RFSILENT                   = BIT(12),
+	ATH9K_HW_CAP_CST                        = BIT(13),
+	ATH9K_HW_CAP_ENHANCEDPM                 = BIT(14),
+	ATH9K_HW_CAP_AUTOSLEEP                  = BIT(15),
+	ATH9K_HW_CAP_4KB_SPLITTRANS             = BIT(16),
+	ATH9K_HW_CAP_BT_COEX			= BIT(17)
 };
 
 enum ath9k_capability_type {
@@ -166,7 +162,6 @@ struct ath9k_hw_capabilities {
 	u16 keycache_size;
 	u16 low_5ghz_chan, high_5ghz_chan;
 	u16 low_2ghz_chan, high_2ghz_chan;
-	u16 num_mr_retries;
 	u16 rts_aggr_limit;
 	u8 tx_chainmask;
 	u8 rx_chainmask;
@@ -184,11 +179,8 @@ struct ath9k_ops_config {
 	int ack_6mb;
 	int cwm_ignore_extcca;
 	u8 pcie_powersave_enable;
-	u8 pcie_l1skp_enable;
 	u8 pcie_clock_req;
 	u32 pcie_waen;
-	int pcie_power_reset;
-	u8 pcie_restore;
 	u8 analog_shiftreg;
 	u8 ht_enable;
 	u32 ofdm_trig_low;
@@ -196,17 +188,10 @@ struct ath9k_ops_config {
 	u32 cck_trig_high;
 	u32 cck_trig_low;
 	u32 enable_ani;
-	u8 noise_immunity_level;
-	u32 ofdm_weaksignal_det;
-	u32 cck_weaksignal_thr;
-	u8 spur_immunity_level;
-	u8 firstep_level;
-	int8_t rssi_thr_high;
-	int8_t rssi_thr_low;
 	u16 diversity_control;
 	u16 antenna_switch_swap;
 	int serialize_regmode;
-	int intr_mitigation;
+	bool intr_mitigation;
 #define SPUR_DISABLE        	0
 #define SPUR_ENABLE_IOCTL   	1
 #define SPUR_ENABLE_EEPROM  	2
@@ -281,13 +266,6 @@ enum ath9k_int {
 #define CHANNEL_HT40PLUS  0x20000
 #define CHANNEL_HT40MINUS 0x40000
 
-#define CHANNEL_INTERFERENCE    0x01
-#define CHANNEL_DFS             0x02
-#define CHANNEL_4MS_LIMIT       0x04
-#define CHANNEL_DFS_CLEAR       0x08
-#define CHANNEL_DISALLOW_ADHOC  0x10
-#define CHANNEL_PER_11D_ADHOC   0x20
-
 #define CHANNEL_A           (CHANNEL_5GHZ|CHANNEL_OFDM)
 #define CHANNEL_B           (CHANNEL_2GHZ|CHANNEL_CCK)
 #define CHANNEL_G           (CHANNEL_2GHZ|CHANNEL_OFDM)
@@ -318,10 +296,6 @@ struct ath9k_channel {
 	int16_t rawNoiseFloor;
 };
 
-#define IS_CHAN_A(_c) ((((_c)->channelFlags & CHANNEL_A) == CHANNEL_A) || \
-       (((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
-       (((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
-       (((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
 #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
        (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
        (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
@@ -329,7 +303,6 @@ struct ath9k_channel {
 #define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
 #define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
 #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
-#define IS_CHAN_PASSIVE(_c) (((_c)->channelFlags & CHANNEL_PASSIVE) != 0)
 #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
 #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
 #define IS_CHAN_A_5MHZ_SPACED(_c)			\
@@ -420,7 +393,7 @@ struct ath_hw {
 	struct ath9k_hw_version hw_version;
 	struct ath9k_ops_config config;
 	struct ath9k_hw_capabilities caps;
-	struct ath9k_regulatory regulatory;
+	struct ath_regulatory regulatory;
 	struct ath9k_channel channels[38];
 	struct ath9k_channel *curchan;
 
@@ -463,14 +436,14 @@ struct ath_hw {
 	enum ath9k_ant_setting diversity_control;
 
 	/* Calibration */
-	enum hal_cal_types supp_cals;
-	struct hal_cal_list iq_caldata;
-	struct hal_cal_list adcgain_caldata;
-	struct hal_cal_list adcdc_calinitdata;
-	struct hal_cal_list adcdc_caldata;
-	struct hal_cal_list *cal_list;
-	struct hal_cal_list *cal_list_last;
-	struct hal_cal_list *cal_list_curr;
+	enum ath9k_cal_types supp_cals;
+	struct ath9k_cal_list iq_caldata;
+	struct ath9k_cal_list adcgain_caldata;
+	struct ath9k_cal_list adcdc_calinitdata;
+	struct ath9k_cal_list adcdc_caldata;
+	struct ath9k_cal_list *cal_list;
+	struct ath9k_cal_list *cal_list_last;
+	struct ath9k_cal_list *cal_list_curr;
 #define totalPowerMeasI meas0.unsign
 #define totalPowerMeasQ meas1.unsign
 #define totalIqCorrMeas meas2.sign
@@ -540,7 +513,6 @@ struct ath_hw {
 	enum ath9k_ani_cmd ani_function;
 
 	u32 intr_txqs;
-	bool intr_mitigation;
 	enum ath9k_ht_extprotspacing extprotspacing;
 	u8 txchainmask;
 	u8 rxchainmask;
@@ -573,7 +545,7 @@ struct ath_hw *ath9k_hw_attach(u16 devid, struct ath_softc *sc, int *error);
 void ath9k_hw_rfdetach(struct ath_hw *ah);
 int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 		   bool bChannelChange);
-bool ath9k_hw_fill_cap_info(struct ath_hw *ah);
+void ath9k_hw_fill_cap_info(struct ath_hw *ah);
 bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
 			    u32 capability, u32 *result);
 bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,

+ 0 - 0
drivers/net/wireless/ath9k/initvals.h → drivers/net/wireless/ath/ath9k/initvals.h


+ 37 - 26
drivers/net/wireless/ath9k/mac.c → drivers/net/wireless/ath/ath9k/mac.c

@@ -49,7 +49,7 @@ bool ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp)
 
 bool ath9k_hw_txstart(struct ath_hw *ah, u32 q)
 {
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q);
 
 	REG_WRITE(ah, AR_Q_TXE, 1 << q);
 
@@ -110,13 +110,15 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
 	u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
 
 	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
+			"invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, "
+			"inactive queue: %u\n", q);
 		return false;
 	}
 
@@ -146,7 +148,7 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
 				break;
 
 			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"TSF have moved while trying to set "
+				"TSF has moved while trying to set "
 				"quiet time TSF: 0x%08x\n", tsfLow);
 		}
 
@@ -158,8 +160,8 @@ bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
 		wait = wait_time;
 		while (ath9k_hw_numtxpending(ah, q)) {
 			if ((--wait) == 0) {
-				DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
-					"Failed to stop Tx DMA in 100 "
+				DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+					"Failed to stop TX DMA in 100 "
 					"msec after killing last frame\n");
 				break;
 			}
@@ -454,17 +456,19 @@ bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
+			"invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, "
+			"inactive queue: %u\n", q);
 		return false;
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi);
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q);
 
 	qi->tqi_ver = qinfo->tqi_ver;
 	qi->tqi_subtype = qinfo->tqi_subtype;
@@ -521,13 +525,15 @@ bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q,
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
+			"invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, "
+			"inactive queue: %u\n", q);
 		return false;
 	}
 
@@ -575,22 +581,23 @@ int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type,
 			    ATH9K_TX_QUEUE_INACTIVE)
 				break;
 		if (q == pCap->total_queues) {
-			DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-				"no available tx queue\n");
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+				"No available TX queue\n");
 			return -1;
 		}
 		break;
 	default:
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n",
+			type);
 		return -1;
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q);
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"tx queue %u already active\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"TX queue: %u already active\n", q);
 		return -1;
 	}
 	memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -620,16 +627,18 @@ bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q)
 	struct ath9k_tx_queue_info *qi;
 
 	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
+			"invalid queue: %u\n", q);
 		return false;
 	}
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, "
+			"inactive queue: %u\n", q);
 		return false;
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q);
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q);
 
 	qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
 	ah->txok_interrupt_mask &= ~(1 << q);
@@ -650,17 +659,19 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q)
 	u32 cwMin, chanCwMin, value;
 
 	if (q >= pCap->total_queues) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
+			"invalid queue: %u\n", q);
 		return false;
 	}
 
 	qi = &ah->txq[q];
 	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
+		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, "
+			"inactive queue: %u\n", q);
 		return true;
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q);
+	DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q);
 
 	if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
 		if (chan && IS_CHAN_B(chan))
@@ -894,7 +905,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
 
 			reg = REG_READ(ah, AR_OBS_BUS_1);
 			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
-				"rx failed to go idle in 10 ms RXSM=0x%x\n", reg);
+				"RX failed to go idle in 10 ms RXSM=0x%x\n", reg);
 
 			return false;
 		}
@@ -949,8 +960,8 @@ bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
 	}
 
 	if (i == 0) {
-		DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
-			"dma failed to stop in %d ms "
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+			"DMA failed to stop in %d ms "
 			"AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
 			AH_RX_STOP_DMA_TIMEOUT / 1000,
 			REG_READ(ah, AR_CR),

+ 0 - 0
drivers/net/wireless/ath9k/mac.h → drivers/net/wireless/ath/ath9k/mac.h


+ 174 - 200
drivers/net/wireless/ath9k/main.c → drivers/net/wireless/ath/ath9k/main.c

@@ -287,7 +287,6 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 	}
 	spin_unlock_bh(&sc->sc_resetlock);
 
-	sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
 	sc->sc_flags &= ~SC_OP_FULL_RESET;
 
 	if (ath_startrecv(sc) != 0) {
@@ -368,28 +367,16 @@ static void ath_ani_calibrate(unsigned long data)
 
 		/* Perform calibration if necessary */
 		if (longcal || shortcal) {
-			bool iscaldone = false;
-
-			if (ath9k_hw_calibrate(ah, ah->curchan,
-					       sc->rx_chainmask, longcal,
-					       &iscaldone)) {
-				if (longcal)
-					sc->ani.noise_floor =
-						ath9k_hw_getchan_noise(ah,
-							       ah->curchan);
-
-				DPRINTF(sc, ATH_DBG_ANI,
-					"calibrate chan %u/%x nf: %d\n",
-					ah->curchan->channel,
-					ah->curchan->channelFlags,
-					sc->ani.noise_floor);
-			} else {
-				DPRINTF(sc, ATH_DBG_ANY,
-					"calibrate chan %u/%x failed\n",
-					ah->curchan->channel,
-					ah->curchan->channelFlags);
-			}
-			sc->ani.caldone = iscaldone;
+			sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan,
+						     sc->rx_chainmask, longcal);
+
+			if (longcal)
+				sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
+								     ah->curchan);
+
+			DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n",
+				ah->curchan->channel, ah->curchan->channelFlags,
+				sc->ani.noise_floor);
 		}
 	}
 
@@ -408,6 +395,18 @@ set_timer:
 	mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
 }
 
+static void ath_start_ani(struct ath_softc *sc)
+{
+	unsigned long timestamp = jiffies_to_msecs(jiffies);
+
+	sc->ani.longcal_timer = timestamp;
+	sc->ani.shortcal_timer = timestamp;
+	sc->ani.checkani_timer = timestamp;
+
+	mod_timer(&sc->ani.timer,
+		  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+}
+
 /*
  * Update tx/rx chainmask. For legacy association,
  * hard code chainmask to 1x1, for 11n association, use
@@ -416,7 +415,6 @@ set_timer:
  */
 void ath_update_chainmask(struct ath_softc *sc, int is_ht)
 {
-	sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
 	if (is_ht ||
 	    (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BT_COEX)) {
 		sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask;
@@ -436,12 +434,12 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 
 	an = (struct ath_node *)sta->drv_priv;
 
-	if (sc->sc_flags & SC_OP_TXAGGR)
+	if (sc->sc_flags & SC_OP_TXAGGR) {
 		ath_tx_node_init(sc, an);
-
-	an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
-			     sta->ht_cap.ampdu_factor);
-	an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+		an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+				     sta->ht_cap.ampdu_factor);
+		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+	}
 }
 
 static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
@@ -458,133 +456,124 @@ static void ath9k_tasklet(unsigned long data)
 	u32 status = sc->intrstatus;
 
 	if (status & ATH9K_INT_FATAL) {
-		/* need a chip reset */
 		ath_reset(sc, false);
 		return;
-	} else {
+	}
 
-		if (status &
-		    (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
-			spin_lock_bh(&sc->rx.rxflushlock);
-			ath_rx_tasklet(sc, 0);
-			spin_unlock_bh(&sc->rx.rxflushlock);
-		}
-		/* XXX: optimize this */
-		if (status & ATH9K_INT_TX)
-			ath_tx_tasklet(sc);
+	if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
+		spin_lock_bh(&sc->rx.rxflushlock);
+		ath_rx_tasklet(sc, 0);
+		spin_unlock_bh(&sc->rx.rxflushlock);
 	}
 
+	if (status & ATH9K_INT_TX)
+		ath_tx_tasklet(sc);
+
 	/* re-enable hardware interrupt */
 	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
 }
 
 irqreturn_t ath_isr(int irq, void *dev)
 {
+#define SCHED_INTR (				\
+		ATH9K_INT_FATAL |		\
+		ATH9K_INT_RXORN |		\
+		ATH9K_INT_RXEOL |		\
+		ATH9K_INT_RX |			\
+		ATH9K_INT_TX |			\
+		ATH9K_INT_BMISS |		\
+		ATH9K_INT_CST |			\
+		ATH9K_INT_TSFOOR)
+
 	struct ath_softc *sc = dev;
 	struct ath_hw *ah = sc->sc_ah;
 	enum ath9k_int status;
 	bool sched = false;
 
-	do {
-		if (sc->sc_flags & SC_OP_INVALID) {
-			/*
-			 * The hardware is not ready/present, don't
-			 * touch anything. Note this can happen early
-			 * on if the IRQ is shared.
-			 */
-			return IRQ_NONE;
-		}
-		if (!ath9k_hw_intrpend(ah)) {	/* shared irq, not for us */
-			return IRQ_NONE;
-		}
+	/*
+	 * The hardware is not ready/present, don't
+	 * touch anything. Note this can happen early
+	 * on if the IRQ is shared.
+	 */
+	if (sc->sc_flags & SC_OP_INVALID)
+		return IRQ_NONE;
 
-		/*
-		 * Figure out the reason(s) for the interrupt.  Note
-		 * that the hal returns a pseudo-ISR that may include
-		 * bits we haven't explicitly enabled so we mask the
-		 * value to insure we only process bits we requested.
-		 */
-		ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
+	ath9k_ps_wakeup(sc);
+
+	/* shared irq, not for us */
+
+	if (!ath9k_hw_intrpend(ah)) {
+		ath9k_ps_restore(sc);
+		return IRQ_NONE;
+	}
+
+	/*
+	 * Figure out the reason(s) for the interrupt.  Note
+	 * that the hal returns a pseudo-ISR that may include
+	 * bits we haven't explicitly enabled so we mask the
+	 * value to insure we only process bits we requested.
+	 */
+	ath9k_hw_getisr(ah, &status);	/* NB: clears ISR too */
+	status &= sc->imask;	/* discard unasked-for bits */
+
+	/*
+	 * If there are no status bits set, then this interrupt was not
+	 * for me (should have been caught above).
+	 */
+	if (!status) {
+		ath9k_ps_restore(sc);
+		return IRQ_NONE;
+	}
+
+	/* Cache the status */
+	sc->intrstatus = status;
 
-		status &= sc->imask;	/* discard unasked-for bits */
+	if (status & SCHED_INTR)
+		sched = true;
 
+	/*
+	 * If a FATAL or RXORN interrupt is received, we have to reset the
+	 * chip immediately.
+	 */
+	if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN))
+		goto chip_reset;
+
+	if (status & ATH9K_INT_SWBA)
+		tasklet_schedule(&sc->bcon_tasklet);
+
+	if (status & ATH9K_INT_TXURN)
+		ath9k_hw_updatetxtriglevel(ah, true);
+
+	if (status & ATH9K_INT_MIB) {
 		/*
-		 * If there are no status bits set, then this interrupt was not
-		 * for me (should have been caught above).
+		 * Disable interrupts until we service the MIB
+		 * interrupt; otherwise it will continue to
+		 * fire.
 		 */
-		if (!status)
-			return IRQ_NONE;
-
-		sc->intrstatus = status;
-		ath9k_ps_wakeup(sc);
+		ath9k_hw_set_interrupts(ah, 0);
+		/*
+		 * Let the hal handle the event. We assume
+		 * it will clear whatever condition caused
+		 * the interrupt.
+		 */
+		ath9k_hw_procmibevent(ah, &sc->nodestats);
+		ath9k_hw_set_interrupts(ah, sc->imask);
+	}
 
-		if (status & ATH9K_INT_FATAL) {
-			/* need a chip reset */
+	if (status & ATH9K_INT_TIM_TIMER) {
+		if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+			/* Clear RxAbort bit so that we can
+			 * receive frames */
+			ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
+			ath9k_hw_setrxabort(ah, 0);
 			sched = true;
-		} else if (status & ATH9K_INT_RXORN) {
-			/* need a chip reset */
-			sched = true;
-		} else {
-			if (status & ATH9K_INT_SWBA) {
-				/* schedule a tasklet for beacon handling */
-				tasklet_schedule(&sc->bcon_tasklet);
-			}
-			if (status & ATH9K_INT_RXEOL) {
-				/*
-				 * NB: the hardware should re-read the link when
-				 *     RXE bit is written, but it doesn't work
-				 *     at least on older hardware revs.
-				 */
-				sched = true;
-			}
-
-			if (status & ATH9K_INT_TXURN)
-				/* bump tx trigger level */
-				ath9k_hw_updatetxtriglevel(ah, true);
-			/* XXX: optimize this */
-			if (status & ATH9K_INT_RX)
-				sched = true;
-			if (status & ATH9K_INT_TX)
-				sched = true;
-			if (status & ATH9K_INT_BMISS)
-				sched = true;
-			/* carrier sense timeout */
-			if (status & ATH9K_INT_CST)
-				sched = true;
-			if (status & ATH9K_INT_MIB) {
-				/*
-				 * Disable interrupts until we service the MIB
-				 * interrupt; otherwise it will continue to
-				 * fire.
-				 */
-				ath9k_hw_set_interrupts(ah, 0);
-				/*
-				 * Let the hal handle the event. We assume
-				 * it will clear whatever condition caused
-				 * the interrupt.
-				 */
-				ath9k_hw_procmibevent(ah, &sc->nodestats);
-				ath9k_hw_set_interrupts(ah, sc->imask);
-			}
-			if (status & ATH9K_INT_TIM_TIMER) {
-				if (!(ah->caps.hw_caps &
-				      ATH9K_HW_CAP_AUTOSLEEP)) {
-					/* Clear RxAbort bit so that we can
-					 * receive frames */
-					ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
-					ath9k_hw_setrxabort(ah, 0);
-					sched = true;
-					sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
-				}
-			}
-			if (status & ATH9K_INT_TSFOOR) {
-				/* FIXME: Handle this interrupt for power save */
-				sched = true;
-			}
+			sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
 		}
-		ath9k_ps_restore(sc);
-	} while (0);
+	}
 
+chip_reset:
+
+	ath9k_ps_restore(sc);
 	ath_debug_stat_interrupt(sc, status);
 
 	if (sched) {
@@ -594,6 +583,8 @@ irqreturn_t ath_isr(int irq, void *dev)
 	}
 
 	return IRQ_HANDLED;
+
+#undef SCHED_INTR
 }
 
 static u32 ath_get_extchanmode(struct ath_softc *sc,
@@ -676,7 +667,7 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
 	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
 	if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
 		/* TX MIC entry failed. No need to proceed further */
-		DPRINTF(sc, ATH_DBG_KEYCACHE,
+		DPRINTF(sc, ATH_DBG_FATAL,
 			"Setting TX MIC Key Failed\n");
 		return 0;
 	}
@@ -920,11 +911,9 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
 		sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
 
-		/* Start ANI */
-		mod_timer(&sc->ani.timer,
-			  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
+		ath_start_ani(sc);
 	} else {
-		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n");
+		DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
 		sc->curaid = 0;
 	}
 }
@@ -1098,10 +1087,10 @@ void ath_radio_enable(struct ath_softc *sc)
 	int r;
 
 	ath9k_ps_wakeup(sc);
-	spin_lock_bh(&sc->sc_resetlock);
+	ath9k_hw_configpcipowersave(ah, 0);
 
+	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, false);
-
 	if (r) {
 		DPRINTF(sc, ATH_DBG_FATAL,
 			"Unable to reset channel %u (%uMhz) ",
@@ -1163,6 +1152,7 @@ void ath_radio_disable(struct ath_softc *sc)
 	spin_unlock_bh(&sc->sc_resetlock);
 
 	ath9k_hw_phy_disable(ah);
+	ath9k_hw_configpcipowersave(ah, 1);
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 	ath9k_ps_restore(sc);
 }
@@ -1267,7 +1257,6 @@ static int ath_init_sw_rfkill(struct ath_softc *sc)
 	sc->rf_kill.rfkill->data = sc;
 	sc->rf_kill.rfkill->toggle_radio = ath_sw_toggle_radio;
 	sc->rf_kill.rfkill->state = RFKILL_STATE_UNBLOCKED;
-	sc->rf_kill.rfkill->user_claim_unsupported = 1;
 
 	return 0;
 }
@@ -1362,6 +1351,17 @@ void ath_detach(struct ath_softc *sc)
 	ath9k_ps_restore(sc);
 }
 
+static int ath9k_reg_notifier(struct wiphy *wiphy,
+			      struct regulatory_request *request)
+{
+	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_regulatory *reg = &sc->sc_ah->regulatory;
+
+	return ath_reg_notifier_apply(wiphy, request, reg);
+}
+
 static int ath_init(u16 devid, struct ath_softc *sc)
 {
 	struct ath_hw *ah = NULL;
@@ -1403,7 +1403,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
 	/* Get the hardware key cache size. */
 	sc->keymax = ah->caps.keycache_size;
 	if (sc->keymax > ATH_KEYMAX) {
-		DPRINTF(sc, ATH_DBG_KEYCACHE,
+		DPRINTF(sc, ATH_DBG_ANY,
 			"Warning, using only %u entries in %u key cache\n",
 			ATH_KEYMAX, sc->keymax);
 		sc->keymax = ATH_KEYMAX;
@@ -1416,7 +1416,9 @@ static int ath_init(u16 devid, struct ath_softc *sc)
 	for (i = 0; i < sc->keymax; i++)
 		ath9k_hw_keyreset(ah, (u16) i);
 
-	if (ath9k_regd_init(sc->sc_ah))
+	error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
+			      ath9k_reg_notifier);
+	if (error)
 		goto bad;
 
 	/* default to MONITOR mode */
@@ -1545,9 +1547,6 @@ static int ath_init(u16 devid, struct ath_softc *sc)
 		sc->beacon.bslot_aphy[i] = NULL;
 	}
 
-	/* save MISC configurations */
-	sc->config.swBeaconProcess = 1;
-
 	/* setup channels and rates */
 
 	sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
@@ -1602,9 +1601,6 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 		BIT(NL80211_IFTYPE_ADHOC) |
 		BIT(NL80211_IFTYPE_MESH_POINT);
 
-	hw->wiphy->reg_notifier = ath9k_reg_notifier;
-	hw->wiphy->strict_regulatory = true;
-
 	hw->queues = 4;
 	hw->max_rates = 4;
 	hw->channel_change_time = 5000;
@@ -1625,8 +1621,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 int ath_attach(u16 devid, struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	const struct ieee80211_regdomain *regd;
 	int error = 0, i;
+	struct ath_regulatory *reg;
 
 	DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
 
@@ -1634,6 +1630,8 @@ int ath_attach(u16 devid, struct ath_softc *sc)
 	if (error != 0)
 		return error;
 
+	reg = &sc->sc_ah->regulatory;
+
 	/* get mac address from hardware and set in mac80211 */
 
 	SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
@@ -1666,31 +1664,14 @@ int ath_attach(u16 devid, struct ath_softc *sc)
 		goto error_attach;
 #endif
 
-	if (ath9k_is_world_regd(sc->sc_ah)) {
-		/* Anything applied here (prior to wiphy registration) gets
-		 * saved on the wiphy orig_* parameters */
-		regd = ath9k_world_regdomain(sc->sc_ah);
-		hw->wiphy->custom_regulatory = true;
-		hw->wiphy->strict_regulatory = false;
-	} else {
-		/* This gets applied in the case of the absense of CRDA,
-		 * it's our own custom world regulatory domain, similar to
-		 * cfg80211's but we enable passive scanning */
-		regd = ath9k_default_world_regdomain();
-	}
-	wiphy_apply_custom_regulatory(hw->wiphy, regd);
-	ath9k_reg_apply_radar_flags(hw->wiphy);
-	ath9k_reg_apply_world_flags(hw->wiphy, NL80211_REGDOM_SET_BY_DRIVER);
-
 	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
 	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
 	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
 
 	error = ieee80211_register_hw(hw);
 
-	if (!ath9k_is_world_regd(sc->sc_ah)) {
-		error = regulatory_hint(hw->wiphy,
-			sc->sc_ah->regulatory.alpha2);
+	if (!ath_is_world_regd(reg)) {
+		error = regulatory_hint(hw->wiphy, reg->alpha2);
 		if (error)
 			goto error_attach;
 	}
@@ -1792,7 +1773,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 		goto fail;
 	}
 
-	dd->dd_name = name;
 	dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
 
 	/*
@@ -1822,7 +1802,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
 	}
 	ds = dd->dd_desc;
 	DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
-		dd->dd_name, ds, (u32) dd->dd_desc_len,
+		name, ds, (u32) dd->dd_desc_len,
 		ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
 
 	/* allocate buffers */
@@ -2043,8 +2023,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
 	 * here except setup the interrupt mask.
 	 */
 	if (ath_startrecv(sc) != 0) {
-		DPRINTF(sc, ATH_DBG_FATAL,
-			"Unable to start recv logic\n");
+		DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
 		r = -EIO;
 		goto mutex_unlock;
 	}
@@ -2257,25 +2236,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
 		sc->imask |= ATH9K_INT_TSFOOR;
 	}
 
-	/*
-	 * Some hardware processes the TIM IE and fires an
-	 * interrupt when the TIM bit is set.  For hardware
-	 * that does, if not overridden by configuration,
-	 * enable the TIM interrupt when operating as station.
-	 */
-	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
-	    (conf->type == NL80211_IFTYPE_STATION) &&
-	    !sc->config.swBeaconProcess)
-		sc->imask |= ATH9K_INT_TIM;
-
 	ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
 
-	if (conf->type == NL80211_IFTYPE_AP) {
-		/* TODO: is this a suitable place to start ANI for AP mode? */
-		/* Start ANI */
-		mod_timer(&sc->ani.timer,
-			  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
-	}
+	if (conf->type == NL80211_IFTYPE_AP)
+		ath_start_ani(sc);
 
 out:
 	mutex_unlock(&sc->mutex);
@@ -2326,26 +2290,33 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ieee80211_conf *conf = &hw->conf;
+	struct ath_hw *ah = sc->sc_ah;
 
 	mutex_lock(&sc->mutex);
 
 	if (changed & IEEE80211_CONF_CHANGE_PS) {
 		if (conf->flags & IEEE80211_CONF_PS) {
-			if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
-				sc->imask |= ATH9K_INT_TIM_TIMER;
-				ath9k_hw_set_interrupts(sc->sc_ah,
-						sc->imask);
+			if (!(ah->caps.hw_caps &
+			      ATH9K_HW_CAP_AUTOSLEEP)) {
+				if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
+					sc->imask |= ATH9K_INT_TIM_TIMER;
+					ath9k_hw_set_interrupts(sc->sc_ah,
+							sc->imask);
+				}
+				ath9k_hw_setrxabort(sc->sc_ah, 1);
 			}
-			ath9k_hw_setrxabort(sc->sc_ah, 1);
 			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP);
 		} else {
 			ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
-			ath9k_hw_setrxabort(sc->sc_ah, 0);
-			sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
-			if (sc->imask & ATH9K_INT_TIM_TIMER) {
-				sc->imask &= ~ATH9K_INT_TIM_TIMER;
-				ath9k_hw_set_interrupts(sc->sc_ah,
-						sc->imask);
+			if (!(ah->caps.hw_caps &
+			      ATH9K_HW_CAP_AUTOSLEEP)) {
+				ath9k_hw_setrxabort(sc->sc_ah, 0);
+				sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON;
+				if (sc->imask & ATH9K_INT_TIM_TIMER) {
+					sc->imask &= ~ATH9K_INT_TIM_TIMER;
+					ath9k_hw_set_interrupts(sc->sc_ah,
+							sc->imask);
+				}
 			}
 		}
 	}
@@ -2562,6 +2533,8 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
 	mutex_lock(&sc->mutex);
 
+	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
+
 	qi.tqi_aifs = params->aifs;
 	qi.tqi_cwmin = params->cw_min;
 	qi.tqi_cwmax = params->cw_max;
@@ -2598,7 +2571,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
-	DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n");
+	DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n");
 
 	switch (cmd) {
 	case SET_KEY:
@@ -2771,6 +2744,7 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
 	mutex_lock(&sc->mutex);
 	aphy->state = ATH_WIPHY_ACTIVE;
 	sc->sc_flags &= ~SC_OP_SCANNING;
+	sc->sc_flags |= SC_OP_FULL_RESET;
 	mutex_unlock(&sc->mutex);
 }
 

+ 0 - 0
drivers/net/wireless/ath9k/pci.c → drivers/net/wireless/ath/ath9k/pci.c


+ 2 - 2
drivers/net/wireless/ath9k/phy.c → drivers/net/wireless/ath/ath9k/phy.c

@@ -46,7 +46,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 			channelSel = ((freq - 704) * 2 - 3040) / 10;
 			bModeSynth = 1;
 		} else {
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+			DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 				"Invalid channel %u MHz\n", freq);
 			return false;
 		}
@@ -79,7 +79,7 @@ ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
 		channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8);
 		aModeRefSel = ath9k_hw_reverse_bits(1, 2);
 	} else {
-		DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
 			"Invalid channel %u MHz\n", freq);
 		return false;
 	}

+ 0 - 3
drivers/net/wireless/ath9k/phy.h → drivers/net/wireless/ath/ath9k/phy.h

@@ -556,9 +556,6 @@ bool ath9k_hw_init_rf(struct ath_hw *ah,
 		int r;							\
 		for (r = 0; r < ((iniarray)->ia_rows); r++) {		\
 			REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \
-			DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, \
-				"RF 0x%x V 0x%x\n", \
-				INI_RA((iniarray), r, 0), (regData)[r]); \
 			DO_DELAY(regWr);				\
 		}							\
 	} while (0)

+ 11 - 15
drivers/net/wireless/ath9k/rc.c → drivers/net/wireless/ath/ath9k/rc.c

@@ -524,7 +524,7 @@ static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
 	u32 valid;
 
 	for (i = 0; i < rate_table->rate_cnt; i++) {
-		valid = (ath_rc_priv->single_stream ?
+		valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
 			 rate_table->info[i].valid_single_stream :
 			 rate_table->info[i].valid);
 		if (valid == 1) {
@@ -557,9 +557,9 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
 	for (i = 0; i < rateset->rs_nrates; i++) {
 		for (j = 0; j < rate_table->rate_cnt; j++) {
 			u32 phy = rate_table->info[j].phy;
-			u32 valid = (ath_rc_priv->single_stream ?
-				rate_table->info[j].valid_single_stream :
-				rate_table->info[j].valid);
+			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
+				     rate_table->info[j].valid_single_stream :
+				     rate_table->info[j].valid);
 			u8 rate = rateset->rs_rates[i];
 			u8 dot11rate = rate_table->info[j].dot11rate;
 
@@ -603,7 +603,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
 	for (i = 0; i < rateset->rs_nrates; i++) {
 		for (j = 0; j < rate_table->rate_cnt; j++) {
 			u32 phy = rate_table->info[j].phy;
-			u32 valid = (ath_rc_priv->single_stream ?
+			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
 				     rate_table->info[j].valid_single_stream :
 				     rate_table->info[j].valid);
 			u8 rate = rateset->rs_rates[i];
@@ -740,9 +740,10 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
 	if (rate > (ath_rc_priv->rate_table_size - 1))
 		rate = ath_rc_priv->rate_table_size - 1;
 
-	ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
+	ASSERT((rate_table->info[rate].valid &&
+		(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) ||
 	       (rate_table->info[rate].valid_single_stream &&
-		ath_rc_priv->single_stream));
+		!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)));
 
 	return rate;
 }
@@ -811,7 +812,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc,
 			     u16 min_rate)
 {
 	u32 j;
-	u8 nextindex;
+	u8 nextindex = 0;
 
 	if (min_rate) {
 		for (j = RATE_TABLE_SIZE; j > 0; j--) {
@@ -1320,7 +1321,7 @@ static void ath_rc_tx_status(struct ath_softc *sc,
 				 * 40 to 20 => don't update */
 
 				if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-				    (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
+				    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
 					return;
 
 				rix = ath_rc_get_rateindex(rate_table, &rates[i]);
@@ -1345,9 +1346,8 @@ static void ath_rc_tx_status(struct ath_softc *sc,
 
 	/* If HT40 and we have switched mode from 40 to 20 => don't update */
 	if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
-	    (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
+	    !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG))
 		return;
-	}
 
 	rix = ath_rc_get_rateindex(rate_table, &rates[i]);
 	ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
@@ -1420,10 +1420,6 @@ static void ath_rc_init(struct ath_softc *sc,
 			ath_rc_priv->valid_phy_rateidx[i][j] = 0;
 		ath_rc_priv->valid_phy_ratecnt[i] = 0;
 	}
-	ath_rc_priv->rc_phy_mode = ath_rc_priv->ht_cap & WLAN_RC_40_FLAG;
-
-	/* Set stream capability */
-	ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
 
 	if (!rateset->rs_nrates) {
 		/* No working rate, just initialize valid rates */

+ 0 - 4
drivers/net/wireless/ath9k/rc.h → drivers/net/wireless/ath/ath9k/rc.h

@@ -24,7 +24,6 @@ struct ath_softc;
 #define ATH_RATE_MAX     30
 #define RATE_TABLE_SIZE  64
 #define MAX_TX_RATE_PHY  48
-#define WLAN_CTRL_FRAME_SIZE (2+2+6+4)
 
 /* VALID_ALL - valid for 20/40/Legacy,
  * VALID - Legacy only,
@@ -158,7 +157,6 @@ struct ath_rateset {
  * @probe_interval: interval for ratectrl to probe for other rates
  * @prev_data_rix: rate idx of last data frame
  * @ht_cap: HT capabilities
- * @single_stream: When TRUE, only single TX stream possible
  * @neg_rates: Negotatied rates
  * @neg_ht_rates: Negotiated HT rates
  */
@@ -176,10 +174,8 @@ struct ath_rate_priv {
 	u8 max_valid_rate;
 	u8 valid_rate_index[RATE_TABLE_SIZE];
 	u8 ht_cap;
-	u8 single_stream;
 	u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
 	u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
-	u8 rc_phy_mode;
 	u8 rate_max_phy;
 	u32 rssi_time;
 	u32 rssi_down_time;

+ 40 - 45
drivers/net/wireless/ath9k/recv.c → drivers/net/wireless/ath/ath9k/recv.c

@@ -283,54 +283,51 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	struct ath_buf *bf;
 	int error = 0;
 
-	do {
-		spin_lock_init(&sc->rx.rxflushlock);
-		sc->sc_flags &= ~SC_OP_RXFLUSH;
-		spin_lock_init(&sc->rx.rxbuflock);
-
-		sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-					   min(sc->cachelsz,
-					       (u16)64));
+	spin_lock_init(&sc->rx.rxflushlock);
+	sc->sc_flags &= ~SC_OP_RXFLUSH;
+	spin_lock_init(&sc->rx.rxbuflock);
 
-		DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
-			sc->cachelsz, sc->rx.bufsize);
+	sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
+				 min(sc->cachelsz, (u16)64));
 
-		/* Initialize rx descriptors */
+	DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
+		sc->cachelsz, sc->rx.bufsize);
 
-		error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
-					  "rx", nbufs, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"failed to allocate rx descriptors: %d\n", error);
-			break;
-		}
+	/* Initialize rx descriptors */
 
-		list_for_each_entry(bf, &sc->rx.rxbuf, list) {
-			skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
-			if (skb == NULL) {
-				error = -ENOMEM;
-				break;
-			}
+	error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
+				  "rx", nbufs, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"failed to allocate rx descriptors: %d\n", error);
+		goto err;
+	}
 
-			bf->bf_mpdu = skb;
-			bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
-							 sc->rx.bufsize,
-							 DMA_FROM_DEVICE);
-			if (unlikely(dma_mapping_error(sc->dev,
-				  bf->bf_buf_addr))) {
-				dev_kfree_skb_any(skb);
-				bf->bf_mpdu = NULL;
-				DPRINTF(sc, ATH_DBG_CONFIG,
-					"dma_mapping_error() on RX init\n");
-				error = -ENOMEM;
-				break;
-			}
-			bf->bf_dmacontext = bf->bf_buf_addr;
+	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+		skb = ath_rxbuf_alloc(sc, sc->rx.bufsize, GFP_KERNEL);
+		if (skb == NULL) {
+			error = -ENOMEM;
+			goto err;
 		}
-		sc->rx.rxlink = NULL;
 
-	} while (0);
+		bf->bf_mpdu = skb;
+		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
+						 sc->rx.bufsize,
+						 DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(sc->dev,
+					       bf->bf_buf_addr))) {
+			dev_kfree_skb_any(skb);
+			bf->bf_mpdu = NULL;
+			DPRINTF(sc, ATH_DBG_FATAL,
+				"dma_mapping_error() on RX init\n");
+			error = -ENOMEM;
+			goto err;
+		}
+		bf->bf_dmacontext = bf->bf_buf_addr;
+	}
+	sc->rx.rxlink = NULL;
 
+err:
 	if (error)
 		ath_rx_cleanup(sc);
 
@@ -345,10 +342,8 @@ void ath_rx_cleanup(struct ath_softc *sc)
 	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
 		skb = bf->bf_mpdu;
 		if (skb) {
-			dma_unmap_single(sc->dev,
-					 bf->bf_buf_addr,
-					 sc->rx.bufsize,
-					 DMA_FROM_DEVICE);
+			dma_unmap_single(sc->dev, bf->bf_buf_addr,
+					 sc->rx.bufsize, DMA_FROM_DEVICE);
 			dev_kfree_skb(skb);
 		}
 	}
@@ -675,7 +670,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 			  bf->bf_buf_addr))) {
 			dev_kfree_skb_any(requeue_skb);
 			bf->bf_mpdu = NULL;
-			DPRINTF(sc, ATH_DBG_CONFIG,
+			DPRINTF(sc, ATH_DBG_FATAL,
 				"dma_mapping_error() on RX\n");
 			break;
 		}

+ 0 - 0
drivers/net/wireless/ath9k/reg.h → drivers/net/wireless/ath/ath9k/reg.h


+ 0 - 0
drivers/net/wireless/ath9k/virtual.c → drivers/net/wireless/ath/ath9k/virtual.c


+ 29 - 35
drivers/net/wireless/ath9k/xmit.c → drivers/net/wireless/ath/ath9k/xmit.c

@@ -283,7 +283,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
 	bool rc_update = true;
 
-	skb = (struct sk_buff *)bf->bf_mpdu;
+	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
 
 	rcu_read_lock();
@@ -380,8 +380,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
 		} else {
 			/* retry the un-acked ones */
-			if (bf->bf_next == NULL &&
-			    bf_last->bf_status & ATH_BUFSTATUS_STALE) {
+			if (bf->bf_next == NULL && bf_last->bf_stale) {
 				struct ath_buf *tbf;
 
 				tbf = ath_clone_txbuf(sc, bf_last);
@@ -444,7 +443,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
 	u16 aggr_limit, legacy = 0, maxampdu;
 	int i;
 
-	skb = (struct sk_buff *)bf->bf_mpdu;
+	skb = bf->bf_mpdu;
 	tx_info = IEEE80211_SKB_CB(skb);
 	rates = tx_info->control.rates;
 	tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
@@ -1004,7 +1003,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
 
 		bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
 
-		if (bf->bf_status & ATH_BUFSTATUS_STALE) {
+		if (bf->bf_stale) {
 			list_del(&bf->list);
 			spin_unlock_bh(&txq->axq_lock);
 
@@ -1452,7 +1451,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
 
 	memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 
-	skb = (struct sk_buff *)bf->bf_mpdu;
+	skb = bf->bf_mpdu;
 	tx_info = IEEE80211_SKB_CB(skb);
 	rates = tx_info->control.rates;
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -1573,8 +1572,9 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
 					   skb->len, DMA_TO_DEVICE);
 	if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) {
 		bf->bf_mpdu = NULL;
-		DPRINTF(sc, ATH_DBG_CONFIG,
-			"dma_mapping_error() on TX\n");
+		kfree(tx_info_priv);
+		tx_info->rate_driver_data[0] = NULL;
+		DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n");
 		return -ENOMEM;
 	}
 
@@ -1586,7 +1586,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
 static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
 			     struct ath_tx_control *txctl)
 {
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+	struct sk_buff *skb = bf->bf_mpdu;
 	struct ieee80211_tx_info *tx_info =  IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ath_node *an = NULL;
@@ -1860,7 +1860,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
 static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
 			     int nbad, int txok, bool update_rc)
 {
-	struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+	struct sk_buff *skb = bf->bf_mpdu;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
@@ -1941,7 +1941,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 		 * it with the STALE flag.
 		 */
 		bf_held = NULL;
-		if (bf->bf_status & ATH_BUFSTATUS_STALE) {
+		if (bf->bf_stale) {
 			bf_held = bf;
 			if (list_is_last(&bf_held->list, &txq->axq_q)) {
 				txq->axq_link = NULL;
@@ -1982,7 +1982,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 		 * however leave the last descriptor back as the holding
 		 * descriptor for hw.
 		 */
-		lastbf->bf_status |= ATH_BUFSTATUS_STALE;
+		lastbf->bf_stale = true;
 		INIT_LIST_HEAD(&bf_head);
 		if (!list_is_singular(&lastbf->list))
 			list_cut_position(&bf_head,
@@ -2048,44 +2048,38 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
 {
 	int error = 0;
 
-	do {
-		spin_lock_init(&sc->tx.txbuflock);
+	spin_lock_init(&sc->tx.txbuflock);
 
-		error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
-			"tx", nbufs, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Failed to allocate tx descriptors: %d\n",
-				error);
-			break;
-		}
-
-		error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
-					  "beacon", ATH_BCBUF, 1);
-		if (error != 0) {
-			DPRINTF(sc, ATH_DBG_FATAL,
-				"Failed to allocate beacon descriptors: %d\n",
-				error);
-			break;
-		}
+	error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
+				  "tx", nbufs, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to allocate tx descriptors: %d\n", error);
+		goto err;
+	}
 
-	} while (0);
+	error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
+				  "beacon", ATH_BCBUF, 1);
+	if (error != 0) {
+		DPRINTF(sc, ATH_DBG_FATAL,
+			"Failed to allocate beacon descriptors: %d\n", error);
+		goto err;
+	}
 
+err:
 	if (error != 0)
 		ath_tx_cleanup(sc);
 
 	return error;
 }
 
-int ath_tx_cleanup(struct ath_softc *sc)
+void ath_tx_cleanup(struct ath_softc *sc)
 {
 	if (sc->beacon.bdma.dd_desc_len != 0)
 		ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
 
 	if (sc->tx.txdma.dd_desc_len != 0)
 		ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
-
-	return 0;
 }
 
 void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)

+ 22 - 0
drivers/net/wireless/ath/main.c

@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2009 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
+MODULE_LICENSE("Dual BSD/GPL");

+ 137 - 104
drivers/net/wireless/ath9k/regd.c → drivers/net/wireless/ath/regd.c

@@ -16,7 +16,9 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include "ath9k.h"
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+#include "regd.h"
 #include "regd_common.h"
 
 /*
@@ -55,7 +57,7 @@
 
 /* Can be used for:
  * 0x60, 0x61, 0x62 */
-static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
+static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = {
 	.n_reg_rules = 5,
 	.alpha2 =  "99",
 	.reg_rules = {
@@ -65,7 +67,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_60_61_62 = {
 };
 
 /* Can be used by 0x63 and 0x65 */
-static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
+static const struct ieee80211_regdomain ath_world_regdom_63_65 = {
 	.n_reg_rules = 4,
 	.alpha2 =  "99",
 	.reg_rules = {
@@ -76,7 +78,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_63_65 = {
 };
 
 /* Can be used by 0x64 only */
-static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
+static const struct ieee80211_regdomain ath_world_regdom_64 = {
 	.n_reg_rules = 3,
 	.alpha2 =  "99",
 	.reg_rules = {
@@ -86,7 +88,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_64 = {
 };
 
 /* Can be used by 0x66 and 0x69 */
-static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
+static const struct ieee80211_regdomain ath_world_regdom_66_69 = {
 	.n_reg_rules = 3,
 	.alpha2 =  "99",
 	.reg_rules = {
@@ -96,7 +98,7 @@ static const struct ieee80211_regdomain ath9k_world_regdom_66_69 = {
 };
 
 /* Can be used by 0x67, 0x6A and 0x68 */
-static const struct ieee80211_regdomain ath9k_world_regdom_67_68_6A = {
+static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = {
 	.n_reg_rules = 4,
 	.alpha2 =  "99",
 	.reg_rules = {
@@ -112,49 +114,51 @@ static inline bool is_wwr_sku(u16 regd)
 		(regd == WORLD);
 }
 
-static u16 ath9k_regd_get_eepromRD(struct ath_hw *ah)
+static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg)
 {
-	return ah->regulatory.current_rd & ~WORLDWIDE_ROAMING_FLAG;
+	return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG;
 }
 
-bool ath9k_is_world_regd(struct ath_hw *ah)
+bool ath_is_world_regd(struct ath_regulatory *reg)
 {
-	return is_wwr_sku(ath9k_regd_get_eepromRD(ah));
+	return is_wwr_sku(ath_regd_get_eepromRD(reg));
 }
+EXPORT_SYMBOL(ath_is_world_regd);
 
-const struct ieee80211_regdomain *ath9k_default_world_regdomain(void)
+static const struct ieee80211_regdomain *ath_default_world_regdomain(void)
 {
 	/* this is the most restrictive */
-	return &ath9k_world_regdom_64;
+	return &ath_world_regdom_64;
 }
 
-const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah)
+static const struct
+ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg)
 {
-	switch (ah->regulatory.regpair->regDmnEnum) {
+	switch (reg->regpair->regDmnEnum) {
 	case 0x60:
 	case 0x61:
 	case 0x62:
-		return &ath9k_world_regdom_60_61_62;
+		return &ath_world_regdom_60_61_62;
 	case 0x63:
 	case 0x65:
-		return &ath9k_world_regdom_63_65;
+		return &ath_world_regdom_63_65;
 	case 0x64:
-		return &ath9k_world_regdom_64;
+		return &ath_world_regdom_64;
 	case 0x66:
 	case 0x69:
-		return &ath9k_world_regdom_66_69;
+		return &ath_world_regdom_66_69;
 	case 0x67:
 	case 0x68:
 	case 0x6A:
-		return &ath9k_world_regdom_67_68_6A;
+		return &ath_world_regdom_67_68_6A;
 	default:
 		WARN_ON(1);
-		return ath9k_default_world_regdomain();
+		return ath_default_world_regdomain();
 	}
 }
 
 /* Frequency is one where radar detection is required */
-static bool ath9k_is_radar_freq(u16 center_freq)
+static bool ath_is_radar_freq(u16 center_freq)
 {
 	return (center_freq >= 5260 && center_freq <= 5700);
 }
@@ -168,9 +172,9 @@ static bool ath9k_is_radar_freq(u16 center_freq)
  *   received a beacon on a channel we can enable active scan and
  *   adhoc (or beaconing).
  */
-static void ath9k_reg_apply_beaconing_flags(
-	struct wiphy *wiphy,
-	enum nl80211_reg_initiator initiator)
+static void
+ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
+			      enum nl80211_reg_initiator initiator)
 {
 	enum ieee80211_band band;
 	struct ieee80211_supported_band *sband;
@@ -191,7 +195,7 @@ static void ath9k_reg_apply_beaconing_flags(
 
 			ch = &sband->channels[i];
 
-			if (ath9k_is_radar_freq(ch->center_freq) ||
+			if (ath_is_radar_freq(ch->center_freq) ||
 			    (ch->flags & IEEE80211_CHAN_RADAR))
 				continue;
 
@@ -227,9 +231,9 @@ static void ath9k_reg_apply_beaconing_flags(
 }
 
 /* Allows active scan scan on Ch 12 and 13 */
-static void ath9k_reg_apply_active_scan_flags(
-	struct wiphy *wiphy,
-	enum nl80211_reg_initiator initiator)
+static void
+ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
+				enum nl80211_reg_initiator initiator)
 {
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *ch;
@@ -278,7 +282,7 @@ static void ath9k_reg_apply_active_scan_flags(
 }
 
 /* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */
-void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
+static void ath_reg_apply_radar_flags(struct wiphy *wiphy)
 {
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *ch;
@@ -291,7 +295,7 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
 
 	for (i = 0; i < sband->n_channels; i++) {
 		ch = &sband->channels[i];
-		if (!ath9k_is_radar_freq(ch->center_freq))
+		if (!ath_is_radar_freq(ch->center_freq))
 			continue;
 		/* We always enable radar detection/DFS on this
 		 * frequency range. Additionally we also apply on
@@ -310,37 +314,31 @@ void ath9k_reg_apply_radar_flags(struct wiphy *wiphy)
 	}
 }
 
-void ath9k_reg_apply_world_flags(struct wiphy *wiphy,
-				 enum nl80211_reg_initiator initiator)
+static void ath_reg_apply_world_flags(struct wiphy *wiphy,
+				      enum nl80211_reg_initiator initiator,
+				      struct ath_regulatory *reg)
 {
-	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
-
-	switch (ah->regulatory.regpair->regDmnEnum) {
+	switch (reg->regpair->regDmnEnum) {
 	case 0x60:
 	case 0x63:
 	case 0x66:
 	case 0x67:
-		ath9k_reg_apply_beaconing_flags(wiphy, initiator);
+		ath_reg_apply_beaconing_flags(wiphy, initiator);
 		break;
 	case 0x68:
-		ath9k_reg_apply_beaconing_flags(wiphy, initiator);
-		ath9k_reg_apply_active_scan_flags(wiphy, initiator);
+		ath_reg_apply_beaconing_flags(wiphy, initiator);
+		ath_reg_apply_active_scan_flags(wiphy, initiator);
 		break;
 	}
 	return;
 }
 
-int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+int ath_reg_notifier_apply(struct wiphy *wiphy,
+			   struct regulatory_request *request,
+			   struct ath_regulatory *reg)
 {
-	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-
 	/* We always apply this */
-	ath9k_reg_apply_radar_flags(wiphy);
+	ath_reg_apply_radar_flags(wiphy);
 
 	switch (request->initiator) {
 	case NL80211_REGDOM_SET_BY_DRIVER:
@@ -348,17 +346,19 @@ int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 	case NL80211_REGDOM_SET_BY_USER:
 		break;
 	case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-		if (ath9k_is_world_regd(sc->sc_ah))
-			ath9k_reg_apply_world_flags(wiphy, request->initiator);
+		if (ath_is_world_regd(reg))
+			ath_reg_apply_world_flags(wiphy, request->initiator,
+						  reg);
 		break;
 	}
 
 	return 0;
 }
+EXPORT_SYMBOL(ath_reg_notifier_apply);
 
-bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah)
+static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg)
 {
-	u16 rd = ath9k_regd_get_eepromRD(ah);
+	 u16 rd = ath_regd_get_eepromRD(reg);
 	int i;
 
 	if (rd & COUNTRY_ERD_FLAG) {
@@ -373,14 +373,14 @@ bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah)
 			if (regDomainPairs[i].regDmnEnum == rd)
 				return true;
 	}
-	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-		 "invalid regulatory domain/country code 0x%x\n", rd);
+	printk(KERN_DEBUG
+		 "ath: invalid regulatory domain/country code 0x%x\n", rd);
 	return false;
 }
 
 /* EEPROM country code to regpair mapping */
 static struct country_code_to_enum_rd*
-ath9k_regd_find_country(u16 countryCode)
+ath_regd_find_country(u16 countryCode)
 {
 	int i;
 
@@ -393,7 +393,7 @@ ath9k_regd_find_country(u16 countryCode)
 
 /* EEPROM rd code to regpair mapping */
 static struct country_code_to_enum_rd*
-ath9k_regd_find_country_by_rd(int regdmn)
+ath_regd_find_country_by_rd(int regdmn)
 {
 	int i;
 
@@ -405,13 +405,13 @@ ath9k_regd_find_country_by_rd(int regdmn)
 }
 
 /* Returns the map of the EEPROM set RD to a country code */
-static u16 ath9k_regd_get_default_country(u16 rd)
+static u16 ath_regd_get_default_country(u16 rd)
 {
 	if (rd & COUNTRY_ERD_FLAG) {
 		struct country_code_to_enum_rd *country = NULL;
 		u16 cc = rd & ~COUNTRY_ERD_FLAG;
 
-		country = ath9k_regd_find_country(cc);
+		country = ath_regd_find_country(cc);
 		if (country != NULL)
 			return cc;
 	}
@@ -420,7 +420,7 @@ static u16 ath9k_regd_get_default_country(u16 rd)
 }
 
 static struct reg_dmn_pair_mapping*
-ath9k_get_regpair(int regdmn)
+ath_get_regpair(int regdmn)
 {
 	int i;
 
@@ -433,87 +433,120 @@ ath9k_get_regpair(int regdmn)
 	return NULL;
 }
 
-int ath9k_regd_init(struct ath_hw *ah)
+static int
+ath_regd_init_wiphy(struct ath_regulatory *reg,
+		    struct wiphy *wiphy,
+		    int (*reg_notifier)(struct wiphy *wiphy,
+					struct regulatory_request *request))
+{
+	const struct ieee80211_regdomain *regd;
+
+	wiphy->reg_notifier = reg_notifier;
+	wiphy->strict_regulatory = true;
+
+	if (ath_is_world_regd(reg)) {
+		/*
+		 * Anything applied here (prior to wiphy registration) gets
+		 * saved on the wiphy orig_* parameters
+		 */
+		regd = ath_world_regdomain(reg);
+		wiphy->custom_regulatory = true;
+		wiphy->strict_regulatory = false;
+	} else {
+		/*
+		 * This gets applied in the case of the absense of CRDA,
+		 * it's our own custom world regulatory domain, similar to
+		 * cfg80211's but we enable passive scanning.
+		 */
+		regd = ath_default_world_regdomain();
+	}
+	wiphy_apply_custom_regulatory(wiphy, regd);
+	ath_reg_apply_radar_flags(wiphy);
+	ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg);
+	return 0;
+}
+
+int
+ath_regd_init(struct ath_regulatory *reg,
+	      struct wiphy *wiphy,
+	      int (*reg_notifier)(struct wiphy *wiphy,
+				  struct regulatory_request *request))
 {
 	struct country_code_to_enum_rd *country = NULL;
 	u16 regdmn;
 
-	if (!ath9k_regd_is_eeprom_valid(ah)) {
-		DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-			"Invalid EEPROM contents\n");
+	if (!ath_regd_is_eeprom_valid(reg)) {
+		printk(KERN_ERR "ath: Invalid EEPROM contents\n");
 		return -EINVAL;
 	}
 
-	regdmn = ath9k_regd_get_eepromRD(ah);
-	ah->regulatory.country_code = ath9k_regd_get_default_country(regdmn);
+	regdmn = ath_regd_get_eepromRD(reg);
+	reg->country_code = ath_regd_get_default_country(regdmn);
 
-	if (ah->regulatory.country_code == CTRY_DEFAULT &&
+	if (reg->country_code == CTRY_DEFAULT &&
 	    regdmn == CTRY_DEFAULT)
-		ah->regulatory.country_code = CTRY_UNITED_STATES;
+		reg->country_code = CTRY_UNITED_STATES;
 
-	if (ah->regulatory.country_code == CTRY_DEFAULT) {
+	if (reg->country_code == CTRY_DEFAULT) {
 		country = NULL;
 	} else {
-		country = ath9k_regd_find_country(ah->regulatory.country_code);
+		country = ath_regd_find_country(reg->country_code);
 		if (country == NULL) {
-			DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-				"Country is NULL!!!!, cc= %d\n",
-				ah->regulatory.country_code);
+			printk(KERN_DEBUG
+				"ath: Country is NULL!!!!, cc= %d\n",
+				reg->country_code);
 			return -EINVAL;
 		} else
 			regdmn = country->regDmnEnum;
 	}
 
-	ah->regulatory.regpair = ath9k_get_regpair(regdmn);
+	reg->regpair = ath_get_regpair(regdmn);
 
-	if (!ah->regulatory.regpair) {
-		DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+	if (!reg->regpair) {
+		printk(KERN_DEBUG "ath: "
 			"No regulatory domain pair found, cannot continue\n");
 		return -EINVAL;
 	}
 
 	if (!country)
-		country = ath9k_regd_find_country_by_rd(regdmn);
+		country = ath_regd_find_country_by_rd(regdmn);
 
 	if (country) {
-		ah->regulatory.alpha2[0] = country->isoName[0];
-		ah->regulatory.alpha2[1] = country->isoName[1];
+		reg->alpha2[0] = country->isoName[0];
+		reg->alpha2[1] = country->isoName[1];
 	} else {
-		ah->regulatory.alpha2[0] = '0';
-		ah->regulatory.alpha2[1] = '0';
+		reg->alpha2[0] = '0';
+		reg->alpha2[1] = '0';
 	}
 
-	DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
-		"Country alpha2 being used: %c%c\n"
-		"Regulatory.Regpair detected: 0x%0x\n",
-		ah->regulatory.alpha2[0], ah->regulatory.alpha2[1],
-		ah->regulatory.regpair->regDmnEnum);
+	printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n",
+		reg->alpha2[0], reg->alpha2[1]);
+	printk(KERN_DEBUG "ath: Regpair detected: 0x%0x\n",
+		reg->regpair->regDmnEnum);
 
+	ath_regd_init_wiphy(reg, wiphy, reg_notifier);
 	return 0;
 }
+EXPORT_SYMBOL(ath_regd_init);
 
-u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan)
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+			  enum ieee80211_band band)
 {
-	u32 ctl = NO_CTL;
-
-	if (!ah->regulatory.regpair ||
-	    (ah->regulatory.country_code == CTRY_DEFAULT &&
-	     is_wwr_sku(ath9k_regd_get_eepromRD(ah)))) {
-		if (IS_CHAN_B(chan))
-			ctl = SD_NO_CTL | CTL_11B;
-		else if (IS_CHAN_G(chan))
-			ctl = SD_NO_CTL | CTL_11G;
-		else
-			ctl = SD_NO_CTL | CTL_11A;
-		return ctl;
+	if (!reg->regpair ||
+	    (reg->country_code == CTRY_DEFAULT &&
+	     is_wwr_sku(ath_regd_get_eepromRD(reg)))) {
+		return SD_NO_CTL;
 	}
 
-	if (IS_CHAN_B(chan))
-		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11B;
-	else if (IS_CHAN_G(chan))
-		ctl = ah->regulatory.regpair->reg_2ghz_ctl | CTL_11G;
-	else
-		ctl = ah->regulatory.regpair->reg_5ghz_ctl | CTL_11A;
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		return reg->regpair->reg_2ghz_ctl;
+	case IEEE80211_BAND_5GHZ:
+		return reg->regpair->reg_5ghz_ctl;
+	default:
+		return NO_CTL;
+	}
 
-	return ctl;
+	return NO_CTL;
 }
+EXPORT_SYMBOL(ath_regd_get_band_ctl);

+ 29 - 11
drivers/net/wireless/ath9k/regd.h → drivers/net/wireless/ath/regd.h

@@ -17,6 +17,25 @@
 #ifndef REGD_H
 #define REGD_H
 
+#include <linux/nl80211.h>
+
+#include <net/cfg80211.h>
+
+#define NO_CTL 0xff
+#define SD_NO_CTL               0xE0
+#define NO_CTL                  0xff
+#define CTL_MODE_M              7
+#define CTL_11A                 0
+#define CTL_11B                 1
+#define CTL_11G                 2
+#define CTL_2GHT20              5
+#define CTL_5GHT20              6
+#define CTL_2GHT40              7
+#define CTL_5GHT40              8
+
+#define CTRY_DEBUG 0x1ff
+#define CTRY_DEFAULT 0
+
 #define COUNTRY_ERD_FLAG        0x8000
 #define WORLDWIDE_ROAMING_FLAG  0x4000
 
@@ -40,7 +59,7 @@ struct country_code_to_enum_rd {
 	const char *isoName;
 };
 
-struct ath9k_regulatory {
+struct ath_regulatory {
 	char alpha2[2];
 	u16 country_code;
 	u16 max_power_level;
@@ -233,15 +252,14 @@ enum CountryCode {
 	CTRY_BELGIUM2 = 5002
 };
 
-bool ath9k_is_world_regd(struct ath_hw *ah);
-const struct ieee80211_regdomain *ath9k_world_regdomain(struct ath_hw *ah);
-const struct ieee80211_regdomain *ath9k_default_world_regdomain(void);
-void ath9k_reg_apply_world_flags(struct wiphy *wiphy,
-				 enum nl80211_reg_initiator initiator);
-void ath9k_reg_apply_radar_flags(struct wiphy *wiphy);
-int ath9k_regd_init(struct ath_hw *ah);
-bool ath9k_regd_is_eeprom_valid(struct ath_hw *ah);
-u32 ath9k_regd_get_ctl(struct ath_hw *ah, struct ath9k_channel *chan);
-int ath9k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+bool ath_is_world_regd(struct ath_regulatory *reg);
+int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
+		  int (*reg_notifier)(struct wiphy *wiphy,
+		  struct regulatory_request *request));
+u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
+			  enum ieee80211_band band);
+int ath_reg_notifier_apply(struct wiphy *wiphy,
+			   struct regulatory_request *request,
+			   struct ath_regulatory *reg);
 
 #endif

+ 0 - 0
drivers/net/wireless/ath9k/regd_common.h → drivers/net/wireless/ath/regd_common.h


+ 7 - 1
drivers/net/wireless/b43/Kconfig

@@ -3,7 +3,6 @@ config B43
 	depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
 	select SSB
 	select FW_LOADER
-	select HW_RANDOM
 	---help---
 	  b43 is a driver for the Broadcom 43xx series wireless devices.
 
@@ -106,6 +105,13 @@ config B43_RFKILL
 	depends on B43 && (RFKILL = y || RFKILL = B43) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43)
 	default y
 
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43_HWRNG
+	bool
+	depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43)
+	default y
+
 config B43_DEBUG
 	bool "Broadcom 43xx debugging"
 	depends on B43

+ 5 - 3
drivers/net/wireless/b43/b43.h

@@ -625,9 +625,11 @@ struct b43_wl {
 	/* Stats about the wireless interface */
 	struct ieee80211_low_level_stats ieee_stats;
 
+#ifdef CONFIG_B43_HWRNG
 	struct hwrng rng;
-	u8 rng_initialized;
+	bool rng_initialized;
 	char rng_name[30 + 1];
+#endif /* CONFIG_B43_HWRNG */
 
 	/* The RF-kill button */
 	struct b43_rfkill rfkill;
@@ -776,8 +778,8 @@ struct b43_wldev {
 	/* Reason code of the last interrupt. */
 	u32 irq_reason;
 	u32 dma_reason[6];
-	/* saved irq enable/disable state bitfield. */
-	u32 irq_savedstate;
+	/* The currently active generic-interrupt mask. */
+	u32 irq_mask;
 	/* Link Quality calculation context. */
 	struct b43_noise_calculation noisecalc;
 	/* if > 0 MAC is suspended. if == 0 MAC is enabled. */

+ 26 - 43
drivers/net/wireless/b43/main.c

@@ -673,32 +673,6 @@ static void b43_short_slot_timing_disable(struct b43_wldev *dev)
 	b43_set_slot_time(dev, 20);
 }
 
-/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43_interrupt_enable(struct b43_wldev *dev, u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
-	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask | mask);
-
-	return old_mask;
-}
-
-/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
- * Returns the _previously_ enabled IRQ mask.
- */
-static inline u32 b43_interrupt_disable(struct b43_wldev *dev, u32 mask)
-{
-	u32 old_mask;
-
-	old_mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
-	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
-
-	return old_mask;
-}
-
 /* Synchronize IRQ top- and bottom-half.
  * IRQs must be masked before calling this.
  * This must not be called with the irq_lock held.
@@ -1593,7 +1567,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
 	/* This is the bottom half of the asynchronous beacon update. */
 
 	/* Ignore interrupt in the future. */
-	dev->irq_savedstate &= ~B43_IRQ_BEACON;
+	dev->irq_mask &= ~B43_IRQ_BEACON;
 
 	cmd = b43_read32(dev, B43_MMIO_MACCMD);
 	beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID);
@@ -1602,7 +1576,7 @@ static void handle_irq_beacon(struct b43_wldev *dev)
 	/* Schedule interrupt manually, if busy. */
 	if (beacon0_valid && beacon1_valid) {
 		b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON);
-		dev->irq_savedstate |= B43_IRQ_BEACON;
+		dev->irq_mask |= B43_IRQ_BEACON;
 		return;
 	}
 
@@ -1641,11 +1615,9 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
 	if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) {
 		spin_lock_irq(&wl->irq_lock);
 		/* update beacon right away or defer to irq */
-		dev->irq_savedstate = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
 		handle_irq_beacon(dev);
 		/* The handler might have updated the IRQ mask. */
-		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK,
-			    dev->irq_savedstate);
+		b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 		mmiowb();
 		spin_unlock_irq(&wl->irq_lock);
 	}
@@ -1879,7 +1851,7 @@ static void b43_interrupt_tasklet(struct b43_wldev *dev)
 	if (reason & B43_IRQ_TX_OK)
 		handle_irq_transmit_status(dev);
 
-	b43_interrupt_enable(dev, dev->irq_savedstate);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 	mmiowb();
 	spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
 }
@@ -1893,7 +1865,9 @@ static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason)
 	b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);
 	b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);
 	b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);
+/* Unused ring
 	b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);
+*/
 }
 
 /* Interrupt handler top-half */
@@ -1903,18 +1877,19 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
 	struct b43_wldev *dev = dev_id;
 	u32 reason;
 
-	if (!dev)
-		return IRQ_NONE;
+	B43_WARN_ON(!dev);
 
 	spin_lock(&dev->wl->irq_lock);
 
-	if (b43_status(dev) < B43_STAT_STARTED)
+	if (unlikely(b43_status(dev) < B43_STAT_STARTED)) {
+		/* This can only happen on shared IRQ lines. */
 		goto out;
+	}
 	reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);
 	if (reason == 0xffffffff)	/* shared IRQ */
 		goto out;
 	ret = IRQ_HANDLED;
-	reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);
+	reason &= dev->irq_mask;
 	if (!reason)
 		goto out;
 
@@ -1928,16 +1903,18 @@ static irqreturn_t b43_interrupt_handler(int irq, void *dev_id)
 	    & 0x0001DC00;
 	dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)
 	    & 0x0000DC00;
+/* Unused ring
 	dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)
 	    & 0x0000DC00;
+*/
 
 	b43_interrupt_ack(dev, reason);
 	/* disable all IRQs. They are enabled again in the bottom half. */
-	dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 	/* save the reason code and call our bottom half. */
 	dev->irq_reason = reason;
 	tasklet_schedule(&dev->isr_tasklet);
-      out:
+out:
 	mmiowb();
 	spin_unlock(&dev->wl->irq_lock);
 
@@ -2980,6 +2957,7 @@ static void b43_security_init(struct b43_wldev *dev)
 	b43_clear_keys(dev);
 }
 
+#ifdef CONFIG_B43_HWRNG
 static int b43_rng_read(struct hwrng *rng, u32 *data)
 {
 	struct b43_wl *wl = (struct b43_wl *)rng->priv;
@@ -2995,17 +2973,21 @@ static int b43_rng_read(struct hwrng *rng, u32 *data)
 
 	return (sizeof(u16));
 }
+#endif /* CONFIG_B43_HWRNG */
 
 static void b43_rng_exit(struct b43_wl *wl)
 {
+#ifdef CONFIG_B43_HWRNG
 	if (wl->rng_initialized)
 		hwrng_unregister(&wl->rng);
+#endif /* CONFIG_B43_HWRNG */
 }
 
 static int b43_rng_init(struct b43_wl *wl)
 {
-	int err;
+	int err = 0;
 
+#ifdef CONFIG_B43_HWRNG
 	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
 		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
 	wl->rng.name = wl->rng_name;
@@ -3018,6 +3000,7 @@ static int b43_rng_init(struct b43_wl *wl)
 		b43err(wl, "Failed to register the random "
 		       "number generator (%d)\n", err);
 	}
+#endif /* CONFIG_B43_HWRNG */
 
 	return err;
 }
@@ -3793,7 +3776,7 @@ static void b43_wireless_core_stop(struct b43_wldev *dev)
 	 * setting the status to INITIALIZED, as the interrupt handler
 	 * won't care about IRQs then. */
 	spin_lock_irqsave(&wl->irq_lock, flags);
-	dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0);
 	b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	/* flush */
 	spin_unlock_irqrestore(&wl->irq_lock, flags);
 	b43_synchronize_irq(dev);
@@ -3834,7 +3817,7 @@ static int b43_wireless_core_start(struct b43_wldev *dev)
 
 	/* Start data flow (TX/RX). */
 	b43_mac_enable(dev);
-	b43_interrupt_enable(dev, dev->irq_savedstate);
+	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 
 	/* Start maintainance work */
 	b43_periodic_tasks_setup(dev);
@@ -3997,9 +3980,9 @@ static void setup_struct_wldev_for_init(struct b43_wldev *dev)
 	/* IRQ related flags */
 	dev->irq_reason = 0;
 	memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
-	dev->irq_savedstate = B43_IRQ_MASKTEMPLATE;
+	dev->irq_mask = B43_IRQ_MASKTEMPLATE;
 	if (b43_modparam_verbose < B43_VERBOSITY_DEBUG)
-		dev->irq_savedstate &= ~B43_IRQ_PHY_TXERR;
+		dev->irq_mask &= ~B43_IRQ_PHY_TXERR;
 
 	dev->mac_suspended = 1;
 

+ 0 - 1
drivers/net/wireless/b43/rfkill.c

@@ -139,7 +139,6 @@ void b43_rfkill_init(struct b43_wldev *dev)
 	rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
 	rfk->rfkill->data = dev;
 	rfk->rfkill->toggle_radio = b43_rfkill_soft_toggle;
-	rfk->rfkill->user_claim_unsupported = 1;
 
 	rfk->poll_dev = input_allocate_polled_device();
 	if (!rfk->poll_dev) {

+ 7 - 1
drivers/net/wireless/b43legacy/Kconfig

@@ -3,7 +3,6 @@ config B43LEGACY
 	depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA
 	select SSB
 	select FW_LOADER
-	select HW_RANDOM
 	---help---
 	  b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and
 	  BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the
@@ -51,6 +50,13 @@ config B43LEGACY_RFKILL
 	depends on B43LEGACY && (RFKILL = y || RFKILL = B43LEGACY) && RFKILL_INPUT && (INPUT_POLLDEV = y || INPUT_POLLDEV = B43LEGACY)
 	default y
 
+# This config option automatically enables b43 HW-RNG support,
+# if the HW-RNG core is enabled.
+config B43LEGACY_HWRNG
+	bool
+	depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY)
+	default y
+
 config B43LEGACY_DEBUG
 	bool "Broadcom 43xx-legacy debugging"
 	depends on B43LEGACY

+ 6 - 2
drivers/net/wireless/b43legacy/b43legacy.h

@@ -59,7 +59,8 @@
 #define B43legacy_MMIO_XMITSTAT_1		0x174
 #define B43legacy_MMIO_REV3PLUS_TSF_LOW	0x180 /* core rev >= 3 only */
 #define B43legacy_MMIO_REV3PLUS_TSF_HIGH	0x184 /* core rev >= 3 only */
-
+#define B43legacy_MMIO_TSF_CFP_REP	0x188
+#define B43legacy_MMIO_TSF_CFP_START	0x18C
 /* 32-bit DMA */
 #define B43legacy_MMIO_DMA32_BASE0	0x200
 #define B43legacy_MMIO_DMA32_BASE1	0x220
@@ -258,7 +259,6 @@
 
 #define B43legacy_IRQ_ALL		0xFFFFFFFF
 #define B43legacy_IRQ_MASKTEMPLATE	(B43legacy_IRQ_MAC_SUSPENDED |	\
-					 B43legacy_IRQ_BEACON |		\
 					 B43legacy_IRQ_TBTT_INDI |	\
 					 B43legacy_IRQ_ATIM_END |	\
 					 B43legacy_IRQ_PMQ |		\
@@ -596,9 +596,11 @@ struct b43legacy_wl {
 	/* Stats about the wireless interface */
 	struct ieee80211_low_level_stats ieee_stats;
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 	struct hwrng rng;
 	u8 rng_initialized;
 	char rng_name[30 + 1];
+#endif
 
 	/* The RF-kill button */
 	struct b43legacy_rfkill rfkill;
@@ -614,6 +616,8 @@ struct b43legacy_wl {
 	struct sk_buff *current_beacon;
 	bool beacon0_uploaded;
 	bool beacon1_uploaded;
+	bool beacon_templates_virgin; /* Never wrote the templates? */
+	struct work_struct beacon_update_trigger;
 };
 
 /* Pointers to the firmware data and meta information about it. */

+ 150 - 43
drivers/net/wireless/b43legacy/main.c

@@ -955,23 +955,54 @@ static void b43legacy_write_template_common(struct b43legacy_wldev *dev,
 			      size + sizeof(struct b43legacy_plcp_hdr6));
 }
 
+/* Convert a b43legacy antenna number value to the PHY TX control value. */
+static u16 b43legacy_antenna_to_phyctl(int antenna)
+{
+	switch (antenna) {
+	case B43legacy_ANTENNA0:
+		return B43legacy_TX4_PHY_ANT0;
+	case B43legacy_ANTENNA1:
+		return B43legacy_TX4_PHY_ANT1;
+	}
+	return B43legacy_TX4_PHY_ANTLAST;
+}
+
 static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
 					    u16 ram_offset,
-					    u16 shm_size_offset, u8 rate)
+					    u16 shm_size_offset)
 {
 
 	unsigned int i, len, variable_len;
 	const struct ieee80211_mgmt *bcn;
 	const u8 *ie;
 	bool tim_found = 0;
+	unsigned int rate;
+	u16 ctl;
+	int antenna;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
 
 	bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
 	len = min((size_t)dev->wl->current_beacon->len,
 		  0x200 - sizeof(struct b43legacy_plcp_hdr6));
+	rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
 
 	b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset,
 					shm_size_offset, rate);
 
+	/* Write the PHY TX control parameters. */
+	antenna = B43legacy_ANTENNA_DEFAULT;
+	antenna = b43legacy_antenna_to_phyctl(antenna);
+	ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+				   B43legacy_SHM_SH_BEACPHYCTL);
+	/* We can't send beacons with short preamble. Would get PHY errors. */
+	ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL;
+	ctl &= ~B43legacy_TX4_PHY_ANT;
+	ctl &= ~B43legacy_TX4_PHY_ENC;
+	ctl |= antenna;
+	ctl |= B43legacy_TX4_PHY_ENC_CCK;
+	b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+			      B43legacy_SHM_SH_BEACPHYCTL, ctl);
+
 	/* Find the position of the TIM and the DTIM_period value
 	 * and write them to SHM. */
 	ie = bcn->u.beacon.variable;
@@ -1013,7 +1044,8 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
 		b43legacywarn(dev->wl, "Did not find a valid TIM IE in the "
 			      "beacon template packet. AP or IBSS operation "
 			      "may be broken.\n");
-	}
+	} else
+		b43legacydbg(dev->wl, "Updated beacon template\n");
 }
 
 static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
@@ -1025,7 +1057,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
 	__le16 dur;
 
 	plcp.data = 0;
-	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->bitrate);
+	b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
 	dur = ieee80211_generic_frame_duration(dev->wl->hw,
 					       dev->wl->vif,
 					       size,
@@ -1129,10 +1161,104 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
 		   0x200 - sizeof(struct b43legacy_plcp_hdr6));
 	b43legacy_write_template_common(dev, probe_resp_data,
 					size, ram_offset,
-					shm_size_offset, rate->bitrate);
+					shm_size_offset, rate->hw_value);
 	kfree(probe_resp_data);
 }
 
+static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon0_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x68, 0x18);
+	/* FIXME: Probe resp upload doesn't really belong here,
+	 *        but we don't use that feature anyway. */
+	b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
+				      &__b43legacy_ratetable[3]);
+	wl->beacon0_uploaded = 1;
+}
+
+static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+
+	if (wl->beacon1_uploaded)
+		return;
+	b43legacy_write_beacon_template(dev, 0x468, 0x1A);
+	wl->beacon1_uploaded = 1;
+}
+
+static void handle_irq_beacon(struct b43legacy_wldev *dev)
+{
+	struct b43legacy_wl *wl = dev->wl;
+	u32 cmd, beacon0_valid, beacon1_valid;
+
+	if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
+		return;
+
+	/* This is the bottom half of the asynchronous beacon update. */
+
+	/* Ignore interrupt in the future. */
+	dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
+
+	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+	beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
+	beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID);
+
+	/* Schedule interrupt manually, if busy. */
+	if (beacon0_valid && beacon1_valid) {
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
+		dev->irq_savedstate |= B43legacy_IRQ_BEACON;
+		return;
+	}
+
+	if (unlikely(wl->beacon_templates_virgin)) {
+		/* We never uploaded a beacon before.
+		 * Upload both templates now, but only mark one valid. */
+		wl->beacon_templates_virgin = 0;
+		b43legacy_upload_beacon0(dev);
+		b43legacy_upload_beacon1(dev);
+		cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+		cmd |= B43legacy_MACCMD_BEACON0_VALID;
+		b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+	} else {
+		if (!beacon0_valid) {
+			b43legacy_upload_beacon0(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON0_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		} else if (!beacon1_valid) {
+			b43legacy_upload_beacon1(dev);
+			cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
+			cmd |= B43legacy_MACCMD_BEACON1_VALID;
+			b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+		}
+	}
+}
+
+static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
+{
+	struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+					 beacon_update_trigger);
+	struct b43legacy_wldev *dev;
+
+	mutex_lock(&wl->mutex);
+	dev = wl->current_dev;
+	if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
+		spin_lock_irq(&wl->irq_lock);
+		/* update beacon right away or defer to irq */
+		dev->irq_savedstate = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
+		handle_irq_beacon(dev);
+		/* The handler might have updated the IRQ mask. */
+		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
+			    dev->irq_savedstate);
+		mmiowb();
+		spin_unlock_irq(&wl->irq_lock);
+	}
+	mutex_unlock(&wl->mutex);
+}
+
 /* Asynchronously update the packet templates in template RAM.
  * Locking: Requires wl->irq_lock to be locked. */
 static void b43legacy_update_templates(struct b43legacy_wl *wl)
@@ -1156,54 +1282,24 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
 	wl->current_beacon = beacon;
 	wl->beacon0_uploaded = 0;
 	wl->beacon1_uploaded = 0;
+	queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
 }
 
 static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
 				     u16 beacon_int)
 {
 	b43legacy_time_lock(dev);
-	if (dev->dev->id.revision >= 3)
-		b43legacy_write32(dev, 0x188, (beacon_int << 16));
-	else {
+	if (dev->dev->id.revision >= 3) {
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP,
+				 (beacon_int << 16));
+		b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START,
+				 (beacon_int << 10));
+	} else {
 		b43legacy_write16(dev, 0x606, (beacon_int >> 6));
 		b43legacy_write16(dev, 0x610, beacon_int);
 	}
 	b43legacy_time_unlock(dev);
-}
-
-static void handle_irq_beacon(struct b43legacy_wldev *dev)
-{
-	struct b43legacy_wl *wl = dev->wl;
-	u32 cmd;
-
-	if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP))
-		return;
-
-	/* This is the bottom half of the asynchronous beacon update. */
-
-	cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
-	if (!(cmd & B43legacy_MACCMD_BEACON0_VALID)) {
-		if (!wl->beacon0_uploaded) {
-			b43legacy_write_beacon_template(dev, 0x68,
-							B43legacy_SHM_SH_BTL0,
-							B43legacy_CCK_RATE_1MB);
-			b43legacy_write_probe_resp_template(dev, 0x268,
-							    B43legacy_SHM_SH_PRTLEN,
-							    &__b43legacy_ratetable[3]);
-			wl->beacon0_uploaded = 1;
-		}
-		cmd |= B43legacy_MACCMD_BEACON0_VALID;
-	}
-	if (!(cmd & B43legacy_MACCMD_BEACON1_VALID)) {
-		if (!wl->beacon1_uploaded) {
-			b43legacy_write_beacon_template(dev, 0x468,
-							B43legacy_SHM_SH_BTL1,
-							B43legacy_CCK_RATE_1MB);
-			wl->beacon1_uploaded = 1;
-		}
-		cmd |= B43legacy_MACCMD_BEACON1_VALID;
-	}
-	b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd);
+	b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int);
 }
 
 static void handle_irq_ucode_debug(struct b43legacy_wldev *dev)
@@ -2297,6 +2393,7 @@ static void b43legacy_security_init(struct b43legacy_wldev *dev)
 				  dev->max_nr_keys - 8);
 }
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
 {
 	struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv;
@@ -2312,17 +2409,21 @@ static int b43legacy_rng_read(struct hwrng *rng, u32 *data)
 
 	return (sizeof(u16));
 }
+#endif
 
 static void b43legacy_rng_exit(struct b43legacy_wl *wl)
 {
+#ifdef CONFIG_B43LEGACY_HWRNG
 	if (wl->rng_initialized)
 		hwrng_unregister(&wl->rng);
+#endif
 }
 
 static int b43legacy_rng_init(struct b43legacy_wl *wl)
 {
-	int err;
+	int err = 0;
 
+#ifdef CONFIG_B43LEGACY_HWRNG
 	snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name),
 		 "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy));
 	wl->rng.name = wl->rng_name;
@@ -2336,6 +2437,7 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
 		       "number generator (%d)\n", err);
 	}
 
+#endif
 	return err;
 }
 
@@ -3392,6 +3494,9 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
 	memset(wl->bssid, 0, ETH_ALEN);
 	memset(wl->mac_addr, 0, ETH_ALEN);
 	wl->filter_flags = 0;
+	wl->beacon0_uploaded = 0;
+	wl->beacon1_uploaded = 0;
+	wl->beacon_templates_virgin = 1;
 
 	mutex_lock(&wl->mutex);
 
@@ -3429,6 +3534,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
 	struct b43legacy_wldev *dev = wl->current_dev;
 
 	b43legacy_rfkill_exit(dev);
+	cancel_work_sync(&(wl->beacon_update_trigger));
 
 	mutex_lock(&wl->mutex);
 	if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
@@ -3760,6 +3866,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
 	spin_lock_init(&wl->leds_lock);
 	mutex_init(&wl->mutex);
 	INIT_LIST_HEAD(&wl->devlist);
+	INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
 
 	ssb_set_devtypedata(dev, wl);
 	b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);

+ 0 - 1
drivers/net/wireless/b43legacy/rfkill.c

@@ -142,7 +142,6 @@ void b43legacy_rfkill_init(struct b43legacy_wldev *dev)
 	rfk->rfkill->state = RFKILL_STATE_UNBLOCKED;
 	rfk->rfkill->data = dev;
 	rfk->rfkill->toggle_radio = b43legacy_rfkill_soft_toggle;
-	rfk->rfkill->user_claim_unsupported = 1;
 
 	rfk->poll_dev = input_allocate_polled_device();
 	if (!rfk->poll_dev) {

+ 1 - 1
drivers/net/wireless/b43legacy/xmit.c

@@ -274,7 +274,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
 
 	/* PHY TX Control word */
 	if (rate_ofdm)
-		phy_ctl |= B43legacy_TX4_PHY_OFDM;
+		phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM;
 	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
 		phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
 	switch (info->antenna_sel_tx) {

+ 3 - 1
drivers/net/wireless/b43legacy/xmit.h

@@ -67,7 +67,9 @@ struct b43legacy_txhdr_fw3 {
 #define B43legacy_TX4_EFT_RTSFBOFDM	0x0010 /* RTS/CTS fallback rate type */
 
 /* PHY TX control word */
-#define B43legacy_TX4_PHY_OFDM		0x0001 /* Data frame rate type */
+#define B43legacy_TX4_PHY_ENC		0x0003 /* Data frame encoding */
+#define B43legacy_TX4_PHY_ENC_CCK	0x0000 /* CCK */
+#define B43legacy_TX4_PHY_ENC_OFDM	0x0001 /* Data frame rate type */
 #define B43legacy_TX4_PHY_SHORTPRMBL	0x0010 /* Use short preamble */
 #define B43legacy_TX4_PHY_ANT		0x03C0 /* Antenna selection */
 #define  B43legacy_TX4_PHY_ANT0		0x0000 /* Use antenna 0 */

+ 1 - 1
drivers/net/wireless/hostap/hostap_plx.c

@@ -435,7 +435,7 @@ static int prism2_plx_probe(struct pci_dev *pdev,
 	unsigned long pccard_attr_mem;
 	unsigned int pccard_attr_len;
 	void __iomem *attr_mem = NULL;
-	unsigned int cor_offset, cor_index;
+	unsigned int cor_offset = 0, cor_index = 0;
 	u32 reg;
 	local_info_t *local = NULL;
 	struct net_device *dev = NULL;

+ 1 - 1
drivers/net/wireless/iwlwifi/iwl-3945-rs.c

@@ -719,7 +719,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pm\n",
 				       hdr->addr1);
 			sta_id = iwl3945_add_station(priv,
-				    hdr->addr1, 0, CMD_ASYNC);
+				    hdr->addr1, 0, CMD_ASYNC, NULL);
 		}
 		if (sta_id != IWL_INVALID_STATION)
 			rs_sta->ibss_sta_added = 1;

+ 206 - 0
drivers/net/wireless/iwlwifi/iwl-3945.c

@@ -1964,6 +1964,194 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
 	return 0;
 }
 
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
+{
+	int rc = 0;
+	struct iwl_rx_packet *res = NULL;
+	struct iwl3945_rxon_assoc_cmd rxon_assoc;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_RXON_ASSOC,
+		.len = sizeof(rxon_assoc),
+		.meta.flags = CMD_WANT_SKB,
+		.data = &rxon_assoc,
+	};
+	const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon;
+	const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon;
+
+	if ((rxon1->flags == rxon2->flags) &&
+	    (rxon1->filter_flags == rxon2->filter_flags) &&
+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
+		return 0;
+	}
+
+	rxon_assoc.flags = priv->staging_rxon.flags;
+	rxon_assoc.filter_flags = priv->staging_rxon.filter_flags;
+	rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+
+	rc = iwl_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	priv->alloc_rxb_skb--;
+	dev_kfree_skb_any(cmd.meta.u.skb);
+
+	return rc;
+}
+
+/**
+ * iwl3945_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed to the hardware and
+ * the active_rxon structure is updated with the new data.  This
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+static int iwl3945_commit_rxon(struct iwl_priv *priv)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
+	struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon;
+	int rc = 0;
+	bool new_assoc =
+		!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_is_alive(priv))
+		return -1;
+
+	/* always get timestamp with Rx frame */
+	staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK;
+
+	/* select antenna */
+	staging_rxon->flags &=
+	    ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK);
+	staging_rxon->flags |= iwl3945_get_antenna_flags(priv);
+
+	rc = iwl_check_rxon_cmd(priv);
+	if (rc) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl3945_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_full_rxon_required(priv)) {
+		rc = iwl_send_rxon_assoc(priv);
+		if (rc) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+
+		memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_is_associated(priv) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		/*
+		 * reserved4 and 5 could have been filled by the iwlcore code.
+		 * Let's clear them before pushing to the 3945.
+		 */
+		active_rxon->reserved4 = 0;
+		active_rxon->reserved5 = 0;
+		rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+				      sizeof(struct iwl3945_rxon_cmd),
+				      &priv->active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (rc) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK on current "
+				  "configuration (%d).\n", rc);
+			return rc;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(staging_rxon->channel),
+		       staging_rxon->bssid_addr);
+
+	/*
+	 * reserved4 and 5 could have been filled by the iwlcore code.
+	 * Let's clear them before pushing to the 3945.
+	 */
+	staging_rxon->reserved4 = 0;
+	staging_rxon->reserved5 = 0;
+
+	iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+
+	/* Apply the new configuration */
+	rc = iwl_send_cmd_pdu(priv, REPLY_RXON,
+			      sizeof(struct iwl3945_rxon_cmd),
+			      staging_rxon);
+	if (rc) {
+		IWL_ERR(priv, "Error setting new configuration (%d).\n", rc);
+		return rc;
+	}
+
+	memcpy(active_rxon, staging_rxon, sizeof(*active_rxon));
+
+	priv->cfg->ops->smgmt->clear_station_table(priv);
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	rc = priv->cfg->ops->lib->send_tx_power(priv);
+	if (rc) {
+		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
+		return rc;
+	}
+
+	/* Add the broadcast address so we can send broadcast frames */
+	if (priv->cfg->ops->smgmt->add_station(priv, iwl_bcast_addr, 0, 0, NULL) ==
+	    IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n");
+		return -EIO;
+	}
+
+	/* If we have set the ASSOC_MSK and we are in BSS mode then
+	 * add the IWL_AP_ID to the station rate table */
+	if (iwl_is_associated(priv) &&
+	    (priv->iw_mode == NL80211_IFTYPE_STATION))
+		if (priv->cfg->ops->smgmt->add_station(priv,
+					priv->active_rxon.bssid_addr, 1, 0, NULL)
+		    == IWL_INVALID_STATION) {
+			IWL_ERR(priv, "Error adding AP address for transmit\n");
+			return -EIO;
+		}
+
+	/* Init the hardware's rate fallback order based on the band */
+	rc = iwl3945_init_hw_rate_table(priv);
+	if (rc) {
+		IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 /* will add 3945 channel switch cmd handling later */
 int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 {
@@ -2729,6 +2917,11 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
 	return 0;
 }
 
+static struct iwl_hcmd_ops iwl3945_hcmd = {
+	.rxon_assoc = iwl3945_send_rxon_assoc,
+	.commit_rxon = iwl3945_commit_rxon,
+};
+
 static struct iwl_lib_ops iwl3945_lib = {
 	.txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd,
 	.txq_free_tfd = iwl3945_hw_txq_free_tfd,
@@ -2758,6 +2951,17 @@ static struct iwl_lib_ops iwl3945_lib = {
 	},
 	.send_tx_power	= iwl3945_send_tx_power,
 	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
+	.post_associate = iwl3945_post_associate,
+	.config_ap = iwl3945_config_ap,
+};
+
+static struct iwl_station_mgmt_ops iwl3945_station_mgmt = {
+	.add_station = iwl3945_add_station,
+#if 0
+	.remove_station = iwl3945_remove_station,
+#endif
+	.find_station = iwl3945_hw_find_station,
+	.clear_station_table = iwl3945_clear_stations_table,
 };
 
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
@@ -2767,7 +2971,9 @@ static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 
 static struct iwl_ops iwl3945_ops = {
 	.lib = &iwl3945_lib,
+	.hcmd = &iwl3945_hcmd,
 	.utils = &iwl3945_hcmd_utils,
+	.smgmt = &iwl3945_station_mgmt,
 };
 
 static struct iwl_cfg iwl3945_bg_cfg = {

+ 4 - 2
drivers/net/wireless/iwlwifi/iwl-3945.h

@@ -162,7 +162,6 @@ struct iwl3945_frame {
 #define STATUS_TEMPERATURE	8
 #define STATUS_GEO_CONFIGURED	9
 #define STATUS_EXIT_PENDING	10
-#define STATUS_IN_SUSPEND	11
 #define STATUS_STATISTICS	12
 #define STATUS_SCANNING		13
 #define STATUS_SCAN_ABORTING	14
@@ -207,7 +206,8 @@ struct iwl3945_addsta_cmd;
 extern int iwl3945_send_add_station(struct iwl_priv *priv,
 				struct iwl3945_addsta_cmd *sta, u8 flags);
 extern u8 iwl3945_add_station(struct iwl_priv *priv, const u8 *bssid,
-			  int is_ap, u8 flags);
+			  int is_ap, u8 flags, struct ieee80211_sta_ht_cap *ht_info);
+extern void iwl3945_clear_stations_table(struct iwl_priv *priv);
 extern int iwl3945_power_init_handle(struct iwl_priv *priv);
 extern int iwl3945_eeprom_init(struct iwl_priv *priv);
 extern int iwl3945_calc_db_from_ratio(int sig_ratio);
@@ -278,6 +278,8 @@ extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 				 struct iwl_rx_mem_buffer *rxb);
 extern void iwl3945_disable_events(struct iwl_priv *priv);
 extern int iwl4965_get_temperature(const struct iwl_priv *priv);
+extern void iwl3945_post_associate(struct iwl_priv *priv);
+extern void iwl3945_config_ap(struct iwl_priv *priv);
 
 /**
  * iwl3945_hw_find_station - Find station id for a given BSSID

+ 11 - 2
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -2268,9 +2268,17 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
 	cancel_work_sync(&priv->txpower_work);
 }
 
+static struct iwl_station_mgmt_ops iwl4965_station_mgmt = {
+	.add_station = iwl_add_station_flags,
+	.remove_station = iwl_remove_station,
+	.find_station = iwl_find_station,
+	.clear_station_table = iwl_clear_stations_table,
+};
 
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 	.rxon_assoc = iwl4965_send_rxon_assoc,
+	.commit_rxon = iwl_commit_rxon,
+	.set_rxon_chain = iwl_set_rxon_chain,
 };
 
 static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
@@ -2324,12 +2332,15 @@ static struct iwl_lib_ops iwl4965_lib = {
 	.send_tx_power	= iwl4965_send_tx_power,
 	.update_chain_flags = iwl_update_chain_flags,
 	.temperature = iwl4965_temperature_calib,
+	.post_associate = iwl_post_associate,
+	.config_ap = iwl_config_ap,
 };
 
 static struct iwl_ops iwl4965_ops = {
 	.lib = &iwl4965_lib,
 	.hcmd = &iwl4965_hcmd,
 	.utils = &iwl4965_hcmd_utils,
+	.smgmt = &iwl4965_station_mgmt,
 };
 
 struct iwl_cfg iwl4965_agn_cfg = {
@@ -2350,8 +2361,6 @@ MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
 
 module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
 module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
 MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
 module_param_named(debug, iwl4965_mod_params.debug, uint, 0444);

+ 13 - 4
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -678,7 +678,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
 		goto restart;
 	}
 
-	iwl_clear_stations_table(priv);
+	priv->cfg->ops->smgmt->clear_station_table(priv);
 	ret = priv->cfg->ops->lib->alive_notify(priv);
 	if (ret) {
 		IWL_WARN(priv,
@@ -1472,8 +1472,17 @@ int iwl5000_calc_rssi(struct iwl_priv *priv,
 	return max_rssi - agc - IWL49_RSSI_OFFSET;
 }
 
+struct iwl_station_mgmt_ops iwl5000_station_mgmt = {
+	.add_station = iwl_add_station_flags,
+	.remove_station = iwl_remove_station,
+	.find_station = iwl_find_station,
+	.clear_station_table = iwl_clear_stations_table,
+};
+
 struct iwl_hcmd_ops iwl5000_hcmd = {
 	.rxon_assoc = iwl5000_send_rxon_assoc,
+	.commit_rxon = iwl_commit_rxon,
+	.set_rxon_chain = iwl_set_rxon_chain,
 };
 
 struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
@@ -1527,12 +1536,15 @@ struct iwl_lib_ops iwl5000_lib = {
 		.calib_version	= iwl5000_eeprom_calib_version,
 		.query_addr = iwl5000_eeprom_query_addr,
 	},
+	.post_associate = iwl_post_associate,
+	.config_ap = iwl_config_ap,
 };
 
 struct iwl_ops iwl5000_ops = {
 	.lib = &iwl5000_lib,
 	.hcmd = &iwl5000_hcmd,
 	.utils = &iwl5000_hcmd_utils,
+	.smgmt = &iwl5000_station_mgmt,
 };
 
 struct iwl_mod_params iwl50_mod_params = {
@@ -1643,9 +1655,6 @@ struct iwl_cfg iwl5150_agn_cfg = {
 MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
 
-module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
-MODULE_PARM_DESC(disable50,
-		  "manually disable the 50XX radio (default 0 [radio on])");
 module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
 MODULE_PARM_DESC(swcrypto50,
 		  "using software crypto engine (default 0 [hardware])\n");

+ 1 - 0
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -72,6 +72,7 @@ static struct iwl_ops iwl6000_ops = {
 	.lib = &iwl5000_lib,
 	.hcmd = &iwl5000_hcmd,
 	.utils = &iwl6000_hcmd_utils,
+	.smgmt = &iwl5000_station_mgmt,
 };
 
 struct iwl_cfg iwl6000_2ag_cfg = {

+ 360 - 50
drivers/net/wireless/iwlwifi/iwl-agn-rs.c

@@ -52,7 +52,7 @@
 /* max allowed rate miss before sync LQ cmd */
 #define IWL_MISSED_RATE_MAX		15
 /* max time to accum history 2 seconds */
-#define IWL_RATE_SCALE_FLUSH_INTVL   (2*HZ)
+#define IWL_RATE_SCALE_FLUSH_INTVL   (3*HZ)
 
 static u8 rs_ht_to_legacy[] = {
 	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
@@ -135,7 +135,7 @@ struct iwl_lq_sta {
 	u32 table_count;
 	u32 total_failed;	/* total failed frames, any/all rates */
 	u32 total_success;	/* total successful frames, any/all rates */
-	u32 flush_timer;	/* time staying in mode before new search */
+	u64 flush_timer;	/* time staying in mode before new search */
 
 	u8 action_counter;	/* # mode-switch actions tried */
 	u8 is_green;
@@ -167,6 +167,8 @@ struct iwl_lq_sta {
 
 	/* used to be in sta_info */
 	int last_txrate_idx;
+	/* last tx rate_n_flags */
+	u32 last_rate_n_flags;
 };
 
 static void rs_rate_scale_perform(struct iwl_priv *priv,
@@ -191,7 +193,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
  * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
  * "G" is the only table that supports CCK (the first 4 rates).
  */
-/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/
+
 static s32 expected_tpt_A[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
 };
@@ -208,11 +210,11 @@ static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211
 };
 
-static s32 expected_tpt_mimo20MHz[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251
 };
 
-static s32 expected_tpt_mimo20MHzSGI[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257
 };
 
@@ -224,14 +226,48 @@ static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264
 };
 
-static s32 expected_tpt_mimo40MHz[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289
 };
 
-static s32 expected_tpt_mimo40MHzSGI[IWL_RATE_COUNT] = {
+static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = {
 	0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293
 };
 
+/* Expected throughput metric MIMO3 */
+static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268
+};
+
+static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273
+};
+
+static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297
+};
+
+static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = {
+	0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300
+};
+
+/* mbps, mcs */
+const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+  {"1", ""},
+  {"2", ""},
+  {"5.5", ""},
+  {"11", ""},
+  {"6", "BPSK 1/2"},
+  {"9", "BPSK 1/2"},
+  {"12", "QPSK 1/2"},
+  {"18", "QPSK 3/4"},
+  {"24", "16QAM 1/2"},
+  {"36", "16QAM 3/4"},
+  {"48", "64QAM 2/3"},
+  {"54", "64QAM 3/4"},
+  {"60", "64QAM 5/6"}
+};
+
 static inline u8 rs_extract_rate(u32 rate_n_flags)
 {
 	return (u8)(rate_n_flags & 0xFF);
@@ -902,6 +938,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
 	 * else look up the rate that was, finally, successful.
 	 */
 	tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags);
+	lq_sta->last_rate_n_flags = tx_rate;
 	rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index);
 
 	/* Update frame history window with "success" if Tx got ACKed ... */
@@ -988,6 +1025,7 @@ static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
 	lq_sta->table_count = 0;
 	lq_sta->total_failed = 0;
 	lq_sta->total_success = 0;
+	lq_sta->flush_timer = jiffies;
 }
 
 /*
@@ -1011,17 +1049,26 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
 			tbl->expected_tpt = expected_tpt_siso20MHzSGI;
 		else
 			tbl->expected_tpt = expected_tpt_siso20MHz;
-
-	} else if (is_mimo(tbl->lq_type)) { /* FIXME:need to separate mimo2/3 */
+	} else if (is_mimo2(tbl->lq_type)) {
+		if (tbl->is_fat && !lq_sta->is_dup)
+			if (tbl->is_SGI)
+				tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI;
+			else
+				tbl->expected_tpt = expected_tpt_mimo2_40MHz;
+		else if (tbl->is_SGI)
+			tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI;
+		else
+			tbl->expected_tpt = expected_tpt_mimo2_20MHz;
+	} else if (is_mimo3(tbl->lq_type)) {
 		if (tbl->is_fat && !lq_sta->is_dup)
 			if (tbl->is_SGI)
-				tbl->expected_tpt = expected_tpt_mimo40MHzSGI;
+				tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI;
 			else
-				tbl->expected_tpt = expected_tpt_mimo40MHz;
+				tbl->expected_tpt = expected_tpt_mimo3_40MHz;
 		else if (tbl->is_SGI)
-			tbl->expected_tpt = expected_tpt_mimo20MHzSGI;
+			tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI;
 		else
-			tbl->expected_tpt = expected_tpt_mimo20MHz;
+			tbl->expected_tpt = expected_tpt_mimo3_20MHz;
 	} else
 		tbl->expected_tpt = expected_tpt_G;
 }
@@ -1130,7 +1177,7 @@ static s32 rs_get_best_rate(struct iwl_priv *priv,
 }
 
 /*
- * Set up search table for MIMO
+ * Set up search table for MIMO2
  */
 static int rs_switch_to_mimo2(struct iwl_priv *priv,
 			     struct iwl_lq_sta *lq_sta,
@@ -1183,7 +1230,73 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
 	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
 
 	IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask);
+	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
+		IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
+						rate, rate_mask);
+		return -1;
+	}
+	tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green);
+
+	IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n",
+		     tbl->current_rate, is_green);
+	return 0;
+}
+
+/*
+ * Set up search table for MIMO3
+ */
+static int rs_switch_to_mimo3(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_scale_tbl_info *tbl, int index)
+{
+	u16 rate_mask;
+	s32 rate;
+	s8 is_green = lq_sta->is_green;
+
+	if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+		return -1;
+
+	if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+						== WLAN_HT_CAP_SM_PS_STATIC)
+		return -1;
+
+	/* Need both Tx chains/antennas to support MIMO */
+	if (priv->hw_params.tx_chains_num < 3)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n");
+
+	tbl->lq_type = LQ_MIMO3;
+	tbl->is_dup = lq_sta->is_dup;
+	tbl->action = 0;
+	rate_mask = lq_sta->active_mimo3_rate;
+
+	if (priv->current_ht_config.supported_chan_width
+					== IWL_CHANNEL_WIDTH_40MHZ)
+		tbl->is_fat = 1;
+	else
+		tbl->is_fat = 0;
+
+	/* FIXME: - don't toggle SGI here
+	if (tbl->is_fat) {
+		if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY)
+			tbl->is_SGI = 1;
+		else
+			tbl->is_SGI = 0;
+	} else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY)
+		tbl->is_SGI = 1;
+	else
+		tbl->is_SGI = 0;
+	*/
+
+	rs_set_expected_tpt_table(lq_sta, tbl);
+
+	rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
 
+	IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n",
+		rate, rate_mask);
 	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
 		IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n",
 						rate, rate_mask);
@@ -1342,9 +1455,29 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
 				goto out;
 			}
 			break;
+
+		case IWL_LEGACY_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n");
+
+			/* Set up search table to try MIMO3 */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret) {
+				lq_sta->action_counter = 0;
+				goto out;
+			}
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+		if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1357,7 +1490,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
 out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_LEGACY_SWITCH_MIMO2_BC)
+	if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
 	return 0;
 
@@ -1457,9 +1590,23 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
 				rate_n_flags_from_tbl(priv, search_tbl,
 						      index, is_green);
 			goto out;
+		case IWL_SISO_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_SISO_SWITCH_GI)
+		if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_SISO_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1471,15 +1618,15 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
  out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_SISO_SWITCH_GI)
+	if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_SISO_SWITCH_ANTENNA1;
 	return 0;
 }
 
 /*
- * Try to switch to new modulation mode from MIMO
+ * Try to switch to new modulation mode from MIMO2
  */
-static int rs_move_mimo_to_other(struct iwl_priv *priv,
+static int rs_move_mimo2_to_other(struct iwl_priv *priv,
 				 struct iwl_lq_sta *lq_sta,
 				 struct ieee80211_conf *conf,
 				 struct ieee80211_sta *sta, int index)
@@ -1501,7 +1648,7 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
 		switch (tbl->action) {
 		case IWL_MIMO2_SWITCH_ANTENNA1:
 		case IWL_MIMO2_SWITCH_ANTENNA2:
-			IWL_DEBUG_RATE(priv, "LQ: MIMO toggle Antennas\n");
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
 
 			if (tx_chains_num <= 2)
 				break;
@@ -1549,9 +1696,9 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
 						HT_SHORT_GI_40MHZ))
 				break;
 
-			IWL_DEBUG_RATE(priv, "LQ: MIMO toggle SGI/NGI\n");
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
 
-			/* Set up new search table for MIMO */
+			/* Set up new search table for MIMO2 */
 			memcpy(search_tbl, tbl, sz);
 			search_tbl->is_SGI = !tbl->is_SGI;
 			rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1571,9 +1718,24 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
 						      index, is_green);
 			goto out;
 
+		case IWL_MIMO2_SWITCH_MIMO3_ABC:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			search_tbl->ant_type = ANT_ABC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
 		}
 		tbl->action++;
-		if (tbl->action > IWL_MIMO2_SWITCH_GI)
+		if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
 			tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
 
 		if (tbl->action == start_action)
@@ -1584,12 +1746,149 @@ static int rs_move_mimo_to_other(struct iwl_priv *priv,
  out:
 	lq_sta->search_better_tbl = 1;
 	tbl->action++;
-	if (tbl->action > IWL_MIMO2_SWITCH_GI)
+	if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC)
 		tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
 	return 0;
 
 }
 
+/*
+ * Try to switch to new modulation mode from MIMO3
+ */
+static int rs_move_mimo3_to_other(struct iwl_priv *priv,
+				 struct iwl_lq_sta *lq_sta,
+				 struct ieee80211_conf *conf,
+				 struct ieee80211_sta *sta, int index)
+{
+	s8 is_green = lq_sta->is_green;
+	struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	struct iwl_scale_tbl_info *search_tbl =
+				&(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+	struct iwl_rate_scale_data *window = &(tbl->win[index]);
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_action = tbl->action;
+	u8 valid_tx_ant = priv->hw_params.valid_tx_ant;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+	int ret;
+
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_MIMO3_SWITCH_ANTENNA1:
+		case IWL_MIMO3_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n");
+
+			if (tx_chains_num <= 3)
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (rs_toggle_antenna(valid_tx_ant,
+				       &search_tbl->current_rate, search_tbl))
+				goto out;
+			break;
+		case IWL_MIMO3_SWITCH_SISO_A:
+		case IWL_MIMO3_SWITCH_SISO_B:
+		case IWL_MIMO3_SWITCH_SISO_C:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n");
+
+			/* Set up new search table for SISO */
+			memcpy(search_tbl, tbl, sz);
+
+			if (tbl->action == IWL_MIMO3_SWITCH_SISO_A)
+				search_tbl->ant_type = ANT_A;
+			else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B)
+				search_tbl->ant_type = ANT_B;
+			else
+				search_tbl->ant_type = ANT_C;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_siso(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO3_SWITCH_MIMO2_AB:
+		case IWL_MIMO3_SWITCH_MIMO2_AC:
+		case IWL_MIMO3_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n");
+
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type))
+				break;
+
+			ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO3_SWITCH_GI:
+			if (!tbl->is_fat &&
+				!(priv->current_ht_config.sgf &
+						HT_SHORT_GI_20MHZ))
+				break;
+			if (tbl->is_fat &&
+				!(priv->current_ht_config.sgf &
+						HT_SHORT_GI_40MHZ))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n");
+
+			/* Set up new search table for MIMO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = !tbl->is_SGI;
+			rs_set_expected_tpt_table(lq_sta, search_tbl);
+			/*
+			 * If active table already uses the fastest possible
+			 * modulation (dual stream with short guard interval),
+			 * and it's working well, there's no need to look
+			 * for a better type of modulation!
+			 */
+			if (tbl->is_SGI) {
+				s32 tpt = lq_sta->last_tpt / 100;
+				if (tpt >= search_tbl->expected_tpt[index])
+					break;
+			}
+			search_tbl->current_rate =
+				rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			goto out;
+		}
+		tbl->action++;
+		if (tbl->action > IWL_MIMO3_SWITCH_GI)
+			tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
+
+		if (tbl->action == start_action)
+			break;
+	}
+	search_tbl->lq_type = LQ_NONE;
+	return 0;
+ out:
+	lq_sta->search_better_tbl = 1;
+	tbl->action++;
+	if (tbl->action > IWL_MIMO3_SWITCH_GI)
+		tbl->action = IWL_MIMO3_SWITCH_ANTENNA1;
+	return 0;
+
+}
+
 /*
  * Check whether we should continue using same modulation mode, or
  * begin search for a new mode, based on:
@@ -1616,8 +1915,8 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta)
 		/* Elapsed time using current modulation mode */
 		if (lq_sta->flush_timer)
 			flush_interval_passed =
-			    time_after(jiffies,
-				       (unsigned long)(lq_sta->flush_timer +
+			time_after(jiffies,
+					(unsigned long)(lq_sta->flush_timer +
 					IWL_RATE_SCALE_FLUSH_INTVL));
 
 		/*
@@ -1951,6 +2250,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 			update_lq = 1;
 			index = low;
 		}
+
 		break;
 	case 1:
 		/* Increase starting rate, update uCode's rate table */
@@ -1997,8 +2297,10 @@ lq_update:
 			rs_move_legacy_other(priv, lq_sta, conf, sta, index);
 		else if (is_siso(tbl->lq_type))
 			rs_move_siso_to_other(priv, lq_sta, conf, sta, index);
+		else if (is_mimo2(tbl->lq_type))
+			rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index);
 		else
-			rs_move_mimo_to_other(priv, lq_sta, conf, sta, index);
+			rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index);
 
 		/* If new "search" mode was selected, set up in uCode table */
 		if (lq_sta->search_better_tbl) {
@@ -2014,8 +2316,11 @@ lq_update:
 				     tbl->current_rate, index);
 			rs_fill_link_cmd(priv, lq_sta, tbl->current_rate);
 			iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
-		}
+		} else
+			done_search = 1;
+	}
 
+	if (done_search && !lq_sta->stay_in_tbl) {
 		/* If the "active" (non-search) mode was legacy,
 		 * and we've tried switching antennas,
 		 * but we haven't been able to try HT modes (not available),
@@ -2050,17 +2355,6 @@ lq_update:
 			lq_sta->action_counter = 0;
 			rs_set_stay_in_table(priv, 0, lq_sta);
 		}
-
-	/*
-	 * Else, don't search for a new modulation mode.
-	 * Put new timestamp in stay-in-modulation-mode flush timer if:
-	 * 1)  Not changing rates right now
-	 * 2)  Not just finishing up a search
-	 * 3)  flush timer is empty
-	 */
-	} else {
-		if ((!update_lq) && (!done_search) && (!lq_sta->flush_timer))
-			lq_sta->flush_timer = jiffies;
 	}
 
 out:
@@ -2173,13 +2467,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
 
 	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
 	    !lq_sta->ibss_sta_added) {
-		u8 sta_id = iwl_find_station(priv, hdr->addr1);
+		u8 sta_id = priv->cfg->ops->smgmt->find_station(priv,
+						   hdr->addr1);
 
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n",
 				       hdr->addr1);
-			sta_id = iwl_add_station_flags(priv, hdr->addr1,
-							0, CMD_ASYNC, NULL);
+			sta_id = priv->cfg->ops->smgmt->add_station(priv,
+						hdr->addr1, 0,
+						CMD_ASYNC, NULL);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2246,15 +2542,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
 
 	lq_sta->ibss_sta_added = 0;
 	if (priv->iw_mode == NL80211_IFTYPE_AP) {
-		u8 sta_id = iwl_find_station(priv, sta->addr);
+		u8 sta_id = priv->cfg->ops->smgmt->find_station(priv,
+								sta->addr);
 
 		/* for IBSS the call are from tasklet */
 		IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
 
 		if (sta_id == IWL_INVALID_STATION) {
 			IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr);
-			sta_id = iwl_add_station_flags(priv, sta->addr,
-							0, CMD_ASYNC, NULL);
+			sta_id = priv->cfg->ops->smgmt->add_station(priv,
+							sta->addr, 0,
+							CMD_ASYNC, NULL);
 		}
 		if ((sta_id != IWL_INVALID_STATION)) {
 			lq_sta->lq.sta_id = sta_id;
@@ -2539,6 +2837,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 	char *buff;
 	int desc = 0;
 	int i = 0;
+	int index = 0;
 	ssize_t ret;
 
 	struct iwl_lq_sta *lq_sta = file->private_data;
@@ -2570,6 +2869,8 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 		   (tbl->is_fat) ? "40MHz" : "20MHz");
 		desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : "");
 	}
+	desc += sprintf(buff+desc, "last tx rate=0x%X\n",
+		lq_sta->last_rate_n_flags);
 	desc += sprintf(buff+desc, "general:"
 		"flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n",
 		lq_sta->lq.general_params.flags,
@@ -2590,10 +2891,19 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
 			lq_sta->lq.general_params.start_rate_index[2],
 			lq_sta->lq.general_params.start_rate_index[3]);
 
-
-	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
-		desc += sprintf(buff+desc, " rate[%d] 0x%X\n",
-			i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+		index = iwl_hwrate_to_plcp_idx(
+			le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags));
+		if (is_legacy(tbl->lq_type)) {
+			desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n",
+				i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+				iwl_rate_mcs[index].mbps);
+		} else {
+			desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps (%s)\n",
+				i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags),
+				iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs);
+		}
+	}
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
 	kfree(buff);

+ 25 - 0
drivers/net/wireless/iwlwifi/iwl-agn-rs.h

@@ -241,6 +241,7 @@ enum {
 #define IWL_LEGACY_SWITCH_MIMO2_AB      3
 #define IWL_LEGACY_SWITCH_MIMO2_AC      4
 #define IWL_LEGACY_SWITCH_MIMO2_BC      5
+#define IWL_LEGACY_SWITCH_MIMO3_ABC     6
 
 /* possible actions when in siso mode */
 #define IWL_SISO_SWITCH_ANTENNA1        0
@@ -249,6 +250,8 @@ enum {
 #define IWL_SISO_SWITCH_MIMO2_AC        3
 #define IWL_SISO_SWITCH_MIMO2_BC        4
 #define IWL_SISO_SWITCH_GI              5
+#define IWL_SISO_SWITCH_MIMO3_ABC       6
+
 
 /* possible actions when in mimo mode */
 #define IWL_MIMO2_SWITCH_ANTENNA1       0
@@ -257,6 +260,21 @@ enum {
 #define IWL_MIMO2_SWITCH_SISO_B         3
 #define IWL_MIMO2_SWITCH_SISO_C         4
 #define IWL_MIMO2_SWITCH_GI             5
+#define IWL_MIMO2_SWITCH_MIMO3_ABC      6
+
+
+/* possible actions when in mimo3 mode */
+#define IWL_MIMO3_SWITCH_ANTENNA1       0
+#define IWL_MIMO3_SWITCH_ANTENNA2       1
+#define IWL_MIMO3_SWITCH_SISO_A         2
+#define IWL_MIMO3_SWITCH_SISO_B         3
+#define IWL_MIMO3_SWITCH_SISO_C         4
+#define IWL_MIMO3_SWITCH_MIMO2_AB       5
+#define IWL_MIMO3_SWITCH_MIMO2_AC       6
+#define IWL_MIMO3_SWITCH_MIMO2_BC       7
+#define IWL_MIMO3_SWITCH_GI             8
+
+
 
 /*FIXME:RS:add possible actions for MIMO3*/
 
@@ -307,6 +325,13 @@ enum iwl_table_type {
 #define ANT_BC		(ANT_B | ANT_C)
 #define ANT_ABC		(ANT_AB | ANT_C)
 
+#define IWL_MAX_MCS_DISPLAY_SIZE	12
+
+struct iwl_rate_mcs_info {
+	char	mbps[IWL_MAX_MCS_DISPLAY_SIZE];
+	char	mcs[IWL_MAX_MCS_DISPLAY_SIZE];
+};
+
 static inline u8 num_of_ant(u8 mask)
 {
 	return  !!((mask) & ANT_A) +

Plik diff jest za duży
+ 51 - 679
drivers/net/wireless/iwlwifi/iwl-agn.c


+ 4 - 3
drivers/net/wireless/iwlwifi/iwl-commands.h

@@ -2469,11 +2469,12 @@ struct iwl_ssid_ie {
 	u8 ssid[32];
 } __attribute__ ((packed));
 
-#define PROBE_OPTION_MAX_API1		0x4
-#define PROBE_OPTION_MAX        	0x14
+#define PROBE_OPTION_MAX_3945		4
+#define PROBE_OPTION_MAX		20
 #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF)
 #define IWL_GOOD_CRC_TH			cpu_to_le16(1)
 #define IWL_MAX_SCAN_SIZE 1024
+#define IWL_MAX_PROBE_REQUEST		200
 
 /*
  * REPLY_SCAN_CMD = 0x80 (command)
@@ -2552,7 +2553,7 @@ struct iwl3945_scan_cmd {
 	struct iwl3945_tx_cmd tx_cmd;
 
 	/* For directed active scans (set to all-0s otherwise) */
-	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_API1];
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
 
 	/*
 	 * Probe request frame, followed by channel list.

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików