Browse Source

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

David S. Miller 15 years ago
parent
commit
dfef948ed2
100 changed files with 1843 additions and 1920 deletions
  1. 21 24
      drivers/net/wireless/at76c50x-usb.c
  2. 28 0
      drivers/net/wireless/ath/ath.h
  3. 21 11
      drivers/net/wireless/ath/ath5k/base.c
  4. 0 2
      drivers/net/wireless/ath/ath5k/base.h
  5. 0 2
      drivers/net/wireless/ath/ath5k/phy.c
  6. 3 0
      drivers/net/wireless/ath/ath9k/Kconfig
  7. 3 0
      drivers/net/wireless/ath/ath9k/Makefile
  8. 14 116
      drivers/net/wireless/ath/ath9k/ath9k.h
  9. 286 0
      drivers/net/wireless/ath/ath9k/common.c
  10. 123 0
      drivers/net/wireless/ath/ath9k/common.h
  11. 15 0
      drivers/net/wireless/ath/ath9k/hw.c
  12. 2 1
      drivers/net/wireless/ath/ath9k/hw.h
  13. 133 110
      drivers/net/wireless/ath/ath9k/main.c
  14. 2 0
      drivers/net/wireless/ath/ath9k/rc.h
  15. 51 262
      drivers/net/wireless/ath/ath9k/recv.c
  16. 2 2
      drivers/net/wireless/ath/ath9k/reg.h
  17. 74 5
      drivers/net/wireless/ath/ath9k/virtual.c
  18. 14 7
      drivers/net/wireless/ath/ath9k/xmit.c
  19. 16 0
      drivers/net/wireless/atmel.c
  20. 20 28
      drivers/net/wireless/b43/dma.c
  21. 5 1
      drivers/net/wireless/b43/pio.c
  22. 19 0
      drivers/net/wireless/b43/xmit.h
  23. 6 0
      drivers/net/wireless/ipw2x00/ipw2100.c
  24. 5 0
      drivers/net/wireless/ipw2x00/ipw2200.c
  25. 2 1
      drivers/net/wireless/iwlwifi/iwl-3945.c
  26. 8 6
      drivers/net/wireless/iwlwifi/iwl-4965.c
  27. 11 5
      drivers/net/wireless/iwlwifi/iwl-5000.c
  28. 5 101
      drivers/net/wireless/iwlwifi/iwl-6000.c
  29. 52 27
      drivers/net/wireless/iwlwifi/iwl-agn.c
  30. 4 3
      drivers/net/wireless/iwlwifi/iwl-commands.h
  31. 31 23
      drivers/net/wireless/iwlwifi/iwl-core.c
  32. 5 0
      drivers/net/wireless/iwlwifi/iwl-core.h
  33. 16 6
      drivers/net/wireless/iwlwifi/iwl-dev.h
  34. 2 2
      drivers/net/wireless/iwlwifi/iwl-hcmd.c
  35. 20 0
      drivers/net/wireless/iwlwifi/iwl-io.h
  36. 16 3
      drivers/net/wireless/iwlwifi/iwl-prph.h
  37. 4 1
      drivers/net/wireless/iwlwifi/iwl-rx.c
  38. 16 2
      drivers/net/wireless/iwlwifi/iwl-scan.c
  39. 9 3
      drivers/net/wireless/iwlwifi/iwl-tx.c
  40. 33 9
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  41. 3 0
      drivers/net/wireless/iwmc3200wifi/sdio.c
  42. 1 0
      drivers/net/wireless/libertas/if_cs.c
  43. 6 0
      drivers/net/wireless/libertas/if_sdio.c
  44. 4 0
      drivers/net/wireless/libertas/if_spi.c
  45. 2 0
      drivers/net/wireless/libertas/if_usb.c
  46. 2 0
      drivers/net/wireless/libertas_tf/if_usb.c
  47. 3 0
      drivers/net/wireless/mwl8k.c
  48. 6 0
      drivers/net/wireless/orinoco/fw.c
  49. 3 0
      drivers/net/wireless/prism54/islpci_dev.c
  50. 1 1
      drivers/net/wireless/ray_cs.c
  51. 2 0
      drivers/net/wireless/rndis_wlan.c
  52. 2 1
      drivers/net/wireless/rt2x00/rt2400pci.c
  53. 1 1
      drivers/net/wireless/rt2x00/rt2400pci.h
  54. 2 1
      drivers/net/wireless/rt2x00/rt2500pci.c
  55. 1 1
      drivers/net/wireless/rt2x00/rt2500pci.h
  56. 2 135
      drivers/net/wireless/rt2x00/rt2500usb.c
  57. 1 1
      drivers/net/wireless/rt2x00/rt2500usb.h
  58. 37 1
      drivers/net/wireless/rt2x00/rt2800.h
  59. 483 11
      drivers/net/wireless/rt2x00/rt2800lib.c
  60. 17 0
      drivers/net/wireless/rt2x00/rt2800lib.h
  61. 26 390
      drivers/net/wireless/rt2x00/rt2800pci.c
  62. 8 29
      drivers/net/wireless/rt2x00/rt2800pci.h
  63. 19 399
      drivers/net/wireless/rt2x00/rt2800usb.c
  64. 25 21
      drivers/net/wireless/rt2x00/rt2800usb.h
  65. 10 12
      drivers/net/wireless/rt2x00/rt2x00.h
  66. 1 1
      drivers/net/wireless/rt2x00/rt2x00config.c
  67. 1 1
      drivers/net/wireless/rt2x00/rt2x00crypto.c
  68. 1 1
      drivers/net/wireless/rt2x00/rt2x00debug.c
  69. 1 1
      drivers/net/wireless/rt2x00/rt2x00debug.h
  70. 1 2
      drivers/net/wireless/rt2x00/rt2x00dev.c
  71. 1 1
      drivers/net/wireless/rt2x00/rt2x00dump.h
  72. 2 1
      drivers/net/wireless/rt2x00/rt2x00firmware.c
  73. 1 1
      drivers/net/wireless/rt2x00/rt2x00ht.c
  74. 1 1
      drivers/net/wireless/rt2x00/rt2x00leds.c
  75. 1 1
      drivers/net/wireless/rt2x00/rt2x00leds.h
  76. 2 14
      drivers/net/wireless/rt2x00/rt2x00lib.h
  77. 1 89
      drivers/net/wireless/rt2x00/rt2x00link.c
  78. 1 1
      drivers/net/wireless/rt2x00/rt2x00mac.c
  79. 3 1
      drivers/net/wireless/rt2x00/rt2x00pci.c
  80. 1 1
      drivers/net/wireless/rt2x00/rt2x00pci.h
  81. 2 1
      drivers/net/wireless/rt2x00/rt2x00queue.c
  82. 1 1
      drivers/net/wireless/rt2x00/rt2x00queue.h
  83. 1 1
      drivers/net/wireless/rt2x00/rt2x00reg.h
  84. 7 1
      drivers/net/wireless/rt2x00/rt2x00soc.c
  85. 1 1
      drivers/net/wireless/rt2x00/rt2x00soc.h
  86. 3 1
      drivers/net/wireless/rt2x00/rt2x00usb.c
  87. 3 1
      drivers/net/wireless/rt2x00/rt2x00usb.h
  88. 20 19
      drivers/net/wireless/rt2x00/rt61pci.c
  89. 1 1
      drivers/net/wireless/rt2x00/rt61pci.h
  90. 2 1
      drivers/net/wireless/rt2x00/rt73usb.c
  91. 1 1
      drivers/net/wireless/rt2x00/rt73usb.h
  92. 1 0
      drivers/net/wireless/wl12xx/wl1251_main.c
  93. 1 0
      drivers/net/wireless/wl12xx/wl1271_main.c
  94. 3 0
      drivers/net/wireless/zd1201.c
  95. 7 0
      drivers/net/wireless/zd1211rw/zd_usb.c
  96. 1 2
      drivers/net/znet.c
  97. 1 1
      drivers/staging/arlan/Kconfig
  98. 1 1
      drivers/staging/netwave/Kconfig
  99. 2 2
      drivers/staging/wavelan/Kconfig
  100. 1 1
      drivers/staging/wavelan/wavelan_cs.p.h

+ 21 - 24
drivers/net/wireless/at76c50x-usb.c

@@ -121,6 +121,14 @@ static struct fwentry firmwares[] = {
 	[BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" },
 	[BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" },
 	[BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" },
 	[BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" },
 };
 };
+MODULE_FIRMWARE("atmel_at76c503-i3861.bin");
+MODULE_FIRMWARE("atmel_at76c503-i3863.bin");
+MODULE_FIRMWARE("atmel_at76c503-rfmd.bin");
+MODULE_FIRMWARE("atmel_at76c503-rfmd-acc.bin");
+MODULE_FIRMWARE("atmel_at76c505-rfmd.bin");
+MODULE_FIRMWARE("atmel_at76c505-rfmd2958.bin");
+MODULE_FIRMWARE("atmel_at76c505a-rfmd2958.bin");
+MODULE_FIRMWARE("atmel_at76c505amx-rfmd.bin");
 
 
 #define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops)
 #define USB_DEVICE_DATA(__ops)	.driver_info = (kernel_ulong_t)(__ops)
 
 
@@ -524,20 +532,6 @@ static char *hex2str(void *buf, int len)
 	return ret;
 	return ret;
 }
 }
 
 
-#define MAC2STR_BUFFERS 4
-
-static inline char *mac2str(u8 *mac)
-{
-	static atomic_t a = ATOMIC_INIT(0);
-	static char bufs[MAC2STR_BUFFERS][6 * 3];
-	char *str;
-
-	str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)];
-	sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
-		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-	return str;
-}
-
 /* LED trigger */
 /* LED trigger */
 static int tx_activity;
 static int tx_activity;
 static void at76_ledtrig_tx_timerfunc(unsigned long data);
 static void at76_ledtrig_tx_timerfunc(unsigned long data);
@@ -973,13 +967,13 @@ static void at76_dump_mib_mac_addr(struct at76_priv *priv)
 		goto exit;
 		goto exit;
 	}
 	}
 
 
-	at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x",
+	at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %pM res 0x%x 0x%x",
 		 wiphy_name(priv->hw->wiphy),
 		 wiphy_name(priv->hw->wiphy),
-		 mac2str(m->mac_addr), m->res[0], m->res[1]);
+		 m->mac_addr, m->res[0], m->res[1]);
 	for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
 	for (i = 0; i < ARRAY_SIZE(m->group_addr); i++)
-		at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, "
+		at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %pM, "
 			 "status %d", wiphy_name(priv->hw->wiphy), i,
 			 "status %d", wiphy_name(priv->hw->wiphy), i,
-			 mac2str(m->group_addr[i]), m->group_addr_status[i]);
+			 m->group_addr[i], m->group_addr_status[i]);
 exit:
 exit:
 	kfree(m);
 	kfree(m);
 }
 }
@@ -1042,7 +1036,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
 	at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
 	at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration "
 		 "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
 		 "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d "
 		 "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
 		 "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d "
-		 "current_bssid %s current_essid %s current_bss_type %d "
+		 "current_bssid %pM current_essid %s current_bss_type %d "
 		 "pm_mode %d ibss_change %d res %d "
 		 "pm_mode %d ibss_change %d res %d "
 		 "multi_domain_capability_implemented %d "
 		 "multi_domain_capability_implemented %d "
 		 "international_roaming %d country_string %.3s",
 		 "international_roaming %d country_string %.3s",
@@ -1051,7 +1045,7 @@ static void at76_dump_mib_mac_mgmt(struct at76_priv *priv)
 		 le16_to_cpu(m->medium_occupancy_limit),
 		 le16_to_cpu(m->medium_occupancy_limit),
 		 le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
 		 le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window),
 		 m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
 		 m->CFP_mode, m->privacy_option_implemented, m->DTIM_period,
-		 m->CFP_period, mac2str(m->current_bssid),
+		 m->CFP_period, m->current_bssid,
 		 hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
 		 hex2str(m->current_essid, IW_ESSID_MAX_SIZE),
 		 m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
 		 m->current_bss_type, m->power_mgmt_mode, m->ibss_change,
 		 m->res, m->multi_domain_capability_implemented,
 		 m->res, m->multi_domain_capability_implemented,
@@ -1080,7 +1074,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
 		 "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
 		 "cwmin %d cwmax %d short_retry_time %d long_retry_time %d "
 		 "scan_type %d scan_channel %d probe_delay %u "
 		 "scan_type %d scan_channel %d probe_delay %u "
 		 "min_channel_time %d max_channel_time %d listen_int %d "
 		 "min_channel_time %d max_channel_time %d listen_int %d "
-		 "desired_ssid %s desired_bssid %s desired_bsstype %d",
+		 "desired_ssid %s desired_bssid %pM desired_bsstype %d",
 		 wiphy_name(priv->hw->wiphy),
 		 wiphy_name(priv->hw->wiphy),
 		 le32_to_cpu(m->max_tx_msdu_lifetime),
 		 le32_to_cpu(m->max_tx_msdu_lifetime),
 		 le32_to_cpu(m->max_rx_lifetime),
 		 le32_to_cpu(m->max_rx_lifetime),
@@ -1092,7 +1086,7 @@ static void at76_dump_mib_mac(struct at76_priv *priv)
 		 le16_to_cpu(m->max_channel_time),
 		 le16_to_cpu(m->max_channel_time),
 		 le16_to_cpu(m->listen_interval),
 		 le16_to_cpu(m->listen_interval),
 		 hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
 		 hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE),
-		 mac2str(m->desired_bssid), m->desired_bsstype);
+		 m->desired_bssid, m->desired_bsstype);
 exit:
 exit:
 	kfree(m);
 	kfree(m);
 }
 }
@@ -1194,6 +1188,9 @@ static int at76_start_monitor(struct at76_priv *priv)
 	scan.channel = priv->channel;
 	scan.channel = priv->channel;
 	scan.scan_type = SCAN_TYPE_PASSIVE;
 	scan.scan_type = SCAN_TYPE_PASSIVE;
 	scan.international_scan = 0;
 	scan.international_scan = 0;
+	scan.min_channel_time = cpu_to_le16(priv->scan_min_time);
+	scan.max_channel_time = cpu_to_le16(priv->scan_max_time);
+	scan.probe_delay = cpu_to_le16(0);
 
 
 	ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
 	ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan));
 	if (ret >= 0)
 	if (ret >= 0)
@@ -2284,9 +2281,9 @@ static int at76_init_new_device(struct at76_priv *priv,
 
 
 	priv->mac80211_registered = 1;
 	priv->mac80211_registered = 1;
 
 
-	printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n",
+	printk(KERN_INFO "%s: USB %s, MAC %pM, firmware %d.%d.%d-%d\n",
 	       wiphy_name(priv->hw->wiphy),
 	       wiphy_name(priv->hw->wiphy),
-	       dev_name(&interface->dev), mac2str(priv->mac_addr),
+	       dev_name(&interface->dev), priv->mac_addr,
 	       priv->fw_version.major, priv->fw_version.minor,
 	       priv->fw_version.major, priv->fw_version.minor,
 	       priv->fw_version.patch, priv->fw_version.build);
 	       priv->fw_version.patch, priv->fw_version.build);
 	printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",
 	printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",

+ 28 - 0
drivers/net/wireless/ath/ath.h

@@ -21,8 +21,28 @@
 #include <linux/if_ether.h>
 #include <linux/if_ether.h>
 #include <net/mac80211.h>
 #include <net/mac80211.h>
 
 
+/*
+ * The key cache is used for h/w cipher state and also for
+ * tracking station state such as the current tx antenna.
+ * We also setup a mapping table between key cache slot indices
+ * and station state to short-circuit node lookups on rx.
+ * Different parts have different size key caches.  We handle
+ * up to ATH_KEYMAX entries (could dynamically allocate state).
+ */
+#define	ATH_KEYMAX	        128     /* max key cache size we handle */
+
 static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
 
+struct ath_ani {
+	bool caldone;
+	int16_t noise_floor;
+	unsigned int longcal_timer;
+	unsigned int shortcal_timer;
+	unsigned int resetcal_timer;
+	unsigned int checkani_timer;
+	struct timer_list timer;
+};
+
 enum ath_device_state {
 enum ath_device_state {
 	ATH_HW_UNAVAILABLE,
 	ATH_HW_UNAVAILABLE,
 	ATH_HW_INITIALIZED,
 	ATH_HW_INITIALIZED,
@@ -66,6 +86,8 @@ struct ath_common {
 	int debug_mask;
 	int debug_mask;
 	enum ath_device_state state;
 	enum ath_device_state state;
 
 
+	struct ath_ani ani;
+
 	u16 cachelsz;
 	u16 cachelsz;
 	u16 curaid;
 	u16 curaid;
 	u8 macaddr[ETH_ALEN];
 	u8 macaddr[ETH_ALEN];
@@ -75,6 +97,12 @@ struct ath_common {
 	u8 tx_chainmask;
 	u8 tx_chainmask;
 	u8 rx_chainmask;
 	u8 rx_chainmask;
 
 
+	u32 rx_bufsize;
+
+	u32 keymax;
+	DECLARE_BITMAP(keymap, ATH_KEYMAX);
+	u8 splitmic;
+
 	struct ath_regulatory regulatory;
 	struct ath_regulatory regulatory;
 	const struct ath_ops *ops;
 	const struct ath_ops *ops;
 	const struct ath_bus_ops *bus_ops;
 	const struct ath_bus_ops *bus_ops;

+ 21 - 11
drivers/net/wireless/ath/ath5k/base.c

@@ -323,10 +323,13 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc,
 static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
 static inline void ath5k_rxbuf_free(struct ath5k_softc *sc,
 				struct ath5k_buf *bf)
 				struct ath5k_buf *bf)
 {
 {
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
+
 	BUG_ON(!bf);
 	BUG_ON(!bf);
 	if (!bf->skb)
 	if (!bf->skb)
 		return;
 		return;
-	pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+	pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
 			PCI_DMA_FROMDEVICE);
 			PCI_DMA_FROMDEVICE);
 	dev_kfree_skb_any(bf->skb);
 	dev_kfree_skb_any(bf->skb);
 	bf->skb = NULL;
 	bf->skb = NULL;
@@ -1181,17 +1184,18 @@ struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr)
 	 * fake physical layer header at the start.
 	 * fake physical layer header at the start.
 	 */
 	 */
 	skb = ath_rxbuf_alloc(common,
 	skb = ath_rxbuf_alloc(common,
-			      sc->rxbufsize + common->cachelsz - 1,
+			      common->rx_bufsize,
 			      GFP_ATOMIC);
 			      GFP_ATOMIC);
 
 
 	if (!skb) {
 	if (!skb) {
 		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
 		ATH5K_ERR(sc, "can't alloc skbuff of size %u\n",
-				sc->rxbufsize + common->cachelsz - 1);
+				common->rx_bufsize);
 		return NULL;
 		return NULL;
 	}
 	}
 
 
 	*skb_addr = pci_map_single(sc->pdev,
 	*skb_addr = pci_map_single(sc->pdev,
-		skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE);
+				   skb->data, common->rx_bufsize,
+				   PCI_DMA_FROMDEVICE);
 	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
 	if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) {
 		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
 		ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__);
 		dev_kfree_skb(skb);
 		dev_kfree_skb(skb);
@@ -1631,10 +1635,10 @@ ath5k_rx_start(struct ath5k_softc *sc)
 	struct ath5k_buf *bf;
 	struct ath5k_buf *bf;
 	int ret;
 	int ret;
 
 
-	sc->rxbufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
+	common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz);
 
 
-	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
-		common->cachelsz, sc->rxbufsize);
+	ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n",
+		  common->cachelsz, common->rx_bufsize);
 
 
 	spin_lock_bh(&sc->rxbuflock);
 	spin_lock_bh(&sc->rxbuflock);
 	sc->rxlink = NULL;
 	sc->rxlink = NULL;
@@ -1679,6 +1683,8 @@ static unsigned int
 ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
 ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
 		struct sk_buff *skb, struct ath5k_rx_status *rs)
 		struct sk_buff *skb, struct ath5k_rx_status *rs)
 {
 {
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	struct ieee80211_hdr *hdr = (void *)skb->data;
 	unsigned int keyix, hlen;
 	unsigned int keyix, hlen;
 
 
@@ -1695,7 +1701,7 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
 	    skb->len >= hlen + 4) {
 	    skb->len >= hlen + 4) {
 		keyix = skb->data[hlen + 3] >> 6;
 		keyix = skb->data[hlen + 3] >> 6;
 
 
-		if (test_bit(keyix, sc->keymap))
+		if (test_bit(keyix, common->keymap))
 			return RX_FLAG_DECRYPTED;
 			return RX_FLAG_DECRYPTED;
 	}
 	}
 
 
@@ -1769,6 +1775,8 @@ ath5k_tasklet_rx(unsigned long data)
 	struct sk_buff *skb, *next_skb;
 	struct sk_buff *skb, *next_skb;
 	dma_addr_t next_skb_addr;
 	dma_addr_t next_skb_addr;
 	struct ath5k_softc *sc = (void *)data;
 	struct ath5k_softc *sc = (void *)data;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
 	struct ath5k_buf *bf;
 	struct ath5k_buf *bf;
 	struct ath5k_desc *ds;
 	struct ath5k_desc *ds;
 	int ret;
 	int ret;
@@ -1846,7 +1854,7 @@ accept:
 		if (!next_skb)
 		if (!next_skb)
 			goto next;
 			goto next;
 
 
-		pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize,
+		pci_unmap_single(sc->pdev, bf->skbaddr, common->rx_bufsize,
 				PCI_DMA_FROMDEVICE);
 				PCI_DMA_FROMDEVICE);
 		skb_put(skb, rs.rs_datalen);
 		skb_put(skb, rs.rs_datalen);
 
 
@@ -3032,6 +3040,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	      struct ieee80211_key_conf *key)
 	      struct ieee80211_key_conf *key)
 {
 {
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_softc *sc = hw->priv;
+	struct ath5k_hw *ah = sc->ah;
+	struct ath_common *common = ath5k_hw_common(ah);
 	int ret = 0;
 	int ret = 0;
 
 
 	if (modparam_nohwcrypt)
 	if (modparam_nohwcrypt)
@@ -3064,14 +3074,14 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			ATH5K_ERR(sc, "can't set the key\n");
 			ATH5K_ERR(sc, "can't set the key\n");
 			goto unlock;
 			goto unlock;
 		}
 		}
-		__set_bit(key->keyidx, sc->keymap);
+		__set_bit(key->keyidx, common->keymap);
 		key->hw_key_idx = key->keyidx;
 		key->hw_key_idx = key->keyidx;
 		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
 		key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
 			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
 			       IEEE80211_KEY_FLAG_GENERATE_MMIC);
 		break;
 		break;
 	case DISABLE_KEY:
 	case DISABLE_KEY:
 		ath5k_hw_reset_key(sc->ah, key->keyidx);
 		ath5k_hw_reset_key(sc->ah, key->keyidx);
-		__clear_bit(key->keyidx, sc->keymap);
+		__clear_bit(key->keyidx, common->keymap);
 		break;
 		break;
 	default:
 	default:
 		ret = -EINVAL;
 		ret = -EINVAL;

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

@@ -153,8 +153,6 @@ struct ath5k_softc {
 
 
 	enum ath5k_int		imask;		/* interrupt mask copy */
 	enum ath5k_int		imask;		/* interrupt mask copy */
 
 
-	DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */
-
 	u8			bssidmask[ETH_ALEN];
 	u8			bssidmask[ETH_ALEN];
 
 
 	unsigned int		led_pin,	/* GPIO pin for driving LED */
 	unsigned int		led_pin,	/* GPIO pin for driving LED */

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

@@ -3025,8 +3025,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel,
 		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
 		ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
-	if (txpower == 0)
-		txpower = AR5K_TUNE_DEFAULT_TXPOWER;
 
 
 	/* Reset TX power values */
 	/* Reset TX power values */
 	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));
 	memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower));

+ 3 - 0
drivers/net/wireless/ath/ath9k/Kconfig

@@ -1,5 +1,7 @@
 config ATH9K_HW
 config ATH9K_HW
 	tristate
 	tristate
+config ATH9K_COMMON
+	tristate
 
 
 config ATH9K
 config ATH9K
 	tristate "Atheros 802.11n wireless cards support"
 	tristate "Atheros 802.11n wireless cards support"
@@ -8,6 +10,7 @@ config ATH9K
 	select MAC80211_LEDS
 	select MAC80211_LEDS
 	select LEDS_CLASS
 	select LEDS_CLASS
 	select NEW_LEDS
 	select NEW_LEDS
+	select ATH9K_COMMON
 	---help---
 	---help---
 	  This module adds support for wireless adapters based on
 	  This module adds support for wireless adapters based on
 	  Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
 	  Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family

+ 3 - 0
drivers/net/wireless/ath/ath9k/Makefile

@@ -23,3 +23,6 @@ ath9k_hw-y:=	hw.o \
 		mac.o \
 		mac.o \
 
 
 obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
 obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
+
+obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
+ath9k_common-y:=	common.o

+ 14 - 116
drivers/net/wireless/ath/ath9k/ath9k.h

@@ -19,14 +19,16 @@
 
 
 #include <linux/etherdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/device.h>
 #include <linux/device.h>
-#include <net/mac80211.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
 
 
-#include "hw.h"
 #include "rc.h"
 #include "rc.h"
 #include "debug.h"
 #include "debug.h"
-#include "../ath.h"
-#include "../debug.h"
+#include "common.h"
+
+/*
+ * Header for the ath9k.ko driver core *only* -- hw code nor any other driver
+ * should rely on this file or its contents.
+ */
 
 
 struct ath_node;
 struct ath_node;
 
 
@@ -99,18 +101,6 @@ enum buffer_type {
 	BUF_XRETRY		= BIT(5),
 	BUF_XRETRY		= BIT(5),
 };
 };
 
 
-struct ath_buf_state {
-	int bfs_nframes;
-	u16 bfs_al;
-	u16 bfs_frmlen;
-	int bfs_seqno;
-	int bfs_tidno;
-	int bfs_retries;
-	u8 bf_type;
-	u32 bfs_keyix;
-	enum ath9k_key_type bfs_keytype;
-};
-
 #define bf_nframes      	bf_state.bfs_nframes
 #define bf_nframes      	bf_state.bfs_nframes
 #define bf_al           	bf_state.bfs_al
 #define bf_al           	bf_state.bfs_al
 #define bf_frmlen       	bf_state.bfs_frmlen
 #define bf_frmlen       	bf_state.bfs_frmlen
@@ -125,21 +115,6 @@ struct ath_buf_state {
 #define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)
 #define bf_isretried(bf)	(bf->bf_state.bf_type & BUF_RETRY)
 #define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY)
 #define bf_isxretried(bf)	(bf->bf_state.bf_type & BUF_XRETRY)
 
 
-struct ath_buf {
-	struct list_head list;
-	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 */
-	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 */
-	bool bf_stale;
-	u16 bf_flags;
-	struct ath_buf_state bf_state;
-	dma_addr_t bf_dmacontext;
-};
-
 struct ath_descdma {
 struct ath_descdma {
 	struct ath_desc *dd_desc;
 	struct ath_desc *dd_desc;
 	dma_addr_t dd_desc_paddr;
 	dma_addr_t dd_desc_paddr;
@@ -159,13 +134,9 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 
 
 #define ATH_MAX_ANTENNA         3
 #define ATH_MAX_ANTENNA         3
 #define ATH_RXBUF               512
 #define ATH_RXBUF               512
-#define WME_NUM_TID             16
 #define ATH_TXBUF               512
 #define ATH_TXBUF               512
 #define ATH_TXMAXTRY            13
 #define ATH_TXMAXTRY            13
 #define ATH_MGT_TXMAXTRY        4
 #define ATH_MGT_TXMAXTRY        4
-#define WME_BA_BMP_SIZE         64
-#define WME_MAX_BA              WME_BA_BMP_SIZE
-#define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 
 
 #define TID_TO_WME_AC(_tid)				\
 #define TID_TO_WME_AC(_tid)				\
 	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
 	((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE :	\
@@ -173,12 +144,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
 	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
 	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
 	 WME_AC_VO)
 	 WME_AC_VO)
 
 
-#define WME_AC_BE   0
-#define WME_AC_BK   1
-#define WME_AC_VI   2
-#define WME_AC_VO   3
-#define WME_NUM_AC  4
-
 #define ADDBA_EXCHANGE_ATTEMPTS    10
 #define ADDBA_EXCHANGE_ATTEMPTS    10
 #define ATH_AGGR_DELIM_SZ          4
 #define ATH_AGGR_DELIM_SZ          4
 #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
 #define ATH_AGGR_MINPLEN           256 /* in bytes, minimum packet length */
@@ -252,30 +217,6 @@ struct ath_txq {
 #define AGGR_ADDBA_COMPLETE  BIT(2)
 #define AGGR_ADDBA_COMPLETE  BIT(2)
 #define AGGR_ADDBA_PROGRESS  BIT(3)
 #define AGGR_ADDBA_PROGRESS  BIT(3)
 
 
-struct ath_atx_tid {
-	struct list_head list;
-	struct list_head buf_q;
-	struct ath_node *an;
-	struct ath_atx_ac *ac;
-	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
-	u16 seq_start;
-	u16 seq_next;
-	u16 baw_size;
-	int tidno;
-	int baw_head;	/* first un-acked tx buffer */
-	int baw_tail;	/* next unused tx buffer slot */
-	int sched;
-	int paused;
-	u8 state;
-};
-
-struct ath_atx_ac {
-	int sched;
-	int qnum;
-	struct list_head list;
-	struct list_head tid_q;
-};
-
 struct ath_tx_control {
 struct ath_tx_control {
 	struct ath_txq *txq;
 	struct ath_txq *txq;
 	int if_id;
 	int if_id;
@@ -286,29 +227,6 @@ struct ath_tx_control {
 #define ATH_TX_XRETRY       0x02
 #define ATH_TX_XRETRY       0x02
 #define ATH_TX_BAR          0x04
 #define ATH_TX_BAR          0x04
 
 
-#define ATH_RSSI_LPF_LEN 		10
-#define RSSI_LPF_THRESHOLD		-20
-#define ATH_RSSI_EP_MULTIPLIER     (1<<7)
-#define ATH_EP_MUL(x, mul)         ((x) * (mul))
-#define ATH_RSSI_IN(x)             (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
-#define ATH_LPF_RSSI(x, y, len) \
-    ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
-#define ATH_RSSI_LPF(x, y) do {                     			\
-    if ((y) >= RSSI_LPF_THRESHOLD)                         		\
-	x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN);  	\
-} while (0)
-#define ATH_EP_RND(x, mul) 						\
-	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
-
-struct ath_node {
-	struct ath_softc *an_sc;
-	struct ath_atx_tid tid[WME_NUM_TID];
-	struct ath_atx_ac ac[WME_NUM_AC];
-	u16 maxampdu;
-	u8 mpdudensity;
-	int last_rssi;
-};
-
 struct ath_tx {
 struct ath_tx {
 	u16 seq_no;
 	u16 seq_no;
 	u32 txqsetup;
 	u32 txqsetup;
@@ -323,7 +241,6 @@ struct ath_rx {
 	u8 defant;
 	u8 defant;
 	u8 rxotherant;
 	u8 rxotherant;
 	u32 *rxlink;
 	u32 *rxlink;
-	int bufsize;
 	unsigned int rxfilter;
 	unsigned int rxfilter;
 	spinlock_t rxflushlock;
 	spinlock_t rxflushlock;
 	spinlock_t rxbuflock;
 	spinlock_t rxbuflock;
@@ -434,16 +351,6 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
 
 
-struct ath_ani {
-	bool caldone;
-	int16_t noise_floor;
-	unsigned int longcal_timer;
-	unsigned int shortcal_timer;
-	unsigned int resetcal_timer;
-	unsigned int checkani_timer;
-	struct timer_list timer;
-};
-
 /* Defines the BT AR_BT_COEX_WGHT used */
 /* Defines the BT AR_BT_COEX_WGHT used */
 enum ath_stomp_type {
 enum ath_stomp_type {
 	ATH_BTCOEX_NO_STOMP,
 	ATH_BTCOEX_NO_STOMP,
@@ -503,18 +410,7 @@ struct ath_led {
 #define ATH_CHAN_MAX            255
 #define ATH_CHAN_MAX            255
 #define IEEE80211_WEP_NKID      4       /* number of key ids */
 #define IEEE80211_WEP_NKID      4       /* number of key ids */
 
 
-/*
- * The key cache is used for h/w cipher state and also for
- * tracking station state such as the current tx antenna.
- * We also setup a mapping table between key cache slot indices
- * and station state to short-circuit node lookups on rx.
- * Different parts have different size key caches.  We handle
- * up to ATH_KEYMAX entries (could dynamically allocate state).
- */
-#define	ATH_KEYMAX	        128     /* max key cache size we handle */
-
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
-#define ATH_RSSI_DUMMY_MARKER   0x127
 #define ATH_RATE_DUMMY_MARKER   0
 #define ATH_RATE_DUMMY_MARKER   0
 
 
 #define SC_OP_INVALID           BIT(0)
 #define SC_OP_INVALID           BIT(0)
@@ -573,9 +469,6 @@ struct ath_softc {
 	u16 curtxpow;
 	u16 curtxpow;
 	u8 nbcnvifs;
 	u8 nbcnvifs;
 	u16 nvifs;
 	u16 nvifs;
-	u32 keymax;
-	DECLARE_BITMAP(keymap, ATH_KEYMAX);
-	u8 splitmic;
 	bool ps_enabled;
 	bool ps_enabled;
 	unsigned long ps_usecount;
 	unsigned long ps_usecount;
 	enum ath9k_int imask;
 	enum ath9k_int imask;
@@ -601,7 +494,6 @@ struct ath_softc {
 
 
 	int beacon_interval;
 	int beacon_interval;
 
 
-	struct ath_ani ani;
 #ifdef CONFIG_ATH9K_DEBUG
 #ifdef CONFIG_ATH9K_DEBUG
 	struct ath9k_debug debug;
 	struct ath9k_debug debug;
 #endif
 #endif
@@ -620,6 +512,7 @@ struct ath_wiphy {
 		ATH_WIPHY_PAUSED,
 		ATH_WIPHY_PAUSED,
 		ATH_WIPHY_SCAN,
 		ATH_WIPHY_SCAN,
 	} state;
 	} state;
+	bool idle;
 	int chan_idx;
 	int chan_idx;
 	int chan_is_ht;
 	int chan_is_ht;
 };
 };
@@ -654,8 +547,9 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 void ath_update_chainmask(struct ath_softc *sc, int is_ht);
 void ath_update_chainmask(struct ath_softc *sc, int is_ht);
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan);
 		    struct ath9k_channel *hchan);
-void ath_radio_enable(struct ath_softc *sc);
-void ath_radio_disable(struct ath_softc *sc);
+
+void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
+void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
 
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI
 int ath_pci_init(void);
 int ath_pci_init(void);
@@ -691,6 +585,10 @@ void ath9k_wiphy_pause_all_forced(struct ath_softc *sc,
 bool ath9k_wiphy_scanning(struct ath_softc *sc);
 bool ath9k_wiphy_scanning(struct ath_softc *sc);
 void ath9k_wiphy_work(struct work_struct *work);
 void ath9k_wiphy_work(struct work_struct *work);
 bool ath9k_all_wiphys_idle(struct ath_softc *sc);
 bool ath9k_all_wiphys_idle(struct ath_softc *sc);
+void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
+
+void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
+void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
 
 
 int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
 int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
 #endif /* ATH9K_H */
 #endif /* ATH9K_H */

+ 286 - 0
drivers/net/wireless/ath/ath9k/common.c

@@ -0,0 +1,286 @@
+/*
+ * 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.
+ */
+
+/*
+ * Module for common driver code between ath9k and ath9k_htc
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "common.h"
+
+MODULE_AUTHOR("Atheros Communications");
+MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
+MODULE_LICENSE("Dual BSD/GPL");
+
+/* Common RX processing */
+
+/* Assumes you've already done the endian to CPU conversion */
+static bool ath9k_rx_accept(struct ath_common *common,
+			    struct sk_buff *skb,
+			    struct ieee80211_rx_status *rxs,
+			    struct ath_rx_status *rx_stats,
+			    bool *decrypt_error)
+{
+	struct ath_hw *ah = common->ah;
+	struct ieee80211_hdr *hdr;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *) skb->data;
+	fc = hdr->frame_control;
+
+	if (!rx_stats->rs_datalen)
+		return false;
+        /*
+         * rs_status follows rs_datalen so if rs_datalen is too large
+         * we can take a hint that hardware corrupted it, so ignore
+         * those frames.
+         */
+	if (rx_stats->rs_datalen > common->rx_bufsize)
+		return false;
+
+	/*
+	 * rs_more indicates chained descriptors which can be used
+	 * to link buffers together for a sort of scatter-gather
+	 * operation.
+	 *
+	 * The rx_stats->rs_status will not be set until the end of the
+	 * chained descriptors so it can be ignored if rs_more is set. The
+	 * rs_more will be false at the last element of the chained
+	 * descriptors.
+	 */
+	if (!rx_stats->rs_more && rx_stats->rs_status != 0) {
+		if (rx_stats->rs_status & ATH9K_RXERR_CRC)
+			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
+		if (rx_stats->rs_status & ATH9K_RXERR_PHY)
+			return false;
+
+		if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
+			*decrypt_error = true;
+		} else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
+			if (ieee80211_is_ctl(fc))
+				/*
+				 * Sometimes, we get invalid
+				 * MIC failures on valid control frames.
+				 * Remove these mic errors.
+				 */
+				rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
+			else
+				rxs->flag |= RX_FLAG_MMIC_ERROR;
+		}
+		/*
+		 * Reject error frames with the exception of
+		 * decryption and MIC failures. For monitor mode,
+		 * we also ignore the CRC error.
+		 */
+		if (ah->opmode == NL80211_IFTYPE_MONITOR) {
+			if (rx_stats->rs_status &
+			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+			      ATH9K_RXERR_CRC))
+				return false;
+		} else {
+			if (rx_stats->rs_status &
+			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
+static u8 ath9k_process_rate(struct ath_common *common,
+			     struct ieee80211_hw *hw,
+			     struct ath_rx_status *rx_stats,
+			     struct ieee80211_rx_status *rxs,
+			     struct sk_buff *skb)
+{
+	struct ieee80211_supported_band *sband;
+	enum ieee80211_band band;
+	unsigned int i = 0;
+
+	band = hw->conf.channel->band;
+	sband = hw->wiphy->bands[band];
+
+	if (rx_stats->rs_rate & 0x80) {
+		/* HT rate */
+		rxs->flag |= RX_FLAG_HT;
+		if (rx_stats->rs_flags & ATH9K_RX_2040)
+			rxs->flag |= RX_FLAG_40MHZ;
+		if (rx_stats->rs_flags & ATH9K_RX_GI)
+			rxs->flag |= RX_FLAG_SHORT_GI;
+		return rx_stats->rs_rate & 0x7f;
+	}
+
+	for (i = 0; i < sband->n_bitrates; i++) {
+		if (sband->bitrates[i].hw_value == rx_stats->rs_rate)
+			return i;
+		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
+			rxs->flag |= RX_FLAG_SHORTPRE;
+			return i;
+		}
+	}
+
+	/* No valid hardware bitrate found -- we should not get here */
+	ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
+		  "0x%02x using 1 Mbit\n", rx_stats->rs_rate);
+	if ((common->debug_mask & ATH_DBG_XMIT))
+		print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len);
+
+        return 0;
+}
+
+static void ath9k_process_rssi(struct ath_common *common,
+			       struct ieee80211_hw *hw,
+			       struct sk_buff *skb,
+			       struct ath_rx_status *rx_stats)
+{
+	struct ath_hw *ah = common->ah;
+	struct ieee80211_sta *sta;
+	struct ieee80211_hdr *hdr;
+	struct ath_node *an;
+	int last_rssi = ATH_RSSI_DUMMY_MARKER;
+	__le16 fc;
+
+	hdr = (struct ieee80211_hdr *)skb->data;
+	fc = hdr->frame_control;
+
+	rcu_read_lock();
+	/*
+	 * XXX: use ieee80211_find_sta! This requires quite a bit of work
+	 * under the current ath9k virtual wiphy implementation as we have
+	 * no way of tying a vif to wiphy. Typically vifs are attached to
+	 * at least one sdata of a wiphy on mac80211 but with ath9k virtual
+	 * wiphy you'd have to iterate over every wiphy and each sdata.
+	 */
+	sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
+	if (sta) {
+		an = (struct ath_node *) sta->drv_priv;
+		if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
+		   !rx_stats->rs_moreaggr)
+			ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
+		last_rssi = an->last_rssi;
+	}
+	rcu_read_unlock();
+
+	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
+					      ATH_RSSI_EP_MULTIPLIER);
+	if (rx_stats->rs_rssi < 0)
+		rx_stats->rs_rssi = 0;
+	else if (rx_stats->rs_rssi > 127)
+		rx_stats->rs_rssi = 127;
+
+	/* Update Beacon RSSI, this is used by ANI. */
+	if (ieee80211_is_beacon(fc))
+		ah->stats.avgbrssi = rx_stats->rs_rssi;
+}
+
+/*
+ * For Decrypt or Demic errors, we only mark packet status here and always push
+ * up the frame up to let mac80211 handle the actual error case, be it no
+ * decryption key or real decryption error. This let us keep statistics there.
+ */
+int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
+				struct ieee80211_hw *hw,
+				struct sk_buff *skb,
+				struct ath_rx_status *rx_stats,
+				struct ieee80211_rx_status *rx_status,
+				bool *decrypt_error)
+{
+	struct ath_hw *ah = common->ah;
+
+	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
+	if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
+		return -EINVAL;
+
+	ath9k_process_rssi(common, hw, skb, rx_stats);
+
+	rx_status->rate_idx = ath9k_process_rate(common, hw,
+						 rx_stats, rx_status, skb);
+	rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
+	rx_status->band = hw->conf.channel->band;
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->noise = common->ani.noise_floor;
+	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
+	rx_status->antenna = rx_stats->rs_antenna;
+	rx_status->flag |= RX_FLAG_TSFT;
+
+	return 0;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess);
+
+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+				  struct sk_buff *skb,
+				  struct ath_rx_status *rx_stats,
+				  struct ieee80211_rx_status *rxs,
+				  bool decrypt_error)
+{
+	struct ath_hw *ah = common->ah;
+	struct ieee80211_hdr *hdr;
+	int hdrlen, padsize;
+	u8 keyix;
+	__le16 fc;
+
+	/* see if any padding is done by the hw and remove it */
+	hdr = (struct ieee80211_hdr *) skb->data;
+	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+	fc = hdr->frame_control;
+
+	/* The MAC header is padded to have 32-bit boundary if the
+	 * packet payload is non-zero. The general calculation for
+	 * padsize would take into account odd header lengths:
+	 * padsize = (4 - hdrlen % 4) % 4; However, since only
+	 * even-length headers are used, padding can only be 0 or 2
+	 * bytes and we can optimize this a bit. In addition, we must
+	 * not try to remove padding from short control frames that do
+	 * not have payload. */
+	padsize = hdrlen & 3;
+	if (padsize && hdrlen >= 24) {
+		memmove(skb->data + padsize, skb->data, hdrlen);
+		skb_pull(skb, padsize);
+	}
+
+	keyix = rx_stats->rs_keyix;
+
+	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
+		rxs->flag |= RX_FLAG_DECRYPTED;
+	} else if (ieee80211_has_protected(fc)
+		   && !decrypt_error && skb->len >= hdrlen + 4) {
+		keyix = skb->data[hdrlen + 3] >> 6;
+
+		if (test_bit(keyix, common->keymap))
+			rxs->flag |= RX_FLAG_DECRYPTED;
+	}
+	if (ah->sw_mgmt_crypto &&
+	    (rxs->flag & RX_FLAG_DECRYPTED) &&
+	    ieee80211_is_mgmt(fc))
+		/* Use software decrypt for management frames. */
+		rxs->flag &= ~RX_FLAG_DECRYPTED;
+}
+EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
+
+static int __init ath9k_cmn_init(void)
+{
+	return 0;
+}
+module_init(ath9k_cmn_init);
+
+static void __exit ath9k_cmn_exit(void)
+{
+	return;
+}
+module_exit(ath9k_cmn_exit);

+ 123 - 0
drivers/net/wireless/ath/ath9k/common.h

@@ -0,0 +1,123 @@
+/*
+ * 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 <net/mac80211.h>
+
+#include "../ath.h"
+#include "../debug.h"
+
+#include "hw.h"
+
+/* Common header for Atheros 802.11n base driver cores */
+
+#define WME_NUM_TID             16
+#define WME_BA_BMP_SIZE         64
+#define WME_MAX_BA              WME_BA_BMP_SIZE
+#define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
+
+#define WME_AC_BE   0
+#define WME_AC_BK   1
+#define WME_AC_VI   2
+#define WME_AC_VO   3
+#define WME_NUM_AC  4
+
+#define ATH_RSSI_DUMMY_MARKER   0x127
+#define ATH_RSSI_LPF_LEN 		10
+#define RSSI_LPF_THRESHOLD		-20
+#define ATH_RSSI_EP_MULTIPLIER     (1<<7)
+#define ATH_EP_MUL(x, mul)         ((x) * (mul))
+#define ATH_RSSI_IN(x)             (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
+#define ATH_LPF_RSSI(x, y, len) \
+    ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y))
+#define ATH_RSSI_LPF(x, y) do {                     			\
+    if ((y) >= RSSI_LPF_THRESHOLD)                         		\
+	x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN);  	\
+} while (0)
+#define ATH_EP_RND(x, mul) 						\
+	((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
+
+struct ath_atx_ac {
+	int sched;
+	int qnum;
+	struct list_head list;
+	struct list_head tid_q;
+};
+
+struct ath_buf_state {
+	int bfs_nframes;
+	u16 bfs_al;
+	u16 bfs_frmlen;
+	int bfs_seqno;
+	int bfs_tidno;
+	int bfs_retries;
+	u8 bf_type;
+	u32 bfs_keyix;
+	enum ath9k_key_type bfs_keytype;
+};
+
+struct ath_buf {
+	struct list_head list;
+	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 */
+	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 */
+	bool bf_stale;
+	u16 bf_flags;
+	struct ath_buf_state bf_state;
+	dma_addr_t bf_dmacontext;
+};
+
+struct ath_atx_tid {
+	struct list_head list;
+	struct list_head buf_q;
+	struct ath_node *an;
+	struct ath_atx_ac *ac;
+	struct ath_buf *tx_buf[ATH_TID_MAX_BUFS];
+	u16 seq_start;
+	u16 seq_next;
+	u16 baw_size;
+	int tidno;
+	int baw_head;   /* first un-acked tx buffer */
+	int baw_tail;   /* next unused tx buffer slot */
+	int sched;
+	int paused;
+	u8 state;
+};
+
+struct ath_node {
+	struct ath_common *common;
+	struct ath_atx_tid tid[WME_NUM_TID];
+	struct ath_atx_ac ac[WME_NUM_AC];
+	u16 maxampdu;
+	u8 mpdudensity;
+	int last_rssi;
+};
+
+int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
+				struct ieee80211_hw *hw,
+				struct sk_buff *skb,
+				struct ath_rx_status *rx_stats,
+				struct ieee80211_rx_status *rx_status,
+				bool *decrypt_error);
+
+void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
+				  struct sk_buff *skb,
+				  struct ath_rx_status *rx_stats,
+				  struct ieee80211_rx_status *rxs,
+				  bool decrypt_error);

+ 15 - 0
drivers/net/wireless/ath/ath9k/hw.c

@@ -3710,6 +3710,21 @@ void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
 }
 }
 EXPORT_SYMBOL(ath9k_hw_set_tsfadjust);
 EXPORT_SYMBOL(ath9k_hw_set_tsfadjust);
 
 
+/*
+ *  Extend 15-bit time stamp from rx descriptor to
+ *  a full 64-bit TSF using the current h/w TSF.
+*/
+u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp)
+{
+	u64 tsf;
+
+	tsf = ath9k_hw_gettsf64(ah);
+	if ((tsf & 0x7fff) < rstamp)
+		tsf -= 0x8000;
+	return (tsf & ~0x7fff) | rstamp;
+}
+EXPORT_SYMBOL(ath9k_hw_extend_tsf);
+
 bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
 bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us)
 {
 {
 	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
 	if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {

+ 2 - 1
drivers/net/wireless/ath/ath9k/hw.h

@@ -432,7 +432,7 @@ struct ath9k_hw_version {
  * Using de Bruijin sequence to to look up 1's index in a 32 bit number
  * Using de Bruijin sequence to to look up 1's index in a 32 bit number
  * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
  * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001
  */
  */
-#define debruijn32 0x077CB531UL
+#define debruijn32 0x077CB531U
 
 
 struct ath_gen_timer_configuration {
 struct ath_gen_timer_configuration {
 	u32 next_addr;
 	u32 next_addr;
@@ -689,6 +689,7 @@ u64 ath9k_hw_gettsf64(struct ath_hw *ah);
 void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
 void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
 void ath9k_hw_reset_tsf(struct ath_hw *ah);
 void ath9k_hw_reset_tsf(struct ath_hw *ah);
 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
+u64 ath9k_hw_extend_tsf(struct ath_hw *ah, u32 rstamp);
 bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
 bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us);
 void ath9k_hw_set11nmac2040(struct ath_hw *ah);
 void ath9k_hw_set11nmac2040(struct ath_hw *ah);
 void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);
 void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period);

+ 133 - 110
drivers/net/wireless/ath/ath9k/main.c

@@ -405,34 +405,34 @@ static void ath_ani_calibrate(unsigned long data)
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
 
 
 	/* Long calibration runs independently of short calibration. */
 	/* Long calibration runs independently of short calibration. */
-	if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
+	if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
 		longcal = true;
 		longcal = true;
 		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
 		ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
-		sc->ani.longcal_timer = timestamp;
+		common->ani.longcal_timer = timestamp;
 	}
 	}
 
 
 	/* Short calibration applies only while caldone is false */
 	/* Short calibration applies only while caldone is false */
-	if (!sc->ani.caldone) {
-		if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) {
+	if (!common->ani.caldone) {
+		if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
 			shortcal = true;
 			shortcal = true;
 			ath_print(common, ATH_DBG_ANI,
 			ath_print(common, ATH_DBG_ANI,
 				  "shortcal @%lu\n", jiffies);
 				  "shortcal @%lu\n", jiffies);
-			sc->ani.shortcal_timer = timestamp;
-			sc->ani.resetcal_timer = timestamp;
+			common->ani.shortcal_timer = timestamp;
+			common->ani.resetcal_timer = timestamp;
 		}
 		}
 	} else {
 	} else {
-		if ((timestamp - sc->ani.resetcal_timer) >=
+		if ((timestamp - common->ani.resetcal_timer) >=
 		    ATH_RESTART_CALINTERVAL) {
 		    ATH_RESTART_CALINTERVAL) {
-			sc->ani.caldone = ath9k_hw_reset_calvalid(ah);
-			if (sc->ani.caldone)
-				sc->ani.resetcal_timer = timestamp;
+			common->ani.caldone = ath9k_hw_reset_calvalid(ah);
+			if (common->ani.caldone)
+				common->ani.resetcal_timer = timestamp;
 		}
 		}
 	}
 	}
 
 
 	/* Verify whether we must check ANI */
 	/* Verify whether we must check ANI */
-	if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
+	if ((timestamp - common->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) {
 		aniflag = true;
 		aniflag = true;
-		sc->ani.checkani_timer = timestamp;
+		common->ani.checkani_timer = timestamp;
 	}
 	}
 
 
 	/* Skip all processing if there's nothing to do. */
 	/* Skip all processing if there's nothing to do. */
@@ -443,21 +443,21 @@ static void ath_ani_calibrate(unsigned long data)
 
 
 		/* Perform calibration if necessary */
 		/* Perform calibration if necessary */
 		if (longcal || shortcal) {
 		if (longcal || shortcal) {
-			sc->ani.caldone =
+			common->ani.caldone =
 				ath9k_hw_calibrate(ah,
 				ath9k_hw_calibrate(ah,
 						   ah->curchan,
 						   ah->curchan,
 						   common->rx_chainmask,
 						   common->rx_chainmask,
 						   longcal);
 						   longcal);
 
 
 			if (longcal)
 			if (longcal)
-				sc->ani.noise_floor = ath9k_hw_getchan_noise(ah,
+				common->ani.noise_floor = ath9k_hw_getchan_noise(ah,
 								     ah->curchan);
 								     ah->curchan);
 
 
 			ath_print(common, ATH_DBG_ANI,
 			ath_print(common, ATH_DBG_ANI,
 				  " calibrate chan %u/%x nf: %d\n",
 				  " calibrate chan %u/%x nf: %d\n",
 				  ah->curchan->channel,
 				  ah->curchan->channel,
 				  ah->curchan->channelFlags,
 				  ah->curchan->channelFlags,
-				  sc->ani.noise_floor);
+				  common->ani.noise_floor);
 		}
 		}
 	}
 	}
 
 
@@ -473,21 +473,21 @@ set_timer:
 	cal_interval = ATH_LONG_CALINTERVAL;
 	cal_interval = ATH_LONG_CALINTERVAL;
 	if (sc->sc_ah->config.enable_ani)
 	if (sc->sc_ah->config.enable_ani)
 		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
 		cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
-	if (!sc->ani.caldone)
+	if (!common->ani.caldone)
 		cal_interval = min(cal_interval, (u32)short_cal_interval);
 		cal_interval = min(cal_interval, (u32)short_cal_interval);
 
 
-	mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+	mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
 }
 }
 
 
-static void ath_start_ani(struct ath_softc *sc)
+static void ath_start_ani(struct ath_common *common)
 {
 {
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
 
 
-	sc->ani.longcal_timer = timestamp;
-	sc->ani.shortcal_timer = timestamp;
-	sc->ani.checkani_timer = timestamp;
+	common->ani.longcal_timer = timestamp;
+	common->ani.shortcal_timer = timestamp;
+	common->ani.checkani_timer = timestamp;
 
 
-	mod_timer(&sc->ani.timer,
+	mod_timer(&common->ani.timer,
 		  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
 		  jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
 }
 }
 
 
@@ -733,10 +733,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
 	return chanmode;
 	return chanmode;
 }
 }
 
 
-static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
+static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key,
 			   struct ath9k_keyval *hk, const u8 *addr,
 			   struct ath9k_keyval *hk, const u8 *addr,
 			   bool authenticator)
 			   bool authenticator)
 {
 {
+	struct ath_hw *ah = common->ah;
 	const u8 *key_rxmic;
 	const u8 *key_rxmic;
 	const u8 *key_txmic;
 	const u8 *key_txmic;
 
 
@@ -756,42 +757,42 @@ static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
 			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 			memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
 			memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic));
 		}
 		}
-		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
+		return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
 	}
 	}
-	if (!sc->splitmic) {
+	if (!common->splitmic) {
 		/* TX and RX keys share the same key cache entry. */
 		/* TX and RX keys share the same key cache entry. */
 		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 		memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
 		memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
-		return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr);
+		return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr);
 	}
 	}
 
 
 	/* Separate key cache entries for TX and RX */
 	/* Separate key cache entries for TX and RX */
 
 
 	/* TX key goes at first index, RX key at +32. */
 	/* TX key goes at first index, RX key at +32. */
 	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
 	memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
-	if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) {
+	if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) {
 		/* TX MIC entry failed. No need to proceed further */
 		/* TX MIC entry failed. No need to proceed further */
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
+		ath_print(common, ATH_DBG_FATAL,
 			  "Setting TX MIC Key Failed\n");
 			  "Setting TX MIC Key Failed\n");
 		return 0;
 		return 0;
 	}
 	}
 
 
 	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 	memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
 	/* XXX delete tx key on failure? */
 	/* XXX delete tx key on failure? */
-	return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr);
+	return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr);
 }
 }
 
 
-static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
+static int ath_reserve_key_cache_slot_tkip(struct ath_common *common)
 {
 {
 	int i;
 	int i;
 
 
-	for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
-		if (test_bit(i, sc->keymap) ||
-		    test_bit(i + 64, sc->keymap))
+	for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+		if (test_bit(i, common->keymap) ||
+		    test_bit(i + 64, common->keymap))
 			continue; /* At least one part of TKIP key allocated */
 			continue; /* At least one part of TKIP key allocated */
-		if (sc->splitmic &&
-		    (test_bit(i + 32, sc->keymap) ||
-		     test_bit(i + 64 + 32, sc->keymap)))
+		if (common->splitmic &&
+		    (test_bit(i + 32, common->keymap) ||
+		     test_bit(i + 64 + 32, common->keymap)))
 			continue; /* At least one part of TKIP key allocated */
 			continue; /* At least one part of TKIP key allocated */
 
 
 		/* Found a free slot for a TKIP key */
 		/* Found a free slot for a TKIP key */
@@ -800,60 +801,60 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
 	return -1;
 	return -1;
 }
 }
 
 
-static int ath_reserve_key_cache_slot(struct ath_softc *sc)
+static int ath_reserve_key_cache_slot(struct ath_common *common)
 {
 {
 	int i;
 	int i;
 
 
 	/* First, try to find slots that would not be available for TKIP. */
 	/* First, try to find slots that would not be available for TKIP. */
-	if (sc->splitmic) {
-		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) {
-			if (!test_bit(i, sc->keymap) &&
-			    (test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
+	if (common->splitmic) {
+		for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) {
+			if (!test_bit(i, common->keymap) &&
+			    (test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
 				return i;
 				return i;
-			if (!test_bit(i + 32, sc->keymap) &&
-			    (test_bit(i, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
+			if (!test_bit(i + 32, common->keymap) &&
+			    (test_bit(i, common->keymap) ||
+			     test_bit(i + 64, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
 				return i + 32;
 				return i + 32;
-			if (!test_bit(i + 64, sc->keymap) &&
-			    (test_bit(i , sc->keymap) ||
-			     test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64 + 32, sc->keymap)))
+			if (!test_bit(i + 64, common->keymap) &&
+			    (test_bit(i , common->keymap) ||
+			     test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64 + 32, common->keymap)))
 				return i + 64;
 				return i + 64;
-			if (!test_bit(i + 64 + 32, sc->keymap) &&
-			    (test_bit(i, sc->keymap) ||
-			     test_bit(i + 32, sc->keymap) ||
-			     test_bit(i + 64, sc->keymap)))
+			if (!test_bit(i + 64 + 32, common->keymap) &&
+			    (test_bit(i, common->keymap) ||
+			     test_bit(i + 32, common->keymap) ||
+			     test_bit(i + 64, common->keymap)))
 				return i + 64 + 32;
 				return i + 64 + 32;
 		}
 		}
 	} else {
 	} else {
-		for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) {
-			if (!test_bit(i, sc->keymap) &&
-			    test_bit(i + 64, sc->keymap))
+		for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) {
+			if (!test_bit(i, common->keymap) &&
+			    test_bit(i + 64, common->keymap))
 				return i;
 				return i;
-			if (test_bit(i, sc->keymap) &&
-			    !test_bit(i + 64, sc->keymap))
+			if (test_bit(i, common->keymap) &&
+			    !test_bit(i + 64, common->keymap))
 				return i + 64;
 				return i + 64;
 		}
 		}
 	}
 	}
 
 
 	/* No partially used TKIP slots, pick any available slot */
 	/* No partially used TKIP slots, pick any available slot */
-	for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) {
+	for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) {
 		/* Do not allow slots that could be needed for TKIP group keys
 		/* Do not allow slots that could be needed for TKIP group keys
 		 * to be used. This limitation could be removed if we know that
 		 * to be used. This limitation could be removed if we know that
 		 * TKIP will not be used. */
 		 * TKIP will not be used. */
 		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
 		if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
 			continue;
 			continue;
-		if (sc->splitmic) {
+		if (common->splitmic) {
 			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
 			if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
 				continue;
 				continue;
 			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
 			if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
 				continue;
 				continue;
 		}
 		}
 
 
-		if (!test_bit(i, sc->keymap))
+		if (!test_bit(i, common->keymap))
 			return i; /* Found a free slot for a key */
 			return i; /* Found a free slot for a key */
 	}
 	}
 
 
@@ -861,11 +862,12 @@ static int ath_reserve_key_cache_slot(struct ath_softc *sc)
 	return -1;
 	return -1;
 }
 }
 
 
-static int ath_key_config(struct ath_softc *sc,
+static int ath_key_config(struct ath_common *common,
 			  struct ieee80211_vif *vif,
 			  struct ieee80211_vif *vif,
 			  struct ieee80211_sta *sta,
 			  struct ieee80211_sta *sta,
 			  struct ieee80211_key_conf *key)
 			  struct ieee80211_key_conf *key)
 {
 {
+	struct ath_hw *ah = common->ah;
 	struct ath9k_keyval hk;
 	struct ath9k_keyval hk;
 	const u8 *mac = NULL;
 	const u8 *mac = NULL;
 	int ret = 0;
 	int ret = 0;
@@ -911,48 +913,50 @@ static int ath_key_config(struct ath_softc *sc,
 		mac = sta->addr;
 		mac = sta->addr;
 
 
 		if (key->alg == ALG_TKIP)
 		if (key->alg == ALG_TKIP)
-			idx = ath_reserve_key_cache_slot_tkip(sc);
+			idx = ath_reserve_key_cache_slot_tkip(common);
 		else
 		else
-			idx = ath_reserve_key_cache_slot(sc);
+			idx = ath_reserve_key_cache_slot(common);
 		if (idx < 0)
 		if (idx < 0)
 			return -ENOSPC; /* no free key cache entries */
 			return -ENOSPC; /* no free key cache entries */
 	}
 	}
 
 
 	if (key->alg == ALG_TKIP)
 	if (key->alg == ALG_TKIP)
-		ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac,
+		ret = ath_setkey_tkip(common, idx, key->key, &hk, mac,
 				      vif->type == NL80211_IFTYPE_AP);
 				      vif->type == NL80211_IFTYPE_AP);
 	else
 	else
-		ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac);
+		ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac);
 
 
 	if (!ret)
 	if (!ret)
 		return -EIO;
 		return -EIO;
 
 
-	set_bit(idx, sc->keymap);
+	set_bit(idx, common->keymap);
 	if (key->alg == ALG_TKIP) {
 	if (key->alg == ALG_TKIP) {
-		set_bit(idx + 64, sc->keymap);
-		if (sc->splitmic) {
-			set_bit(idx + 32, sc->keymap);
-			set_bit(idx + 64 + 32, sc->keymap);
+		set_bit(idx + 64, common->keymap);
+		if (common->splitmic) {
+			set_bit(idx + 32, common->keymap);
+			set_bit(idx + 64 + 32, common->keymap);
 		}
 		}
 	}
 	}
 
 
 	return idx;
 	return idx;
 }
 }
 
 
-static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
+static void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key)
 {
 {
-	ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
+	struct ath_hw *ah = common->ah;
+
+	ath9k_hw_keyreset(ah, key->hw_key_idx);
 	if (key->hw_key_idx < IEEE80211_WEP_NKID)
 	if (key->hw_key_idx < IEEE80211_WEP_NKID)
 		return;
 		return;
 
 
-	clear_bit(key->hw_key_idx, sc->keymap);
+	clear_bit(key->hw_key_idx, common->keymap);
 	if (key->alg != ALG_TKIP)
 	if (key->alg != ALG_TKIP)
 		return;
 		return;
 
 
-	clear_bit(key->hw_key_idx + 64, sc->keymap);
-	if (sc->splitmic) {
-		clear_bit(key->hw_key_idx + 32, sc->keymap);
-		clear_bit(key->hw_key_idx + 64 + 32, sc->keymap);
+	clear_bit(key->hw_key_idx + 64, common->keymap);
+	if (common->splitmic) {
+		clear_bit(key->hw_key_idx + 32, common->keymap);
+		clear_bit(key->hw_key_idx + 64 + 32, common->keymap);
 	}
 	}
 }
 }
 
 
@@ -1023,12 +1027,12 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		/* Reset rssi stats */
 		/* Reset rssi stats */
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 
-		ath_start_ani(sc);
+		ath_start_ani(common);
 	} else {
 	} else {
 		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
 		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
 		common->curaid = 0;
 		common->curaid = 0;
 		/* Stop ANI */
 		/* Stop ANI */
-		del_timer_sync(&sc->ani.timer);
+		del_timer_sync(&common->ani.timer);
 	}
 	}
 }
 }
 
 
@@ -1200,11 +1204,11 @@ fail:
 	ath_deinit_leds(sc);
 	ath_deinit_leds(sc);
 }
 }
 
 
-void ath_radio_enable(struct ath_softc *sc)
+void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
-	struct ieee80211_channel *channel = sc->hw->conf.channel;
+	struct ieee80211_channel *channel = hw->conf.channel;
 	int r;
 	int r;
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
@@ -1241,18 +1245,18 @@ void ath_radio_enable(struct ath_softc *sc)
 			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 			    AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
 
-	ieee80211_wake_queues(sc->hw);
+	ieee80211_wake_queues(hw);
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 }
 }
 
 
-void ath_radio_disable(struct ath_softc *sc)
+void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
-	struct ieee80211_channel *channel = sc->hw->conf.channel;
+	struct ieee80211_channel *channel = hw->conf.channel;
 	int r;
 	int r;
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
-	ieee80211_stop_queues(sc->hw);
+	ieee80211_stop_queues(hw);
 
 
 	/* Disable LED */
 	/* Disable LED */
 	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
 	ath9k_hw_set_gpio(ah, ah->led_pin, 1);
@@ -1266,7 +1270,7 @@ void ath_radio_disable(struct ath_softc *sc)
 	ath_flushrecv(sc);		/* flush recv queue */
 	ath_flushrecv(sc);		/* flush recv queue */
 
 
 	if (!ah->curchan)
 	if (!ah->curchan)
-		ah->curchan = ath_get_curchannel(sc, sc->hw);
+		ah->curchan = ath_get_curchannel(sc, hw);
 
 
 	spin_lock_bh(&sc->sc_resetlock);
 	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, false);
 	r = ath9k_hw_reset(ah, ah->curchan, false);
@@ -1679,19 +1683,19 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	}
 	}
 
 
 	/* Get the hardware key cache size. */
 	/* Get the hardware key cache size. */
-	sc->keymax = ah->caps.keycache_size;
-	if (sc->keymax > ATH_KEYMAX) {
+	common->keymax = ah->caps.keycache_size;
+	if (common->keymax > ATH_KEYMAX) {
 		ath_print(common, ATH_DBG_ANY,
 		ath_print(common, ATH_DBG_ANY,
 			  "Warning, using only %u entries in %u key cache\n",
 			  "Warning, using only %u entries in %u key cache\n",
-			  ATH_KEYMAX, sc->keymax);
-		sc->keymax = ATH_KEYMAX;
+			  ATH_KEYMAX, common->keymax);
+		common->keymax = ATH_KEYMAX;
 	}
 	}
 
 
 	/*
 	/*
 	 * Reset the key cache since some parts do not
 	 * Reset the key cache since some parts do not
 	 * reset the contents on initial power up.
 	 * reset the contents on initial power up.
 	 */
 	 */
-	for (i = 0; i < sc->keymax; i++)
+	for (i = 0; i < common->keymax; i++)
 		ath9k_hw_keyreset(ah, (u16) i);
 		ath9k_hw_keyreset(ah, (u16) i);
 
 
 	/* default to MONITOR mode */
 	/* default to MONITOR mode */
@@ -1761,8 +1765,8 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	/* Initializes the noise floor to a reasonable default value.
 	/* Initializes the noise floor to a reasonable default value.
 	 * Later on this will be updated during ANI processing. */
 	 * Later on this will be updated during ANI processing. */
 
 
-	sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
-	setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc);
+	common->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+	setup_timer(&common->ani.timer, ath_ani_calibrate, (unsigned long)sc);
 
 
 	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
 	if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
 				   ATH9K_CIPHER_TKIP, NULL)) {
 				   ATH9K_CIPHER_TKIP, NULL)) {
@@ -1788,7 +1792,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 				      ATH9K_CIPHER_MIC, NULL)
 				      ATH9K_CIPHER_MIC, NULL)
 	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
 	    && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
 				      0, NULL))
 				      0, NULL))
-		sc->splitmic = 1;
+		common->splitmic = 1;
 
 
 	/* turn on mcast key search if possible */
 	/* turn on mcast key search if possible */
 	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
 	if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
@@ -2634,7 +2638,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
 	if (conf->type == NL80211_IFTYPE_AP    ||
 	if (conf->type == NL80211_IFTYPE_AP    ||
 	    conf->type == NL80211_IFTYPE_ADHOC ||
 	    conf->type == NL80211_IFTYPE_ADHOC ||
 	    conf->type == NL80211_IFTYPE_MONITOR)
 	    conf->type == NL80211_IFTYPE_MONITOR)
-		ath_start_ani(sc);
+		ath_start_ani(common);
 
 
 out:
 out:
 	mutex_unlock(&sc->mutex);
 	mutex_unlock(&sc->mutex);
@@ -2655,7 +2659,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 	mutex_lock(&sc->mutex);
 	mutex_lock(&sc->mutex);
 
 
 	/* Stop ANI */
 	/* Stop ANI */
-	del_timer_sync(&sc->ani.timer);
+	del_timer_sync(&common->ani.timer);
 
 
 	/* Reclaim beacon resources */
 	/* Reclaim beacon resources */
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
 	if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) ||
@@ -2688,23 +2692,38 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ieee80211_conf *conf = &hw->conf;
 	struct ieee80211_conf *conf = &hw->conf;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
-	bool all_wiphys_idle = false, disable_radio = false;
+	bool disable_radio;
 
 
 	mutex_lock(&sc->mutex);
 	mutex_lock(&sc->mutex);
 
 
-	/* Leave this as the first check */
+	/*
+	 * Leave this as the first check because we need to turn on the
+	 * radio if it was disabled before prior to processing the rest
+	 * of the changes. Likewise we must only disable the radio towards
+	 * the end.
+	 */
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+		bool enable_radio;
+		bool all_wiphys_idle;
+		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
 
 		spin_lock_bh(&sc->wiphy_lock);
 		spin_lock_bh(&sc->wiphy_lock);
 		all_wiphys_idle =  ath9k_all_wiphys_idle(sc);
 		all_wiphys_idle =  ath9k_all_wiphys_idle(sc);
+		ath9k_set_wiphy_idle(aphy, idle);
+
+		if (!idle && all_wiphys_idle)
+			enable_radio = true;
+
+		/*
+		 * After we unlock here its possible another wiphy
+		 * can be re-renabled so to account for that we will
+		 * only disable the radio toward the end of this routine
+		 * if by then all wiphys are still idle.
+		 */
 		spin_unlock_bh(&sc->wiphy_lock);
 		spin_unlock_bh(&sc->wiphy_lock);
 
 
-		if (conf->flags & IEEE80211_CONF_IDLE){
-			if (all_wiphys_idle)
-				disable_radio = true;
-		}
-		else if (all_wiphys_idle) {
-			ath_radio_enable(sc);
+		if (enable_radio) {
+			ath_radio_enable(sc, hw);
 			ath_print(common, ATH_DBG_CONFIG,
 			ath_print(common, ATH_DBG_CONFIG,
 				  "not-idle: enabling radio\n");
 				  "not-idle: enabling radio\n");
 		}
 		}
@@ -2779,9 +2798,13 @@ skip_chan_change:
 	if (changed & IEEE80211_CONF_CHANGE_POWER)
 	if (changed & IEEE80211_CONF_CHANGE_POWER)
 		sc->config.txpowlimit = 2 * conf->power_level;
 		sc->config.txpowlimit = 2 * conf->power_level;
 
 
+	spin_lock_bh(&sc->wiphy_lock);
+	disable_radio = ath9k_all_wiphys_idle(sc);
+	spin_unlock_bh(&sc->wiphy_lock);
+
 	if (disable_radio) {
 	if (disable_radio) {
 		ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
 		ath_print(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
-		ath_radio_disable(sc);
+		ath_radio_disable(sc, hw);
 	}
 	}
 
 
 	mutex_unlock(&sc->mutex);
 	mutex_unlock(&sc->mutex);
@@ -2898,7 +2921,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 
 
 	switch (cmd) {
 	switch (cmd) {
 	case SET_KEY:
 	case SET_KEY:
-		ret = ath_key_config(sc, vif, sta, key);
+		ret = ath_key_config(common, vif, sta, key);
 		if (ret >= 0) {
 		if (ret >= 0) {
 			key->hw_key_idx = ret;
 			key->hw_key_idx = ret;
 			/* push IV and Michael MIC generation to stack */
 			/* push IV and Michael MIC generation to stack */
@@ -2911,7 +2934,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
 		}
 		}
 		break;
 		break;
 	case DISABLE_KEY:
 	case DISABLE_KEY:
-		ath_key_delete(sc, key);
+		ath_key_delete(common, key);
 		break;
 		break;
 	default:
 	default:
 		ret = -EINVAL;
 		ret = -EINVAL;

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

@@ -19,6 +19,8 @@
 #ifndef RC_H
 #ifndef RC_H
 #define RC_H
 #define RC_H
 
 
+#include "hw.h"
+
 struct ath_softc;
 struct ath_softc;
 
 
 #define ATH_RATE_MAX     30
 #define ATH_RATE_MAX     30

+ 51 - 262
drivers/net/wireless/ath/ath9k/recv.c

@@ -48,6 +48,7 @@ static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc,
 static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
 static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
 {
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_desc *ds;
 	struct ath_desc *ds;
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 
 
@@ -62,11 +63,13 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
 	BUG_ON(skb == NULL);
 	BUG_ON(skb == NULL);
 	ds->ds_vdata = skb->data;
 	ds->ds_vdata = skb->data;
 
 
-	/* setup rx descriptors. The rx.bufsize here tells the harware
+	/*
+	 * setup rx descriptors. The rx_bufsize here tells the hardware
 	 * how much data it can DMA to us and that we are prepared
 	 * how much data it can DMA to us and that we are prepared
-	 * to process */
+	 * to process
+	 */
 	ath9k_hw_setuprxdesc(ah, ds,
 	ath9k_hw_setuprxdesc(ah, ds,
-			     sc->rx.bufsize,
+			     common->rx_bufsize,
 			     0);
 			     0);
 
 
 	if (sc->rx.rxlink == NULL)
 	if (sc->rx.rxlink == NULL)
@@ -86,190 +89,6 @@ static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
 	sc->rx.rxotherant = 0;
 	sc->rx.rxotherant = 0;
 }
 }
 
 
-/*
- *  Extend 15-bit time stamp from rx descriptor to
- *  a full 64-bit TSF using the current h/w TSF.
-*/
-static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
-{
-	u64 tsf;
-
-	tsf = ath9k_hw_gettsf64(sc->sc_ah);
-	if ((tsf & 0x7fff) < rstamp)
-		tsf -= 0x8000;
-	return (tsf & ~0x7fff) | rstamp;
-}
-
-/*
- * For Decrypt or Demic errors, we only mark packet status here and always push
- * up the frame up to let mac80211 handle the actual error case, be it no
- * decryption key or real decryption error. This let us keep statistics there.
- */
-static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
-			  struct ieee80211_rx_status *rx_status, bool *decrypt_error,
-			  struct ath_softc *sc)
-{
-	struct ieee80211_hdr *hdr;
-	u8 ratecode;
-	__le16 fc;
-	struct ieee80211_hw *hw;
-	struct ieee80211_sta *sta;
-	struct ath_node *an;
-	int last_rssi = ATH_RSSI_DUMMY_MARKER;
-
-
-	hdr = (struct ieee80211_hdr *)skb->data;
-	fc = hdr->frame_control;
-	memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-	hw = ath_get_virt_hw(sc, hdr);
-
-	if (ds->ds_rxstat.rs_more) {
-		/*
-		 * Frame spans multiple descriptors; this cannot happen yet
-		 * as we don't support jumbograms. If not in monitor mode,
-		 * discard the frame. Enable this if you want to see
-		 * error frames in Monitor mode.
-		 */
-		if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR)
-			goto rx_next;
-	} else if (ds->ds_rxstat.rs_status != 0) {
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
-			rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
-			goto rx_next;
-
-		if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
-			*decrypt_error = true;
-		} else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
-			if (ieee80211_is_ctl(fc))
-				/*
-				 * Sometimes, we get invalid
-				 * MIC failures on valid control frames.
-				 * Remove these mic errors.
-				 */
-				ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
-			else
-				rx_status->flag |= RX_FLAG_MMIC_ERROR;
-		}
-		/*
-		 * Reject error frames with the exception of
-		 * decryption and MIC failures. For monitor mode,
-		 * we also ignore the CRC error.
-		 */
-		if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) {
-			if (ds->ds_rxstat.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
-			      ATH9K_RXERR_CRC))
-				goto rx_next;
-		} else {
-			if (ds->ds_rxstat.rs_status &
-			    ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
-				goto rx_next;
-			}
-		}
-	}
-
-	ratecode = ds->ds_rxstat.rs_rate;
-
-	if (ratecode & 0x80) {
-		/* HT rate */
-		rx_status->flag |= RX_FLAG_HT;
-		if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
-			rx_status->flag |= RX_FLAG_40MHZ;
-		if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
-			rx_status->flag |= RX_FLAG_SHORT_GI;
-		rx_status->rate_idx = ratecode & 0x7f;
-	} else {
-		int i = 0, cur_band, n_rates;
-
-		cur_band = hw->conf.channel->band;
-		n_rates = sc->sbands[cur_band].n_bitrates;
-
-		for (i = 0; i < n_rates; i++) {
-			if (sc->sbands[cur_band].bitrates[i].hw_value ==
-			    ratecode) {
-				rx_status->rate_idx = i;
-				break;
-			}
-
-			if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
-			    ratecode) {
-				rx_status->rate_idx = i;
-				rx_status->flag |= RX_FLAG_SHORTPRE;
-				break;
-			}
-		}
-	}
-
-	rcu_read_lock();
-	/* XXX: use ieee80211_find_sta! */
-	sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr2);
-	if (sta) {
-		an = (struct ath_node *) sta->drv_priv;
-		if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD &&
-		   !ds->ds_rxstat.rs_moreaggr)
-			ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi);
-		last_rssi = an->last_rssi;
-	}
-	rcu_read_unlock();
-
-	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-		ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi,
-					ATH_RSSI_EP_MULTIPLIER);
-	if (ds->ds_rxstat.rs_rssi < 0)
-		ds->ds_rxstat.rs_rssi = 0;
-	else if (ds->ds_rxstat.rs_rssi > 127)
-		ds->ds_rxstat.rs_rssi = 127;
-
-	/* Update Beacon RSSI, this is used by ANI. */
-	if (ieee80211_is_beacon(fc))
-		sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi;
-
-	rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
-	rx_status->band = hw->conf.channel->band;
-	rx_status->freq = hw->conf.channel->center_freq;
-	rx_status->noise = sc->ani.noise_floor;
-	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi;
-	rx_status->antenna = ds->ds_rxstat.rs_antenna;
-
-	/*
-	 * Theory for reporting quality:
-	 *
-	 * At a hardware RSSI of 45 you will be able to use MCS 7  reliably.
-	 * At a hardware RSSI of 45 you will be able to use MCS 15 reliably.
-	 * At a hardware RSSI of 35 you should be able use 54 Mbps reliably.
-	 *
-	 * MCS 7  is the highets MCS index usable by a 1-stream device.
-	 * MCS 15 is the highest MCS index usable by a 2-stream device.
-	 *
-	 * All ath9k devices are either 1-stream or 2-stream.
-	 *
-	 * How many bars you see is derived from the qual reporting.
-	 *
-	 * A more elaborate scheme can be used here but it requires tables
-	 * of SNR/throughput for each possible mode used. For the MCS table
-	 * you can refer to the wireless wiki:
-	 *
-	 * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
-	 *
-	 */
-	if (conf_is_ht(&hw->conf))
-		rx_status->qual =  ds->ds_rxstat.rs_rssi * 100 / 45;
-	else
-		rx_status->qual =  ds->ds_rxstat.rs_rssi * 100 / 35;
-
-	/* rssi can be more than 45 though, anything above that
-	 * should be considered at 100% */
-	if (rx_status->qual > 100)
-		rx_status->qual = 100;
-
-	rx_status->flag |= RX_FLAG_TSFT;
-
-	return 1;
-rx_next:
-	return 0;
-}
-
 static void ath_opmode_init(struct ath_softc *sc)
 static void ath_opmode_init(struct ath_softc *sc)
 {
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
@@ -307,11 +126,11 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	spin_lock_init(&sc->rx.rxbuflock);
 	spin_lock_init(&sc->rx.rxbuflock);
 
 
-	sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-				 min(common->cachelsz, (u16)64));
+	common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
+				     min(common->cachelsz, (u16)64));
 
 
 	ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
 	ath_print(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
-		  common->cachelsz, sc->rx.bufsize);
+		  common->cachelsz, common->rx_bufsize);
 
 
 	/* Initialize rx descriptors */
 	/* Initialize rx descriptors */
 
 
@@ -324,7 +143,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	}
 	}
 
 
 	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
 	list_for_each_entry(bf, &sc->rx.rxbuf, list) {
-		skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_KERNEL);
+		skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
 		if (skb == NULL) {
 		if (skb == NULL) {
 			error = -ENOMEM;
 			error = -ENOMEM;
 			goto err;
 			goto err;
@@ -332,7 +151,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 
 
 		bf->bf_mpdu = skb;
 		bf->bf_mpdu = skb;
 		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
 		bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
-						 sc->rx.bufsize,
+						 common->rx_bufsize,
 						 DMA_FROM_DEVICE);
 						 DMA_FROM_DEVICE);
 		if (unlikely(dma_mapping_error(sc->dev,
 		if (unlikely(dma_mapping_error(sc->dev,
 					       bf->bf_buf_addr))) {
 					       bf->bf_buf_addr))) {
@@ -356,6 +175,8 @@ err:
 
 
 void ath_rx_cleanup(struct ath_softc *sc)
 void ath_rx_cleanup(struct ath_softc *sc)
 {
 {
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 	struct ath_buf *bf;
 	struct ath_buf *bf;
 
 
@@ -363,7 +184,7 @@ void ath_rx_cleanup(struct ath_softc *sc)
 		skb = bf->bf_mpdu;
 		skb = bf->bf_mpdu;
 		if (skb) {
 		if (skb) {
 			dma_unmap_single(sc->dev, bf->bf_buf_addr,
 			dma_unmap_single(sc->dev, bf->bf_buf_addr,
-					 sc->rx.bufsize, DMA_FROM_DEVICE);
+					 common->rx_bufsize, DMA_FROM_DEVICE);
 			dev_kfree_skb(skb);
 			dev_kfree_skb(skb);
 		}
 		}
 	}
 	}
@@ -616,8 +437,9 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
 	}
 	}
 }
 }
 
 
-static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
-				    struct ieee80211_rx_status *rx_status)
+static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
+				    struct ath_softc *sc, struct sk_buff *skb,
+				    struct ieee80211_rx_status *rxs)
 {
 {
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_hdr *hdr;
 
 
@@ -637,19 +459,14 @@ static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
 			if (aphy == NULL)
 			if (aphy == NULL)
 				continue;
 				continue;
 			nskb = skb_copy(skb, GFP_ATOMIC);
 			nskb = skb_copy(skb, GFP_ATOMIC);
-			if (nskb) {
-				memcpy(IEEE80211_SKB_RXCB(nskb), rx_status,
-					sizeof(*rx_status));
-				ieee80211_rx(aphy->hw, nskb);
-			}
+			if (!nskb)
+				continue;
+			ieee80211_rx(aphy->hw, nskb);
 		}
 		}
-		memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
 		ieee80211_rx(sc->hw, skb);
 		ieee80211_rx(sc->hw, skb);
-	} else {
+	} else
 		/* Deliver unicast frames based on receiver address */
 		/* Deliver unicast frames based on receiver address */
-		memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
-		ieee80211_rx(ath_get_virt_hw(sc, hdr), skb);
-	}
+		ieee80211_rx(hw, skb);
 }
 }
 
 
 int ath_rx_tasklet(struct ath_softc *sc, int flush)
 int ath_rx_tasklet(struct ath_softc *sc, int flush)
@@ -660,15 +477,20 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 
 
 	struct ath_buf *bf;
 	struct ath_buf *bf;
 	struct ath_desc *ds;
 	struct ath_desc *ds;
+	struct ath_rx_status *rx_stats;
 	struct sk_buff *skb = NULL, *requeue_skb;
 	struct sk_buff *skb = NULL, *requeue_skb;
-	struct ieee80211_rx_status rx_status;
+	struct ieee80211_rx_status *rxs;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
+	/*
+	 * The hw can techncically differ from common->hw when using ath9k
+	 * virtual wiphy so to account for that we iterate over the active
+	 * wiphys and find the appropriate wiphy and therefore hw.
+	 */
+	struct ieee80211_hw *hw = NULL;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_hdr *hdr;
-	int hdrlen, padsize, retval;
+	int retval;
 	bool decrypt_error = false;
 	bool decrypt_error = false;
-	u8 keyix;
-	__le16 fc;
 
 
 	spin_lock_bh(&sc->rx.rxbuflock);
 	spin_lock_bh(&sc->rx.rxbuflock);
 
 
@@ -740,9 +562,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 		 * 2. requeueing the same buffer to h/w
 		 * 2. requeueing the same buffer to h/w
 		 */
 		 */
 		dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
 		dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr,
-				sc->rx.bufsize,
+				common->rx_bufsize,
 				DMA_FROM_DEVICE);
 				DMA_FROM_DEVICE);
 
 
+		hdr = (struct ieee80211_hdr *) skb->data;
+		rxs =  IEEE80211_SKB_RXCB(skb);
+
+		hw = ath_get_virt_hw(sc, hdr);
+		rx_stats = &ds->ds_rxstat;
+
 		/*
 		/*
 		 * If we're asked to flush receive queue, directly
 		 * If we're asked to flush receive queue, directly
 		 * chain it back at the queue without processing it.
 		 * chain it back at the queue without processing it.
@@ -750,19 +578,14 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 		if (flush)
 		if (flush)
 			goto requeue;
 			goto requeue;
 
 
-		if (!ds->ds_rxstat.rs_datalen)
-			goto requeue;
-
-		/* The status portion of the descriptor could get corrupted. */
-		if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
-			goto requeue;
-
-		if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
+		retval = ath9k_cmn_rx_skb_preprocess(common, hw, skb, rx_stats,
+						     rxs, &decrypt_error);
+		if (retval)
 			goto requeue;
 			goto requeue;
 
 
 		/* Ensure we always have an skb to requeue once we are done
 		/* Ensure we always have an skb to requeue once we are done
 		 * processing the current buffer's skb */
 		 * processing the current buffer's skb */
-		requeue_skb = ath_rxbuf_alloc(common, sc->rx.bufsize, GFP_ATOMIC);
+		requeue_skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_ATOMIC);
 
 
 		/* If there is no memory we ignore the current RX'd frame,
 		/* If there is no memory we ignore the current RX'd frame,
 		 * tell hardware it can give us a new frame using the old
 		 * tell hardware it can give us a new frame using the old
@@ -773,60 +596,26 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 
 
 		/* Unmap the frame */
 		/* Unmap the frame */
 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
-				 sc->rx.bufsize,
+				 common->rx_bufsize,
 				 DMA_FROM_DEVICE);
 				 DMA_FROM_DEVICE);
 
 
-		skb_put(skb, ds->ds_rxstat.rs_datalen);
-
-		/* see if any padding is done by the hw and remove it */
-		hdr = (struct ieee80211_hdr *)skb->data;
-		hdrlen = ieee80211_get_hdrlen_from_skb(skb);
-		fc = hdr->frame_control;
-
-		/* The MAC header is padded to have 32-bit boundary if the
-		 * packet payload is non-zero. The general calculation for
-		 * padsize would take into account odd header lengths:
-		 * padsize = (4 - hdrlen % 4) % 4; However, since only
-		 * even-length headers are used, padding can only be 0 or 2
-		 * bytes and we can optimize this a bit. In addition, we must
-		 * not try to remove padding from short control frames that do
-		 * not have payload. */
-		padsize = hdrlen & 3;
-		if (padsize && hdrlen >= 24) {
-			memmove(skb->data + padsize, skb->data, hdrlen);
-			skb_pull(skb, padsize);
-		}
-
-		keyix = ds->ds_rxstat.rs_keyix;
+		skb_put(skb, rx_stats->rs_datalen);
 
 
-		if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
-			rx_status.flag |= RX_FLAG_DECRYPTED;
-		} else if (ieee80211_has_protected(fc)
-			   && !decrypt_error && skb->len >= hdrlen + 4) {
-			keyix = skb->data[hdrlen + 3] >> 6;
-
-			if (test_bit(keyix, sc->keymap))
-				rx_status.flag |= RX_FLAG_DECRYPTED;
-		}
-		if (ah->sw_mgmt_crypto &&
-		    (rx_status.flag & RX_FLAG_DECRYPTED) &&
-		    ieee80211_is_mgmt(fc)) {
-			/* Use software decrypt for management frames. */
-			rx_status.flag &= ~RX_FLAG_DECRYPTED;
-		}
+		ath9k_cmn_rx_skb_postprocess(common, skb, rx_stats,
+					     rxs, decrypt_error);
 
 
 		/* We will now give hardware our shiny new allocated skb */
 		/* We will now give hardware our shiny new allocated skb */
 		bf->bf_mpdu = requeue_skb;
 		bf->bf_mpdu = requeue_skb;
 		bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
 		bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
-					 sc->rx.bufsize,
-					 DMA_FROM_DEVICE);
+						 common->rx_bufsize,
+						 DMA_FROM_DEVICE);
 		if (unlikely(dma_mapping_error(sc->dev,
 		if (unlikely(dma_mapping_error(sc->dev,
 			  bf->bf_buf_addr))) {
 			  bf->bf_buf_addr))) {
 			dev_kfree_skb_any(requeue_skb);
 			dev_kfree_skb_any(requeue_skb);
 			bf->bf_mpdu = NULL;
 			bf->bf_mpdu = NULL;
 			ath_print(common, ATH_DBG_FATAL,
 			ath_print(common, ATH_DBG_FATAL,
 				  "dma_mapping_error() on RX\n");
 				  "dma_mapping_error() on RX\n");
-			ath_rx_send_to_mac80211(sc, skb, &rx_status);
+			ath_rx_send_to_mac80211(hw, sc, skb, rxs);
 			break;
 			break;
 		}
 		}
 		bf->bf_dmacontext = bf->bf_buf_addr;
 		bf->bf_dmacontext = bf->bf_buf_addr;
@@ -837,7 +626,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 		 */
 		 */
 		if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
 		if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
 			if (++sc->rx.rxotherant >= 3)
 			if (++sc->rx.rxotherant >= 3)
-				ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
+				ath_setdefantenna(sc, rx_stats->rs_antenna);
 		} else {
 		} else {
 			sc->rx.rxotherant = 0;
 			sc->rx.rxotherant = 0;
 		}
 		}
@@ -847,7 +636,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
 					     SC_OP_WAIT_FOR_PSPOLL_DATA)))
 					     SC_OP_WAIT_FOR_PSPOLL_DATA)))
 			ath_rx_ps(sc, skb);
 			ath_rx_ps(sc, skb);
 
 
-		ath_rx_send_to_mac80211(sc, skb, &rx_status);
+		ath_rx_send_to_mac80211(hw, sc, skb, rxs);
 
 
 requeue:
 requeue:
 		list_move_tail(&bf->list, &sc->rx.rxbuf);
 		list_move_tail(&bf->list, &sc->rx.rxbuf);

+ 2 - 2
drivers/net/wireless/ath/ath9k/reg.h

@@ -971,10 +971,10 @@ enum {
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S         4
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF        0x00000080
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S      7
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB      0x00000400
+#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S    10
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB        0x00001000
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
 #define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S      12
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB      0x00001000
-#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S    1
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB         0x00008000
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
 #define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S       15
 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000
 #define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE        0x00010000

+ 74 - 5
drivers/net/wireless/ath/ath9k/virtual.c

@@ -298,6 +298,7 @@ static void ath9k_wiphy_unpause_channel(struct ath_softc *sc)
 void ath9k_wiphy_chan_work(struct work_struct *work)
 void ath9k_wiphy_chan_work(struct work_struct *work)
 {
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
 	struct ath_softc *sc = container_of(work, struct ath_softc, chan_work);
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_wiphy *aphy = sc->next_wiphy;
 	struct ath_wiphy *aphy = sc->next_wiphy;
 
 
 	if (aphy == NULL)
 	if (aphy == NULL)
@@ -313,6 +314,10 @@ void ath9k_wiphy_chan_work(struct work_struct *work)
 	/* XXX: remove me eventually */
 	/* XXX: remove me eventually */
 	ath9k_update_ichannel(sc, aphy->hw,
 	ath9k_update_ichannel(sc, aphy->hw,
 			      &sc->sc_ah->channels[sc->chan_idx]);
 			      &sc->sc_ah->channels[sc->chan_idx]);
+
+	/* sync hw configuration for hw code */
+	common->hw = aphy->hw;
+
 	ath_update_chainmask(sc, sc->chan_is_ht);
 	ath_update_chainmask(sc, sc->chan_is_ht);
 	if (ath_set_channel(sc, aphy->hw,
 	if (ath_set_channel(sc, aphy->hw,
 			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
 			    &sc->sc_ah->channels[sc->chan_idx]) < 0) {
@@ -521,8 +526,9 @@ int ath9k_wiphy_select(struct ath_wiphy *aphy)
 			 * frame being completed)
 			 * frame being completed)
 			 */
 			 */
 			spin_unlock_bh(&sc->wiphy_lock);
 			spin_unlock_bh(&sc->wiphy_lock);
-			ath_radio_disable(sc);
-			ath_radio_enable(sc);
+			ath_radio_disable(sc, aphy->hw);
+			ath_radio_enable(sc, aphy->hw);
+			/* Only the primary wiphy hw is used for queuing work */
 			ieee80211_queue_work(aphy->sc->hw,
 			ieee80211_queue_work(aphy->sc->hw,
 				   &aphy->sc->chan_work);
 				   &aphy->sc->chan_work);
 			return -EBUSY; /* previous select still in progress */
 			return -EBUSY; /* previous select still in progress */
@@ -668,15 +674,78 @@ void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int)
 bool ath9k_all_wiphys_idle(struct ath_softc *sc)
 bool ath9k_all_wiphys_idle(struct ath_softc *sc)
 {
 {
 	unsigned int i;
 	unsigned int i;
-	if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) {
+	if (!sc->pri_wiphy->idle)
 		return false;
 		return false;
-	}
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 	for (i = 0; i < sc->num_sec_wiphy; i++) {
 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
 		struct ath_wiphy *aphy = sc->sec_wiphy[i];
 		if (!aphy)
 		if (!aphy)
 			continue;
 			continue;
-		if (aphy->state != ATH_WIPHY_INACTIVE)
+		if (!aphy->idle)
 			return false;
 			return false;
 	}
 	}
 	return true;
 	return true;
 }
 }
+
+/* caller must hold wiphy_lock */
+void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
+{
+	struct ath_softc *sc = aphy->sc;
+
+	aphy->idle = idle;
+	ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
+		  "Marking %s as %s\n",
+		  wiphy_name(aphy->hw->wiphy),
+		  idle ? "idle" : "not-idle");
+}
+/* Only bother starting a queue on an active virtual wiphy */
+void ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
+{
+	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
+	unsigned int i;
+
+	spin_lock_bh(&sc->wiphy_lock);
+
+	/* Start the primary wiphy */
+	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
+		ieee80211_wake_queue(hw, skb_queue);
+		goto unlock;
+	}
+
+	/* Now start the secondary wiphy queues */
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (!aphy)
+			continue;
+		if (aphy->state != ATH_WIPHY_ACTIVE)
+			continue;
+
+		hw = aphy->hw;
+		ieee80211_wake_queue(hw, skb_queue);
+		break;
+	}
+
+unlock:
+	spin_unlock_bh(&sc->wiphy_lock);
+}
+
+/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
+void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
+{
+	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
+	unsigned int i;
+
+	spin_lock_bh(&sc->wiphy_lock);
+
+	/* Stop the primary wiphy */
+	ieee80211_stop_queue(hw, skb_queue);
+
+	/* Now stop the secondary wiphy queues */
+	for (i = 0; i < sc->num_sec_wiphy; i++) {
+		struct ath_wiphy *aphy = sc->sec_wiphy[i];
+		if (!aphy)
+			continue;
+		hw = aphy->hw;
+		ieee80211_stop_queue(hw, skb_queue);
+	}
+	spin_unlock_bh(&sc->wiphy_lock);
+}

+ 14 - 7
drivers/net/wireless/ath/ath9k/xmit.c

@@ -267,7 +267,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	struct ath_node *an = NULL;
 	struct ath_node *an = NULL;
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 	struct ieee80211_sta *sta;
 	struct ieee80211_sta *sta;
+	struct ieee80211_hw *hw;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_hdr *hdr;
+	struct ieee80211_tx_info *tx_info;
+	struct ath_tx_info_priv *tx_info_priv;
 	struct ath_atx_tid *tid = NULL;
 	struct ath_atx_tid *tid = NULL;
 	struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
 	struct ath_buf *bf_next, *bf_last = bf->bf_lastbf;
 	struct ath_desc *ds = bf_last->bf_desc;
 	struct ath_desc *ds = bf_last->bf_desc;
@@ -280,10 +283,14 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	skb = bf->bf_mpdu;
 	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
 	hdr = (struct ieee80211_hdr *)skb->data;
 
 
+	tx_info = IEEE80211_SKB_CB(skb);
+	tx_info_priv = (struct ath_tx_info_priv *) tx_info->rate_driver_data[0];
+	hw = tx_info_priv->aphy->hw;
+
 	rcu_read_lock();
 	rcu_read_lock();
 
 
 	/* XXX: use ieee80211_find_sta! */
 	/* XXX: use ieee80211_find_sta! */
-	sta = ieee80211_find_sta_by_hw(sc->hw, hdr->addr1);
+	sta = ieee80211_find_sta_by_hw(hw, hdr->addr1);
 	if (!sta) {
 	if (!sta) {
 		rcu_read_unlock();
 		rcu_read_unlock();
 		return;
 		return;
@@ -908,9 +915,10 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
 struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
 struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
 {
 {
 	struct ath_txq *txq = NULL;
 	struct ath_txq *txq = NULL;
+	u16 skb_queue = skb_get_queue_mapping(skb);
 	int qnum;
 	int qnum;
 
 
-	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+	qnum = ath_get_hal_qnum(skb_queue, sc);
 	txq = &sc->tx.txq[qnum];
 	txq = &sc->tx.txq[qnum];
 
 
 	spin_lock_bh(&txq->axq_lock);
 	spin_lock_bh(&txq->axq_lock);
@@ -919,7 +927,7 @@ struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_XMIT,
 			  "TX queue: %d is full, depth: %d\n",
 			  "TX queue: %d is full, depth: %d\n",
 			  qnum, txq->axq_depth);
 			  qnum, txq->axq_depth);
-		ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
+		ath_mac80211_stop_queue(sc, skb_queue);
 		txq->stopped = 1;
 		txq->stopped = 1;
 		spin_unlock_bh(&txq->axq_lock);
 		spin_unlock_bh(&txq->axq_lock);
 		return NULL;
 		return NULL;
@@ -1569,7 +1577,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
 
 
 	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
 	bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
 
 
-	if (conf_is_ht(&sc->hw->conf) && !is_pae(skb))
+	if (conf_is_ht(&hw->conf) && !is_pae(skb))
 		bf->bf_state.bf_type |= BUF_HT;
 		bf->bf_state.bf_type |= BUF_HT;
 
 
 	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
 	bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
@@ -1698,8 +1706,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		 * on the queue */
 		 * on the queue */
 		spin_lock_bh(&txq->axq_lock);
 		spin_lock_bh(&txq->axq_lock);
 		if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
 		if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) {
-			ieee80211_stop_queue(sc->hw,
-				skb_get_queue_mapping(skb));
+			ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
 			txq->stopped = 1;
 			txq->stopped = 1;
 		}
 		}
 		spin_unlock_bh(&txq->axq_lock);
 		spin_unlock_bh(&txq->axq_lock);
@@ -1939,7 +1946,7 @@ static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
 	    sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
 	    sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) {
 		qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
 		qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc);
 		if (qnum != -1) {
 		if (qnum != -1) {
-			ieee80211_wake_queue(sc->hw, qnum);
+			ath_mac80211_start_queue(sc, qnum);
 			txq->stopped = 0;
 			txq->stopped = 0;
 		}
 		}
 	}
 	}

+ 16 - 0
drivers/net/wireless/atmel.c

@@ -99,6 +99,22 @@ static struct {
 	{ ATMEL_FW_TYPE_506,		"atmel_at76c506",	"bin" },
 	{ ATMEL_FW_TYPE_506,		"atmel_at76c506",	"bin" },
 	{ ATMEL_FW_TYPE_NONE,		NULL,			NULL }
 	{ ATMEL_FW_TYPE_NONE,		NULL,			NULL }
 };
 };
+MODULE_FIRMWARE("atmel_at76c502-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c502.bin");
+MODULE_FIRMWARE("atmel_at76c502d-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c502d.bin");
+MODULE_FIRMWARE("atmel_at76c502e-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c502e.bin");
+MODULE_FIRMWARE("atmel_at76c502_3com-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c502_3com.bin");
+MODULE_FIRMWARE("atmel_at76c504-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c504.bin");
+MODULE_FIRMWARE("atmel_at76c504_2958-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c504_2958.bin");
+MODULE_FIRMWARE("atmel_at76c504a_2958-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c504a_2958.bin");
+MODULE_FIRMWARE("atmel_at76c506-wpa.bin");
+MODULE_FIRMWARE("atmel_at76c506.bin");
 
 
 #define MAX_SSID_LENGTH 32
 #define MAX_SSID_LENGTH 32
 #define MGMT_JIFFIES (256 * HZ / 100)
 #define MGMT_JIFFIES (256 * HZ / 100)

+ 20 - 28
drivers/net/wireless/b43/dma.c

@@ -1157,18 +1157,17 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
 }
 }
 
 
 static int dma_tx_fragment(struct b43_dmaring *ring,
 static int dma_tx_fragment(struct b43_dmaring *ring,
-			   struct sk_buff **in_skb)
+			   struct sk_buff *skb)
 {
 {
-	struct sk_buff *skb = *in_skb;
 	const struct b43_dma_ops *ops = ring->ops;
 	const struct b43_dma_ops *ops = ring->ops;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct b43_private_tx_info *priv_info = b43_get_priv_tx_info(info);
 	u8 *header;
 	u8 *header;
 	int slot, old_top_slot, old_used_slots;
 	int slot, old_top_slot, old_used_slots;
 	int err;
 	int err;
 	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_generic *desc;
 	struct b43_dmadesc_meta *meta;
 	struct b43_dmadesc_meta *meta;
 	struct b43_dmadesc_meta *meta_hdr;
 	struct b43_dmadesc_meta *meta_hdr;
-	struct sk_buff *bounce_skb;
 	u16 cookie;
 	u16 cookie;
 	size_t hdrsize = b43_txhdr_size(ring->dev);
 	size_t hdrsize = b43_txhdr_size(ring->dev);
 
 
@@ -1212,34 +1211,28 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 
 
 	meta->skb = skb;
 	meta->skb = skb;
 	meta->is_last_fragment = 1;
 	meta->is_last_fragment = 1;
+	priv_info->bouncebuffer = NULL;
 
 
 	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
 	/* create a bounce buffer in zone_dma on mapping failure. */
 	/* create a bounce buffer in zone_dma on mapping failure. */
 	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
 	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
-		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
-		if (!bounce_skb) {
+		priv_info->bouncebuffer = kmalloc(skb->len, GFP_ATOMIC | GFP_DMA);
+		if (!priv_info->bouncebuffer) {
 			ring->current_slot = old_top_slot;
 			ring->current_slot = old_top_slot;
 			ring->used_slots = old_used_slots;
 			ring->used_slots = old_used_slots;
 			err = -ENOMEM;
 			err = -ENOMEM;
 			goto out_unmap_hdr;
 			goto out_unmap_hdr;
 		}
 		}
+		memcpy(priv_info->bouncebuffer, skb->data, skb->len);
 
 
-		memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
-		memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
-		bounce_skb->dev = skb->dev;
-		skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
-		info = IEEE80211_SKB_CB(bounce_skb);
-
-		dev_kfree_skb_any(skb);
-		skb = bounce_skb;
-		*in_skb = bounce_skb;
-		meta->skb = skb;
-		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+		meta->dmaaddr = map_descbuffer(ring, priv_info->bouncebuffer, skb->len, 1);
 		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
 		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+			kfree(priv_info->bouncebuffer);
+			priv_info->bouncebuffer = NULL;
 			ring->current_slot = old_top_slot;
 			ring->current_slot = old_top_slot;
 			ring->used_slots = old_used_slots;
 			ring->used_slots = old_used_slots;
 			err = -EIO;
 			err = -EIO;
-			goto out_free_bounce;
+			goto out_unmap_hdr;
 		}
 		}
 	}
 	}
 
 
@@ -1256,8 +1249,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
 	ops->poke_tx(ring, next_slot(ring, slot));
 	ops->poke_tx(ring, next_slot(ring, slot));
 	return 0;
 	return 0;
 
 
-out_free_bounce:
-	dev_kfree_skb_any(skb);
 out_unmap_hdr:
 out_unmap_hdr:
 	unmap_descbuffer(ring, meta_hdr->dmaaddr,
 	unmap_descbuffer(ring, meta_hdr->dmaaddr,
 			 hdrsize, 1);
 			 hdrsize, 1);
@@ -1362,11 +1353,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
 	 * static, so we don't need to store it per frame. */
 	 * static, so we don't need to store it per frame. */
 	ring->queue_prio = skb_get_queue_mapping(skb);
 	ring->queue_prio = skb_get_queue_mapping(skb);
 
 
-	/* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
-	 * into the skb data or cb now. */
-	hdr = NULL;
-	info = NULL;
-	err = dma_tx_fragment(ring, &skb);
+	err = dma_tx_fragment(ring, skb);
 	if (unlikely(err == -ENOKEY)) {
 	if (unlikely(err == -ENOKEY)) {
 		/* Drop this packet, as we don't have the encryption key
 		/* Drop this packet, as we don't have the encryption key
 		 * anymore and must not transmit it unencrypted. */
 		 * anymore and must not transmit it unencrypted. */
@@ -1413,12 +1400,17 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 		B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
 		B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
 		desc = ops->idx2desc(ring, slot, &meta);
 		desc = ops->idx2desc(ring, slot, &meta);
 
 
-		if (meta->skb)
-			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len,
-					 1);
-		else
+		if (meta->skb) {
+			struct b43_private_tx_info *priv_info =
+				b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+
+			unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+			kfree(priv_info->bouncebuffer);
+			priv_info->bouncebuffer = NULL;
+		} else {
 			unmap_descbuffer(ring, meta->dmaaddr,
 			unmap_descbuffer(ring, meta->dmaaddr,
 					 b43_txhdr_size(dev), 1);
 					 b43_txhdr_size(dev), 1);
+		}
 
 
 		if (meta->is_last_fragment) {
 		if (meta->is_last_fragment) {
 			struct ieee80211_tx_info *info;
 			struct ieee80211_tx_info *info;

+ 5 - 1
drivers/net/wireless/b43/pio.c

@@ -761,7 +761,11 @@ data_ready:
 rx_error:
 rx_error:
 	if (err_msg)
 	if (err_msg)
 		b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
 		b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
-	b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
+	if (q->rev >= 8)
+		b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
+	else
+		b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
+
 	return 1;
 	return 1;
 }
 }
 
 

+ 19 - 0
drivers/net/wireless/b43/xmit.h

@@ -2,6 +2,8 @@
 #define B43_XMIT_H_
 #define B43_XMIT_H_
 
 
 #include "main.h"
 #include "main.h"
+#include <net/mac80211.h>
+
 
 
 #define _b43_declare_plcp_hdr(size) \
 #define _b43_declare_plcp_hdr(size) \
 	struct b43_plcp_hdr##size {		\
 	struct b43_plcp_hdr##size {		\
@@ -332,4 +334,21 @@ static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx)
 	return raw_kidx;
 	return raw_kidx;
 }
 }
 
 
+/* struct b43_private_tx_info - TX info private to b43.
+ * The structure is placed in (struct ieee80211_tx_info *)->rate_driver_data
+ *
+ * @bouncebuffer: DMA Bouncebuffer (if used)
+ */
+struct b43_private_tx_info {
+	void *bouncebuffer;
+};
+
+static inline struct b43_private_tx_info *
+b43_get_priv_tx_info(struct ieee80211_tx_info *info)
+{
+	BUILD_BUG_ON(sizeof(struct b43_private_tx_info) >
+		     sizeof(info->rate_driver_data));
+	return (struct b43_private_tx_info *)info->rate_driver_data;
+}
+
 #endif /* B43_XMIT_H_ */
 #endif /* B43_XMIT_H_ */

+ 6 - 0
drivers/net/wireless/ipw2x00/ipw2100.c

@@ -8462,6 +8462,12 @@ static int ipw2100_get_firmware(struct ipw2100_priv *priv,
 	return 0;
 	return 0;
 }
 }
 
 
+MODULE_FIRMWARE(IPW2100_FW_NAME("-i"));
+#ifdef CONFIG_IPW2100_MONITOR
+MODULE_FIRMWARE(IPW2100_FW_NAME("-p"));
+#endif
+MODULE_FIRMWARE(IPW2100_FW_NAME(""));
+
 static void ipw2100_release_firmware(struct ipw2100_priv *priv,
 static void ipw2100_release_firmware(struct ipw2100_priv *priv,
 				     struct ipw2100_fw *fw)
 				     struct ipw2100_fw *fw)
 {
 {

+ 5 - 0
drivers/net/wireless/ipw2x00/ipw2200.c

@@ -80,6 +80,11 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_VERSION(DRV_VERSION);
 MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_AUTHOR(DRV_COPYRIGHT);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("ipw2200-ibss.fw");
+#ifdef CONFIG_IPW2200_MONITOR
+MODULE_FIRMWARE("ipw2200-sniffer.fw");
+#endif
+MODULE_FIRMWARE("ipw2200-bss.fw");
 
 
 static int cmdlog = 0;
 static int cmdlog = 0;
 static int debug = 0;
 static int debug = 0;

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

@@ -564,7 +564,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
 		return;
 		return;
 	}
 	}
 
 
-	skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
+	skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
 	if (!skb) {
 	if (!skb) {
 		IWL_ERR(priv, "alloc_skb failed\n");
 		IWL_ERR(priv, "alloc_skb failed\n");
 		return;
 		return;
@@ -575,6 +575,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
 				       (struct ieee80211_hdr *)rxb_addr(rxb),
 				       (struct ieee80211_hdr *)rxb_addr(rxb),
 				       le32_to_cpu(rx_end->status), stats);
 				       le32_to_cpu(rx_end->status), stats);
 
 
+	skb_reserve(skb, IWL_LINK_HDR_MAX);
 	skb_add_rx_frag(skb, 0, rxb->page,
 	skb_add_rx_frag(skb, 0, rxb->page,
 			(void *)rx_hdr->payload - (void *)pkt, len);
 			(void *)rx_hdr->payload - (void *)pkt, len);
 
 

+ 8 - 6
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -1449,14 +1449,14 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 	is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
 	is_ht40 = is_ht40_channel(priv->staging_rxon.flags);
 
 
 	if (is_ht40 &&
 	if (is_ht40 &&
-	    (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+	    (priv->staging_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
 		ctrl_chan_high = 1;
 		ctrl_chan_high = 1;
 
 
 	cmd.band = band;
 	cmd.band = band;
 	cmd.expect_beacon = 0;
 	cmd.expect_beacon = 0;
 	cmd.channel = cpu_to_le16(channel);
 	cmd.channel = cpu_to_le16(channel);
-	cmd.rxon_flags = priv->active_rxon.flags;
-	cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
+	cmd.rxon_flags = priv->staging_rxon.flags;
+	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	if (ch_info)
 	if (ch_info)
 		cmd.expect_beacon = is_channel_radar(ch_info);
 		cmd.expect_beacon = is_channel_radar(ch_info);
@@ -1473,8 +1473,10 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 		return rc;
 		return rc;
 	}
 	}
 
 
-	rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-	return rc;
+	priv->switch_rxon.channel = cpu_to_le16(channel);
+	priv->switch_rxon.switch_in_progress = true;
+
+	return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
 }
 }
 
 
 /**
 /**
@@ -2228,7 +2230,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
 	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
 	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
 	.mod_params = &iwl4965_mod_params,
 	.mod_params = &iwl4965_mod_params,
 	.valid_tx_ant = ANT_AB,
 	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
+	.valid_rx_ant = ANT_ABC,
 	.pll_cfg_val = 0,
 	.pll_cfg_val = 0,
 	.set_l0s = true,
 	.set_l0s = true,
 	.use_bsm = true,
 	.use_bsm = true,

+ 11 - 5
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -661,9 +661,13 @@ int iwl5000_alive_notify(struct iwl_priv *priv)
 		iwl_txq_ctx_activate(priv, i);
 		iwl_txq_ctx_activate(priv, i);
 		iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
 		iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
 	}
 	}
-	/* TODO - need to initialize those FIFOs inside the loop above,
-	 * not only mark them as active */
-	iwl_txq_ctx_activate(priv, 4);
+
+	/*
+	 * TODO - need to initialize these queues and map them to FIFOs
+	 * in the loop above, not only mark them as active. We do this
+	 * because we want the first aggregation queue to be queue #10,
+	 * but do not use 8 or 9 otherwise yet.
+	 */
 	iwl_txq_ctx_activate(priv, 7);
 	iwl_txq_ctx_activate(priv, 7);
 	iwl_txq_ctx_activate(priv, 8);
 	iwl_txq_ctx_activate(priv, 8);
 	iwl_txq_ctx_activate(priv, 9);
 	iwl_txq_ctx_activate(priv, 9);
@@ -1387,8 +1391,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 		priv->active_rxon.channel, channel);
 		priv->active_rxon.channel, channel);
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
 	cmd.channel = cpu_to_le16(channel);
 	cmd.channel = cpu_to_le16(channel);
-	cmd.rxon_flags = priv->active_rxon.flags;
-	cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
+	cmd.rxon_flags = priv->staging_rxon.flags;
+	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 	if (ch_info)
 	if (ch_info)
@@ -1398,6 +1402,8 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 			priv->active_rxon.channel, channel);
 			priv->active_rxon.channel, channel);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
+	priv->switch_rxon.channel = cpu_to_le16(channel);
+	priv->switch_rxon.switch_in_progress = true;
 
 
 	return iwl_send_cmd_sync(priv, &hcmd);
 	return iwl_send_cmd_sync(priv, &hcmd);
 }
 }

+ 5 - 101
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -90,11 +90,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
 		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
 		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
 
 
 	/* no locking required for register write */
 	/* no locking required for register write */
-	if (priv->cfg->pa_type == IWL_PA_HYBRID) {
-		/* 2x2 hybrid phy type */
-		iwl_write32(priv, CSR_GP_DRIVER_REG,
-			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB);
-	} else if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
+	if (priv->cfg->pa_type == IWL_PA_INTERNAL) {
 		/* 2x2 IPA phy type */
 		/* 2x2 IPA phy type */
 		iwl_write32(priv, CSR_GP_DRIVER_REG,
 		iwl_write32(priv, CSR_GP_DRIVER_REG,
 			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
 			     CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA);
@@ -166,9 +162,7 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 			BIT(IWL_CALIB_XTAL)		|
 			BIT(IWL_CALIB_XTAL)		|
 			BIT(IWL_CALIB_LO)		|
 			BIT(IWL_CALIB_LO)		|
 			BIT(IWL_CALIB_TX_IQ) 		|
 			BIT(IWL_CALIB_TX_IQ) 		|
-			BIT(IWL_CALIB_TX_IQ_PERD)	|
 			BIT(IWL_CALIB_BASE_BAND);
 			BIT(IWL_CALIB_BASE_BAND);
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -188,8 +182,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 
 
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
 	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
 	cmd.channel = cpu_to_le16(channel);
 	cmd.channel = cpu_to_le16(channel);
-	cmd.rxon_flags = priv->active_rxon.flags;
-	cmd.rxon_filter_flags = priv->active_rxon.filter_flags;
+	cmd.rxon_flags = priv->staging_rxon.flags;
+	cmd.rxon_filter_flags = priv->staging_rxon.filter_flags;
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 	ch_info = iwl_get_channel_info(priv, priv->band, channel);
 	if (ch_info)
 	if (ch_info)
@@ -199,6 +193,8 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, u16 channel)
 			priv->active_rxon.channel, channel);
 			priv->active_rxon.channel, channel);
 		return -EFAULT;
 		return -EFAULT;
 	}
 	}
+	priv->switch_rxon.channel = cpu_to_le16(channel);
+	priv->switch_rxon.switch_in_progress = true;
 
 
 	return iwl_send_cmd_sync(priv, &hcmd);
 	return iwl_send_cmd_sync(priv, &hcmd);
 }
 }
@@ -279,98 +275,6 @@ static struct iwl_ops iwl6050_ops = {
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
 };
 };
 
 
-
-/*
- * "h": Hybrid configuration, use both internal and external Power Amplifier
- */
-struct iwl_cfg iwl6000h_2agn_cfg = {
-	.name = "6000 Series 2x2 AGN",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWL50_NUM_QUEUES,
-	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
-	.mod_params = &iwl50_mod_params,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_HYBRID,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.use_rts_for_ht = true, /* use rts/cts protection */
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-};
-
-struct iwl_cfg iwl6000h_2abg_cfg = {
-	.name = "6000 Series 2x2 ABG",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWL50_NUM_QUEUES,
-	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
-	.mod_params = &iwl50_mod_params,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_HYBRID,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-};
-
-struct iwl_cfg iwl6000h_2bg_cfg = {
-	.name = "6000 Series 2x2 BG",
-	.fw_name_pre = IWL6000_FW_PRE,
-	.ucode_api_max = IWL6000_UCODE_API_MAX,
-	.ucode_api_min = IWL6000_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.ops = &iwl6000_ops,
-	.eeprom_size = OTP_LOW_IMAGE_SIZE,
-	.eeprom_ver = EEPROM_6000_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
-	.num_of_queues = IWL50_NUM_QUEUES,
-	.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
-	.mod_params = &iwl50_mod_params,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_AB,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = false,
-	.pa_type = IWL_PA_HYBRID,
-	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
-	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
-	.led_compensation = 51,
-	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
-	.adv_thermal_throttle = true,
-	.support_ct_kill_exit = true,
-};
-
 /*
 /*
  * "i": Internal configuration, use internal Power Amplifier
  * "i": Internal configuration, use internal Power Amplifier
  */
  */

+ 52 - 27
drivers/net/wireless/iwlwifi/iwl-agn.c

@@ -122,6 +122,17 @@ int iwl_commit_rxon(struct iwl_priv *priv)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
+	/*
+	 * receive commit_rxon request
+	 * abort any previous channel switch if still in process
+	 */
+	if (priv->switch_rxon.switch_in_progress &&
+	    (priv->switch_rxon.channel != priv->staging_rxon.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		priv->switch_rxon.switch_in_progress = false;
+	}
+
 	/* If we don't need to send a full RXON, we can use
 	/* If we don't need to send a full RXON, we can use
 	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
 	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
 	 * and other flags for the current radio configuration. */
 	 * and other flags for the current radio configuration. */
@@ -133,6 +144,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
 		}
 		}
 
 
 		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
 		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
+		iwl_print_rx_config_cmd(priv);
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -228,6 +240,7 @@ int iwl_commit_rxon(struct iwl_priv *priv)
 		}
 		}
 		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
 		memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
 	}
 	}
+	iwl_print_rx_config_cmd(priv);
 
 
 	iwl_init_sensitivity(priv);
 	iwl_init_sensitivity(priv);
 
 
@@ -1071,6 +1084,7 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 	u32 inta = 0;
 	u32 inta = 0;
 	u32 handled = 0;
 	u32 handled = 0;
 	unsigned long flags;
 	unsigned long flags;
+	u32 i;
 #ifdef CONFIG_IWLWIFI_DEBUG
 #ifdef CONFIG_IWLWIFI_DEBUG
 	u32 inta_mask;
 	u32 inta_mask;
 #endif
 #endif
@@ -1181,12 +1195,8 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
 	if (inta & CSR_INT_BIT_WAKEUP) {
 	if (inta & CSR_INT_BIT_WAKEUP) {
 		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
 		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
 		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
 		iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
-		iwl_txq_update_write_ptr(priv, &priv->txq[0]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[1]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[2]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[3]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[4]);
-		iwl_txq_update_write_ptr(priv, &priv->txq[5]);
+		for (i = 0; i < priv->hw_params.max_txq_num; i++)
+			iwl_txq_update_write_ptr(priv, &priv->txq[i]);
 
 
 		priv->isr_stats.wakeup++;
 		priv->isr_stats.wakeup++;
 
 
@@ -1653,6 +1663,7 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
 	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
 	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ev, time, data; /* event log data */
 	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
 
 
 	if (num_events == 0)
 	if (num_events == 0)
 		return;
 		return;
@@ -1668,27 +1679,39 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
 
 
 	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
 	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
 
 
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
 	/* "time" is actually "data" for mode 0 (no timestamp).
 	/* "time" is actually "data" for mode 0 (no timestamp).
 	* place event id # at far right for easier visual parsing. */
 	* place event id # at far right for easier visual parsing. */
 	for (i = 0; i < num_events; i++) {
 	for (i = 0; i < num_events; i++) {
-		ev = iwl_read_targ_mem(priv, ptr);
-		ptr += sizeof(u32);
-		time = iwl_read_targ_mem(priv, ptr);
-		ptr += sizeof(u32);
+		ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
 		if (mode == 0) {
 		if (mode == 0) {
 			/* data, ev */
 			/* data, ev */
 			trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
 			trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
 			IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
 			IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev);
 		} else {
 		} else {
-			data = iwl_read_targ_mem(priv, ptr);
-			ptr += sizeof(u32);
+			data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
 			IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
 			IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
 					time, data, ev);
 					time, data, ev);
 			trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
 			trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
 		}
 		}
 	}
 	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 }
 
 
+/* For sanity check only.  Actual size is determined by uCode, typ. 512 */
+#define MAX_EVENT_LOG_SIZE (512)
+
 void iwl_dump_nic_event_log(struct iwl_priv *priv)
 void iwl_dump_nic_event_log(struct iwl_priv *priv)
 {
 {
 	u32 base;       /* SRAM byte address of event log header */
 	u32 base;       /* SRAM byte address of event log header */
@@ -1714,6 +1737,18 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
 	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
 	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
 	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 
 
+	if (capacity > MAX_EVENT_LOG_SIZE) {
+		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
+			capacity, MAX_EVENT_LOG_SIZE);
+		capacity = MAX_EVENT_LOG_SIZE;
+	}
+
+	if (next_entry > MAX_EVENT_LOG_SIZE) {
+		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
+			next_entry, MAX_EVENT_LOG_SIZE);
+		next_entry = MAX_EVENT_LOG_SIZE;
+	}
+
 	size = num_wraps ? capacity : next_entry;
 	size = num_wraps ? capacity : next_entry;
 
 
 	/* bail out if nothing in log */
 	/* bail out if nothing in log */
@@ -1899,19 +1934,17 @@ static void __iwl_down(struct iwl_priv *priv)
 
 
 	/* device going down, Stop using ICT table */
 	/* device going down, Stop using ICT table */
 	iwl_disable_ict(priv);
 	iwl_disable_ict(priv);
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_clear_bit(priv, CSR_GP_CNTRL,
-			 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-	spin_unlock_irqrestore(&priv->lock, flags);
 
 
 	iwl_txq_ctx_stop(priv);
 	iwl_txq_ctx_stop(priv);
 	iwl_rxq_stop(priv);
 	iwl_rxq_stop(priv);
 
 
-	iwl_write_prph(priv, APMG_CLK_DIS_REG,
-				APMG_CLK_VAL_DMA_CLK_RQT);
-
+	/* Power-down device's busmaster DMA clocks */
+	iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
 	udelay(5);
 	udelay(5);
 
 
+	/* Make sure (redundant) we've released our request to stay awake */
+	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
 	/* Stop the device, and put it in low power state */
 	/* Stop the device, and put it in low power state */
 	priv->cfg->ops->lib->apm_ops.stop(priv);
 	priv->cfg->ops->lib->apm_ops.stop(priv);
 
 
@@ -3439,14 +3472,6 @@ static struct pci_device_id iwl_hw_card_ids[] = {
 	{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
 	{IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
 
 
 /* 6x00 Series */
 /* 6x00 Series */
-	{IWL_PCI_DEVICE(0x008D, 0x1301, iwl6000h_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008D, 0x1321, iwl6000h_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008D, 0x1326, iwl6000h_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008D, 0x1306, iwl6000h_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008D, 0x1307, iwl6000h_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x008E, 0x1311, iwl6000h_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008E, 0x1316, iwl6000h_2abg_cfg)},
-
 	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422B, 0x1121, iwl6000_3agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x422C, 0x1301, iwl6000i_2agn_cfg)},

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

@@ -2566,9 +2566,10 @@ struct iwl_scan_channel {
 /**
 /**
  * struct iwl_ssid_ie - directed scan network information element
  * struct iwl_ssid_ie - directed scan network information element
  *
  *
- * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
- * in struct iwl_scan_channel; each channel may select different ssids from
- * among the 4 entries.  SSID IEs get transmitted in reverse order of entry.
+ * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
+ * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
+ * each channel may select different ssids from among the 20 (4) entries.
+ * SSID IEs get transmitted in reverse order of entry.
  */
  */
 struct iwl_ssid_ie {
 struct iwl_ssid_ie {
 	u8 id;
 	u8 id;

+ 31 - 23
drivers/net/wireless/iwlwifi/iwl-core.c

@@ -1316,19 +1316,24 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
 	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
 	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
 	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
 	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
 
 
-	if (!le32_to_cpu(csa->status)) {
-		rxon->channel = csa->channel;
-		priv->staging_rxon.channel = csa->channel;
-		IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-		      le16_to_cpu(csa->channel));
-	} else
-		IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
-		      le16_to_cpu(csa->channel));
+	if (priv->switch_rxon.switch_in_progress) {
+		if (!le32_to_cpu(csa->status) &&
+		    (csa->channel == priv->switch_rxon.channel)) {
+			rxon->channel = csa->channel;
+			priv->staging_rxon.channel = csa->channel;
+			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+			      le16_to_cpu(csa->channel));
+		} else
+			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+			      le16_to_cpu(csa->channel));
+
+		priv->switch_rxon.switch_in_progress = false;
+	}
 }
 }
 EXPORT_SYMBOL(iwl_rx_csa);
 EXPORT_SYMBOL(iwl_rx_csa);
 
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 #ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 {
 {
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 	struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
 
 
@@ -1346,6 +1351,7 @@ static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
 	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
 }
+EXPORT_SYMBOL(iwl_print_rx_config_cmd);
 #endif
 #endif
 /**
 /**
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
@@ -2310,12 +2316,6 @@ static void iwl_ht_conf(struct iwl_priv *priv,
 					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
 					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
 			maxstreams += 1;
 			maxstreams += 1;
 
 
-			ht_conf->sm_ps =
-				(u8)((ht_cap->cap & IEEE80211_HT_CAP_SM_PS)
-				>> 2);
-			IWL_DEBUG_MAC80211(priv, "sm_ps: 0x%x\n",
-				ht_conf->sm_ps);
-
 			if ((ht_cap->mcs.rx_mask[1] == 0) &&
 			if ((ht_cap->mcs.rx_mask[1] == 0) &&
 			    (ht_cap->mcs.rx_mask[2] == 0))
 			    (ht_cap->mcs.rx_mask[2] == 0))
 				ht_conf->single_chain_sufficient = true;
 				ht_conf->single_chain_sufficient = true;
@@ -2689,14 +2689,6 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 			goto set_ch_out;
 			goto set_ch_out;
 		}
 		}
 
 
-		if (iwl_is_associated(priv) &&
-		    (le16_to_cpu(priv->active_rxon.channel) != ch) &&
-		    priv->cfg->ops->lib->set_channel_switch) {
-			ret = priv->cfg->ops->lib->set_channel_switch(priv,
-				ch);
-			goto out;
-		}
-
 		spin_lock_irqsave(&priv->lock, flags);
 		spin_lock_irqsave(&priv->lock, flags);
 
 
 		/* Configure HT40 channels */
 		/* Configure HT40 channels */
@@ -2731,6 +2723,22 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 
 
 		iwl_set_flags_for_band(priv, conf->channel->band);
 		iwl_set_flags_for_band(priv, conf->channel->band);
 		spin_unlock_irqrestore(&priv->lock, flags);
 		spin_unlock_irqrestore(&priv->lock, flags);
+		if (iwl_is_associated(priv) &&
+		    (le16_to_cpu(priv->active_rxon.channel) != ch) &&
+		    priv->cfg->ops->lib->set_channel_switch) {
+			iwl_set_rate(priv);
+			/*
+			 * at this point, staging_rxon has the
+			 * configuration for channel switch
+			 */
+			ret = priv->cfg->ops->lib->set_channel_switch(priv,
+				ch);
+			if (!ret) {
+				iwl_print_rx_config_cmd(priv);
+				goto out;
+			}
+			priv->switch_rxon.switch_in_progress = false;
+		}
  set_ch_out:
  set_ch_out:
 		/* The list of supported rates and rate mask can be different
 		/* The list of supported rates and rate mask can be different
 		 * for each band; since the band may have changed, reset
 		 * for each band; since the band may have changed, reset

+ 5 - 0
drivers/net/wireless/iwlwifi/iwl-core.h

@@ -579,6 +579,7 @@ int iwl_pci_resume(struct pci_dev *pdev);
 #ifdef CONFIG_IWLWIFI_DEBUG
 #ifdef CONFIG_IWLWIFI_DEBUG
 void iwl_dump_nic_event_log(struct iwl_priv *priv);
 void iwl_dump_nic_event_log(struct iwl_priv *priv);
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
 void iwl_dump_nic_error_log(struct iwl_priv *priv);
+void iwl_print_rx_config_cmd(struct iwl_priv *priv);
 #else
 #else
 static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
 static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
 {
 {
@@ -587,6 +588,10 @@ static inline void iwl_dump_nic_event_log(struct iwl_priv *priv)
 static inline void iwl_dump_nic_error_log(struct iwl_priv *priv)
 static inline void iwl_dump_nic_error_log(struct iwl_priv *priv)
 {
 {
 }
 }
+
+static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv)
+{
+}
 #endif
 #endif
 
 
 void iwl_clear_isr_stats(struct iwl_priv *priv);
 void iwl_clear_isr_stats(struct iwl_priv *priv);

+ 16 - 6
drivers/net/wireless/iwlwifi/iwl-dev.h

@@ -324,8 +324,9 @@ struct iwl_channel_info {
 #define IWL_MIN_NUM_QUEUES	10
 #define IWL_MIN_NUM_QUEUES	10
 
 
 /*
 /*
- * uCode queue management definitions ...
- * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00.
+ * Queue #4 is the command queue for 3945/4965/5x00/1000/6x00,
+ * the driver maps it into the appropriate device FIFO for the
+ * uCode.
  */
  */
 #define IWL_CMD_QUEUE_NUM	4
 #define IWL_CMD_QUEUE_NUM	4
 
 
@@ -926,13 +927,11 @@ enum iwl_access_mode {
 /**
 /**
  * enum iwl_pa_type - Power Amplifier type
  * enum iwl_pa_type - Power Amplifier type
  * @IWL_PA_SYSTEM:  based on uCode configuration
  * @IWL_PA_SYSTEM:  based on uCode configuration
- * @IWL_PA_HYBRID: use both Internal and external PA
  * @IWL_PA_INTERNAL: use Internal only
  * @IWL_PA_INTERNAL: use Internal only
  */
  */
 enum iwl_pa_type {
 enum iwl_pa_type {
 	IWL_PA_SYSTEM = 0,
 	IWL_PA_SYSTEM = 0,
-	IWL_PA_HYBRID = 1,
-	IWL_PA_INTERNAL = 2,
+	IWL_PA_INTERNAL = 1,
 };
 };
 
 
 /* interrupt statistics */
 /* interrupt statistics */
@@ -993,6 +992,17 @@ struct traffic_stats {
 };
 };
 #endif
 #endif
 
 
+/*
+ * iwl_switch_rxon: "channel switch" structure
+ *
+ * @ switch_in_progress: channel switch in progress
+ * @ channel: new channel
+ */
+struct iwl_switch_rxon {
+	bool switch_in_progress;
+	__le16 channel;
+};
+
 struct iwl_priv {
 struct iwl_priv {
 
 
 	/* ieee device used by generic ieee processing code */
 	/* ieee device used by generic ieee processing code */
@@ -1086,7 +1096,7 @@ struct iwl_priv {
 	const struct iwl_rxon_cmd active_rxon;
 	const struct iwl_rxon_cmd active_rxon;
 	struct iwl_rxon_cmd staging_rxon;
 	struct iwl_rxon_cmd staging_rxon;
 
 
-	struct iwl_rxon_cmd recovery_rxon;
+	struct iwl_switch_rxon switch_rxon;
 
 
 	/* 1st responses from initialize and runtime uCode images.
 	/* 1st responses from initialize and runtime uCode images.
 	 * 4965's initialize alive response contains some calibration data. */
 	 * 4965's initialize alive response contains some calibration data. */

+ 2 - 2
drivers/net/wireless/iwlwifi/iwl-hcmd.c

@@ -199,13 +199,13 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 	}
 	}
 
 
 	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
 	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
-		IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n",
+		IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
 			       get_cmd_string(cmd->id));
 			       get_cmd_string(cmd->id));
 		ret = -ECANCELED;
 		ret = -ECANCELED;
 		goto fail;
 		goto fail;
 	}
 	}
 	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
 	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
-		IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n",
+		IWL_ERR(priv, "Command %s failed: FW Error\n",
 			       get_cmd_string(cmd->id));
 			       get_cmd_string(cmd->id));
 		ret = -EIO;
 		ret = -EIO;
 		goto fail;
 		goto fail;

+ 20 - 0
drivers/net/wireless/iwlwifi/iwl-io.h

@@ -200,6 +200,26 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
 
 
 	/* this bit wakes up the NIC */
 	/* this bit wakes up the NIC */
 	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 	_iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/*
+	 * These bits say the device is running, and should keep running for
+	 * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
+	 * but they do not indicate that embedded SRAM is restored yet;
+	 * 3945 and 4965 have volatile SRAM, and must save/restore contents
+	 * to/from host DRAM when sleeping/waking for power-saving.
+	 * Each direction takes approximately 1/4 millisecond; with this
+	 * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
+	 * series of register accesses are expected (e.g. reading Event Log),
+	 * to keep device from sleeping.
+	 *
+	 * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
+	 * SRAM is okay/restored.  We don't check that here because this call
+	 * is just for hardware register access; but GP1 MAC_SLEEP check is a
+	 * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
+	 *
+	 * 5000 series and later (including 1000 series) have non-volatile SRAM,
+	 * and do not save/restore SRAM when power cycling.
+	 */
 	ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
 	ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
 			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
 			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
 			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
 			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |

+ 16 - 3
drivers/net/wireless/iwlwifi/iwl-prph.h

@@ -254,7 +254,8 @@
  * device.  A queue maps to only one (selectable by driver) Tx DMA channel,
  * device.  A queue maps to only one (selectable by driver) Tx DMA channel,
  * but one DMA channel may take input from several queues.
  * but one DMA channel may take input from several queues.
  *
  *
- * Tx DMA channels have dedicated purposes.  For 4965, they are used as follows:
+ * Tx DMA channels have dedicated purposes.  For 4965, they are used as follows
+ * (cf. default_queue_to_tx_fifo in iwl-4965.c):
  *
  *
  * 0 -- EDCA BK (background) frames, lowest priority
  * 0 -- EDCA BK (background) frames, lowest priority
  * 1 -- EDCA BE (best effort) frames, normal priority
  * 1 -- EDCA BE (best effort) frames, normal priority
@@ -265,9 +266,21 @@
  * 6 -- HCCA long frames
  * 6 -- HCCA long frames
  * 7 -- not used by driver (device-internal only)
  * 7 -- not used by driver (device-internal only)
  *
  *
+ * For 5000 series and up, they are used slightly differently
+ * (cf. iwl5000_default_queue_to_tx_fifo in iwl-5000.c):
+ *
+ * 0 -- EDCA BK (background) frames, lowest priority
+ * 1 -- EDCA BE (best effort) frames, normal priority
+ * 2 -- EDCA VI (video) frames, higher priority
+ * 3 -- EDCA VO (voice) and management frames, highest priority
+ * 4 -- (TBD)
+ * 5 -- HCCA short frames
+ * 6 -- HCCA long frames
+ * 7 -- Commands
+ *
  * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
  * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
- * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to
- * support 11n aggregation via EDCA DMA channels.
+ * In addition, driver can map the remaining queues to Tx DMA/FIFO
+ * channels 0-3 to support 11n aggregation via EDCA DMA channels.
  *
  *
  * The driver sets up each queue to work in one of two modes:
  * The driver sets up each queue to work in one of two modes:
  *
  *

+ 4 - 1
drivers/net/wireless/iwlwifi/iwl-rx.c

@@ -140,6 +140,8 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
 		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 
 
 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+			IWL_DEBUG_INFO(priv, "Rx queue requesting wakeup, GP1 = 0x%x\n",
+				      reg);
 			iwl_set_bit(priv, CSR_GP_CNTRL,
 			iwl_set_bit(priv, CSR_GP_CNTRL,
 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 			goto exit_unlock;
 			goto exit_unlock;
@@ -937,12 +939,13 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
 	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
 	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
 		return;
 		return;
 
 
-	skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
+	skb = alloc_skb(IWL_LINK_HDR_MAX * 2, GFP_ATOMIC);
 	if (!skb) {
 	if (!skb) {
 		IWL_ERR(priv, "alloc_skb failed\n");
 		IWL_ERR(priv, "alloc_skb failed\n");
 		return;
 		return;
 	}
 	}
 
 
+	skb_reserve(skb, IWL_LINK_HDR_MAX);
 	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
 	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
 
 
 	/* mac80211 currently doesn't support paged SKB. Convert it to
 	/* mac80211 currently doesn't support paged SKB. Convert it to

+ 16 - 2
drivers/net/wireless/iwlwifi/iwl-scan.c

@@ -581,6 +581,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
 	u8 rate;
 	u8 rate;
 	bool is_active = false;
 	bool is_active = false;
 	int  chan_mod;
 	int  chan_mod;
+	u8 active_chains;
 
 
 	conf = ieee80211_get_hw_conf(priv->hw);
 	conf = ieee80211_get_hw_conf(priv->hw);
 
 
@@ -734,9 +735,22 @@ static void iwl_bg_request_scan(struct work_struct *data)
 	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
 	rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
 	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
 	scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
 
 
+	/* In power save mode use one chain, otherwise use all chains */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* rx_ant has been set to all valid chains previously */
+		active_chains = rx_ant &
+				((u8)(priv->chain_noise_data.active_chains));
+		if (!active_chains)
+			active_chains = rx_ant;
+
+		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+				priv->chain_noise_data.active_chains);
+
+		rx_ant = first_antenna(active_chains);
+	}
 	/* MIMO is not used here, but value is required */
 	/* MIMO is not used here, but value is required */
-	rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS;
-	rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
+	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
 	rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
 	rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
 	scan->rx_chain = cpu_to_le16(rx_chain);
 	scan->rx_chain = cpu_to_le16(rx_chain);

+ 9 - 3
drivers/net/wireless/iwlwifi/iwl-tx.c

@@ -96,7 +96,8 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 
 
 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
 		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-			IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg);
+			IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
+				      txq_id, reg);
 			iwl_set_bit(priv, CSR_GP_CNTRL,
 			iwl_set_bit(priv, CSR_GP_CNTRL,
 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 			return ret;
 			return ret;
@@ -364,8 +365,13 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 
 
 	txq->need_update = 0;
 	txq->need_update = 0;
 
 
-	/* aggregation TX queues will get their ID when aggregation begins */
-	if (txq_id <= IWL_TX_FIFO_AC3)
+	/*
+	 * Aggregation TX queues will get their ID when aggregation begins;
+	 * they overwrite the setting done here. The command FIFO doesn't
+	 * need an swq_id so don't set one to catch errors, all others can
+	 * be set up to the identity mapping.
+	 */
+	if (txq_id != IWL_CMD_QUEUE_NUM)
 		txq->swq_id = txq_id;
 		txq->swq_id = txq_id;
 
 
 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
 	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise

+ 33 - 9
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -1570,6 +1570,7 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
 	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
 	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ptr;        /* SRAM byte address of log data */
 	u32 ev, time, data; /* event log data */
 	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
 
 
 	if (num_events == 0)
 	if (num_events == 0)
 		return;
 		return;
@@ -1583,26 +1584,38 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
 
 
 	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
 	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
 
 
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
 	/* "time" is actually "data" for mode 0 (no timestamp).
 	/* "time" is actually "data" for mode 0 (no timestamp).
 	 * place event id # at far right for easier visual parsing. */
 	 * place event id # at far right for easier visual parsing. */
 	for (i = 0; i < num_events; i++) {
 	for (i = 0; i < num_events; i++) {
-		ev = iwl_read_targ_mem(priv, ptr);
-		ptr += sizeof(u32);
-		time = iwl_read_targ_mem(priv, ptr);
-		ptr += sizeof(u32);
+		ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
 		if (mode == 0) {
 		if (mode == 0) {
 			/* data, ev */
 			/* data, ev */
 			IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
 			IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
 			trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
 			trace_iwlwifi_dev_ucode_event(priv, 0, time, ev);
 		} else {
 		} else {
-			data = iwl_read_targ_mem(priv, ptr);
-			ptr += sizeof(u32);
+			data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
 			IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
 			IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev);
 			trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
 			trace_iwlwifi_dev_ucode_event(priv, time, data, ev);
 		}
 		}
 	}
 	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
 }
 }
 
 
+/* For sanity check only.  Actual size is determined by uCode, typ. 512 */
+#define IWL3945_MAX_EVENT_LOG_SIZE (512)
+
 void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 {
 {
 	u32 base;       /* SRAM byte address of event log header */
 	u32 base;       /* SRAM byte address of event log header */
@@ -1624,6 +1637,18 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
 	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
 	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
 	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
 
 
+	if (capacity > IWL3945_MAX_EVENT_LOG_SIZE) {
+		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
+			capacity, IWL3945_MAX_EVENT_LOG_SIZE);
+		capacity = IWL3945_MAX_EVENT_LOG_SIZE;
+	}
+
+	if (next_entry > IWL3945_MAX_EVENT_LOG_SIZE) {
+		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
+			next_entry, IWL3945_MAX_EVENT_LOG_SIZE);
+		next_entry = IWL3945_MAX_EVENT_LOG_SIZE;
+	}
+
 	size = num_wraps ? capacity : next_entry;
 	size = num_wraps ? capacity : next_entry;
 
 
 	/* bail out if nothing in log */
 	/* bail out if nothing in log */
@@ -2575,9 +2600,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
 	iwl3945_hw_txq_ctx_stop(priv);
 	iwl3945_hw_txq_ctx_stop(priv);
 	iwl3945_hw_rxq_stop(priv);
 	iwl3945_hw_rxq_stop(priv);
 
 
-	iwl_write_prph(priv, APMG_CLK_DIS_REG,
-				APMG_CLK_VAL_DMA_CLK_RQT);
-
+	/* Power-down device's busmaster DMA clocks */
+	iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
 	udelay(5);
 	udelay(5);
 
 
 	/* Stop the device, and put it in low power state */
 	/* Stop the device, and put it in low power state */

+ 3 - 0
drivers/net/wireless/iwmc3200wifi/sdio.c

@@ -399,6 +399,9 @@ static struct iwm_if_ops if_sdio_ops = {
 	.calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
 	.calib_lmac_name = "iwmc3200wifi-calib-sdio.bin",
 	.lmac_name = "iwmc3200wifi-lmac-sdio.bin",
 	.lmac_name = "iwmc3200wifi-lmac-sdio.bin",
 };
 };
+MODULE_FIRMWARE("iwmc3200wifi-umac-sdio.bin");
+MODULE_FIRMWARE("iwmc3200wifi-calib-sdio.bin");
+MODULE_FIRMWARE("iwmc3200wifi-lmac-sdio.bin");
 
 
 static int iwm_sdio_probe(struct sdio_func *func,
 static int iwm_sdio_probe(struct sdio_func *func,
 			  const struct sdio_device_id *id)
 			  const struct sdio_device_id *id)

+ 1 - 0
drivers/net/wireless/libertas/if_cs.c

@@ -48,6 +48,7 @@
 MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
 MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
 MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
 MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("libertas_cs_helper.fw");
 
 
 
 
 
 

+ 6 - 0
drivers/net/wireless/libertas/if_sdio.c

@@ -99,6 +99,12 @@ static struct if_sdio_model if_sdio_models[] = {
 		.firmware = "sd8688.bin",
 		.firmware = "sd8688.bin",
 	},
 	},
 };
 };
+MODULE_FIRMWARE("sd8385_helper.bin");
+MODULE_FIRMWARE("sd8385.bin");
+MODULE_FIRMWARE("sd8686_helper.bin");
+MODULE_FIRMWARE("sd8686.bin");
+MODULE_FIRMWARE("sd8688_helper.bin");
+MODULE_FIRMWARE("sd8688.bin");
 
 
 struct if_sdio_packet {
 struct if_sdio_packet {
 	struct if_sdio_packet	*next;
 	struct if_sdio_packet	*next;

+ 4 - 0
drivers/net/wireless/libertas/if_spi.c

@@ -902,6 +902,10 @@ static int if_spi_calculate_fw_names(u16 card_id,
 		 chip_id_to_device_name[i].name);
 		 chip_id_to_device_name[i].name);
 	return 0;
 	return 0;
 }
 }
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8385.bin");
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8686.bin");
 
 
 static int __devinit if_spi_probe(struct spi_device *spi)
 static int __devinit if_spi_probe(struct spi_device *spi)
 {
 {

+ 2 - 0
drivers/net/wireless/libertas/if_usb.c

@@ -28,6 +28,8 @@
 static char *lbs_fw_name = "usb8388.bin";
 static char *lbs_fw_name = "usb8388.bin";
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 
 
+MODULE_FIRMWARE("usb8388.bin");
+
 static struct usb_device_id if_usb_table[] = {
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
 	/* Enter the device signature inside */
 	{ USB_DEVICE(0x1286, 0x2001) },
 	{ USB_DEVICE(0x1286, 0x2001) },

+ 2 - 0
drivers/net/wireless/libertas_tf/if_usb.c

@@ -23,6 +23,8 @@
 static char *lbtf_fw_name = "lbtf_usb.bin";
 static char *lbtf_fw_name = "lbtf_usb.bin";
 module_param_named(fw_name, lbtf_fw_name, charp, 0644);
 module_param_named(fw_name, lbtf_fw_name, charp, 0644);
 
 
+MODULE_FIRMWARE("lbtf_usb.bin");
+
 static struct usb_device_id if_usb_table[] = {
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
 	/* Enter the device signature inside */
 	{ USB_DEVICE(0x1286, 0x2001) },
 	{ USB_DEVICE(0x1286, 0x2001) },

+ 3 - 0
drivers/net/wireless/mwl8k.c

@@ -400,6 +400,9 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv)
 	return 0;
 	return 0;
 }
 }
 
 
+MODULE_FIRMWARE("mwl8k/helper_8687.fw");
+MODULE_FIRMWARE("mwl8k/fmimage_8687.fw");
+
 struct mwl8k_cmd_pkt {
 struct mwl8k_cmd_pkt {
 	__le16	code;
 	__le16	code;
 	__le16	length;
 	__le16	length;

+ 6 - 0
drivers/net/wireless/orinoco/fw.c

@@ -28,6 +28,12 @@ static const struct fw_info orinoco_fw[] = {
 	{ NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
 	{ NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
 	{ "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
 	{ "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
 };
 };
+MODULE_FIRMWARE("agere_sta_fw.bin");
+MODULE_FIRMWARE("agere_ap_fw.bin");
+MODULE_FIRMWARE("prism_sta_fw.bin");
+MODULE_FIRMWARE("prism_ap_fw.bin");
+MODULE_FIRMWARE("symbol_sp24t_prim_fw");
+MODULE_FIRMWARE("symbol_sp24t_sec_fw");
 
 
 /* Structure used to access fields in FW
 /* Structure used to access fields in FW
  * Make sure LE decoding macros are used
  * Make sure LE decoding macros are used

+ 3 - 0
drivers/net/wireless/prism54/islpci_dev.c

@@ -40,6 +40,9 @@
 #define ISL3877_IMAGE_FILE	"isl3877"
 #define ISL3877_IMAGE_FILE	"isl3877"
 #define ISL3886_IMAGE_FILE	"isl3886"
 #define ISL3886_IMAGE_FILE	"isl3886"
 #define ISL3890_IMAGE_FILE	"isl3890"
 #define ISL3890_IMAGE_FILE	"isl3890"
+MODULE_FIRMWARE(ISL3877_IMAGE_FILE);
+MODULE_FIRMWARE(ISL3886_IMAGE_FILE);
+MODULE_FIRMWARE(ISL3890_IMAGE_FILE);
 
 
 static int prism54_bring_down(islpci_private *);
 static int prism54_bring_down(islpci_private *);
 static int islpci_alloc_memory(islpci_private *);
 static int islpci_alloc_memory(islpci_private *);

+ 1 - 1
drivers/net/wireless/ray_cs.c

@@ -2074,7 +2074,7 @@ static irqreturn_t ray_interrupt(int irq, void *dev_id)
 				del_timer(&local->timer);
 				del_timer(&local->timer);
 				local->timer.expires = jiffies + HZ * 5;
 				local->timer.expires = jiffies + HZ * 5;
 				local->timer.data = (long)local;
 				local->timer.data = (long)local;
-				if (status == CCS_START_NETWORK) {
+				if (cmd == CCS_START_NETWORK) {
 					DEBUG(0,
 					DEBUG(0,
 					      "ray_cs interrupt network \"%s\" start failed\n",
 					      "ray_cs interrupt network \"%s\" start failed\n",
 					      local->sparm.b4.a_current_ess_id);
 					      local->sparm.b4.a_current_ess_id);

+ 2 - 0
drivers/net/wireless/rndis_wlan.c

@@ -1072,6 +1072,8 @@ static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version,
 		auth_mode = NDIS_80211_AUTH_SHARED;
 		auth_mode = NDIS_80211_AUTH_SHARED;
 	else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
 	else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM)
 		auth_mode = NDIS_80211_AUTH_OPEN;
 		auth_mode = NDIS_80211_AUTH_OPEN;
+	else if (auth_type == NL80211_AUTHTYPE_AUTOMATIC)
+		auth_mode = NDIS_80211_AUTH_AUTO_SWITCH;
 	else
 	else
 		return -ENOTSUPP;
 		return -ENOTSUPP;
 
 

+ 2 - 1
drivers/net/wireless/rt2x00/rt2400pci.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -1341,6 +1341,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
+	rt2x00_print_chip(rt2x00dev);
 
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2420) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421)) {
 	    !rt2x00_rf(&rt2x00dev->chip, RF2421)) {

+ 1 - 1
drivers/net/wireless/rt2x00/rt2400pci.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 1
drivers/net/wireless/rt2x00/rt2500pci.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -1505,6 +1505,7 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
 	rt2x00pci_register_read(rt2x00dev, CSR0, &reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
+	rt2x00_print_chip(rt2x00dev);
 
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	if (!rt2x00_rf(&rt2x00dev->chip, RF2522) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF2523) &&

+ 1 - 1
drivers/net/wireless/rt2x00/rt2500pci.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 135
drivers/net/wireless/rt2x00/rt2500usb.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -715,139 +715,6 @@ static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev,
 	qual->vgc_level = value;
 	qual->vgc_level = value;
 }
 }
 
 
-/*
- * NOTE: This function is directly ported from legacy driver, but
- * despite it being declared it was never called. Although link tuning
- * sounds like a good idea, and usually works well for the other drivers,
- * it does _not_ work with rt2500usb. Enabling this function will result
- * in TX capabilities only until association kicks in. Immediately
- * after the successful association all TX frames will be kept in the
- * hardware queue and never transmitted.
- */
-#if 0
-static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev)
-{
-	int rssi = rt2x00_get_link_rssi(&rt2x00dev->link);
-	u16 bbp_thresh;
-	u16 vgc_bound;
-	u16 sens;
-	u16 r24;
-	u16 r25;
-	u16 r61;
-	u16 r17_sens;
-	u8 r17;
-	u8 up_bound;
-	u8 low_bound;
-
-	/*
-	 * Read current r17 value, as well as the sensitivity values
-	 * for the r17 register.
-	 */
-	rt2500usb_bbp_read(rt2x00dev, 17, &r17);
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound);
-	up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER);
-	low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER);
-
-	/*
-	 * If we are not associated, we should go straight to the
-	 * dynamic CCA tuning.
-	 */
-	if (!rt2x00dev->intf_associated)
-		goto dynamic_cca_tune;
-
-	/*
-	 * Determine the BBP tuning threshold and correctly
-	 * set BBP 24, 25 and 61.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &bbp_thresh);
-	bbp_thresh = rt2x00_get_field16(bbp_thresh, EEPROM_BBPTUNE_THRESHOLD);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &r24);
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &r25);
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &r61);
-
-	if ((rssi + bbp_thresh) > 0) {
-		r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_HIGH);
-		r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_HIGH);
-		r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_HIGH);
-	} else {
-		r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_LOW);
-		r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_LOW);
-		r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_LOW);
-	}
-
-	rt2500usb_bbp_write(rt2x00dev, 24, r24);
-	rt2500usb_bbp_write(rt2x00dev, 25, r25);
-	rt2500usb_bbp_write(rt2x00dev, 61, r61);
-
-	/*
-	 * A too low RSSI will cause too much false CCA which will
-	 * then corrupt the R17 tuning. To remidy this the tuning should
-	 * be stopped (While making sure the R17 value will not exceed limits)
-	 */
-	if (rssi >= -40) {
-		if (r17 != 0x60)
-			rt2500usb_bbp_write(rt2x00dev, 17, 0x60);
-		return;
-	}
-
-	/*
-	 * Special big-R17 for short distance
-	 */
-	if (rssi >= -58) {
-		sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_LOW);
-		if (r17 != sens)
-			rt2500usb_bbp_write(rt2x00dev, 17, sens);
-		return;
-	}
-
-	/*
-	 * Special mid-R17 for middle distance
-	 */
-	if (rssi >= -74) {
-		sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_HIGH);
-		if (r17 != sens)
-			rt2500usb_bbp_write(rt2x00dev, 17, sens);
-		return;
-	}
-
-	/*
-	 * Leave short or middle distance condition, restore r17
-	 * to the dynamic tuning range.
-	 */
-	low_bound = 0x32;
-	if (rssi < -77)
-		up_bound -= (-77 - rssi);
-
-	if (up_bound < low_bound)
-		up_bound = low_bound;
-
-	if (r17 > up_bound) {
-		rt2500usb_bbp_write(rt2x00dev, 17, up_bound);
-		rt2x00dev->link.vgc_level = up_bound;
-		return;
-	}
-
-dynamic_cca_tune:
-
-	/*
-	 * R17 is inside the dynamic tuning range,
-	 * start tuning the link based on the false cca counter.
-	 */
-	if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) {
-		rt2500usb_bbp_write(rt2x00dev, 17, ++r17);
-		rt2x00dev->link.vgc_level = r17;
-	} else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) {
-		rt2500usb_bbp_write(rt2x00dev, 17, --r17);
-		rt2x00dev->link.vgc_level = r17;
-	}
-}
-#else
-#define rt2500usb_link_tuner	NULL
-#endif
-
 /*
 /*
  * Initialization functions.
  * Initialization functions.
  */
  */
@@ -1542,6 +1409,7 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2500usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
 	rt2x00_set_chip(rt2x00dev, RT2570, value, reg);
+	rt2x00_print_chip(rt2x00dev);
 
 
 	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
 	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) ||
 	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
 	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
@@ -1910,7 +1778,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 	.rfkill_poll		= rt2500usb_rfkill_poll,
 	.rfkill_poll		= rt2500usb_rfkill_poll,
 	.link_stats		= rt2500usb_link_stats,
 	.link_stats		= rt2500usb_link_stats,
 	.reset_tuner		= rt2500usb_reset_tuner,
 	.reset_tuner		= rt2500usb_reset_tuner,
-	.link_tuner		= rt2500usb_link_tuner,
 	.write_tx_desc		= rt2500usb_write_tx_desc,
 	.write_tx_desc		= rt2500usb_write_tx_desc,
 	.write_tx_data		= rt2x00usb_write_tx_data,
 	.write_tx_data		= rt2x00usb_write_tx_data,
 	.write_beacon		= rt2500usb_write_beacon,
 	.write_beacon		= rt2500usb_write_beacon,

+ 1 - 1
drivers/net/wireless/rt2x00/rt2500usb.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 37 - 1
drivers/net/wireless/rt2x00/rt2800.h

@@ -1,5 +1,12 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -361,6 +368,35 @@
 #define RF_CSR_CFG_WRITE		FIELD32(0x00010000)
 #define RF_CSR_CFG_WRITE		FIELD32(0x00010000)
 #define RF_CSR_CFG_BUSY			FIELD32(0x00020000)
 #define RF_CSR_CFG_BUSY			FIELD32(0x00020000)
 
 
+/*
+ * EFUSE_CSR: RT30x0 EEPROM
+ */
+#define EFUSE_CTRL			0x0580
+#define EFUSE_CTRL_ADDRESS_IN		FIELD32(0x03fe0000)
+#define EFUSE_CTRL_MODE			FIELD32(0x000000c0)
+#define EFUSE_CTRL_KICK			FIELD32(0x40000000)
+#define EFUSE_CTRL_PRESENT		FIELD32(0x80000000)
+
+/*
+ * EFUSE_DATA0
+ */
+#define EFUSE_DATA0			0x0590
+
+/*
+ * EFUSE_DATA1
+ */
+#define EFUSE_DATA1			0x0594
+
+/*
+ * EFUSE_DATA2
+ */
+#define EFUSE_DATA2			0x0598
+
+/*
+ * EFUSE_DATA3
+ */
+#define EFUSE_DATA3			0x059c
+
 /*
 /*
  * MAC Control/Status Registers(CSR).
  * MAC Control/Status Registers(CSR).
  * Some values are set in TU, whereas 1 TU == 1024 us.
  * Some values are set in TU, whereas 1 TU == 1024 us.

+ 483 - 11
drivers/net/wireless/rt2x00/rt2800lib.c

@@ -1,9 +1,15 @@
 /*
 /*
-	Copyright (C) 2009 Bartlomiej Zolnierkiewicz
-
-	Based on the original rt2800pci.c and rt2800usb.c:
-
-	  Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+	Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com>
+
+	Based on the original rt2800pci.c and rt2800usb.c.
+	  Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	  Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+	  Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	  Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+	  Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	  Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+	  Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
 	  <http://rt2x00.serialmonkey.com>
 	  <http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -555,7 +561,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
+		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
+				   (conf->sync == TSF_SYNC_BEACON));
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 	}
 	}
 
 
@@ -769,7 +776,7 @@ static void rt2800_config_channel_rt3x(struct rt2x00_dev *rt2x00dev,
 	u8 rfcsr;
 	u8 rfcsr;
 
 
 	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
 	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf1);
-	rt2800_rfcsr_write(rt2x00dev, 2, rf->rf3);
+	rt2800_rfcsr_write(rt2x00dev, 3, rf->rf3);
 
 
 	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
 	rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
 	rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2);
@@ -801,10 +808,15 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	unsigned int tx_pin;
 	unsigned int tx_pin;
 	u8 bbp;
 	u8 bbp;
 
 
-	if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION)
-		rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
-	else
+	if ((rt2x00_rt(&rt2x00dev->chip, RT3070) ||
+	     rt2x00_rt(&rt2x00dev->chip, RT3090)) &&
+	    (rt2x00_rf(&rt2x00dev->chip, RF2020) ||
+	     rt2x00_rf(&rt2x00dev->chip, RF3020) ||
+	     rt2x00_rf(&rt2x00dev->chip, RF3021) ||
+	     rt2x00_rf(&rt2x00dev->chip, RF3022)))
 		rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
 		rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info);
+	else
+		rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info);
 
 
 	/*
 	/*
 	 * Change BBP settings
 	 * Change BBP settings
@@ -1084,7 +1096,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
 
 	if (rt2x00_intf_is_usb(rt2x00dev)) {
 	if (rt2x00_intf_is_usb(rt2x00dev)) {
 		/*
 		/*
-		 * Wait untill BBP and RF are ready.
+		 * Wait until BBP and RF are ready.
 		 */
 		 */
 		for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 			rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
 			rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
@@ -1659,6 +1671,466 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 }
 }
 EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
 EXPORT_SYMBOL_GPL(rt2800_init_rfcsr);
 
 
+int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+
+	rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
+
+	return rt2x00_get_field32(reg, EFUSE_CTRL_PRESENT);
+}
+EXPORT_SYMBOL_GPL(rt2800_efuse_detect);
+
+static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
+{
+	u32 reg;
+
+	mutex_lock(&rt2x00dev->csr_mutex);
+
+	rt2800_register_read_lock(rt2x00dev, EFUSE_CTRL, &reg);
+	rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
+	rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
+	rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
+	rt2800_register_write_lock(rt2x00dev, EFUSE_CTRL, reg);
+
+	/* Wait until the EEPROM has been loaded */
+	rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
+
+	/* Apparently the data is read from end to start */
+	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3,
+					(u32 *)&rt2x00dev->eeprom[i]);
+	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2,
+					(u32 *)&rt2x00dev->eeprom[i + 2]);
+	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1,
+					(u32 *)&rt2x00dev->eeprom[i + 4]);
+	rt2800_register_read_lock(rt2x00dev, EFUSE_DATA0,
+					(u32 *)&rt2x00dev->eeprom[i + 6]);
+
+	mutex_unlock(&rt2x00dev->csr_mutex);
+}
+
+void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+
+	for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
+		rt2800_efuse_read(rt2x00dev, i);
+}
+EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse);
+
+int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+	u16 word;
+	u8 *mac;
+	u8 default_lna_gain;
+
+	/*
+	 * Start validation of the data that has been read.
+	 */
+	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
+	if (!is_valid_ether_addr(mac)) {
+		random_ether_addr(mac);
+		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
+	if (word == 0xffff) {
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
+		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
+	} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
+		/*
+		 * There is a max of 2 RX streams for RT28x0 series
+		 */
+		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
+			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
+	if (word == 0xffff) {
+		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
+		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
+	}
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
+	if ((word & 0x00ff) == 0x00ff) {
+		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
+				   LED_MODE_TXRX_ACTIVITY);
+		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
+		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+	}
+
+	/*
+	 * During the LNA validation we are going to use
+	 * lna0 as correct value. Note that EEPROM_LNA
+	 * is never validated.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
+	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
+	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
+	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
+		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
+				   default_lna_gain);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
+	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
+	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
+	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
+		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
+				   default_lna_gain);
+	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
+
+int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev)
+{
+	u32 reg;
+	u16 value;
+	u16 eeprom;
+
+	/*
+	 * Read EEPROM word for configuration.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+	/*
+	 * Identify RF chipset.
+	 */
+	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
+	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+
+	rt2x00_set_chip_rf(rt2x00dev, value, reg);
+
+	if (rt2x00_intf_is_usb(rt2x00dev)) {
+		struct rt2x00_chip *chip = &rt2x00dev->chip;
+
+		/*
+		 * The check for rt2860 is not a typo, some rt2870 hardware
+		 * identifies itself as rt2860 in the CSR register.
+		 */
+		if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) ||
+		    rt2x00_check_rev(chip, 0xfff00000, 0x28700000) ||
+		    rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) {
+			rt2x00_set_chip_rt(rt2x00dev, RT2870);
+		} else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) {
+			rt2x00_set_chip_rt(rt2x00dev, RT3070);
+		} else {
+			ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
+			return -ENODEV;
+		}
+	}
+	rt2x00_print_chip(rt2x00dev);
+
+	if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2850) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2720) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2750) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF3020) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF2020) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
+	    !rt2x00_rf(&rt2x00dev->chip, RF3022)) {
+		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
+		return -ENODEV;
+	}
+
+	/*
+	 * Identify default antenna configuration.
+	 */
+	rt2x00dev->default_ant.tx =
+	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
+	rt2x00dev->default_ant.rx =
+	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
+
+	/*
+	 * Read frequency offset and RF programming sequence.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
+	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
+
+	/*
+	 * Read external LNA informations.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
+
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
+		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
+		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
+
+	/*
+	 * Detect if this device has an hardware controlled radio.
+	 */
+	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
+		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
+
+	/*
+	 * Store led settings, for correct led behaviour.
+	 */
+#ifdef CONFIG_RT2X00_LIB_LEDS
+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
+	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
+#endif /* CONFIG_RT2X00_LIB_LEDS */
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
+
+/*
+ * RF value list for rt28x0
+ * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
+ */
+static const struct rf_channel rf_vals[] = {
+	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
+	{ 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
+	{ 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
+	{ 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
+	{ 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
+	{ 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
+	{ 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
+	{ 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
+	{ 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
+	{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
+	{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
+	{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
+	{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
+	{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
+
+	/* 802.11 UNI / HyperLan 2 */
+	{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
+	{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
+	{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
+	{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
+	{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
+	{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
+	{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
+	{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
+	{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
+	{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
+	{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
+	{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
+
+	/* 802.11 HyperLan 2 */
+	{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
+	{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
+	{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
+	{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
+	{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
+	{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
+	{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
+	{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
+	{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
+	{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
+	{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
+	{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
+	{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
+	{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
+	{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
+	{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
+
+	/* 802.11 UNII */
+	{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
+	{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
+	{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
+	{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
+	{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
+	{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
+	{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
+	{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
+	{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
+	{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
+	{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
+
+	/* 802.11 Japan */
+	{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
+	{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
+	{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
+	{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
+	{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
+	{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
+	{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
+};
+
+/*
+ * RF value list for rt3070
+ * Supports: 2.4 GHz
+ */
+static const struct rf_channel rf_vals_302x[] = {
+	{1,  241, 2, 2 },
+	{2,  241, 2, 7 },
+	{3,  242, 2, 2 },
+	{4,  242, 2, 7 },
+	{5,  243, 2, 2 },
+	{6,  243, 2, 7 },
+	{7,  244, 2, 2 },
+	{8,  244, 2, 7 },
+	{9,  245, 2, 2 },
+	{10, 245, 2, 7 },
+	{11, 246, 2, 2 },
+	{12, 246, 2, 7 },
+	{13, 247, 2, 2 },
+	{14, 248, 2, 4 },
+};
+
+int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
+{
+	struct rt2x00_chip *chip = &rt2x00dev->chip;
+	struct hw_mode_spec *spec = &rt2x00dev->spec;
+	struct channel_info *info;
+	char *tx_power1;
+	char *tx_power2;
+	unsigned int i;
+	u16 eeprom;
+
+	/*
+	 * Initialize all hw fields.
+	 */
+	rt2x00dev->hw->flags =
+	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+	    IEEE80211_HW_SIGNAL_DBM |
+	    IEEE80211_HW_SUPPORTS_PS |
+	    IEEE80211_HW_PS_NULLFUNC_STACK;
+
+	if (rt2x00_intf_is_usb(rt2x00dev))
+		rt2x00dev->hw->extra_tx_headroom =
+			TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
+	else if (rt2x00_intf_is_pci(rt2x00dev))
+		rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE;
+
+	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
+	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
+				rt2x00_eeprom_addr(rt2x00dev,
+						   EEPROM_MAC_ADDR_0));
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
+
+	/*
+	 * Initialize hw_mode information.
+	 */
+	spec->supported_bands = SUPPORT_BAND_2GHZ;
+	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
+
+	if (rt2x00_rf(chip, RF2820) ||
+	    rt2x00_rf(chip, RF2720) ||
+	    (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) {
+		spec->num_channels = 14;
+		spec->channels = rf_vals;
+	} else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) {
+		spec->supported_bands |= SUPPORT_BAND_5GHZ;
+		spec->num_channels = ARRAY_SIZE(rf_vals);
+		spec->channels = rf_vals;
+	} else if (rt2x00_rf(chip, RF3020) ||
+		   rt2x00_rf(chip, RF2020) ||
+		   rt2x00_rf(chip, RF3021) ||
+		   rt2x00_rf(chip, RF3022)) {
+		spec->num_channels = ARRAY_SIZE(rf_vals_302x);
+		spec->channels = rf_vals_302x;
+	}
+
+	/*
+	 * Initialize HT information.
+	 */
+	spec->ht.ht_supported = true;
+	spec->ht.cap =
+	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+	    IEEE80211_HT_CAP_GRN_FLD |
+	    IEEE80211_HT_CAP_SGI_20 |
+	    IEEE80211_HT_CAP_SGI_40 |
+	    IEEE80211_HT_CAP_TX_STBC |
+	    IEEE80211_HT_CAP_RX_STBC |
+	    IEEE80211_HT_CAP_PSMP_SUPPORT;
+	spec->ht.ampdu_factor = 3;
+	spec->ht.ampdu_density = 4;
+	spec->ht.mcs.tx_params =
+	    IEEE80211_HT_MCS_TX_DEFINED |
+	    IEEE80211_HT_MCS_TX_RX_DIFF |
+	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
+		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+
+	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
+	case 3:
+		spec->ht.mcs.rx_mask[2] = 0xff;
+	case 2:
+		spec->ht.mcs.rx_mask[1] = 0xff;
+	case 1:
+		spec->ht.mcs.rx_mask[0] = 0xff;
+		spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
+		break;
+	}
+
+	/*
+	 * Create channel information array
+	 */
+	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	spec->channels_info = info;
+
+	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
+	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
+
+	for (i = 0; i < 14; i++) {
+		info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
+		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
+	}
+
+	if (spec->num_channels > 14) {
+		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
+		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
+
+		for (i = 14; i < spec->num_channels; i++) {
+			info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
+			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);
+
 /*
 /*
  * IEEE80211 stack callback functions.
  * IEEE80211 stack callback functions.
  */
  */

+ 17 - 0
drivers/net/wireless/rt2x00/rt2800lib.h

@@ -23,6 +23,8 @@
 struct rt2800_ops {
 struct rt2800_ops {
 	void (*register_read)(struct rt2x00_dev *rt2x00dev,
 	void (*register_read)(struct rt2x00_dev *rt2x00dev,
 			      const unsigned int offset, u32 *value);
 			      const unsigned int offset, u32 *value);
+	void (*register_read_lock)(struct rt2x00_dev *rt2x00dev,
+				   const unsigned int offset, u32 *value);
 	void (*register_write)(struct rt2x00_dev *rt2x00dev,
 	void (*register_write)(struct rt2x00_dev *rt2x00dev,
 			       const unsigned int offset, u32 value);
 			       const unsigned int offset, u32 value);
 	void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
 	void (*register_write_lock)(struct rt2x00_dev *rt2x00dev,
@@ -49,6 +51,15 @@ static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev,
 	rt2800ops->register_read(rt2x00dev, offset, value);
 	rt2800ops->register_read(rt2x00dev, offset, value);
 }
 }
 
 
+static inline void rt2800_register_read_lock(struct rt2x00_dev *rt2x00dev,
+					     const unsigned int offset,
+					     u32 *value)
+{
+	const struct rt2800_ops *rt2800ops = rt2x00dev->priv;
+
+	rt2800ops->register_read_lock(rt2x00dev, offset, value);
+}
+
 static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
 static inline void rt2800_register_write(struct rt2x00_dev *rt2x00dev,
 					 const unsigned int offset,
 					 const unsigned int offset,
 					 u32 value)
 					 u32 value)
@@ -129,6 +140,12 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev);
 int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
 int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev);
 int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
 int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev);
 
 
+int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev);
+void rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev);
+int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev);
+int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev);
+int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev);
+
 extern const struct ieee80211_ops rt2800_mac80211_ops;
 extern const struct ieee80211_ops rt2800_mac80211_ops;
 
 
 #endif /* RT2800LIB_H */
 #endif /* RT2800LIB_H */

+ 26 - 390
drivers/net/wireless/rt2x00/rt2800pci.c

@@ -1,5 +1,12 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -145,43 +152,25 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
 			       EEPROM_SIZE / sizeof(u16));
 			       EEPROM_SIZE / sizeof(u16));
 }
 }
 
 
-static void rt2800pci_efuse_read(struct rt2x00_dev *rt2x00dev,
-				 unsigned int i)
+static int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
 {
 {
-	u32 reg;
-
-	rt2800_register_read(rt2x00dev, EFUSE_CTRL, &reg);
-	rt2x00_set_field32(&reg, EFUSE_CTRL_ADDRESS_IN, i);
-	rt2x00_set_field32(&reg, EFUSE_CTRL_MODE, 0);
-	rt2x00_set_field32(&reg, EFUSE_CTRL_KICK, 1);
-	rt2800_register_write(rt2x00dev, EFUSE_CTRL, reg);
-
-	/* Wait until the EEPROM has been loaded */
-	rt2800_regbusy_read(rt2x00dev, EFUSE_CTRL, EFUSE_CTRL_KICK, &reg);
-
-	/* Apparently the data is read from end to start */
-	rt2800_register_read(rt2x00dev, EFUSE_DATA3,
-				(u32 *)&rt2x00dev->eeprom[i]);
-	rt2800_register_read(rt2x00dev, EFUSE_DATA2,
-				(u32 *)&rt2x00dev->eeprom[i + 2]);
-	rt2800_register_read(rt2x00dev, EFUSE_DATA1,
-				(u32 *)&rt2x00dev->eeprom[i + 4]);
-	rt2800_register_read(rt2x00dev, EFUSE_DATA0,
-				(u32 *)&rt2x00dev->eeprom[i + 6]);
+	return rt2800_efuse_detect(rt2x00dev);
 }
 }
 
 
-static void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
+static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
 {
 {
-	unsigned int i;
-
-	for (i = 0; i < EEPROM_SIZE / sizeof(u16); i += 8)
-		rt2800pci_efuse_read(rt2x00dev, i);
+	rt2800_read_eeprom_efuse(rt2x00dev);
 }
 }
 #else
 #else
 static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
 static inline void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
 {
 {
 }
 }
 
 
+static inline int rt2800pci_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+	return 0;
+}
+
 static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
 static inline void rt2800pci_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev)
 {
 {
 }
 }
@@ -1079,379 +1068,28 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
  */
  */
 static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 {
 {
-	u16 word;
-	u8 *mac;
-	u8 default_lna_gain;
-
 	/*
 	/*
 	 * Read EEPROM into buffer
 	 * Read EEPROM into buffer
 	 */
 	 */
-	switch(rt2x00dev->chip.rt) {
+	switch (rt2x00dev->chip.rt) {
 	case RT2880:
 	case RT2880:
 	case RT3052:
 	case RT3052:
 		rt2800pci_read_eeprom_soc(rt2x00dev);
 		rt2800pci_read_eeprom_soc(rt2x00dev);
 		break;
 		break;
-	case RT3090:
-		rt2800pci_read_eeprom_efuse(rt2x00dev);
-		break;
 	default:
 	default:
-		rt2800pci_read_eeprom_pci(rt2x00dev);
-		break;
-	}
-
-	/*
-	 * Start validation of the data that has been read.
-	 */
-	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-	if (!is_valid_ether_addr(mac)) {
-		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-	if (word == 0xffff) {
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
-	} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
-		/*
-		 * There is a max of 2 RX streams for RT2860 series
-		 */
-		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
-			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-	if (word == 0xffff) {
-		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
-	if ((word & 0x00ff) == 0x00ff) {
-		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
-				   LED_MODE_TXRX_ACTIVITY);
-		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
-		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
-	}
-
-	/*
-	 * During the LNA validation we are going to use
-	 * lna0 as correct value. Note that EEPROM_LNA
-	 * is never validated.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
-	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
-
-	return 0;
-}
-
-static int rt2800pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-	u32 reg;
-	u16 value;
-	u16 eeprom;
-
-	/*
-	 * Read EEPROM word for configuration.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-	/*
-	 * Identify RF chipset.
-	 */
-	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-	rt2x00_set_chip_rf(rt2x00dev, value, reg);
-
-	if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2850) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2720) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2750) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF3020) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2020) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF3021) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF3022)) {
-		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
-		return -ENODEV;
-	}
-
-	/*
-	 * Identify default antenna configuration.
-	 */
-	rt2x00dev->default_ant.tx =
-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
-	rt2x00dev->default_ant.rx =
-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
-
-	/*
-	 * Read frequency offset and RF programming sequence.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
-
-	/*
-	 * Read external LNA informations.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
-
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
-
-	/*
-	 * Detect if this device has an hardware controlled radio.
-	 */
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-
-	/*
-	 * Store led settings, for correct led behaviour.
-	 */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-	return 0;
-}
-
-/*
- * RF value list for rt2860
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
- */
-static const struct rf_channel rf_vals[] = {
-	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
-	{ 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
-	{ 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
-	{ 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
-	{ 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
-	{ 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
-	{ 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
-	{ 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
-	{ 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
-	{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
-	{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
-	{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
-	{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
-	{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
-
-	/* 802.11 UNI / HyperLan 2 */
-	{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
-	{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
-	{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
-	{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
-	{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
-	{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
-	{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
-	{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
-	{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
-	{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
-	{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
-	{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
-
-	/* 802.11 HyperLan 2 */
-	{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
-	{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
-	{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
-	{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
-	{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
-	{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
-	{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
-	{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
-	{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
-	{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
-	{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
-	{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
-	{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
-	{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
-	{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
-	{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
-
-	/* 802.11 UNII */
-	{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
-	{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
-	{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
-	{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
-	{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
-	{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
-	{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
-
-	/* 802.11 Japan */
-	{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
-	{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
-	{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
-	{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
-	{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
-	{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
-	{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
-};
-
-static int rt2800pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	struct channel_info *info;
-	char *tx_power1;
-	char *tx_power2;
-	unsigned int i;
-	u16 eeprom;
-
-	/*
-	 * Initialize all hw fields.
-	 */
-	rt2x00dev->hw->flags =
-	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-	    IEEE80211_HW_SIGNAL_DBM |
-	    IEEE80211_HW_SUPPORTS_PS |
-	    IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE;
-
-	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-				rt2x00_eeprom_addr(rt2x00dev,
-						   EEPROM_MAC_ADDR_0));
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-	/*
-	 * Initialize hw_mode information.
-	 */
-	spec->supported_bands = SUPPORT_BAND_2GHZ;
-	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-	if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF2720) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF3020) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF3021) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF3022) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF2020) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF3052)) {
-		spec->num_channels = 14;
-		spec->channels = rf_vals;
-	} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
-		   rt2x00_rf(&rt2x00dev->chip, RF2750)) {
-		spec->supported_bands |= SUPPORT_BAND_5GHZ;
-		spec->num_channels = ARRAY_SIZE(rf_vals);
-		spec->channels = rf_vals;
-	}
-
-	/*
-	 * Initialize HT information.
-	 */
-	spec->ht.ht_supported = true;
-	spec->ht.cap =
-	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-	    IEEE80211_HT_CAP_GRN_FLD |
-	    IEEE80211_HT_CAP_SGI_20 |
-	    IEEE80211_HT_CAP_SGI_40 |
-	    IEEE80211_HT_CAP_TX_STBC |
-	    IEEE80211_HT_CAP_RX_STBC |
-	    IEEE80211_HT_CAP_PSMP_SUPPORT;
-	spec->ht.ampdu_factor = 3;
-	spec->ht.ampdu_density = 4;
-	spec->ht.mcs.tx_params =
-	    IEEE80211_HT_MCS_TX_DEFINED |
-	    IEEE80211_HT_MCS_TX_RX_DIFF |
-	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
-		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
-
-	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
-	case 3:
-		spec->ht.mcs.rx_mask[2] = 0xff;
-	case 2:
-		spec->ht.mcs.rx_mask[1] = 0xff;
-	case 1:
-		spec->ht.mcs.rx_mask[0] = 0xff;
-		spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
+		if (rt2800pci_efuse_detect(rt2x00dev))
+			rt2800pci_read_eeprom_efuse(rt2x00dev);
+		else
+			rt2800pci_read_eeprom_pci(rt2x00dev);
 		break;
 		break;
 	}
 	}
 
 
-	/*
-	 * Create channel information array
-	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	spec->channels_info = info;
-
-	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
-
-	for (i = 0; i < 14; i++) {
-		info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
-		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
-	}
-
-	if (spec->num_channels > 14) {
-		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
-		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
-
-		for (i = 14; i < spec->num_channels; i++) {
-			info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
-			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
-		}
-	}
-
-	return 0;
+	return rt2800_validate_eeprom(rt2x00dev);
 }
 }
 
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
 	.register_read		= rt2x00pci_register_read,
 	.register_read		= rt2x00pci_register_read,
+	.register_read_lock	= rt2x00pci_register_read, /* same for PCI */
 	.register_write		= rt2x00pci_register_write,
 	.register_write		= rt2x00pci_register_write,
 	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */
 	.register_write_lock	= rt2x00pci_register_write, /* same for PCI */
 
 
@@ -1465,8 +1103,6 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 {
 	int retval;
 	int retval;
 
 
-	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
-
 	rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops;
 	rt2x00dev->priv = (void *)&rt2800pci_rt2800_ops;
 
 
 	/*
 	/*
@@ -1476,14 +1112,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	retval = rt2800pci_init_eeprom(rt2x00dev);
+	retval = rt2800_init_eeprom(rt2x00dev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
 	/*
 	/*
 	 * Initialize hw specifications.
 	 * Initialize hw specifications.
 	 */
 	 */
-	retval = rt2800pci_probe_hw_mode(rt2x00dev);
+	retval = rt2800_probe_hw_mode(rt2x00dev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 

+ 8 - 29
drivers/net/wireless/rt2x00/rt2800pci.h

@@ -1,5 +1,12 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com>
+	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com>
+	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	Copyright (C) 2009 Mark Asselstine <asselsm@gmail.com>
+	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+	Copyright (C) 2009 Bart Zolnierkiewicz <bzolnier@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -55,34 +62,6 @@
 #define TX_CTX_IDX(__x)			TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
 #define TX_CTX_IDX(__x)			TX_CTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
 #define TX_DTX_IDX(__x)			TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
 #define TX_DTX_IDX(__x)			TX_DTX_IDX0 + ((__x) * TX_QUEUE_REG_OFFSET)
 
 
-/*
- * EFUSE_CSR: RT3090 EEPROM
- */
-#define EFUSE_CTRL			0x0580
-#define EFUSE_CTRL_ADDRESS_IN		FIELD32(0x03fe0000)
-#define EFUSE_CTRL_MODE			FIELD32(0x000000c0)
-#define EFUSE_CTRL_KICK			FIELD32(0x40000000)
-
-/*
- * EFUSE_DATA0
- */
-#define EFUSE_DATA0			0x0590
-
-/*
- * EFUSE_DATA1
- */
-#define EFUSE_DATA1			0x0594
-
-/*
- * EFUSE_DATA2
- */
-#define EFUSE_DATA2			0x0598
-
-/*
- * EFUSE_DATA3
- */
-#define EFUSE_DATA3			0x059c
-
 /*
 /*
  * 8051 firmware image.
  * 8051 firmware image.
  */
  */

+ 19 - 399
drivers/net/wireless/rt2x00/rt2800usb.c

@@ -1,5 +1,9 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+	Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -594,16 +598,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
 	rt2x00_desc_read(rxwi, 2, &rxwi2);
 	rt2x00_desc_read(rxwi, 2, &rxwi2);
 	rt2x00_desc_read(rxwi, 3, &rxwi3);
 	rt2x00_desc_read(rxwi, 3, &rxwi3);
 
 
-	if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR))
+	if (rt2x00_get_field32(rxd0, RXINFO_W0_CRC_ERROR))
 		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
 		rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC;
 
 
 	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
 	if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
 		rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
 		rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF);
 		rxdesc->cipher_status =
 		rxdesc->cipher_status =
-		    rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR);
+		    rt2x00_get_field32(rxd0, RXINFO_W0_CIPHER_ERROR);
 	}
 	}
 
 
-	if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) {
+	if (rt2x00_get_field32(rxd0, RXINFO_W0_DECRYPTED)) {
 		/*
 		/*
 		 * Hardware has stripped IV/EIV data from 802.11 frame during
 		 * Hardware has stripped IV/EIV data from 802.11 frame during
 		 * decryption. Unfortunately the descriptor doesn't contain
 		 * decryption. Unfortunately the descriptor doesn't contain
@@ -618,10 +622,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
 			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
 			rxdesc->flags |= RX_FLAG_MMIC_ERROR;
 	}
 	}
 
 
-	if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS))
+	if (rt2x00_get_field32(rxd0, RXINFO_W0_MY_BSS))
 		rxdesc->dev_flags |= RXDONE_MY_BSS;
 		rxdesc->dev_flags |= RXDONE_MY_BSS;
 
 
-	if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) {
+	if (rt2x00_get_field32(rxd0, RXINFO_W0_L2PAD)) {
 		rxdesc->dev_flags |= RXDONE_L2PAD;
 		rxdesc->dev_flags |= RXDONE_L2PAD;
 		skbdesc->flags |= SKBDESC_L2_PADDED;
 		skbdesc->flags |= SKBDESC_L2_PADDED;
 	}
 	}
@@ -667,400 +671,18 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
  */
  */
 static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 {
 {
-	u16 word;
-	u8 *mac;
-	u8 default_lna_gain;
-
-	rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE);
-
-	/*
-	 * Start validation of the data that has been read.
-	 */
-	mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
-	if (!is_valid_ether_addr(mac)) {
-		random_ether_addr(mac);
-		EEPROM(rt2x00dev, "MAC: %pM\n", mac);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
-	if (word == 0xffff) {
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1);
-		rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
-	} else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) {
-		/*
-		 * There is a max of 2 RX streams for RT2870 series
-		 */
-		if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2)
-			rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word);
-	if (word == 0xffff) {
-		rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
-		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
-		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
-	}
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
-	if ((word & 0x00ff) == 0x00ff) {
-		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
-		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
-				   LED_MODE_TXRX_ACTIVITY);
-		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
-		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
-		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
-	}
-
-	/*
-	 * During the LNA validation we are going to use
-	 * lna0 as correct value. Note that EEPROM_LNA
-	 * is never validated.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word);
-	default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word);
-	if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0);
-	if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 ||
-	    rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2,
-				   default_lna_gain);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
-
-	return 0;
-}
-
-static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
-{
-	u32 reg;
-	u16 value;
-	u16 eeprom;
-
-	/*
-	 * Read EEPROM word for configuration.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-	/*
-	 * Identify RF chipset.
-	 */
-	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
-	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
-	rt2x00_set_chip(rt2x00dev, RT2870, value, reg);
-
-	/*
-	 * The check for rt2860 is not a typo, some rt2870 hardware
-	 * identifies itself as rt2860 in the CSR register.
-	 */
-	if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) &&
-	    !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) &&
-	    !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) &&
-	    !rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) {
-		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
-		return -ENODEV;
-	}
-
-	if (!rt2x00_rf(&rt2x00dev->chip, RF2820) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2850) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2720) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2750) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF3020) &&
-	    !rt2x00_rf(&rt2x00dev->chip, RF2020)) {
-		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
-		return -ENODEV;
-	}
-
-	/*
-	 * Identify default antenna configuration.
-	 */
-	rt2x00dev->default_ant.tx =
-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH);
-	rt2x00dev->default_ant.rx =
-	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH);
-
-	/*
-	 * Read frequency offset and RF programming sequence.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom);
-	rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET);
-
-	/*
-	 * Read external LNA informations.
-	 */
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom);
-
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A))
-		__set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags);
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG))
-		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
-
-	/*
-	 * Detect if this device has an hardware controlled radio.
-	 */
-	if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO))
-		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
-
-	/*
-	 * Store led settings, for correct led behaviour.
-	 */
-#ifdef CONFIG_RT2X00_LIB_LEDS
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO);
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC);
-	rt2800_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY);
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ,
-			   &rt2x00dev->led_mcu_reg);
-#endif /* CONFIG_RT2X00_LIB_LEDS */
-
-	return 0;
-}
-
-/*
- * RF value list for rt2870
- * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750)
- */
-static const struct rf_channel rf_vals[] = {
-	{ 1,  0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b },
-	{ 2,  0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f },
-	{ 3,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b },
-	{ 4,  0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f },
-	{ 5,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b },
-	{ 6,  0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f },
-	{ 7,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b },
-	{ 8,  0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f },
-	{ 9,  0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b },
-	{ 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f },
-	{ 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b },
-	{ 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f },
-	{ 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b },
-	{ 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 },
-
-	/* 802.11 UNI / HyperLan 2 */
-	{ 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 },
-	{ 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 },
-	{ 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 },
-	{ 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 },
-	{ 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b },
-	{ 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b },
-	{ 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 },
-	{ 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 },
-	{ 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b },
-	{ 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 },
-	{ 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 },
-	{ 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 },
-
-	/* 802.11 HyperLan 2 */
-	{ 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 },
-	{ 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 },
-	{ 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 },
-	{ 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 },
-	{ 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 },
-	{ 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b },
-	{ 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 },
-	{ 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 },
-	{ 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 },
-	{ 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 },
-	{ 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b },
-	{ 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 },
-	{ 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b },
-	{ 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 },
-	{ 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b },
-	{ 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 },
-
-	/* 802.11 UNII */
-	{ 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 },
-	{ 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 },
-	{ 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f },
-	{ 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f },
-	{ 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 },
-	{ 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 },
-	{ 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 },
-	{ 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f },
-	{ 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 },
-	{ 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 },
-	{ 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f },
-
-	/* 802.11 Japan */
-	{ 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b },
-	{ 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 },
-	{ 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b },
-	{ 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 },
-	{ 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 },
-	{ 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b },
-	{ 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 },
-};
-
-/*
- * RF value list for rt3070
- * Supports: 2.4 GHz
- */
-static const struct rf_channel rf_vals_3070[] = {
-	{1,  241, 2, 2 },
-	{2,  241, 2, 7 },
-	{3,  242, 2, 2 },
-	{4,  242, 2, 7 },
-	{5,  243, 2, 2 },
-	{6,  243, 2, 7 },
-	{7,  244, 2, 2 },
-	{8,  244, 2, 7 },
-	{9,  245, 2, 2 },
-	{10, 245, 2, 7 },
-	{11, 246, 2, 2 },
-	{12, 246, 2, 7 },
-	{13, 247, 2, 2 },
-	{14, 248, 2, 4 },
-};
-
-static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
-{
-	struct hw_mode_spec *spec = &rt2x00dev->spec;
-	struct channel_info *info;
-	char *tx_power1;
-	char *tx_power2;
-	unsigned int i;
-	u16 eeprom;
-
-	/*
-	 * Initialize all hw fields.
-	 */
-	rt2x00dev->hw->flags =
-	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-	    IEEE80211_HW_SIGNAL_DBM |
-	    IEEE80211_HW_SUPPORTS_PS |
-	    IEEE80211_HW_PS_NULLFUNC_STACK;
-	rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
-
-	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
-	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
-				rt2x00_eeprom_addr(rt2x00dev,
-						   EEPROM_MAC_ADDR_0));
-
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom);
-
-	/*
-	 * Initialize HT information.
-	 */
-	spec->ht.ht_supported = true;
-	spec->ht.cap =
-	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
-	    IEEE80211_HT_CAP_GRN_FLD |
-	    IEEE80211_HT_CAP_SGI_20 |
-	    IEEE80211_HT_CAP_SGI_40 |
-	    IEEE80211_HT_CAP_TX_STBC |
-	    IEEE80211_HT_CAP_RX_STBC |
-	    IEEE80211_HT_CAP_PSMP_SUPPORT;
-	spec->ht.ampdu_factor = 3;
-	spec->ht.ampdu_density = 4;
-	spec->ht.mcs.tx_params =
-	    IEEE80211_HT_MCS_TX_DEFINED |
-	    IEEE80211_HT_MCS_TX_RX_DIFF |
-	    ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) <<
-		IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
-
-	switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) {
-	case 3:
-		spec->ht.mcs.rx_mask[2] = 0xff;
-	case 2:
-		spec->ht.mcs.rx_mask[1] = 0xff;
-	case 1:
-		spec->ht.mcs.rx_mask[0] = 0xff;
-		spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */
-		break;
-	}
-
-	/*
-	 * Initialize hw_mode information.
-	 */
-	spec->supported_bands = SUPPORT_BAND_2GHZ;
-	spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM;
-
-	if (rt2x00_rf(&rt2x00dev->chip, RF2820) ||
-	    rt2x00_rf(&rt2x00dev->chip, RF2720)) {
-		spec->num_channels = 14;
-		spec->channels = rf_vals;
-	} else if (rt2x00_rf(&rt2x00dev->chip, RF2850) ||
-		   rt2x00_rf(&rt2x00dev->chip, RF2750)) {
-		spec->supported_bands |= SUPPORT_BAND_5GHZ;
-		spec->num_channels = ARRAY_SIZE(rf_vals);
-		spec->channels = rf_vals;
-	} else if (rt2x00_rf(&rt2x00dev->chip, RF3020) ||
-		   rt2x00_rf(&rt2x00dev->chip, RF2020)) {
-		spec->num_channels = ARRAY_SIZE(rf_vals_3070);
-		spec->channels = rf_vals_3070;
-	}
-
-	/*
-	 * Create channel information array
-	 */
-	info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-
-	spec->channels_info = info;
-
-	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
-	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
-
-	for (i = 0; i < 14; i++) {
-		info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
-		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
-	}
-
-	if (spec->num_channels > 14) {
-		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
-		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
-
-		for (i = 14; i < spec->num_channels; i++) {
-			info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
-			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
-		}
-	}
+	if (rt2800_efuse_detect(rt2x00dev))
+		rt2800_read_eeprom_efuse(rt2x00dev);
+	else
+		rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
+				      EEPROM_SIZE);
 
 
-	return 0;
+	return rt2800_validate_eeprom(rt2x00dev);
 }
 }
 
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
 	.register_read		= rt2x00usb_register_read,
 	.register_read		= rt2x00usb_register_read,
+	.register_read_lock	= rt2x00usb_register_read_lock,
 	.register_write		= rt2x00usb_register_write,
 	.register_write		= rt2x00usb_register_write,
 	.register_write_lock	= rt2x00usb_register_write_lock,
 	.register_write_lock	= rt2x00usb_register_write_lock,
 
 
@@ -1074,8 +696,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
 {
 	int retval;
 	int retval;
 
 
-	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
-
 	rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops;
 	rt2x00dev->priv = (void *)&rt2800usb_rt2800_ops;
 
 
 	/*
 	/*
@@ -1085,14 +705,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
-	retval = rt2800usb_init_eeprom(rt2x00dev);
+	retval = rt2800_init_eeprom(rt2x00dev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 
 	/*
 	/*
 	 * Initialize hw specifications.
 	 * Initialize hw specifications.
 	 */
 	 */
-	retval = rt2800usb_probe_hw_mode(rt2x00dev);
+	retval = rt2800_probe_hw_mode(rt2x00dev);
 	if (retval)
 	if (retval)
 		return retval;
 		return retval;
 
 

+ 25 - 21
drivers/net/wireless/rt2x00/rt2800usb.h

@@ -1,5 +1,9 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de>
+	Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
+	Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com>
+	Copyright (C) 2009 Axel Kollhofer <rain_maker@root-forum.org>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -111,25 +115,25 @@
  * AMSDU: rx with 802.3 header, not 802.11 header.
  * AMSDU: rx with 802.3 header, not 802.11 header.
  */
  */
 
 
-#define RXD_W0_BA			FIELD32(0x00000001)
-#define RXD_W0_DATA			FIELD32(0x00000002)
-#define RXD_W0_NULLDATA			FIELD32(0x00000004)
-#define RXD_W0_FRAG			FIELD32(0x00000008)
-#define RXD_W0_UNICAST_TO_ME		FIELD32(0x00000010)
-#define RXD_W0_MULTICAST		FIELD32(0x00000020)
-#define RXD_W0_BROADCAST		FIELD32(0x00000040)
-#define RXD_W0_MY_BSS			FIELD32(0x00000080)
-#define RXD_W0_CRC_ERROR		FIELD32(0x00000100)
-#define RXD_W0_CIPHER_ERROR		FIELD32(0x00000600)
-#define RXD_W0_AMSDU			FIELD32(0x00000800)
-#define RXD_W0_HTC			FIELD32(0x00001000)
-#define RXD_W0_RSSI			FIELD32(0x00002000)
-#define RXD_W0_L2PAD			FIELD32(0x00004000)
-#define RXD_W0_AMPDU			FIELD32(0x00008000)
-#define RXD_W0_DECRYPTED		FIELD32(0x00010000)
-#define RXD_W0_PLCP_RSSI		FIELD32(0x00020000)
-#define RXD_W0_CIPHER_ALG		FIELD32(0x00040000)
-#define RXD_W0_LAST_AMSDU		FIELD32(0x00080000)
-#define RXD_W0_PLCP_SIGNAL		FIELD32(0xfff00000)
+#define RXINFO_W0_BA			FIELD32(0x00000001)
+#define RXINFO_W0_DATA			FIELD32(0x00000002)
+#define RXINFO_W0_NULLDATA		FIELD32(0x00000004)
+#define RXINFO_W0_FRAG			FIELD32(0x00000008)
+#define RXINFO_W0_UNICAST_TO_ME		FIELD32(0x00000010)
+#define RXINFO_W0_MULTICAST		FIELD32(0x00000020)
+#define RXINFO_W0_BROADCAST		FIELD32(0x00000040)
+#define RXINFO_W0_MY_BSS		FIELD32(0x00000080)
+#define RXINFO_W0_CRC_ERROR		FIELD32(0x00000100)
+#define RXINFO_W0_CIPHER_ERROR		FIELD32(0x00000600)
+#define RXINFO_W0_AMSDU			FIELD32(0x00000800)
+#define RXINFO_W0_HTC			FIELD32(0x00001000)
+#define RXINFO_W0_RSSI			FIELD32(0x00002000)
+#define RXINFO_W0_L2PAD			FIELD32(0x00004000)
+#define RXINFO_W0_AMPDU			FIELD32(0x00008000)
+#define RXINFO_W0_DECRYPTED		FIELD32(0x00010000)
+#define RXINFO_W0_PLCP_RSSI		FIELD32(0x00020000)
+#define RXINFO_W0_CIPHER_ALG		FIELD32(0x00040000)
+#define RXINFO_W0_LAST_AMSDU		FIELD32(0x00080000)
+#define RXINFO_W0_PLCP_SIGNAL		FIELD32(0xfff00000)
 
 
 #endif /* RT2800USB_H */
 #endif /* RT2800USB_H */

+ 10 - 12
drivers/net/wireless/rt2x00/rt2x00.h

@@ -1,5 +1,6 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -171,6 +172,7 @@ struct rt2x00_chip {
 #define RT3052		0x3052	/* WSOC */
 #define RT3052		0x3052	/* WSOC */
 #define RT3090		0x3090	/* 2.4GHz PCIe */
 #define RT3090		0x3090	/* 2.4GHz PCIe */
 #define RT2870		0x1600
 #define RT2870		0x1600
+#define RT3070		0x1800
 
 
 	u16 rf;
 	u16 rf;
 	u32 rev;
 	u32 rev;
@@ -312,13 +314,6 @@ struct link {
 	 */
 	 */
 	struct avg_val avg_rssi;
 	struct avg_val avg_rssi;
 
 
-	/*
-	 * Currently precalculated percentages of successful
-	 * TX and RX frames.
-	 */
-	int rx_percentage;
-	int tx_percentage;
-
 	/*
 	/*
 	 * Work structure for scheduling periodic link tuning.
 	 * Work structure for scheduling periodic link tuning.
 	 */
 	 */
@@ -911,10 +906,6 @@ static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev,
 static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
 static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev,
 				   const u16 rt, const u16 rf, const u32 rev)
 				   const u16 rt, const u16 rf, const u32 rev)
 {
 {
-	INFO(rt2x00dev,
-	     "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
-	     rt, rf, rev);
-
 	rt2x00dev->chip.rt = rt;
 	rt2x00dev->chip.rt = rt;
 	rt2x00dev->chip.rf = rf;
 	rt2x00dev->chip.rf = rf;
 	rt2x00dev->chip.rev = rev;
 	rt2x00dev->chip.rev = rev;
@@ -932,6 +923,13 @@ static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
 	rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev);
 }
 }
 
 
+static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev)
+{
+	INFO(rt2x00dev,
+	     "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n",
+	     rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev);
+}
+
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
 static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip)
 {
 {
 	return (chipset->rt == chip);
 	return (chipset->rt == chip);

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00config.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00crypto.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00debug.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00debug.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 2
drivers/net/wireless/rt2x00/rt2x00dev.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -430,7 +430,6 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
 
 
 	rx_status->mactime = rxdesc.timestamp;
 	rx_status->mactime = rxdesc.timestamp;
 	rx_status->rate_idx = rate_idx;
 	rx_status->rate_idx = rate_idx;
-	rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi);
 	rx_status->signal = rxdesc.rssi;
 	rx_status->signal = rxdesc.rssi;
 	rx_status->noise = rxdesc.noise;
 	rx_status->noise = rxdesc.noise;
 	rx_status->flag = rxdesc.flags;
 	rx_status->flag = rxdesc.flags;

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00dump.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 1
drivers/net/wireless/rt2x00/rt2x00firmware.c

@@ -1,5 +1,6 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00ht.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00leds.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00leds.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 14
drivers/net/wireless/rt2x00/rt2x00lib.h

@@ -1,5 +1,6 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -222,19 +223,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
 			     struct sk_buff *skb,
 			     struct sk_buff *skb,
 			     struct rxdone_entry_desc *rxdesc);
 			     struct rxdone_entry_desc *rxdesc);
 
 
-/**
- * rt2x00link_calculate_signal - Calculate signal quality
- * @rt2x00dev: Pointer to &struct rt2x00_dev.
- * @rssi: RX Frame RSSI
- *
- * Calculate the signal quality of a frame based on the rssi
- * measured during the receiving of the frame and the global
- * link quality statistics measured since the start of the
- * link tuning. The result is a value between 0 and 100 which
- * is an indication of the signal quality.
- */
-int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi);
-
 /**
 /**
  * rt2x00link_start_tuner - Start periodic link tuner work
  * rt2x00link_start_tuner - Start periodic link tuner work
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @rt2x00dev: Pointer to &struct rt2x00_dev.

+ 1 - 89
drivers/net/wireless/rt2x00/rt2x00link.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -35,24 +35,6 @@
  */
  */
 #define DEFAULT_RSSI		-128
 #define DEFAULT_RSSI		-128
 
 
-/*
- * When no TX/RX percentage could be calculated due to lack of
- * frames on the air, we fallback to a percentage of 50%.
- * This will assure we will get at least get some decent value
- * when the link tuner starts.
- * The value will be dropped and overwritten with the correct (measured)
- * value anyway during the first run of the link tuner.
- */
-#define DEFAULT_PERCENTAGE	50
-
-/*
- * Small helper macro for percentage calculation
- * This is a very simple macro with the only catch that it will
- * produce a default value in case no total value was provided.
- */
-#define PERCENTAGE(__value, __total) \
-	( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) )
-
 /*
 /*
  * Helper struct and macro to work with moving/walking averages.
  * Helper struct and macro to work with moving/walking averages.
  * When adding a value to the average value the following calculation
  * When adding a value to the average value the following calculation
@@ -91,27 +73,6 @@
 	__new; \
 	__new; \
 })
 })
 
 
-/*
- * For calculating the Signal quality we have determined
- * the total number of success and failed RX and TX frames.
- * With the addition of the average RSSI value we can determine
- * the link quality using the following algorithm:
- *
- *         rssi_percentage = (avg_rssi * 100) / rssi_offset
- *         rx_percentage = (rx_success * 100) / rx_total
- *         tx_percentage = (tx_success * 100) / tx_total
- *         avg_signal = ((WEIGHT_RSSI * avg_rssi) +
- *                       (WEIGHT_TX * tx_percentage) +
- *                       (WEIGHT_RX * rx_percentage)) / 100
- *
- * This value should then be checked to not be greater then 100.
- * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must
- * sum up to 100 as well.
- */
-#define WEIGHT_RSSI	20
-#define WEIGHT_RX	40
-#define WEIGHT_TX	40
-
 static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
 static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev)
 {
 {
 	struct link_ant *ant = &rt2x00dev->link.ant;
 	struct link_ant *ant = &rt2x00dev->link.ant;
@@ -304,46 +265,6 @@ void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev,
 	ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
 	ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi);
 }
 }
 
 
-static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev)
-{
-	struct link *link = &rt2x00dev->link;
-	struct link_qual *qual = &rt2x00dev->link.qual;
-
-	link->rx_percentage =
-	    PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success);
-	link->tx_percentage =
-	    PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success);
-}
-
-int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi)
-{
-	struct link *link = &rt2x00dev->link;
-	int rssi_percentage = 0;
-	int signal;
-
-	/*
-	 * We need a positive value for the RSSI.
-	 */
-	if (rssi < 0)
-		rssi += rt2x00dev->rssi_offset;
-
-	/*
-	 * Calculate the different percentages,
-	 * which will be used for the signal.
-	 */
-	rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset);
-
-	/*
-	 * Add the individual percentages and use the WEIGHT
-	 * defines to calculate the current link signal.
-	 */
-	signal = ((WEIGHT_RSSI * rssi_percentage) +
-		  (WEIGHT_TX * link->tx_percentage) +
-		  (WEIGHT_RX * link->rx_percentage)) / 100;
-
-	return max_t(int, signal, 100);
-}
-
 void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
 void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
 {
 {
 	struct link *link = &rt2x00dev->link;
 	struct link *link = &rt2x00dev->link;
@@ -357,9 +278,6 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
 	if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
 	if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
 		return;
 		return;
 
 
-	link->rx_percentage = DEFAULT_PERCENTAGE;
-	link->tx_percentage = DEFAULT_PERCENTAGE;
-
 	rt2x00link_reset_tuner(rt2x00dev, false);
 	rt2x00link_reset_tuner(rt2x00dev, false);
 
 
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
@@ -447,12 +365,6 @@ static void rt2x00link_tuner(struct work_struct *work)
 	if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
 	if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags))
 		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
 		rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count);
 
 
-	/*
-	 * Precalculate a portion of the link signal which is
-	 * in based on the tx/rx success/failure counters.
-	 */
-	rt2x00link_precalculate_signal(rt2x00dev);
-
 	/*
 	/*
 	 * Send a signal to the led to update the led signal strength.
 	 * Send a signal to the led to update the led signal strength.
 	 */
 	 */

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00mac.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 3 - 1
drivers/net/wireless/rt2x00/rt2x00pci.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -310,6 +310,8 @@ int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
 	rt2x00dev->irq = pci_dev->irq;
 	rt2x00dev->irq = pci_dev->irq;
 	rt2x00dev->name = pci_name(pci_dev);
 	rt2x00dev->name = pci_name(pci_dev);
 
 
+	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+
 	/*
 	/*
 	 * Determine RT chipset by reading PCI header.
 	 * Determine RT chipset by reading PCI header.
 	 */
 	 */

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00pci.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 1
drivers/net/wireless/rt2x00/rt2x00queue.c

@@ -1,5 +1,6 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00queue.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00reg.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 7 - 1
drivers/net/wireless/rt2x00/rt2x00soc.c

@@ -1,5 +1,6 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
+	Copyright (C) 2004 - 2009 Felix Fietkau <nbd@openwrt.org>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -93,6 +94,11 @@ int rt2x00soc_probe(struct platform_device *pdev,
 	rt2x00dev->irq = platform_get_irq(pdev, 0);
 	rt2x00dev->irq = platform_get_irq(pdev, 0);
 	rt2x00dev->name = pdev->dev.driver->name;
 	rt2x00dev->name = pdev->dev.driver->name;
 
 
+	/*
+	 * SoC devices mimic PCI behavior.
+	 */
+	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI);
+
 	rt2x00_set_chip_rt(rt2x00dev, chipset);
 	rt2x00_set_chip_rt(rt2x00dev, chipset);
 
 
 	retval = rt2x00soc_alloc_reg(rt2x00dev);
 	retval = rt2x00soc_alloc_reg(rt2x00dev);

+ 1 - 1
drivers/net/wireless/rt2x00/rt2x00soc.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 3 - 1
drivers/net/wireless/rt2x00/rt2x00usb.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -653,6 +653,8 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
 	rt2x00dev->ops = ops;
 	rt2x00dev->ops = ops;
 	rt2x00dev->hw = hw;
 	rt2x00dev->hw = hw;
 
 
+	rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB);
+
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	retval = rt2x00usb_alloc_reg(rt2x00dev);
 	if (retval)
 	if (retval)
 		goto exit_free_device;
 		goto exit_free_device;

+ 3 - 1
drivers/net/wireless/rt2x00/rt2x00usb.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -26,6 +26,8 @@
 #ifndef RT2X00USB_H
 #ifndef RT2X00USB_H
 #define RT2X00USB_H
 #define RT2X00USB_H
 
 
+#include <linux/usb.h>
+
 #define to_usb_device_intf(d) \
 #define to_usb_device_intf(d) \
 ({ \
 ({ \
 	struct usb_interface *intf = to_usb_interface(d); \
 	struct usb_interface *intf = to_usb_interface(d); \

+ 20 - 19
drivers/net/wireless/rt2x00/rt61pci.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
  * These indirect registers work with busy bits,
  * These indirect registers work with busy bits,
  * and we will try maximal REGISTER_BUSY_COUNT times to access
  * and we will try maximal REGISTER_BUSY_COUNT times to access
  * the register while taking a REGISTER_BUSY_DELAY us delay
  * the register while taking a REGISTER_BUSY_DELAY us delay
- * between each attampt. When the busy bit is still set at that time,
+ * between each attempt. When the busy bit is still set at that time,
  * the access attempt is considered to have failed,
  * the access attempt is considered to have failed,
  * and we will print an error.
  * and we will print an error.
  */
  */
@@ -386,7 +386,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
 		 * The driver does not support the IV/EIV generation
 		 * The driver does not support the IV/EIV generation
 		 * in hardware. However it doesn't support the IV/EIV
 		 * in hardware. However it doesn't support the IV/EIV
 		 * inside the ieee80211 frame either, but requires it
 		 * inside the ieee80211 frame either, but requires it
-		 * to be provided seperately for the descriptor.
+		 * to be provided separately for the descriptor.
 		 * rt2x00lib will cut the IV/EIV data out of all frames
 		 * rt2x00lib will cut the IV/EIV data out of all frames
 		 * given to us by mac80211, but we must tell mac80211
 		 * given to us by mac80211, but we must tell mac80211
 		 * to generate the IV/EIV data.
 		 * to generate the IV/EIV data.
@@ -397,7 +397,7 @@ static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev,
 	/*
 	/*
 	 * SEC_CSR0 contains only single-bit fields to indicate
 	 * SEC_CSR0 contains only single-bit fields to indicate
 	 * a particular key is valid. Because using the FIELD32()
 	 * a particular key is valid. Because using the FIELD32()
-	 * defines directly will cause a lot of overhead we use
+	 * defines directly will cause a lot of overhead, we use
 	 * a calculation to determine the correct bit directly.
 	 * a calculation to determine the correct bit directly.
 	 */
 	 */
 	mask = 1 << key->hw_key_idx;
 	mask = 1 << key->hw_key_idx;
@@ -425,11 +425,11 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 		/*
 		/*
 		 * rt2x00lib can't determine the correct free
 		 * rt2x00lib can't determine the correct free
 		 * key_idx for pairwise keys. We have 2 registers
 		 * key_idx for pairwise keys. We have 2 registers
-		 * with key valid bits. The goal is simple, read
-		 * the first register, if that is full move to
+		 * with key valid bits. The goal is simple: read
+		 * the first register. If that is full, move to
 		 * the next register.
 		 * the next register.
-		 * When both registers are full, we drop the key,
-		 * otherwise we use the first invalid entry.
+		 * When both registers are full, we drop the key.
+		 * Otherwise, we use the first invalid entry.
 		 */
 		 */
 		rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
 		rt2x00pci_register_read(rt2x00dev, SEC_CSR2, &reg);
 		if (reg && reg == ~0) {
 		if (reg && reg == ~0) {
@@ -464,8 +464,8 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 					      &addr_entry, sizeof(addr_entry));
 					      &addr_entry, sizeof(addr_entry));
 
 
 		/*
 		/*
-		 * Enable pairwise lookup table for given BSS idx,
-		 * without this received frames will not be decrypted
+		 * Enable pairwise lookup table for given BSS idx.
+		 * Without this, received frames will not be decrypted
 		 * by the hardware.
 		 * by the hardware.
 		 */
 		 */
 		rt2x00pci_register_read(rt2x00dev, SEC_CSR4, &reg);
 		rt2x00pci_register_read(rt2x00dev, SEC_CSR4, &reg);
@@ -487,7 +487,7 @@ static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 	/*
 	/*
 	 * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
 	 * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate
 	 * a particular key is valid. Because using the FIELD32()
 	 * a particular key is valid. Because using the FIELD32()
-	 * defines directly will cause a lot of overhead we use
+	 * defines directly will cause a lot of overhead, we use
 	 * a calculation to determine the correct bit directly.
 	 * a calculation to determine the correct bit directly.
 	 */
 	 */
 	if (key->hw_key_idx < 32) {
 	if (key->hw_key_idx < 32) {
@@ -556,7 +556,7 @@ static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev,
 	if (flags & CONFIG_UPDATE_TYPE) {
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
 		/*
 		 * Clear current synchronisation setup.
 		 * Clear current synchronisation setup.
-		 * For the Beacon base registers we only need to clear
+		 * For the Beacon base registers, we only need to clear
 		 * the first byte since that byte contains the VALID and OWNER
 		 * the first byte since that byte contains the VALID and OWNER
 		 * bits which (when set to 0) will invalidate the entire beacon.
 		 * bits which (when set to 0) will invalidate the entire beacon.
 		 */
 		 */
@@ -1168,8 +1168,8 @@ static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev,
 		return FW_BAD_LENGTH;
 		return FW_BAD_LENGTH;
 
 
 	/*
 	/*
-	 * The last 2 bytes in the firmware array are the crc checksum itself,
-	 * this means that we should never pass those 2 bytes to the crc
+	 * The last 2 bytes in the firmware array are the crc checksum itself.
+	 * This means that we should never pass those 2 bytes to the crc
 	 * algorithm.
 	 * algorithm.
 	 */
 	 */
 	fw_crc = (data[len - 2] << 8 | data[len - 1]);
 	fw_crc = (data[len - 2] << 8 | data[len - 1]);
@@ -1986,7 +1986,7 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
 
 
 		/*
 		/*
 		 * Hardware has stripped IV/EIV data from 802.11 frame during
 		 * Hardware has stripped IV/EIV data from 802.11 frame during
-		 * decryption. It has provided the data seperately but rt2x00lib
+		 * decryption. It has provided the data separately but rt2x00lib
 		 * should decide if it should be reinserted.
 		 * should decide if it should be reinserted.
 		 */
 		 */
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
@@ -2042,7 +2042,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 	 * During each loop we will compare the freshly read
 	 * During each loop we will compare the freshly read
 	 * STA_CSR4 register value with the value read from
 	 * STA_CSR4 register value with the value read from
 	 * the previous loop. If the 2 values are equal then
 	 * the previous loop. If the 2 values are equal then
-	 * we should stop processing because the chance it
+	 * we should stop processing because the chance is
 	 * quite big that the device has been unplugged and
 	 * quite big that the device has been unplugged and
 	 * we risk going into an endless loop.
 	 * we risk going into an endless loop.
 	 */
 	 */
@@ -2300,6 +2300,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00pci_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
 	rt2x00_set_chip_rf(rt2x00dev, value, reg);
+	rt2x00_print_chip(rt2x00dev);
 
 
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	if (!rt2x00_rf(&rt2x00dev->chip, RF5225) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
 	    !rt2x00_rf(&rt2x00dev->chip, RF5325) &&
@@ -2330,7 +2331,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
 		__set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags);
 
 
 	/*
 	/*
-	 * Detect if this device has an hardware controlled radio.
+	 * Detect if this device has a hardware controlled radio.
 	 */
 	 */
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
 		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
 		__set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags);
@@ -2355,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
 		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
 		__set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags);
 
 
 	/*
 	/*
-	 * When working with a RF2529 chip without double antenna
+	 * When working with a RF2529 chip without double antenna,
 	 * the antenna settings should be gathered from the NIC
 	 * the antenna settings should be gathered from the NIC
 	 * eeprom word.
 	 * eeprom word.
 	 */
 	 */
@@ -2668,7 +2669,7 @@ static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
 
 
 	/*
 	/*
 	 * We only need to perform additional register initialization
 	 * We only need to perform additional register initialization
-	 * for WMM queues/
+	 * for WMM queues.
 	 */
 	 */
 	if (queue_idx >= 4)
 	if (queue_idx >= 4)
 		return 0;
 		return 0;

+ 1 - 1
drivers/net/wireless/rt2x00/rt61pci.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 2 - 1
drivers/net/wireless/rt2x00/rt73usb.c

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify
@@ -1825,6 +1825,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
 	rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
 	rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
 	rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
+	rt2x00_print_chip(rt2x00dev);
 
 
 	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
 	if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) ||
 	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {
 	    rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) {

+ 1 - 1
drivers/net/wireless/rt2x00/rt73usb.h

@@ -1,5 +1,5 @@
 /*
 /*
-	Copyright (C) 2004 - 2009 rt2x00 SourceForge Project
+	Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com>
 	<http://rt2x00.serialmonkey.com>
 	<http://rt2x00.serialmonkey.com>
 
 
 	This program is free software; you can redistribute it and/or modify
 	This program is free software; you can redistribute it and/or modify

+ 1 - 0
drivers/net/wireless/wl12xx/wl1251_main.c

@@ -1431,3 +1431,4 @@ MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core");
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
 MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
 MODULE_ALIAS("spi:wl1251");
 MODULE_ALIAS("spi:wl1251");
+MODULE_FIRMWARE(WL1251_FW_NAME);

+ 1 - 0
drivers/net/wireless/wl12xx/wl1271_main.c

@@ -1979,3 +1979,4 @@ module_exit(wl1271_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
 MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
+MODULE_FIRMWARE(WL1271_FW_NAME);

+ 3 - 0
drivers/net/wireless/zd1201.c

@@ -112,6 +112,9 @@ exit:
 	return err;
 	return err;
 }
 }
 
 
+MODULE_FIRMWARE("zd1201-ap.fw");
+MODULE_FIRMWARE("zd1201.fw");
+
 static void zd1201_usbfree(struct urb *urb)
 static void zd1201_usbfree(struct urb *urb)
 {
 {
 	struct zd1201 *zd = urb->context;
 	struct zd1201 *zd = urb->context;

+ 7 - 0
drivers/net/wireless/zd1211rw/zd_usb.c

@@ -318,6 +318,13 @@ error:
 	return r;
 	return r;
 }
 }
 
 
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ur");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "ur");
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "ub");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "ub");
+MODULE_FIRMWARE(FW_ZD1211B_PREFIX "uphr");
+MODULE_FIRMWARE(FW_ZD1211_PREFIX "uphr");
+
 /* Read data from device address space using "firmware interface" which does
 /* Read data from device address space using "firmware interface" which does
  * not require firmware to be loaded. */
  * not require firmware to be loaded. */
 int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)
 int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len)

+ 1 - 2
drivers/net/znet.c

@@ -103,8 +103,7 @@
 #include <asm/io.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/dma.h>
 
 
-/* This include could be elsewhere, since it is not wireless specific */
-#include "wireless/i82593.h"
+#include <linux/i82593.h>
 
 
 static char version[] __initdata = "znet.c:v1.02 9/23/94 becker@scyld.com\n";
 static char version[] __initdata = "znet.c:v1.02 9/23/94 becker@scyld.com\n";
 
 

+ 1 - 1
drivers/staging/arlan/Kconfig

@@ -1,6 +1,6 @@
 config ARLAN
 config ARLAN
 	tristate "Aironet Arlan 655 & IC2200 DS support"
 	tristate "Aironet Arlan 655 & IC2200 DS support"
-	depends on ISA && !64BIT
+	depends on ISA && !64BIT && WLAN
 	select WIRELESS_EXT
 	select WIRELESS_EXT
 	---help---
 	---help---
 	  Aironet makes Arlan, a class of wireless LAN adapters. These use the
 	  Aironet makes Arlan, a class of wireless LAN adapters. These use the

+ 1 - 1
drivers/staging/netwave/Kconfig

@@ -1,6 +1,6 @@
 config PCMCIA_NETWAVE
 config PCMCIA_NETWAVE
 	tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
 	tristate "Xircom Netwave AirSurfer Pcmcia wireless support"
-	depends on PCMCIA
+	depends on PCMCIA && WLAN
 	select WIRELESS_EXT
 	select WIRELESS_EXT
 	select WEXT_PRIV
 	select WEXT_PRIV
 	help
 	help

+ 2 - 2
drivers/staging/wavelan/Kconfig

@@ -1,6 +1,6 @@
 config WAVELAN
 config WAVELAN
 	tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
 	tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support"
-	depends on ISA
+	depends on ISA && WLAN
 	select WIRELESS_EXT
 	select WIRELESS_EXT
 	select WEXT_SPY
 	select WEXT_SPY
 	select WEXT_PRIV
 	select WEXT_PRIV
@@ -25,7 +25,7 @@ config WAVELAN
 
 
 config PCMCIA_WAVELAN
 config PCMCIA_WAVELAN
 	tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
 	tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support"
-	depends on PCMCIA
+	depends on PCMCIA && WLAN
 	select WIRELESS_EXT
 	select WIRELESS_EXT
 	select WEXT_SPY
 	select WEXT_SPY
 	select WEXT_PRIV
 	select WEXT_PRIV

+ 1 - 1
drivers/staging/wavelan/wavelan_cs.p.h

@@ -446,7 +446,7 @@
 #include <pcmcia/ds.h>
 #include <pcmcia/ds.h>
 
 
 /* Wavelan declarations */
 /* Wavelan declarations */
-#include "i82593.h"	/* Definitions for the Intel chip */
+#include <linux/i82593.h>	/* Definitions for the Intel chip */
 
 
 #include "wavelan_cs.h"	/* Others bits of the hardware */
 #include "wavelan_cs.h"	/* Others bits of the hardware */
 
 

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