瀏覽代碼

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

David S. Miller 14 年之前
父節點
當前提交
b5e4156743
共有 100 個文件被更改,包括 4517 次插入2355 次删除
  1. 9 23
      arch/arm/mach-omap2/board-omap3pandora.c
  2. 21 3
      drivers/net/wireless/ath/ath5k/base.c
  3. 15 15
      drivers/net/wireless/ath/ath5k/debug.c
  4. 9 9
      drivers/net/wireless/ath/ath5k/desc.h
  5. 1 7
      drivers/net/wireless/ath/ath5k/phy.c
  6. 7 7
      drivers/net/wireless/ath/ath9k/ar5008_phy.c
  7. 53 70
      drivers/net/wireless/ath/ath9k/ar9002_mac.c
  8. 4 4
      drivers/net/wireless/ath/ath9k/ar9002_phy.c
  9. 15 5
      drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
  10. 36 33
      drivers/net/wireless/ath/ath9k/ar9003_mac.c
  11. 3 3
      drivers/net/wireless/ath/ath9k/ar9003_mac.h
  12. 7 7
      drivers/net/wireless/ath/ath9k/ar9003_phy.c
  13. 5 9
      drivers/net/wireless/ath/ath9k/ath9k.h
  14. 6 6
      drivers/net/wireless/ath/ath9k/beacon.c
  15. 6 9
      drivers/net/wireless/ath/ath9k/common.c
  16. 8 6
      drivers/net/wireless/ath/ath9k/common.h
  17. 25 23
      drivers/net/wireless/ath/ath9k/debug.c
  18. 2 3
      drivers/net/wireless/ath/ath9k/debug.h
  19. 2 1
      drivers/net/wireless/ath/ath9k/eeprom.h
  20. 7 2
      drivers/net/wireless/ath/ath9k/eeprom_4k.c
  21. 15 12
      drivers/net/wireless/ath/ath9k/eeprom_9287.c
  22. 33 29
      drivers/net/wireless/ath/ath9k/eeprom_def.c
  23. 4 6
      drivers/net/wireless/ath/ath9k/gpio.c
  24. 9 61
      drivers/net/wireless/ath/ath9k/htc_drv_main.c
  25. 8 1
      drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
  26. 4 5
      drivers/net/wireless/ath/ath9k/hw.c
  27. 8 8
      drivers/net/wireless/ath/ath9k/hw.h
  28. 41 47
      drivers/net/wireless/ath/ath9k/init.c
  29. 50 36
      drivers/net/wireless/ath/ath9k/mac.c
  30. 6 7
      drivers/net/wireless/ath/ath9k/mac.h
  31. 54 113
      drivers/net/wireless/ath/ath9k/main.c
  32. 22 18
      drivers/net/wireless/ath/ath9k/pci.c
  33. 5 26
      drivers/net/wireless/ath/ath9k/rc.c
  34. 15 27
      drivers/net/wireless/ath/ath9k/recv.c
  35. 2 1
      drivers/net/wireless/ath/ath9k/virtual.c
  36. 45 57
      drivers/net/wireless/ath/ath9k/xmit.c
  37. 3 2
      drivers/net/wireless/ath/carl9170/carl9170.h
  38. 9 4
      drivers/net/wireless/ath/carl9170/fwcmd.h
  39. 6 1
      drivers/net/wireless/ath/carl9170/hw.h
  40. 34 22
      drivers/net/wireless/ath/carl9170/mac.c
  41. 18 1
      drivers/net/wireless/ath/carl9170/main.c
  42. 4 13
      drivers/net/wireless/ath/carl9170/phy.c
  43. 12 12
      drivers/net/wireless/ath/carl9170/phy.h
  44. 67 13
      drivers/net/wireless/ath/carl9170/tx.c
  45. 1 1
      drivers/net/wireless/ath/carl9170/usb.c
  46. 3 3
      drivers/net/wireless/ath/carl9170/version.h
  47. 2 0
      drivers/net/wireless/ath/debug.h
  48. 5 4
      drivers/net/wireless/ath/key.c
  49. 13 0
      drivers/net/wireless/b43/b43.h
  50. 0 5
      drivers/net/wireless/b43/dma.c
  51. 9 5
      drivers/net/wireless/b43/phy_n.c
  52. 5 3
      drivers/net/wireless/b43/radio_2055.c
  53. 51 0
      drivers/net/wireless/b43/radio_2056.c
  54. 1078 3
      drivers/net/wireless/b43/radio_2056.h
  55. 1 1
      drivers/net/wireless/b43legacy/rfkill.c
  56. 3 0
      drivers/net/wireless/iwlwifi/Kconfig
  57. 5 2
      drivers/net/wireless/iwlwifi/Makefile
  58. 8 5
      drivers/net/wireless/iwlwifi/iwl-1000.c
  59. 17 5
      drivers/net/wireless/iwlwifi/iwl-3945.c
  60. 4 4
      drivers/net/wireless/iwlwifi/iwl-3945.h
  61. 321 31
      drivers/net/wireless/iwlwifi/iwl-4965.c
  62. 16 10
      drivers/net/wireless/iwlwifi/iwl-5000.c
  63. 25 21
      drivers/net/wireless/iwlwifi/iwl-6000.c
  64. 124 106
      drivers/net/wireless/iwlwifi/iwl-agn-calib.c
  65. 32 21
      drivers/net/wireless/iwlwifi/iwl-agn-lib.c
  66. 619 0
      drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
  67. 31 1
      drivers/net/wireless/iwlwifi/iwl-agn-sta.c
  68. 75 418
      drivers/net/wireless/iwlwifi/iwl-agn.c
  69. 40 1
      drivers/net/wireless/iwlwifi/iwl-agn.h
  70. 153 688
      drivers/net/wireless/iwlwifi/iwl-core.c
  71. 40 30
      drivers/net/wireless/iwlwifi/iwl-core.h
  72. 2 0
      drivers/net/wireless/iwlwifi/iwl-csr.h
  73. 3 0
      drivers/net/wireless/iwlwifi/iwl-dev.h
  74. 2 0
      drivers/net/wireless/iwlwifi/iwl-led.c
  75. 662 0
      drivers/net/wireless/iwlwifi/iwl-legacy.c
  76. 79 0
      drivers/net/wireless/iwlwifi/iwl-legacy.h
  77. 60 35
      drivers/net/wireless/iwlwifi/iwl-power.c
  78. 3 0
      drivers/net/wireless/iwlwifi/iwl-power.h
  79. 27 18
      drivers/net/wireless/iwlwifi/iwl-rx.c
  80. 7 4
      drivers/net/wireless/iwlwifi/iwl-scan.c
  81. 30 21
      drivers/net/wireless/iwlwifi/iwl-tx.c
  82. 25 24
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  83. 4 1
      drivers/net/wireless/mac80211_hwsim.c
  84. 6 1
      drivers/net/wireless/mwl8k.c
  85. 6 8
      drivers/net/wireless/rt2x00/rt2400pci.c
  86. 3 3
      drivers/net/wireless/rt2x00/rt2400pci.h
  87. 9 11
      drivers/net/wireless/rt2x00/rt2500pci.c
  88. 2 2
      drivers/net/wireless/rt2x00/rt2500pci.h
  89. 10 12
      drivers/net/wireless/rt2x00/rt2500usb.c
  90. 48 13
      drivers/net/wireless/rt2x00/rt2800.h
  91. 37 6
      drivers/net/wireless/rt2x00/rt2800lib.c
  92. 7 9
      drivers/net/wireless/rt2x00/rt2800pci.c
  93. 6 6
      drivers/net/wireless/rt2x00/rt2800pci.h
  94. 54 12
      drivers/net/wireless/rt2x00/rt2800usb.c
  95. 2 2
      drivers/net/wireless/rt2x00/rt2800usb.h
  96. 1 0
      drivers/net/wireless/rt2x00/rt2x00.h
  97. 5 3
      drivers/net/wireless/rt2x00/rt2x00config.c
  98. 5 5
      drivers/net/wireless/rt2x00/rt2x00debug.c
  99. 15 22
      drivers/net/wireless/rt2x00/rt2x00dev.c
  100. 1 2
      drivers/net/wireless/rt2x00/rt2x00lib.h

+ 9 - 23
arch/arm/mach-omap2/board-omap3pandora.c

@@ -642,31 +642,13 @@ static void __init omap3pandora_init_irq(void)
 	omap_gpio_init();
 	omap_gpio_init();
 }
 }
 
 
-static void pandora_wl1251_set_power(bool enable)
-{
-	/*
-	 * Keep power always on until wl1251_sdio driver learns to re-init
-	 * the chip after powering it down and back up.
-	 */
-}
-
-static struct wl12xx_platform_data pandora_wl1251_pdata = {
-	.set_power	= pandora_wl1251_set_power,
-	.use_eeprom	= true,
-};
-
-static struct platform_device pandora_wl1251_data = {
-	.name           = "wl1251_data",
-	.id             = -1,
-	.dev		= {
-		.platform_data	= &pandora_wl1251_pdata,
-	},
-};
-
-static void pandora_wl1251_init(void)
+static void __init pandora_wl1251_init(void)
 {
 {
+	struct wl12xx_platform_data pandora_wl1251_pdata;
 	int ret;
 	int ret;
 
 
+	memset(&pandora_wl1251_pdata, 0, sizeof(pandora_wl1251_pdata));
+
 	ret = gpio_request(PANDORA_WIFI_IRQ_GPIO, "wl1251 irq");
 	ret = gpio_request(PANDORA_WIFI_IRQ_GPIO, "wl1251 irq");
 	if (ret < 0)
 	if (ret < 0)
 		goto fail;
 		goto fail;
@@ -679,6 +661,11 @@ static void pandora_wl1251_init(void)
 	if (pandora_wl1251_pdata.irq < 0)
 	if (pandora_wl1251_pdata.irq < 0)
 		goto fail_irq;
 		goto fail_irq;
 
 
+	pandora_wl1251_pdata.use_eeprom = true;
+	ret = wl12xx_set_platform_data(&pandora_wl1251_pdata);
+	if (ret < 0)
+		goto fail_irq;
+
 	return;
 	return;
 
 
 fail_irq:
 fail_irq:
@@ -691,7 +678,6 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
 	&pandora_leds_gpio,
 	&pandora_leds_gpio,
 	&pandora_keys_gpio,
 	&pandora_keys_gpio,
 	&pandora_dss_device,
 	&pandora_dss_device,
-	&pandora_wl1251_data,
 	&pandora_vwlan_device,
 	&pandora_vwlan_device,
 };
 };
 
 

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

@@ -566,8 +566,8 @@ static void ath_do_set_opmode(struct ath5k_softc *sc)
 		  sc->opmode, ath_opmode_to_string(sc->opmode));
 		  sc->opmode, ath_opmode_to_string(sc->opmode));
 }
 }
 
 
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
-					struct ieee80211_vif *vif)
+static void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+					       struct ieee80211_vif *vif)
 {
 {
 	struct ath_common *common = ath5k_hw_common(sc->ah);
 	struct ath_common *common = ath5k_hw_common(sc->ah);
 	struct ath_vif_iter_data iter_data;
 	struct ath_vif_iter_data iter_data;
@@ -3206,14 +3206,32 @@ static int ath5k_get_survey(struct ieee80211_hw *hw, int idx,
 {
 {
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_softc *sc = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	struct ieee80211_conf *conf = &hw->conf;
+	struct ath_common *common = ath5k_hw_common(sc->ah);
+	struct ath_cycle_counters *cc = &common->cc_survey;
+	unsigned int div = common->clockrate * 1000;
 
 
-	 if (idx != 0)
+	if (idx != 0)
 		return -ENOENT;
 		return -ENOENT;
 
 
 	survey->channel = conf->channel;
 	survey->channel = conf->channel;
 	survey->filled = SURVEY_INFO_NOISE_DBM;
 	survey->filled = SURVEY_INFO_NOISE_DBM;
 	survey->noise = sc->ah->ah_noise_floor;
 	survey->noise = sc->ah->ah_noise_floor;
 
 
+	spin_lock_bh(&common->cc_lock);
+	ath_hw_cycle_counters_update(common);
+	if (cc->cycles > 0) {
+		survey->filled |= SURVEY_INFO_CHANNEL_TIME |
+			SURVEY_INFO_CHANNEL_TIME_BUSY |
+			SURVEY_INFO_CHANNEL_TIME_RX |
+			SURVEY_INFO_CHANNEL_TIME_TX;
+		survey->channel_time += cc->cycles / div;
+		survey->channel_time_busy += cc->rx_busy / div;
+		survey->channel_time_rx += cc->rx_frame / div;
+		survey->channel_time_tx += cc->tx_frame / div;
+	}
+	memset(cc, 0, sizeof(*cc));
+	spin_unlock_bh(&common->cc_lock);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 15 - 15
drivers/net/wireless/ath/ath5k/debug.c

@@ -554,63 +554,63 @@ static ssize_t read_file_frameerrors(struct file *file, char __user *user_buf,
 
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"RX\n---------------------\n");
 			"RX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "CRC\t%u\t(%u%%)\n",
 			st->rxerr_crc,
 			st->rxerr_crc,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_crc*100/st->rx_all_count : 0);
 				st->rxerr_crc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "PHY\t%u\t(%u%%)\n",
 			st->rxerr_phy,
 			st->rxerr_phy,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_phy*100/st->rx_all_count : 0);
 				st->rxerr_phy*100/st->rx_all_count : 0);
 	for (i = 0; i < 32; i++) {
 	for (i = 0; i < 32; i++) {
 		if (st->rxerr_phy_code[i])
 		if (st->rxerr_phy_code[i])
 			len += snprintf(buf+len, sizeof(buf)-len,
 			len += snprintf(buf+len, sizeof(buf)-len,
-				" phy_err[%d]\t%d\n",
+				" phy_err[%u]\t%u\n",
 				i, st->rxerr_phy_code[i]);
 				i, st->rxerr_phy_code[i]);
 	}
 	}
 
 
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
 			st->rxerr_fifo,
 			st->rxerr_fifo,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_fifo*100/st->rx_all_count : 0);
 				st->rxerr_fifo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "decrypt\t%u\t(%u%%)\n",
 			st->rxerr_decrypt,
 			st->rxerr_decrypt,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_decrypt*100/st->rx_all_count : 0);
 				st->rxerr_decrypt*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "MIC\t%u\t(%u%%)\n",
 			st->rxerr_mic,
 			st->rxerr_mic,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_mic*100/st->rx_all_count : 0);
 				st->rxerr_mic*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "process\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "process\t%u\t(%u%%)\n",
 			st->rxerr_proc,
 			st->rxerr_proc,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_proc*100/st->rx_all_count : 0);
 				st->rxerr_proc*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "jumbo\t%u\t(%u%%)\n",
 			st->rxerr_jumbo,
 			st->rxerr_jumbo,
 			st->rx_all_count > 0 ?
 			st->rx_all_count > 0 ?
 				st->rxerr_jumbo*100/st->rx_all_count : 0);
 				st->rxerr_jumbo*100/st->rx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%d]\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "[RX all\t%u]\n",
 			st->rx_all_count);
 			st->rx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%d\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "RX-all-bytes\t%u\n",
 			st->rx_bytes_count);
 			st->rx_bytes_count);
 
 
 	len += snprintf(buf+len, sizeof(buf)-len,
 	len += snprintf(buf+len, sizeof(buf)-len,
 			"\nTX\n---------------------\n");
 			"\nTX\n---------------------\n");
-	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "retry\t%u\t(%u%%)\n",
 			st->txerr_retry,
 			st->txerr_retry,
 			st->tx_all_count > 0 ?
 			st->tx_all_count > 0 ?
 				st->txerr_retry*100/st->tx_all_count : 0);
 				st->txerr_retry*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "FIFO\t%u\t(%u%%)\n",
 			st->txerr_fifo,
 			st->txerr_fifo,
 			st->tx_all_count > 0 ?
 			st->tx_all_count > 0 ?
 				st->txerr_fifo*100/st->tx_all_count : 0);
 				st->txerr_fifo*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%d\t(%d%%)\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "filter\t%u\t(%u%%)\n",
 			st->txerr_filt,
 			st->txerr_filt,
 			st->tx_all_count > 0 ?
 			st->tx_all_count > 0 ?
 				st->txerr_filt*100/st->tx_all_count : 0);
 				st->txerr_filt*100/st->tx_all_count : 0);
-	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%d]\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "[TX all\t%u]\n",
 			st->tx_all_count);
 			st->tx_all_count);
-	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%d\n",
+	len += snprintf(buf+len, sizeof(buf)-len, "TX-all-bytes\t%u\n",
 			st->tx_bytes_count);
 			st->tx_bytes_count);
 
 
 	if (len > sizeof(buf))
 	if (len > sizeof(buf))

+ 9 - 9
drivers/net/wireless/ath/ath5k/desc.h

@@ -26,7 +26,7 @@
 struct ath5k_hw_rx_ctl {
 struct ath5k_hw_rx_ctl {
 	u32	rx_control_0; /* RX control word 0 */
 	u32	rx_control_0; /* RX control word 0 */
 	u32	rx_control_1; /* RX control word 1 */
 	u32	rx_control_1; /* RX control word 1 */
-} __packed;
+} __packed __aligned(4);
 
 
 /* RX control word 1 fields/flags */
 /* RX control word 1 fields/flags */
 #define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff /* data buffer length */
 #define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff /* data buffer length */
@@ -39,7 +39,7 @@ struct ath5k_hw_rx_ctl {
 struct ath5k_hw_rx_status {
 struct ath5k_hw_rx_status {
 	u32	rx_status_0; /* RX status word 0 */
 	u32	rx_status_0; /* RX status word 0 */
 	u32	rx_status_1; /* RX status word 1 */
 	u32	rx_status_1; /* RX status word 1 */
-} __packed;
+} __packed __aligned(4);
 
 
 /* 5210/5211 */
 /* 5210/5211 */
 /* RX status word 0 fields/flags */
 /* RX status word 0 fields/flags */
@@ -129,7 +129,7 @@ enum ath5k_phy_error_code {
 struct ath5k_hw_2w_tx_ctl {
 struct ath5k_hw_2w_tx_ctl {
 	u32	tx_control_0; /* TX control word 0 */
 	u32	tx_control_0; /* TX control word 0 */
 	u32	tx_control_1; /* TX control word 1 */
 	u32	tx_control_1; /* TX control word 1 */
-} __packed;
+} __packed __aligned(4);
 
 
 /* TX control word 0 fields/flags */
 /* TX control word 0 fields/flags */
 #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
 #define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
@@ -185,7 +185,7 @@ struct ath5k_hw_4w_tx_ctl {
 	u32	tx_control_1; /* TX control word 1 */
 	u32	tx_control_1; /* TX control word 1 */
 	u32	tx_control_2; /* TX control word 2 */
 	u32	tx_control_2; /* TX control word 2 */
 	u32	tx_control_3; /* TX control word 3 */
 	u32	tx_control_3; /* TX control word 3 */
-} __packed;
+} __packed __aligned(4);
 
 
 /* TX control word 0 fields/flags */
 /* TX control word 0 fields/flags */
 #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
 #define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff /* frame length */
@@ -244,7 +244,7 @@ struct ath5k_hw_4w_tx_ctl {
 struct ath5k_hw_tx_status {
 struct ath5k_hw_tx_status {
 	u32	tx_status_0; /* TX status word 0 */
 	u32	tx_status_0; /* TX status word 0 */
 	u32	tx_status_1; /* TX status word 1 */
 	u32	tx_status_1; /* TX status word 1 */
-} __packed;
+} __packed __aligned(4);
 
 
 /* TX status word 0 fields/flags */
 /* TX status word 0 fields/flags */
 #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001 /* TX success */
 #define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001 /* TX success */
@@ -282,7 +282,7 @@ struct ath5k_hw_tx_status {
 struct ath5k_hw_5210_tx_desc {
 struct ath5k_hw_5210_tx_desc {
 	struct ath5k_hw_2w_tx_ctl	tx_ctl;
 	struct ath5k_hw_2w_tx_ctl	tx_ctl;
 	struct ath5k_hw_tx_status	tx_stat;
 	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
+} __packed __aligned(4);
 
 
 /*
 /*
  * 5212 hardware TX descriptor
  * 5212 hardware TX descriptor
@@ -290,7 +290,7 @@ struct ath5k_hw_5210_tx_desc {
 struct ath5k_hw_5212_tx_desc {
 struct ath5k_hw_5212_tx_desc {
 	struct ath5k_hw_4w_tx_ctl	tx_ctl;
 	struct ath5k_hw_4w_tx_ctl	tx_ctl;
 	struct ath5k_hw_tx_status	tx_stat;
 	struct ath5k_hw_tx_status	tx_stat;
-} __packed;
+} __packed __aligned(4);
 
 
 /*
 /*
  * Common hardware RX descriptor
  * Common hardware RX descriptor
@@ -298,7 +298,7 @@ struct ath5k_hw_5212_tx_desc {
 struct ath5k_hw_all_rx_desc {
 struct ath5k_hw_all_rx_desc {
 	struct ath5k_hw_rx_ctl		rx_ctl;
 	struct ath5k_hw_rx_ctl		rx_ctl;
 	struct ath5k_hw_rx_status	rx_stat;
 	struct ath5k_hw_rx_status	rx_stat;
-} __packed;
+} __packed __aligned(4);
 
 
 /*
 /*
  * Atheros hardware DMA descriptor
  * Atheros hardware DMA descriptor
@@ -313,7 +313,7 @@ struct ath5k_desc {
 		struct ath5k_hw_5212_tx_desc	ds_tx5212;
 		struct ath5k_hw_5212_tx_desc	ds_tx5212;
 		struct ath5k_hw_all_rx_desc	ds_rx;
 		struct ath5k_hw_all_rx_desc	ds_rx;
 	} ud;
 	} ud;
-} __packed;
+} __packed __aligned(4);
 
 
 #define AR5K_RXDESC_INTREQ	0x0020
 #define AR5K_RXDESC_INTREQ	0x0020
 
 

+ 1 - 7
drivers/net/wireless/ath/ath5k/phy.c

@@ -1102,18 +1102,12 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel)
   PHY calibration
   PHY calibration
 \*****************/
 \*****************/
 
 
-static int sign_extend(int val, const int nbits)
-{
-	int order = BIT(nbits-1);
-	return (val ^ order) - order;
-}
-
 static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
 static s32 ath5k_hw_read_measured_noise_floor(struct ath5k_hw *ah)
 {
 {
 	s32 val;
 	s32 val;
 
 
 	val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
 	val = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-	return sign_extend(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 9);
+	return sign_extend32(AR5K_REG_MS(val, AR5K_PHY_NF_MINCCA_PWR), 8);
 }
 }
 
 
 void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)
 void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah)

+ 7 - 7
drivers/net/wireless/ath/ath9k/ar5008_phy.c

@@ -873,7 +873,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
 				 channel->max_antenna_gain * 2,
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), false);
 
 
 	/* Write analog registers */
 	/* Write analog registers */
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
 	if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
@@ -1490,25 +1490,25 @@ static void ar5008_hw_do_getnf(struct ath_hw *ah,
 	int16_t nf;
 	int16_t nf;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend(nf, 9);
+	nfarray[2] = sign_extend32(nf, 8);
 
 
 	if (!IS_CHAN_HT40(ah->curchan))
 	if (!IS_CHAN_HT40(ah->curchan))
 		return;
 		return;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend(nf, 9);
+	nfarray[3] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend(nf, 9);
+	nfarray[4] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend(nf, 9);
+	nfarray[5] = sign_extend32(nf, 8);
 }
 }
 
 
 /*
 /*

+ 53 - 70
drivers/net/wireless/ath/ath9k/ar9002_mac.c

@@ -90,13 +90,10 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 
 
 		*masked = isr & ATH9K_INT_COMMON;
 		*masked = isr & ATH9K_INT_COMMON;
 
 
-		if (ah->config.rx_intr_mitigation) {
-			if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
-				*masked |= ATH9K_INT_RX;
-		}
-
-		if (isr & (AR_ISR_RXOK | AR_ISR_RXERR))
+		if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM |
+			   AR_ISR_RXOK | AR_ISR_RXERR))
 			*masked |= ATH9K_INT_RX;
 			*masked |= ATH9K_INT_RX;
+
 		if (isr &
 		if (isr &
 		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
 		    (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR |
 		     AR_ISR_TXEOL)) {
 		     AR_ISR_TXEOL)) {
@@ -118,14 +115,6 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 				  "receive FIFO overrun interrupt\n");
 				  "receive FIFO overrun interrupt\n");
 		}
 		}
 
 
-		if (!AR_SREV_9100(ah)) {
-			if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
-				u32 isr5 = REG_READ(ah, AR_ISR_S5_S);
-				if (isr5 & AR_ISR_S5_TIM_TIMER)
-					*masked |= ATH9K_INT_TIM_TIMER;
-			}
-		}
-
 		*masked |= mask2;
 		*masked |= mask2;
 	}
 	}
 
 
@@ -136,17 +125,18 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked)
 		u32 s5_s;
 		u32 s5_s;
 
 
 		s5_s = REG_READ(ah, AR_ISR_S5_S);
 		s5_s = REG_READ(ah, AR_ISR_S5_S);
-		if (isr & AR_ISR_GENTMR) {
-			ah->intr_gen_timer_trigger =
+		ah->intr_gen_timer_trigger =
 				MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 				MS(s5_s, AR_ISR_S5_GENTIMER_TRIG);
 
 
-			ah->intr_gen_timer_thresh =
-				MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
+		ah->intr_gen_timer_thresh =
+			MS(s5_s, AR_ISR_S5_GENTIMER_THRESH);
 
 
-			if (ah->intr_gen_timer_trigger)
-				*masked |= ATH9K_INT_GENTIMER;
+		if (ah->intr_gen_timer_trigger)
+			*masked |= ATH9K_INT_GENTIMER;
 
 
-		}
+		if ((s5_s & AR_ISR_S5_TIM_TIMER) &&
+		    !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+			*masked |= ATH9K_INT_TIM_TIMER;
 	}
 	}
 
 
 	if (sync_cause) {
 	if (sync_cause) {
@@ -218,77 +208,70 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 				 struct ath_tx_status *ts)
 				 struct ath_tx_status *ts)
 {
 {
 	struct ar5416_desc *ads = AR5416DESC(ds);
 	struct ar5416_desc *ads = AR5416DESC(ds);
+	u32 status;
 
 
-	if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+	status = ACCESS_ONCE(ads->ds_txstatus9);
+	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 		return -EINPROGRESS;
 
 
-	ts->ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
 	ts->ts_tstamp = ads->AR_SendTimestamp;
 	ts->ts_tstamp = ads->AR_SendTimestamp;
 	ts->ts_status = 0;
 	ts->ts_status = 0;
 	ts->ts_flags = 0;
 	ts->ts_flags = 0;
 
 
-	if (ads->ds_txstatus1 & AR_FrmXmitOK)
+	if (status & AR_TxOpExceeded)
+		ts->ts_status |= ATH9K_TXERR_XTXOP;
+	ts->tid = MS(status, AR_TxTid);
+	ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+	ts->ts_seqnum = MS(status, AR_SeqNum);
+
+	status = ACCESS_ONCE(ads->ds_txstatus0);
+	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+	ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+	if (status & AR_TxBaStatus) {
+		ts->ts_flags |= ATH9K_TX_BA;
+		ts->ba_low = ads->AR_BaBitmapLow;
+		ts->ba_high = ads->AR_BaBitmapHigh;
+	}
+
+	status = ACCESS_ONCE(ads->ds_txstatus1);
+	if (status & AR_FrmXmitOK)
 		ts->ts_status |= ATH9K_TX_ACKED;
 		ts->ts_status |= ATH9K_TX_ACKED;
-	if (ads->ds_txstatus1 & AR_ExcessiveRetries)
-		ts->ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->ds_txstatus1 & AR_Filtered)
-		ts->ts_status |= ATH9K_TXERR_FILT;
-	if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
-		ts->ts_status |= ATH9K_TXERR_FIFO;
-		ath9k_hw_updatetxtriglevel(ah, true);
+	else {
+		if (status & AR_ExcessiveRetries)
+			ts->ts_status |= ATH9K_TXERR_XRETRY;
+		if (status & AR_Filtered)
+			ts->ts_status |= ATH9K_TXERR_FILT;
+		if (status & AR_FIFOUnderrun) {
+			ts->ts_status |= ATH9K_TXERR_FIFO;
+			ath9k_hw_updatetxtriglevel(ah, true);
+		}
 	}
 	}
-	if (ads->ds_txstatus9 & AR_TxOpExceeded)
-		ts->ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->ds_txstatus1 & AR_TxTimerExpired)
+	if (status & AR_TxTimerExpired)
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->ds_txstatus1 & AR_DescCfgErr)
+	if (status & AR_DescCfgErr)
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+	if (status & AR_TxDataUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
 	}
-	if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+	if (status & AR_TxDelimUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
 	}
-	if (ads->ds_txstatus0 & AR_TxBaStatus) {
-		ts->ts_flags |= ATH9K_TX_BA;
-		ts->ba_low = ads->AR_BaBitmapLow;
-		ts->ba_high = ads->AR_BaBitmapHigh;
-	}
+	ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+	ts->ts_longretry = MS(status, AR_DataFailCnt);
+	ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
 
 
-	ts->ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
-	switch (ts->ts_rateindex) {
-	case 0:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
-		break;
-	case 1:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
-		break;
-	case 2:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
-		break;
-	case 3:
-		ts->ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
-		break;
-	}
+	status = ACCESS_ONCE(ads->ds_txstatus5);
+	ts->ts_rssi = MS(status, AR_TxRSSICombined);
+	ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
 
-	ts->ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
-	ts->ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
-	ts->ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
-	ts->ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
-	ts->ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
-	ts->ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
-	ts->ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
 	ts->evm0 = ads->AR_TxEVM0;
 	ts->evm0 = ads->AR_TxEVM0;
 	ts->evm1 = ads->AR_TxEVM1;
 	ts->evm1 = ads->AR_TxEVM1;
 	ts->evm2 = ads->AR_TxEVM2;
 	ts->evm2 = ads->AR_TxEVM2;
-	ts->ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
-	ts->ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
-	ts->ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
-	ts->tid = MS(ads->ds_txstatus9, AR_TxTid);
-	ts->ts_antenna = 0;
 
 
 	return 0;
 	return 0;
 }
 }

+ 4 - 4
drivers/net/wireless/ath/ath9k/ar9002_phy.c

@@ -473,21 +473,21 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
 	int16_t nf;
 	int16_t nf;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR9280_PHY_EXT_MINCCA_PWR);
 	if (IS_CHAN_HT40(ah->curchan))
 	if (IS_CHAN_HT40(ah->curchan))
-		nfarray[3] = sign_extend(nf, 9);
+		nfarray[3] = sign_extend32(nf, 8);
 
 
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 	if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
 		return;
 		return;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), AR9280_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), AR9280_PHY_CH1_EXT_MINCCA_PWR);
 	if (IS_CHAN_HT40(ah->curchan))
 	if (IS_CHAN_HT40(ah->curchan))
-		nfarray[4] = sign_extend(nf, 9);
+		nfarray[4] = sign_extend32(nf, 8);
 }
 }
 
 
 static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
 static void ar9002_hw_set_nf_limits(struct ath_hw *ah)

+ 15 - 5
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c

@@ -2131,8 +2131,9 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					u8 twiceAntennaReduction,
 					u8 twiceAntennaReduction,
 					u8 twiceMaxRegulatoryPower,
 					u8 twiceMaxRegulatoryPower,
-					u8 powerLimit)
+					u8 powerLimit, bool test)
 {
 {
+	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 	u8 targetPowerValT2[ar9300RateSize];
 	u8 targetPowerValT2[ar9300RateSize];
 	unsigned int i = 0;
 	unsigned int i = 0;
@@ -2144,7 +2145,16 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 					   twiceMaxRegulatoryPower,
 					   twiceMaxRegulatoryPower,
 					   powerLimit);
 					   powerLimit);
 
 
-	while (i < ar9300RateSize) {
+	regulatory->max_power_level = 0;
+	for (i = 0; i < ar9300RateSize; i++) {
+		if (targetPowerValT2[i] > regulatory->max_power_level)
+			regulatory->max_power_level = targetPowerValT2[i];
+	}
+
+	if (test)
+		return;
+
+	for (i = 0; i < ar9300RateSize; i++) {
 		ath_print(common, ATH_DBG_EEPROM,
 		ath_print(common, ATH_DBG_EEPROM,
 			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
 			  "TPC[%02d] 0x%08x ", i, targetPowerValT2[i]);
 		i++;
 		i++;
@@ -2159,9 +2169,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 		i++;
 		i++;
 	}
 	}
 
 
-	/* Write target power array to registers */
-	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
-
 	/*
 	/*
 	 * This is the TX power we send back to driver core,
 	 * This is the TX power we send back to driver core,
 	 * and it can use to pass to userspace to display our
 	 * and it can use to pass to userspace to display our
@@ -2180,7 +2187,10 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
 		i = ALL_TARGET_HT20_0_8_16; /* ht20 */
 
 
 	ah->txpower_limit = targetPowerValT2[i];
 	ah->txpower_limit = targetPowerValT2[i];
+	regulatory->max_power_level = targetPowerValT2[i];
 
 
+	/* Write target power array to registers */
+	ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
 	ar9003_hw_calibration_apply(ah, chan->channel);
 	ar9003_hw_calibration_apply(ah, chan->channel);
 }
 }
 
 

+ 36 - 33
drivers/net/wireless/ath/ath9k/ar9003_mac.c

@@ -237,10 +237,12 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 				 struct ath_tx_status *ts)
 				 struct ath_tx_status *ts)
 {
 {
 	struct ar9003_txs *ads;
 	struct ar9003_txs *ads;
+	u32 status;
 
 
 	ads = &ah->ts_ring[ah->ts_tail];
 	ads = &ah->ts_ring[ah->ts_tail];
 
 
-	if ((ads->status8 & AR_TxDone) == 0)
+	status = ACCESS_ONCE(ads->status8);
+	if ((status & AR_TxDone) == 0)
 		return -EINPROGRESS;
 		return -EINPROGRESS;
 
 
 	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
 	ah->ts_tail = (ah->ts_tail + 1) % ah->ts_size;
@@ -253,57 +255,58 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
+	if (status & AR_TxOpExceeded)
+		ts->ts_status |= ATH9K_TXERR_XTXOP;
+	ts->ts_rateindex = MS(status, AR_FinalTxIdx);
+	ts->ts_seqnum = MS(status, AR_SeqNum);
+	ts->tid = MS(status, AR_TxTid);
+
 	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
 	ts->qid = MS(ads->ds_info, AR_TxQcuNum);
 	ts->desc_id = MS(ads->status1, AR_TxDescId);
 	ts->desc_id = MS(ads->status1, AR_TxDescId);
-	ts->ts_seqnum = MS(ads->status8, AR_SeqNum);
 	ts->ts_tstamp = ads->status4;
 	ts->ts_tstamp = ads->status4;
 	ts->ts_status = 0;
 	ts->ts_status = 0;
 	ts->ts_flags  = 0;
 	ts->ts_flags  = 0;
 
 
-	if (ads->status3 & AR_ExcessiveRetries)
+	status = ACCESS_ONCE(ads->status2);
+	ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00);
+	ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01);
+	ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02);
+	if (status & AR_TxBaStatus) {
+		ts->ts_flags |= ATH9K_TX_BA;
+		ts->ba_low = ads->status5;
+		ts->ba_high = ads->status6;
+	}
+
+	status = ACCESS_ONCE(ads->status3);
+	if (status & AR_ExcessiveRetries)
 		ts->ts_status |= ATH9K_TXERR_XRETRY;
 		ts->ts_status |= ATH9K_TXERR_XRETRY;
-	if (ads->status3 & AR_Filtered)
+	if (status & AR_Filtered)
 		ts->ts_status |= ATH9K_TXERR_FILT;
 		ts->ts_status |= ATH9K_TXERR_FILT;
-	if (ads->status3 & AR_FIFOUnderrun) {
+	if (status & AR_FIFOUnderrun) {
 		ts->ts_status |= ATH9K_TXERR_FIFO;
 		ts->ts_status |= ATH9K_TXERR_FIFO;
 		ath9k_hw_updatetxtriglevel(ah, true);
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
 	}
-	if (ads->status8 & AR_TxOpExceeded)
-		ts->ts_status |= ATH9K_TXERR_XTXOP;
-	if (ads->status3 & AR_TxTimerExpired)
+	if (status & AR_TxTimerExpired)
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
 		ts->ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
-	if (ads->status3 & AR_DescCfgErr)
+	if (status & AR_DescCfgErr)
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
 		ts->ts_flags |= ATH9K_TX_DESC_CFG_ERR;
-	if (ads->status3 & AR_TxDataUnderrun) {
+	if (status & AR_TxDataUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ts->ts_flags |= ATH9K_TX_DATA_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
 	}
-	if (ads->status3 & AR_TxDelimUnderrun) {
+	if (status & AR_TxDelimUnderrun) {
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ts->ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
 		ath9k_hw_updatetxtriglevel(ah, true);
 		ath9k_hw_updatetxtriglevel(ah, true);
 	}
 	}
-	if (ads->status2 & AR_TxBaStatus) {
-		ts->ts_flags |= ATH9K_TX_BA;
-		ts->ba_low = ads->status5;
-		ts->ba_high = ads->status6;
-	}
-
-	ts->ts_rateindex = MS(ads->status8, AR_FinalTxIdx);
-
-	ts->ts_rssi = MS(ads->status7, AR_TxRSSICombined);
-	ts->ts_rssi_ctl0 = MS(ads->status2, AR_TxRSSIAnt00);
-	ts->ts_rssi_ctl1 = MS(ads->status2, AR_TxRSSIAnt01);
-	ts->ts_rssi_ctl2 = MS(ads->status2, AR_TxRSSIAnt02);
-	ts->ts_rssi_ext0 = MS(ads->status7, AR_TxRSSIAnt10);
-	ts->ts_rssi_ext1 = MS(ads->status7, AR_TxRSSIAnt11);
-	ts->ts_rssi_ext2 = MS(ads->status7, AR_TxRSSIAnt12);
-	ts->ts_shortretry = MS(ads->status3, AR_RTSFailCnt);
-	ts->ts_longretry = MS(ads->status3, AR_DataFailCnt);
-	ts->ts_virtcol = MS(ads->status3, AR_VirtRetryCnt);
-	ts->ts_antenna = 0;
-
-	ts->tid = MS(ads->status8, AR_TxTid);
+	ts->ts_shortretry = MS(status, AR_RTSFailCnt);
+	ts->ts_longretry = MS(status, AR_DataFailCnt);
+	ts->ts_virtcol = MS(status, AR_VirtRetryCnt);
+
+	status = ACCESS_ONCE(ads->status7);
+	ts->ts_rssi = MS(status, AR_TxRSSICombined);
+	ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10);
+	ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
+	ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
 
 
 	memset(ads, 0, sizeof(*ads));
 	memset(ads, 0, sizeof(*ads));
 
 

+ 3 - 3
drivers/net/wireless/ath/ath9k/ar9003_mac.h

@@ -65,7 +65,7 @@ struct ar9003_rxs {
 	u32 status9;
 	u32 status9;
 	u32 status10;
 	u32 status10;
 	u32 status11;
 	u32 status11;
-} __packed;
+} __packed __aligned(4);
 
 
 /* Transmit Control Descriptor */
 /* Transmit Control Descriptor */
 struct ar9003_txc {
 struct ar9003_txc {
@@ -93,7 +93,7 @@ struct ar9003_txc {
 	u32 ctl21;  /* DMA control 21 */
 	u32 ctl21;  /* DMA control 21 */
 	u32 ctl22;  /* DMA control 22 */
 	u32 ctl22;  /* DMA control 22 */
 	u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
 	u32 pad[9]; /* pad to cache line (128 bytes/32 dwords) */
-} __packed;
+} __packed __aligned(4);
 
 
 struct ar9003_txs {
 struct ar9003_txs {
 	u32 ds_info;
 	u32 ds_info;
@@ -105,7 +105,7 @@ struct ar9003_txs {
 	u32 status6;
 	u32 status6;
 	u32 status7;
 	u32 status7;
 	u32 status8;
 	u32 status8;
-} __packed;
+} __packed __aligned(4);
 
 
 void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
 void ar9003_hw_attach_mac_ops(struct ath_hw *hw);
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);
 void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size);

+ 7 - 7
drivers/net/wireless/ath/ath9k/ar9003_phy.c

@@ -614,7 +614,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
 				 channel->max_antenna_gain * 2,
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), false);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -1023,25 +1023,25 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
 	int16_t nf;
 	int16_t nf;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend(nf, 9);
+	nfarray[0] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend(nf, 9);
+	nfarray[1] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend(nf, 9);
+	nfarray[2] = sign_extend32(nf, 8);
 
 
 	if (!IS_CHAN_HT40(ah->curchan))
 	if (!IS_CHAN_HT40(ah->curchan))
 		return;
 		return;
 
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend(nf, 9);
+	nfarray[3] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend(nf, 9);
+	nfarray[4] = sign_extend32(nf, 8);
 
 
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
 	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend(nf, 9);
+	nfarray[5] = sign_extend32(nf, 8);
 }
 }
 
 
 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)

+ 5 - 9
drivers/net/wireless/ath/ath9k/ath9k.h

@@ -195,7 +195,6 @@ enum ATH_AGGR_STATUS {
 
 
 #define ATH_TXFIFO_DEPTH 8
 #define ATH_TXFIFO_DEPTH 8
 struct ath_txq {
 struct ath_txq {
-	int axq_class;
 	u32 axq_qnum;
 	u32 axq_qnum;
 	u32 *axq_link;
 	u32 *axq_link;
 	struct list_head axq_q;
 	struct list_head axq_q;
@@ -208,11 +207,12 @@ struct ath_txq {
 	struct list_head txq_fifo_pending;
 	struct list_head txq_fifo_pending;
 	u8 txq_headidx;
 	u8 txq_headidx;
 	u8 txq_tailidx;
 	u8 txq_tailidx;
+	int pending_frames;
 };
 };
 
 
 struct ath_atx_ac {
 struct ath_atx_ac {
+	struct ath_txq *txq;
 	int sched;
 	int sched;
-	int qnum;
 	struct list_head list;
 	struct list_head list;
 	struct list_head tid_q;
 	struct list_head tid_q;
 };
 };
@@ -270,7 +270,6 @@ struct ath_node {
 	struct ath_atx_ac ac[WME_NUM_AC];
 	struct ath_atx_ac ac[WME_NUM_AC];
 	u16 maxampdu;
 	u16 maxampdu;
 	u8 mpdudensity;
 	u8 mpdudensity;
-	int last_rssi;
 };
 };
 
 
 #define AGGR_CLEANUP         BIT(1)
 #define AGGR_CLEANUP         BIT(1)
@@ -291,12 +290,11 @@ struct ath_tx_control {
 struct ath_tx {
 struct ath_tx {
 	u16 seq_no;
 	u16 seq_no;
 	u32 txqsetup;
 	u32 txqsetup;
-	int hwq_map[WME_NUM_AC];
 	spinlock_t txbuflock;
 	spinlock_t txbuflock;
 	struct list_head txbuf;
 	struct list_head txbuf;
 	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
 	struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
 	struct ath_descdma txdma;
 	struct ath_descdma txdma;
-	int pending_frames[WME_NUM_AC];
+	struct ath_txq *txq_map[WME_NUM_AC];
 };
 };
 
 
 struct ath_rx_edma {
 struct ath_rx_edma {
@@ -310,7 +308,6 @@ struct ath_rx {
 	u8 rxotherant;
 	u8 rxotherant;
 	u32 *rxlink;
 	u32 *rxlink;
 	unsigned int rxfilter;
 	unsigned int rxfilter;
-	spinlock_t pcu_lock;
 	spinlock_t rxbuflock;
 	spinlock_t rxbuflock;
 	struct list_head rxbuf;
 	struct list_head rxbuf;
 	struct ath_descdma rxdma;
 	struct ath_descdma rxdma;
@@ -327,7 +324,6 @@ void ath_rx_cleanup(struct ath_softc *sc);
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
 void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
-int ath_tx_setup(struct ath_softc *sc, int haltype);
 void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
 void ath_draintxq(struct ath_softc *sc,
 void ath_draintxq(struct ath_softc *sc,
 		     struct ath_txq *txq, bool retry_tx);
 		     struct ath_txq *txq, bool retry_tx);
@@ -600,9 +596,9 @@ struct ath_softc {
 	struct ath_hw *sc_ah;
 	struct ath_hw *sc_ah;
 	void __iomem *mem;
 	void __iomem *mem;
 	int irq;
 	int irq;
-	spinlock_t sc_resetlock;
 	spinlock_t sc_serial_rw;
 	spinlock_t sc_serial_rw;
 	spinlock_t sc_pm_lock;
 	spinlock_t sc_pm_lock;
+	spinlock_t sc_pcu_lock;
 	struct mutex mutex;
 	struct mutex mutex;
 	struct work_struct paprd_work;
 	struct work_struct paprd_work;
 	struct work_struct hw_check_work;
 	struct work_struct hw_check_work;
@@ -662,11 +658,11 @@ struct ath_wiphy {
 	bool idle;
 	bool idle;
 	int chan_idx;
 	int chan_idx;
 	int chan_is_ht;
 	int chan_is_ht;
+	int last_rssi;
 };
 };
 
 
 void ath9k_tasklet(unsigned long data);
 void ath9k_tasklet(unsigned long data);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
 int ath_cabq_update(struct ath_softc *);
 int ath_cabq_update(struct ath_softc *);
 
 
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 static inline void ath_read_cachesize(struct ath_common *common, int *csz)

+ 6 - 6
drivers/net/wireless/ath/ath9k/beacon.c

@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc)
 	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 ath9k_tx_queue_info qi, qi_be;
 	struct ath9k_tx_queue_info qi, qi_be;
-	int qnum;
+	struct ath_txq *txq;
 
 
 	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
 	ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,8 +38,8 @@ int ath_beaconq_config(struct ath_softc *sc)
 		qi.tqi_cwmax = 0;
 		qi.tqi_cwmax = 0;
 	} else {
 	} else {
 		/* Adhoc mode; important thing is to use 2x cwmin. */
 		/* Adhoc mode; important thing is to use 2x cwmin. */
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+		txq = sc->tx.txq_map[WME_AC_BE];
+		ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
 		qi.tqi_aifs = qi_be.tqi_aifs;
 		qi.tqi_aifs = qi_be.tqi_aifs;
 		qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
 		qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
 		qi.tqi_cwmax = qi_be.tqi_cwmax;
 		qi.tqi_cwmax = qi_be.tqi_cwmax;
@@ -503,7 +503,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
 
 
 	/* Set the computed AP beacon timers */
 	/* Set the computed AP beacon timers */
 
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	sc->beacon.bmisscnt = 0;
 	sc->beacon.bmisscnt = 0;
 	ath9k_hw_set_interrupts(ah, ah->imask);
 	ath9k_hw_set_interrupts(ah, ah->imask);
@@ -638,7 +638,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
 
 
 	/* Set the computed STA beacon timers */
 	/* Set the computed STA beacon timers */
 
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_hw_set_sta_beacon_timers(ah, &bs);
 	ath9k_hw_set_sta_beacon_timers(ah, &bs);
 	ah->imask |= ATH9K_INT_BMISS;
 	ah->imask |= ATH9K_INT_BMISS;
 	ath9k_hw_set_interrupts(ah, ah->imask);
 	ath9k_hw_set_interrupts(ah, ah->imask);
@@ -686,7 +686,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
 
 
 	/* Set the computed ADHOC beacon timers */
 	/* Set the computed ADHOC beacon timers */
 
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	ath9k_beacon_init(sc, nexttbtt, intval);
 	sc->beacon.bmisscnt = 0;
 	sc->beacon.bmisscnt = 0;
 	ath9k_hw_set_interrupts(ah, ah->imask);
 	ath9k_hw_set_interrupts(ah, ah->imask);

+ 6 - 9
drivers/net/wireless/ath/ath9k/common.c

@@ -107,12 +107,10 @@ static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan,
 /*
 /*
  * Update internal channel flags.
  * Update internal channel flags.
  */
  */
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
-			       struct ath9k_channel *ichan)
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+			       struct ieee80211_channel *chan,
+			       enum nl80211_channel_type channel_type)
 {
 {
-	struct ieee80211_channel *chan = hw->conf.channel;
-	struct ieee80211_conf *conf = &hw->conf;
-
 	ichan->channel = chan->center_freq;
 	ichan->channel = chan->center_freq;
 	ichan->chan = chan;
 	ichan->chan = chan;
 
 
@@ -124,9 +122,8 @@ void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
 		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
 	}
 	}
 
 
-	if (conf_is_ht(conf))
-		ichan->chanmode = ath9k_get_extchanmode(chan,
-							conf->channel_type);
+	if (channel_type != NL80211_CHAN_NO_HT)
+		ichan->chanmode = ath9k_get_extchanmode(chan, channel_type);
 }
 }
 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
 EXPORT_SYMBOL(ath9k_cmn_update_ichannel);
 
 
@@ -142,7 +139,7 @@ struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 
 
 	chan_idx = curchan->hw_value;
 	chan_idx = curchan->hw_value;
 	channel = &ah->channels[chan_idx];
 	channel = &ah->channels[chan_idx];
-	ath9k_cmn_update_ichannel(hw, channel);
+	ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type);
 
 
 	return channel;
 	return channel;
 }
 }

+ 8 - 6
drivers/net/wireless/ath/ath9k/common.h

@@ -31,10 +31,11 @@
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define WME_MAX_BA              WME_BA_BMP_SIZE
 #define ATH_TID_MAX_BUFS        (2 * WME_MAX_BA)
 #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
+/* These must match mac80211 skb queue mapping numbers */
+#define WME_AC_VO   0
+#define WME_AC_VI   1
+#define WME_AC_BE   2
+#define WME_AC_BK   3
 #define WME_NUM_AC  4
 #define WME_NUM_AC  4
 
 
 #define ATH_RSSI_DUMMY_MARKER   0x127
 #define ATH_RSSI_DUMMY_MARKER   0x127
@@ -62,8 +63,9 @@ enum ath_stomp_type {
 
 
 int ath9k_cmn_padpos(__le16 frame_control);
 int ath9k_cmn_padpos(__le16 frame_control);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
 int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb);
-void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw,
-			       struct ath9k_channel *ichan);
+void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
+			       struct ieee80211_channel *chan,
+			       enum nl80211_channel_type channel_type);
 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw,
 					       struct ath_hw *ah);
 					       struct ath_hw *ah);
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);

+ 25 - 23
drivers/net/wireless/ath/ath9k/debug.c

@@ -461,16 +461,16 @@ static ssize_t read_file_wiphy(struct file *file, char __user *user_buf,
 
 
 	/* Put variable-length stuff down here, and check for overflows. */
 	/* Put variable-length stuff down here, and check for overflows. */
 	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];
-		if (aphy == NULL)
+		struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
+		if (aphy_tmp == NULL)
 			continue;
 			continue;
-		chan = aphy->hw->conf.channel;
+		chan = aphy_tmp->hw->conf.channel;
 		len += snprintf(buf + len, sizeof(buf) - len,
 		len += snprintf(buf + len, sizeof(buf) - len,
 			"secondary: %s (%s chan=%d ht=%d)\n",
 			"secondary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(aphy->hw->wiphy),
-			ath_wiphy_state_str(aphy->state),
+			wiphy_name(aphy_tmp->hw->wiphy),
+			ath_wiphy_state_str(aphy_tmp->state),
 			ieee80211_frequency_to_channel(chan->center_freq),
 			ieee80211_frequency_to_channel(chan->center_freq),
-			aphy->chan_is_ht);
+						       aphy_tmp->chan_is_ht);
 	}
 	}
 	if (len > sizeof(buf))
 	if (len > sizeof(buf))
 		len = sizeof(buf);
 		len = sizeof(buf);
@@ -585,10 +585,10 @@ static const struct file_operations fops_wiphy = {
 	do {								\
 	do {								\
 		len += snprintf(buf + len, size - len,			\
 		len += snprintf(buf + len, size - len,			\
 				"%s%13u%11u%10u%10u\n", str,		\
 				"%s%13u%11u%10u%10u\n", str,		\
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BE]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_BK]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VI]].elem, \
-		sc->debug.stats.txstats[sc->tx.hwq_map[WME_AC_VO]].elem); \
+		sc->debug.stats.txstats[WME_AC_BE].elem, \
+		sc->debug.stats.txstats[WME_AC_BK].elem, \
+		sc->debug.stats.txstats[WME_AC_VI].elem, \
+		sc->debug.stats.txstats[WME_AC_VO].elem); \
 } while(0)
 } while(0)
 
 
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
@@ -630,33 +630,35 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
 	return retval;
 	return retval;
 }
 }
 
 
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
-		       struct ath_buf *bf, struct ath_tx_status *ts)
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+		       struct ath_tx_status *ts)
 {
 {
-	TX_STAT_INC(txq->axq_qnum, tx_pkts_all);
-	sc->debug.stats.txstats[txq->axq_qnum].tx_bytes_all += bf->bf_mpdu->len;
+	int qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
+	TX_STAT_INC(qnum, tx_pkts_all);
+	sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
 
 
 	if (bf_isampdu(bf)) {
 	if (bf_isampdu(bf)) {
 		if (bf_isxretried(bf))
 		if (bf_isxretried(bf))
-			TX_STAT_INC(txq->axq_qnum, a_xretries);
+			TX_STAT_INC(qnum, a_xretries);
 		else
 		else
-			TX_STAT_INC(txq->axq_qnum, a_completed);
+			TX_STAT_INC(qnum, a_completed);
 	} else {
 	} else {
-		TX_STAT_INC(txq->axq_qnum, completed);
+		TX_STAT_INC(qnum, completed);
 	}
 	}
 
 
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
 	if (ts->ts_status & ATH9K_TXERR_FIFO)
-		TX_STAT_INC(txq->axq_qnum, fifo_underrun);
+		TX_STAT_INC(qnum, fifo_underrun);
 	if (ts->ts_status & ATH9K_TXERR_XTXOP)
 	if (ts->ts_status & ATH9K_TXERR_XTXOP)
-		TX_STAT_INC(txq->axq_qnum, xtxop);
+		TX_STAT_INC(qnum, xtxop);
 	if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
 	if (ts->ts_status & ATH9K_TXERR_TIMER_EXPIRED)
-		TX_STAT_INC(txq->axq_qnum, timer_exp);
+		TX_STAT_INC(qnum, timer_exp);
 	if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
 	if (ts->ts_flags & ATH9K_TX_DESC_CFG_ERR)
-		TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
+		TX_STAT_INC(qnum, desc_cfg_err);
 	if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
 	if (ts->ts_flags & ATH9K_TX_DATA_UNDERRUN)
-		TX_STAT_INC(txq->axq_qnum, data_underrun);
+		TX_STAT_INC(qnum, data_underrun);
 	if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
 	if (ts->ts_flags & ATH9K_TX_DELIM_UNDERRUN)
-		TX_STAT_INC(txq->axq_qnum, delim_underrun);
+		TX_STAT_INC(qnum, delim_underrun);
 }
 }
 
 
 static const struct file_operations fops_xmit = {
 static const struct file_operations fops_xmit = {

+ 2 - 3
drivers/net/wireless/ath/ath9k/debug.h

@@ -169,8 +169,8 @@ void ath9k_exit_debug(struct ath_hw *ah);
 int ath9k_debug_create_root(void);
 int ath9k_debug_create_root(void);
 void ath9k_debug_remove_root(void);
 void ath9k_debug_remove_root(void);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
-void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
-		       struct ath_buf *bf, struct ath_tx_status *ts);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
+		       struct ath_tx_status *ts);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 
 
 #else
 #else
@@ -199,7 +199,6 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
 }
 }
 
 
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
-				     struct ath_txq *txq,
 				     struct ath_buf *bf,
 				     struct ath_buf *bf,
 				     struct ath_tx_status *ts)
 				     struct ath_tx_status *ts)
 {
 {

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

@@ -680,7 +680,8 @@ struct eeprom_ops {
 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
 	void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan);
 	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
 	void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan,
 			   u16 cfgCtl, u8 twiceAntennaReduction,
 			   u16 cfgCtl, u8 twiceAntennaReduction,
-			   u8 twiceMaxRegulatoryPower, u8 powerLimit);
+			   u8 twiceMaxRegulatoryPower, u8 powerLimit,
+			   bool test);
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 	u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz);
 };
 };
 
 

+ 7 - 2
drivers/net/wireless/ath/ath9k/eeprom_4k.c

@@ -726,7 +726,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
 				    u16 cfgCtl,
 				    u16 cfgCtl,
 				    u8 twiceAntennaReduction,
 				    u8 twiceAntennaReduction,
 				    u8 twiceMaxRegulatoryPower,
 				    u8 twiceMaxRegulatoryPower,
-				    u8 powerLimit)
+				    u8 powerLimit, bool test)
 {
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
 	struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -751,15 +751,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
 
 
 	ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
 	ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset);
 
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
+
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
 	}
 	}
 
 
+	if (test)
+	    return;
 
 
 	/* Update regulatory */
 	/* Update regulatory */
-
 	i = rate6mb;
 	i = rate6mb;
 	if (IS_CHAN_HT40(chan))
 	if (IS_CHAN_HT40(chan))
 		i = rateHt40_0;
 		i = rateHt40_0;

+ 15 - 12
drivers/net/wireless/ath/ath9k/eeprom_9287.c

@@ -853,7 +853,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					struct ath9k_channel *chan, u16 cfgCtl,
 					u8 twiceAntennaReduction,
 					u8 twiceAntennaReduction,
 					u8 twiceMaxRegulatoryPower,
 					u8 twiceMaxRegulatoryPower,
-					u8 powerLimit)
+					u8 powerLimit, bool test)
 {
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
 	struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
@@ -877,12 +877,26 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
 
 
 	ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
 	ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset);
 
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
 		ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
 		if (ratesArray[i] > AR9287_MAX_RATE_POWER)
 		if (ratesArray[i] > AR9287_MAX_RATE_POWER)
 			ratesArray[i] = AR9287_MAX_RATE_POWER;
 			ratesArray[i] = AR9287_MAX_RATE_POWER;
+
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
 	}
 	}
 
 
+	if (test)
+		return;
+
+	if (IS_CHAN_2GHZ(chan))
+		i = rate1l;
+	else
+		i = rate6mb;
+
+	regulatory->max_power_level = ratesArray[i];
+
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++)
 		for (i = 0; i < Ar5416RateSize; i++)
 			ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
 			ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
@@ -971,17 +985,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
 			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
 			  | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
 			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
 			  | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
 	}
 	}
-
-	if (IS_CHAN_2GHZ(chan))
-		i = rate1l;
-	else
-		i = rate6mb;
-
-	if (AR_SREV_9280_20_OR_LATER(ah))
-		regulatory->max_power_level =
-			ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2;
-	else
-		regulatory->max_power_level = ratesArray[i];
 }
 }
 
 
 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,
 static void ath9k_hw_ar9287_set_addac(struct ath_hw *ah,

+ 33 - 29
drivers/net/wireless/ath/ath9k/eeprom_def.c

@@ -1258,7 +1258,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 				    u16 cfgCtl,
 				    u16 cfgCtl,
 				    u8 twiceAntennaReduction,
 				    u8 twiceAntennaReduction,
 				    u8 twiceMaxRegulatoryPower,
 				    u8 twiceMaxRegulatoryPower,
-				    u8 powerLimit)
+				    u8 powerLimit, bool test)
 {
 {
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
 #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta)
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -1285,12 +1285,44 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 
 
 	ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
 	ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset);
 
 
+	regulatory->max_power_level = 0;
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 	for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 		ratesArray[i] =	(int16_t)(txPowerIndexOffset + ratesArray[i]);
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 		if (ratesArray[i] > AR5416_MAX_RATE_POWER)
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
 			ratesArray[i] = AR5416_MAX_RATE_POWER;
+		if (ratesArray[i] > regulatory->max_power_level)
+			regulatory->max_power_level = ratesArray[i];
 	}
 	}
 
 
+	if (!test) {
+		i = rate6mb;
+
+		if (IS_CHAN_HT40(chan))
+			i = rateHt40_0;
+		else if (IS_CHAN_HT20(chan))
+			i = rateHt20_0;
+
+		regulatory->max_power_level = ratesArray[i];
+	}
+
+	switch(ar5416_get_ntxchains(ah->txchainmask)) {
+	case 1:
+		break;
+	case 2:
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
+		break;
+	case 3:
+		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
+		break;
+	default:
+		ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
+			  "Invalid chainmask configuration\n");
+		break;
+	}
+
+	if (test)
+		return;
+
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		for (i = 0; i < Ar5416RateSize; i++) {
 		for (i = 0; i < Ar5416RateSize; i++) {
 			int8_t pwr_table_offset;
 			int8_t pwr_table_offset;
@@ -1387,34 +1419,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
 	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
 	REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
 		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
 		  ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
 		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
 		  | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
-
-	i = rate6mb;
-
-	if (IS_CHAN_HT40(chan))
-		i = rateHt40_0;
-	else if (IS_CHAN_HT20(chan))
-		i = rateHt20_0;
-
-	if (AR_SREV_9280_20_OR_LATER(ah))
-		regulatory->max_power_level =
-			ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2;
-	else
-		regulatory->max_power_level = ratesArray[i];
-
-	switch(ar5416_get_ntxchains(ah->txchainmask)) {
-	case 1:
-		break;
-	case 2:
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN;
-		break;
-	case 3:
-		regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN;
-		break;
-	default:
-		ath_print(ath9k_hw_common(ah), ATH_DBG_EEPROM,
-			  "Invalid chainmask configuration\n");
-		break;
-	}
 }
 }
 
 
 static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,
 static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah,

+ 4 - 6
drivers/net/wireless/ath/ath9k/gpio.c

@@ -259,7 +259,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
 	ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
 	ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
 
 
 	if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
 	if ((ah->imask & ATH9K_INT_GENTIMER) == 0) {
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		ah->imask |= ATH9K_INT_GENTIMER;
 		ah->imask |= ATH9K_INT_GENTIMER;
 		ath9k_hw_set_interrupts(ah, ah->imask);
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
 	}
@@ -273,7 +273,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
 
 
 	/* if no timer is enabled, turn off interrupt mask */
 	/* if no timer is enabled, turn off interrupt mask */
 	if (timer_table->timer_mask.val == 0) {
 	if (timer_table->timer_mask.val == 0) {
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		ah->imask &= ~ATH9K_INT_GENTIMER;
 		ah->imask &= ~ATH9K_INT_GENTIMER;
 		ath9k_hw_set_interrupts(ah, ah->imask);
 		ath9k_hw_set_interrupts(ah, ah->imask);
 	}
 	}
@@ -310,10 +310,8 @@ static void ath_btcoex_period_timer(unsigned long data)
 
 
 		timer_period = is_btscan ? btcoex->btscan_no_stomp :
 		timer_period = is_btscan ? btcoex->btscan_no_stomp :
 					   btcoex->btcoex_no_stomp;
 					   btcoex->btcoex_no_stomp;
-		ath9k_gen_timer_start(ah,
-				      btcoex->no_stomp_timer,
-				      (ath9k_hw_gettsf32(ah) +
-				       timer_period), timer_period * 10);
+		ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, 0,
+				      timer_period * 10);
 		btcoex->hw_timer_enabled = true;
 		btcoex->hw_timer_enabled = true;
 	}
 	}
 
 

+ 9 - 61
drivers/net/wireless/ath/ath9k/htc_drv_main.c

@@ -29,7 +29,7 @@ static void ath_update_txpow(struct ath9k_htc_priv *priv)
 	struct ath_hw *ah = priv->ah;
 	struct ath_hw *ah = priv->ah;
 
 
 	if (priv->curtxpow != priv->txpowlimit) {
 	if (priv->curtxpow != priv->txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit);
+		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
 		/* read back in case value is clamped */
 		/* read back in case value is clamped */
 		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 	}
 	}
@@ -184,47 +184,6 @@ err:
 	return ret;
 	return ret;
 }
 }
 
 
-static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
-{
-	struct ath_common *common = ath9k_hw_common(priv->ah);
-	struct ath9k_htc_target_vif hvif;
-	int ret = 0;
-	u8 cmd_rsp;
-
-	if (priv->nvifs > 0)
-		return -ENOBUFS;
-
-	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
-	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
-
-	hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
-	priv->ah->opmode = NL80211_IFTYPE_MONITOR;
-	hvif.index = priv->nvifs;
-
-	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
-	if (ret)
-		return ret;
-
-	priv->nvifs++;
-	return 0;
-}
-
-static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
-{
-	struct ath_common *common = ath9k_hw_common(priv->ah);
-	struct ath9k_htc_target_vif hvif;
-	int ret = 0;
-	u8 cmd_rsp;
-
-	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
-	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
-	hvif.index = 0; /* Should do for now */
-	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
-	priv->nvifs--;
-
-	return ret;
-}
-
 static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 static int ath9k_htc_add_station(struct ath9k_htc_priv *priv,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_sta *sta)
 				 struct ieee80211_sta *sta)
@@ -1240,16 +1199,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 	skb_queue_purge(&priv->tx_queue);
 	skb_queue_purge(&priv->tx_queue);
 
 
-	/* Remove monitor interface here */
-	if (ah->opmode == NL80211_IFTYPE_MONITOR) {
-		if (ath9k_htc_remove_monitor_interface(priv))
-			ath_print(common, ATH_DBG_FATAL,
-				  "Unable to remove monitor interface\n");
-		else
-			ath_print(common, ATH_DBG_CONFIG,
-				  "Monitor interface removed\n");
-	}
-
 	if (ah->btcoex_hw.enabled) {
 	if (ah->btcoex_hw.enabled) {
 		ath9k_hw_btcoex_disable(ah);
 		ath9k_hw_btcoex_disable(ah);
 		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
 		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
@@ -1400,7 +1349,9 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
 		ath_print(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
 			  curchan->center_freq);
 			  curchan->center_freq);
 
 
-		ath9k_cmn_update_ichannel(hw, &priv->ah->channels[pos]);
+		ath9k_cmn_update_ichannel(&priv->ah->channels[pos],
+					  hw->conf.channel,
+					  hw->conf.channel_type);
 
 
 		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
 		if (ath9k_htc_set_channel(priv, hw, &priv->ah->channels[pos]) < 0) {
 			ath_print(common, ATH_DBG_FATAL,
 			ath_print(common, ATH_DBG_FATAL,
@@ -1421,16 +1372,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		}
 		}
 	}
 	}
 
 
-	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
+	if (changed & IEEE80211_CONF_CHANGE_MONITOR)
 		if (conf->flags & IEEE80211_CONF_MONITOR) {
 		if (conf->flags & IEEE80211_CONF_MONITOR) {
-			if (ath9k_htc_add_monitor_interface(priv))
-				ath_print(common, ATH_DBG_FATAL,
-					  "Failed to set monitor mode\n");
-			else
-				ath_print(common, ATH_DBG_CONFIG,
-					  "HW opmode set to Monitor mode\n");
+			ath_print(common, ATH_DBG_CONFIG,
+				  "HW opmode set to Monitor mode\n");
+			priv->ah->opmode = NL80211_IFTYPE_MONITOR;
 		}
 		}
-	}
+
 
 
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
 		mutex_lock(&priv->htc_pm_lock);
 		mutex_lock(&priv->htc_pm_lock);

+ 8 - 1
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c

@@ -20,8 +20,15 @@
 /* TX */
 /* TX */
 /******/
 /******/
 
 
+static const int subtype_txq_to_hwq[] = {
+	[WME_AC_BE] = ATH_TXQ_AC_BE,
+	[WME_AC_BK] = ATH_TXQ_AC_BK,
+	[WME_AC_VI] = ATH_TXQ_AC_VI,
+	[WME_AC_VO] = ATH_TXQ_AC_VO,
+};
+
 #define ATH9K_HTC_INIT_TXQ(subtype) do {			\
 #define ATH9K_HTC_INIT_TXQ(subtype) do {			\
-		qi.tqi_subtype = subtype;			\
+		qi.tqi_subtype = subtype_txq_to_hwq[subtype];	\
 		qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;		\
 		qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;		\

+ 4 - 5
drivers/net/wireless/ath/ath9k/hw.c

@@ -1170,7 +1170,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
 			     channel->max_antenna_gain * 2,
 			     channel->max_antenna_gain * 2,
 			     channel->max_power * 2,
 			     channel->max_power * 2,
 			     min((u32) MAX_RATE_POWER,
 			     min((u32) MAX_RATE_POWER,
-			     (u32) regulatory->power_limit));
+			     (u32) regulatory->power_limit), false);
 
 
 	ath9k_hw_rfbus_done(ah);
 	ath9k_hw_rfbus_done(ah);
 
 
@@ -2176,7 +2176,7 @@ bool ath9k_hw_disable(struct ath_hw *ah)
 }
 }
 EXPORT_SYMBOL(ath9k_hw_disable);
 EXPORT_SYMBOL(ath9k_hw_disable);
 
 
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
 {
 {
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
 	struct ath9k_channel *chan = ah->curchan;
 	struct ath9k_channel *chan = ah->curchan;
@@ -2189,7 +2189,7 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit)
 				 channel->max_antenna_gain * 2,
 				 channel->max_antenna_gain * 2,
 				 channel->max_power * 2,
 				 channel->max_power * 2,
 				 min((u32) MAX_RATE_POWER,
 				 min((u32) MAX_RATE_POWER,
-				 (u32) regulatory->power_limit));
+				 (u32) regulatory->power_limit), test);
 }
 }
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
 
 
@@ -2323,11 +2323,10 @@ static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask)
 	return timer_table->gen_timer_index[b];
 	return timer_table->gen_timer_index[b];
 }
 }
 
 
-u32 ath9k_hw_gettsf32(struct ath_hw *ah)
+static u32 ath9k_hw_gettsf32(struct ath_hw *ah)
 {
 {
 	return REG_READ(ah, AR_TSF_L32);
 	return REG_READ(ah, AR_TSF_L32);
 }
 }
-EXPORT_SYMBOL(ath9k_hw_gettsf32);
 
 
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
 					  void (*trigger)(void *),
 					  void (*trigger)(void *),

+ 8 - 8
drivers/net/wireless/ath/ath9k/hw.h

@@ -157,6 +157,13 @@
 #define PAPRD_GAIN_TABLE_ENTRIES    32
 #define PAPRD_GAIN_TABLE_ENTRIES    32
 #define PAPRD_TABLE_SZ              24
 #define PAPRD_TABLE_SZ              24
 
 
+enum ath_hw_txq_subtype {
+	ATH_TXQ_AC_BE = 0,
+	ATH_TXQ_AC_BK = 1,
+	ATH_TXQ_AC_VI = 2,
+	ATH_TXQ_AC_VO = 3,
+};
+
 enum ath_ini_subsys {
 enum ath_ini_subsys {
 	ATH_INI_PRE = 0,
 	ATH_INI_PRE = 0,
 	ATH_INI_CORE,
 	ATH_INI_CORE,
@@ -819,12 +826,6 @@ static inline struct ath_hw_ops *ath9k_hw_ops(struct ath_hw *ah)
 	return &ah->ops;
 	return &ah->ops;
 }
 }
 
 
-static inline int sign_extend(int val, const int nbits)
-{
-	int order = BIT(nbits-1);
-	return (val ^ order) - order;
-}
-
 /* Initialization, Detach, Reset */
 /* Initialization, Detach, Reset */
 const char *ath9k_hw_probe(u16 vendorid, u16 devid);
 const char *ath9k_hw_probe(u16 vendorid, u16 devid);
 void ath9k_hw_deinit(struct ath_hw *ah);
 void ath9k_hw_deinit(struct ath_hw *ah);
@@ -861,7 +862,7 @@ u32 ath9k_hw_getrxfilter(struct ath_hw *ah);
 void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
 void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits);
 bool ath9k_hw_phy_disable(struct ath_hw *ah);
 bool ath9k_hw_phy_disable(struct ath_hw *ah);
 bool ath9k_hw_disable(struct ath_hw *ah);
 bool ath9k_hw_disable(struct ath_hw *ah);
-void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit);
+void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test);
 void ath9k_hw_setopmode(struct ath_hw *ah);
 void ath9k_hw_setopmode(struct ath_hw *ah);
 void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
 void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1);
 void ath9k_hw_setbssidmask(struct ath_hw *ah);
 void ath9k_hw_setbssidmask(struct ath_hw *ah);
@@ -893,7 +894,6 @@ void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
 
 
 void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
 void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
 void ath_gen_timer_isr(struct ath_hw *hw);
 void ath_gen_timer_isr(struct ath_hw *hw);
-u32 ath9k_hw_gettsf32(struct ath_hw *ah);
 
 
 void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
 void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len);
 
 

+ 41 - 47
drivers/net/wireless/ath/ath9k/init.c

@@ -398,7 +398,8 @@ static void ath9k_init_crypto(struct ath_softc *sc)
 
 
 static int ath9k_init_btcoex(struct ath_softc *sc)
 static int ath9k_init_btcoex(struct ath_softc *sc)
 {
 {
-	int r, qnum;
+	struct ath_txq *txq;
+	int r;
 
 
 	switch (sc->sc_ah->btcoex_hw.scheme) {
 	switch (sc->sc_ah->btcoex_hw.scheme) {
 	case ATH_BTCOEX_CFG_NONE:
 	case ATH_BTCOEX_CFG_NONE:
@@ -411,8 +412,8 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
 		r = ath_init_btcoex_timer(sc);
 		r = ath_init_btcoex_timer(sc);
 		if (r)
 		if (r)
 			return -1;
 			return -1;
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		ath9k_hw_init_btcoex_hw(sc->sc_ah, qnum);
+		txq = sc->tx.txq_map[WME_AC_BE];
+		ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
 		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
 		break;
 		break;
 	default:
 	default:
@@ -425,59 +426,18 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
 
 
 static int ath9k_init_queues(struct ath_softc *sc)
 static int ath9k_init_queues(struct ath_softc *sc)
 {
 {
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int i = 0;
 	int i = 0;
 
 
-	for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
-		sc->tx.hwq_map[i] = -1;
-
 	sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
 	sc->beacon.beaconq = ath9k_hw_beaconq_setup(sc->sc_ah);
-	if (sc->beacon.beaconq == -1) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup a beacon xmit queue\n");
-		goto err;
-	}
-
 	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
 	sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
-	if (sc->beacon.cabq == NULL) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup CAB xmit queue\n");
-		goto err;
-	}
 
 
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	ath_cabq_update(sc);
 	ath_cabq_update(sc);
 
 
-	if (!ath_tx_setup(sc, WME_AC_BK)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BK traffic\n");
-		goto err;
-	}
-
-	if (!ath_tx_setup(sc, WME_AC_BE)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for BE traffic\n");
-		goto err;
-	}
-	if (!ath_tx_setup(sc, WME_AC_VI)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VI traffic\n");
-		goto err;
-	}
-	if (!ath_tx_setup(sc, WME_AC_VO)) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to setup xmit queue for VO traffic\n");
-		goto err;
-	}
+	for (i = 0; i < WME_NUM_AC; i++)
+		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
 
 
 	return 0;
 	return 0;
-
-err:
-	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_tx_cleanupq(sc, &sc->tx.txq[i]);
-
-	return -EIO;
 }
 }
 
 
 static int ath9k_init_channels_rates(struct ath_softc *sc)
 static int ath9k_init_channels_rates(struct ath_softc *sc)
@@ -583,7 +543,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
 	spin_lock_init(&common->cc_lock);
 	spin_lock_init(&common->cc_lock);
 
 
 	spin_lock_init(&sc->wiphy_lock);
 	spin_lock_init(&sc->wiphy_lock);
-	spin_lock_init(&sc->sc_resetlock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	spin_lock_init(&sc->sc_pm_lock);
 	mutex_init(&sc->mutex);
 	mutex_init(&sc->mutex);
@@ -645,6 +604,37 @@ err_hw:
 	return ret;
 	return ret;
 }
 }
 
 
+static void ath9k_init_band_txpower(struct ath_softc *sc, int band)
+{
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *chan;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
+	int i;
+
+	sband = &sc->sbands[band];
+	for (i = 0; i < sband->n_channels; i++) {
+		chan = &sband->channels[i];
+		ah->curchan = &ah->channels[chan->hw_value];
+		ath9k_cmn_update_ichannel(ah->curchan, chan, NL80211_CHAN_HT20);
+		ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
+		chan->max_power = reg->max_power_level / 2;
+	}
+}
+
+static void ath9k_init_txpower_limits(struct ath_softc *sc)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath9k_channel *curchan = ah->curchan;
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ)
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_2GHZ);
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ)
+		ath9k_init_band_txpower(sc, IEEE80211_BAND_5GHZ);
+
+	ah->curchan = curchan;
+}
+
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
 {
 {
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -706,6 +696,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 		    const struct ath_bus_ops *bus_ops)
 		    const struct ath_bus_ops *bus_ops)
 {
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hw *hw = sc->hw;
+	struct ath_wiphy *aphy = hw->priv;
 	struct ath_common *common;
 	struct ath_common *common;
 	struct ath_hw *ah;
 	struct ath_hw *ah;
 	int error = 0;
 	int error = 0;
@@ -738,6 +729,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 	if (error != 0)
 	if (error != 0)
 		goto error_rx;
 		goto error_rx;
 
 
+	ath9k_init_txpower_limits(sc);
+
 	/* Register with mac80211 */
 	/* Register with mac80211 */
 	error = ieee80211_register_hw(hw);
 	error = ieee80211_register_hw(hw);
 	if (error)
 	if (error)
@@ -755,6 +748,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
 	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
 	INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work);
 	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
 	INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work);
 	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
 	sc->wiphy_scheduler_int = msecs_to_jiffies(500);
+	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 
 
 	ath_init_leds(sc);
 	ath_init_leds(sc);
 	ath_start_rfkill_poll(sc);
 	ath_start_rfkill_poll(sc);

+ 50 - 36
drivers/net/wireless/ath/ath9k/mac.c

@@ -117,12 +117,11 @@ EXPORT_SYMBOL(ath9k_hw_numtxpending);
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 {
 {
 	u32 txcfg, curLevel, newLevel;
 	u32 txcfg, curLevel, newLevel;
-	enum ath9k_int omask;
 
 
 	if (ah->tx_trig_level >= ah->config.max_txtrig_level)
 	if (ah->tx_trig_level >= ah->config.max_txtrig_level)
 		return false;
 		return false;
 
 
-	omask = ath9k_hw_set_interrupts(ah, ah->imask & ~ATH9K_INT_GLOBAL);
+	ath9k_hw_disable_interrupts(ah);
 
 
 	txcfg = REG_READ(ah, AR_TXCFG);
 	txcfg = REG_READ(ah, AR_TXCFG);
 	curLevel = MS(txcfg, AR_FTRIG);
 	curLevel = MS(txcfg, AR_FTRIG);
@@ -136,7 +135,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 		REG_WRITE(ah, AR_TXCFG,
 		REG_WRITE(ah, AR_TXCFG,
 			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
 			  (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
 
 
-	ath9k_hw_set_interrupts(ah, omask);
+	ath9k_hw_enable_interrupts(ah);
 
 
 	ah->tx_trig_level = newLevel;
 	ah->tx_trig_level = newLevel;
 
 
@@ -849,28 +848,59 @@ bool ath9k_hw_intrpend(struct ath_hw *ah)
 }
 }
 EXPORT_SYMBOL(ath9k_hw_intrpend);
 EXPORT_SYMBOL(ath9k_hw_intrpend);
 
 
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
-					      enum ath9k_int ints)
+void ath9k_hw_disable_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
+	REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
+	(void) REG_READ(ah, AR_IER);
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
+		(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+		(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
+	}
+}
+EXPORT_SYMBOL(ath9k_hw_disable_interrupts);
+
+void ath9k_hw_enable_interrupts(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!(ah->imask & ATH9K_INT_GLOBAL))
+		return;
+
+	ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
+	REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
+	if (!AR_SREV_9100(ah)) {
+		REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
+			  AR_INTR_MAC_IRQ);
+		REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
+
+
+		REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
+			  AR_INTR_SYNC_DEFAULT);
+		REG_WRITE(ah, AR_INTR_SYNC_MASK,
+			  AR_INTR_SYNC_DEFAULT);
+	}
+	ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
+		  REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
+}
+EXPORT_SYMBOL(ath9k_hw_enable_interrupts);
+
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
 {
 {
 	enum ath9k_int omask = ah->imask;
 	enum ath9k_int omask = ah->imask;
 	u32 mask, mask2;
 	u32 mask, mask2;
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath9k_hw_capabilities *pCap = &ah->caps;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 
 
-	ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
-
-	if (omask & ATH9K_INT_GLOBAL) {
-		ath_print(common, ATH_DBG_INTERRUPT, "disable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
-		(void) REG_READ(ah, AR_IER);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_ASYNC_ENABLE);
+	if (!(ints & ATH9K_INT_GLOBAL))
+		ath9k_hw_enable_interrupts(ah);
 
 
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
-			(void) REG_READ(ah, AR_INTR_SYNC_ENABLE);
-		}
-	}
+	ath_print(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
 
 
 	/* TODO: global int Ref count */
 	/* TODO: global int Ref count */
 	mask = ints & ATH9K_INT_COMMON;
 	mask = ints & ATH9K_INT_COMMON;
@@ -946,24 +976,8 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
 			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
 			REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
 	}
 	}
 
 
-	if (ints & ATH9K_INT_GLOBAL) {
-		ath_print(common, ATH_DBG_INTERRUPT, "enable IER\n");
-		REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
-		if (!AR_SREV_9100(ah)) {
-			REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
-				  AR_INTR_MAC_IRQ);
-			REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ);
-
-
-			REG_WRITE(ah, AR_INTR_SYNC_ENABLE,
-				  AR_INTR_SYNC_DEFAULT);
-			REG_WRITE(ah, AR_INTR_SYNC_MASK,
-				  AR_INTR_SYNC_DEFAULT);
-		}
-		ath_print(common, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n",
-			  REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER));
-	}
+	ath9k_hw_enable_interrupts(ah);
 
 
-	return omask;
+	return;
 }
 }
 EXPORT_SYMBOL(ath9k_hw_set_interrupts);
 EXPORT_SYMBOL(ath9k_hw_set_interrupts);

+ 6 - 7
drivers/net/wireless/ath/ath9k/mac.h

@@ -104,13 +104,11 @@ struct ath_tx_status {
 	u32 ts_tstamp;
 	u32 ts_tstamp;
 	u16 ts_seqnum;
 	u16 ts_seqnum;
 	u8 ts_status;
 	u8 ts_status;
-	u8 ts_ratecode;
 	u8 ts_rateindex;
 	u8 ts_rateindex;
 	int8_t ts_rssi;
 	int8_t ts_rssi;
 	u8 ts_shortretry;
 	u8 ts_shortretry;
 	u8 ts_longretry;
 	u8 ts_longretry;
 	u8 ts_virtcol;
 	u8 ts_virtcol;
-	u8 ts_antenna;
 	u8 ts_flags;
 	u8 ts_flags;
 	int8_t ts_rssi_ctl0;
 	int8_t ts_rssi_ctl0;
 	int8_t ts_rssi_ctl1;
 	int8_t ts_rssi_ctl1;
@@ -121,7 +119,6 @@ struct ath_tx_status {
 	u8 qid;
 	u8 qid;
 	u16 desc_id;
 	u16 desc_id;
 	u8 tid;
 	u8 tid;
-	u8 pad[2];
 	u32 ba_low;
 	u32 ba_low;
 	u32 ba_high;
 	u32 ba_high;
 	u32 evm0;
 	u32 evm0;
@@ -240,7 +237,7 @@ struct ath_desc {
 	u32 ds_ctl1;
 	u32 ds_ctl1;
 	u32 ds_hw[20];
 	u32 ds_hw[20];
 	void *ds_vdata;
 	void *ds_vdata;
-} __packed;
+} __packed __aligned(4);
 
 
 #define ATH9K_TXDESC_CLRDMASK		0x0001
 #define ATH9K_TXDESC_CLRDMASK		0x0001
 #define ATH9K_TXDESC_NOACK		0x0002
 #define ATH9K_TXDESC_NOACK		0x0002
@@ -310,7 +307,7 @@ struct ar5416_desc {
 			u32 status8;
 			u32 status8;
 		} rx;
 		} rx;
 	} u;
 	} u;
-} __packed;
+} __packed __aligned(4);
 
 
 #define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
 #define AR5416DESC(_ds)         ((struct ar5416_desc *)(_ds))
 #define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
 #define AR5416DESC_CONST(_ds)   ((const struct ar5416_desc *)(_ds))
@@ -669,6 +666,7 @@ enum ath9k_key_type {
 
 
 struct ath_hw;
 struct ath_hw;
 struct ath9k_channel;
 struct ath9k_channel;
+enum ath9k_int;
 
 
 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
 u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
 void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
 void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
@@ -700,8 +698,9 @@ int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 
 /* Interrupt Handling */
 /* Interrupt Handling */
 bool ath9k_hw_intrpend(struct ath_hw *ah);
 bool ath9k_hw_intrpend(struct ath_hw *ah);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
-				       enum ath9k_int ints);
+void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints);
+void ath9k_hw_enable_interrupts(struct ath_hw *ah);
+void ath9k_hw_disable_interrupts(struct ath_hw *ah);
 
 
 void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
 void ar9002_hw_attach_mac_ops(struct ath_hw *ah);
 
 

+ 54 - 113
drivers/net/wireless/ath/ath9k/main.c

@@ -24,7 +24,7 @@ static void ath_update_txpow(struct ath_softc *sc)
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_hw *ah = sc->sc_ah;
 
 
 	if (sc->curtxpow != sc->config.txpowlimit) {
 	if (sc->curtxpow != sc->config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit);
+		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
 		/* read back in case value is clamped */
 		/* read back in case value is clamped */
 		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
 	}
 	}
@@ -235,6 +235,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
 
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	/*
 	/*
 	 * This is only performed if the channel settings have
 	 * This is only performed if the channel settings have
 	 * actually changed.
 	 * actually changed.
@@ -244,11 +246,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 	 * hardware at the new frequency, and then re-enable
 	 * hardware at the new frequency, and then re-enable
 	 * the relevant bits of the h/w.
 	 * the relevant bits of the h/w.
 	 */
 	 */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath_drain_all_txq(sc, false);
 	ath_drain_all_txq(sc, false);
 
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	stopped = ath_stoprecv(sc);
 	stopped = ath_stoprecv(sc);
 
 
 	/* XXX: do not flush receive queue here. We don't want
 	/* XXX: do not flush receive queue here. We don't want
@@ -267,30 +267,22 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		  channel->center_freq, conf_is_ht40(conf),
 		  channel->center_freq, conf_is_ht40(conf),
 		  fastcc);
 		  fastcc);
 
 
-	spin_lock_bh(&sc->sc_resetlock);
-
 	r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	if (r) {
 	if (r) {
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to reset channel (%u MHz), "
 			  "Unable to reset channel (%u MHz), "
 			  "reset status %d\n",
 			  "reset status %d\n",
 			  channel->center_freq, r);
 			  channel->center_freq, r);
-		spin_unlock_bh(&sc->sc_resetlock);
-		spin_unlock_bh(&sc->rx.pcu_lock);
 		goto ps_restore;
 		goto ps_restore;
 	}
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	if (ath_startrecv(sc) != 0) {
 	if (ath_startrecv(sc) != 0) {
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to restart recv logic\n");
 			  "Unable to restart recv logic\n");
 		r = -EIO;
 		r = -EIO;
-		spin_unlock_bh(&sc->rx.pcu_lock);
 		goto ps_restore;
 		goto ps_restore;
 	}
 	}
 
 
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	ath_update_txpow(sc);
 	ath_update_txpow(sc);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
 
@@ -301,6 +293,8 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 	}
 	}
 
 
  ps_restore:
  ps_restore:
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 	return r;
 	return r;
 }
 }
@@ -341,7 +335,7 @@ void ath_paprd_calibrate(struct work_struct *work)
 	struct ath_tx_control txctl;
 	struct ath_tx_control txctl;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 	struct ath9k_hw_cal_data *caldata = ah->caldata;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
-	int qnum, ftype;
+	int ftype;
 	int chain_ok = 0;
 	int chain_ok = 0;
 	int chain;
 	int chain;
 	int len = 1800;
 	int len = 1800;
@@ -368,8 +362,7 @@ void ath_paprd_calibrate(struct work_struct *work)
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 	memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 
 
 	memset(&txctl, 0, sizeof(txctl));
 	memset(&txctl, 0, sizeof(txctl));
-	qnum = sc->tx.hwq_map[WME_AC_BE];
-	txctl.txq = &sc->tx.txq[qnum];
+	txctl.txq = sc->tx.txq_map[WME_AC_BE];
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
 	ar9003_paprd_init_table(ah);
 	ar9003_paprd_init_table(ah);
@@ -567,7 +560,6 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
 		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
 		an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
 				     sta->ht_cap.ampdu_factor);
 				     sta->ht_cap.ampdu_factor);
 		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
 		an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
-		an->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	}
 	}
 }
 }
 
 
@@ -615,6 +607,8 @@ void ath9k_tasklet(unsigned long data)
 		return;
 		return;
 	}
 	}
 
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	if (!ath9k_hw_check_alive(ah))
 	if (!ath9k_hw_check_alive(ah))
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 
 
@@ -625,15 +619,12 @@ void ath9k_tasklet(unsigned long data)
 		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
 		rxmask = (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
 
 
 	if (status & rxmask) {
 	if (status & rxmask) {
-		spin_lock_bh(&sc->rx.pcu_lock);
-
 		/* Check for high priority Rx first */
 		/* Check for high priority Rx first */
 		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
 		if ((ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) &&
 		    (status & ATH9K_INT_RXHP))
 		    (status & ATH9K_INT_RXHP))
 			ath_rx_tasklet(sc, 0, true);
 			ath_rx_tasklet(sc, 0, true);
 
 
 		ath_rx_tasklet(sc, 0, false);
 		ath_rx_tasklet(sc, 0, false);
-		spin_unlock_bh(&sc->rx.pcu_lock);
 	}
 	}
 
 
 	if (status & ATH9K_INT_TX) {
 	if (status & ATH9K_INT_TX) {
@@ -658,7 +649,9 @@ void ath9k_tasklet(unsigned long data)
 			ath_gen_timer_isr(sc->sc_ah);
 			ath_gen_timer_isr(sc->sc_ah);
 
 
 	/* re-enable hardware interrupt */
 	/* re-enable hardware interrupt */
-	ath9k_hw_set_interrupts(ah, ah->imask);
+	ath9k_hw_enable_interrupts(ah);
+
+	spin_unlock_bh(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 }
 }
 
 
@@ -757,7 +750,7 @@ irqreturn_t ath_isr(int irq, void *dev)
 		 * interrupt; otherwise it will continue to
 		 * interrupt; otherwise it will continue to
 		 * fire.
 		 * fire.
 		 */
 		 */
-		ath9k_hw_set_interrupts(ah, 0);
+		ath9k_hw_disable_interrupts(ah);
 		/*
 		/*
 		 * Let the hal handle the event. We assume
 		 * Let the hal handle the event. We assume
 		 * it will clear whatever condition caused
 		 * it will clear whatever condition caused
@@ -766,7 +759,7 @@ irqreturn_t ath_isr(int irq, void *dev)
 		spin_lock(&common->cc_lock);
 		spin_lock(&common->cc_lock);
 		ath9k_hw_proc_mib_event(ah);
 		ath9k_hw_proc_mib_event(ah);
 		spin_unlock(&common->cc_lock);
 		spin_unlock(&common->cc_lock);
-		ath9k_hw_set_interrupts(ah, ah->imask);
+		ath9k_hw_enable_interrupts(ah);
 	}
 	}
 
 
 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
 	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
@@ -783,8 +776,8 @@ chip_reset:
 	ath_debug_stat_interrupt(sc, status);
 	ath_debug_stat_interrupt(sc, status);
 
 
 	if (sched) {
 	if (sched) {
-		/* turn off every interrupt except SWBA */
-		ath9k_hw_set_interrupts(ah, (ah->imask & ATH9K_INT_SWBA));
+		/* turn off every interrupt */
+		ath9k_hw_disable_interrupts(ah);
 		tasklet_schedule(&sc->intr_tq);
 		tasklet_schedule(&sc->intr_tq);
 	}
 	}
 
 
@@ -836,9 +829,11 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
 }
 }
 
 
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
 static void ath9k_bss_assoc_info(struct ath_softc *sc,
+				 struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
 				 struct ieee80211_bss_conf *bss_conf)
 {
 {
+	struct ath_wiphy *aphy = hw->priv;
 	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);
 
 
@@ -862,6 +857,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		ath_beacon_config(sc, vif);
 		ath_beacon_config(sc, vif);
 
 
 		/* Reset rssi stats */
 		/* Reset rssi stats */
+		aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 
 		sc->sc_flags |= SC_OP_ANI_RUN;
 		sc->sc_flags |= SC_OP_ANI_RUN;
@@ -883,13 +879,13 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	int r;
 	int r;
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 
 
 	if (!ah->curchan)
 	if (!ah->curchan)
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
 		ah->curchan = ath_get_curchannel(sc, sc->hw);
 
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
 	if (r) {
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
@@ -897,17 +893,14 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 			  "reset status %d\n",
 			  "reset status %d\n",
 			  channel->center_freq, r);
 			  channel->center_freq, r);
 	}
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	ath_update_txpow(sc);
 	ath_update_txpow(sc);
 	if (ath_startrecv(sc) != 0) {
 	if (ath_startrecv(sc) != 0) {
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to restart recv logic\n");
 			  "Unable to restart recv logic\n");
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		return;
 		return;
 	}
 	}
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	if (sc->sc_flags & SC_OP_BEACONS)
 	if (sc->sc_flags & SC_OP_BEACONS)
 		ath_beacon_config(sc, NULL);	/* restart beacons */
 		ath_beacon_config(sc, NULL);	/* restart beacons */
 
 
@@ -920,6 +913,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
 
 	ieee80211_wake_queues(hw);
 	ieee80211_wake_queues(hw);
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 }
 }
 
 
@@ -930,6 +925,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	int r;
 	int r;
 
 
 	ath9k_ps_wakeup(sc);
 	ath9k_ps_wakeup(sc);
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ieee80211_stop_queues(hw);
 	ieee80211_stop_queues(hw);
 
 
 	/*
 	/*
@@ -942,19 +939,16 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 	}
 	}
 
 
 	/* Disable interrupts */
 	/* Disable interrupts */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 
 
 	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
 	ath_drain_all_txq(sc, false);	/* clear pending tx frames */
 
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	ath_stoprecv(sc);		/* turn off frame recv */
 	ath_stoprecv(sc);		/* turn off frame recv */
 	ath_flushrecv(sc);		/* flush recv queue */
 	ath_flushrecv(sc);		/* flush recv queue */
 
 
 	if (!ah->curchan)
 	if (!ah->curchan)
 		ah->curchan = ath_get_curchannel(sc, hw);
 		ah->curchan = ath_get_curchannel(sc, hw);
 
 
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
 	if (r) {
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
 		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
@@ -962,14 +956,14 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
 			  "reset status %d\n",
 			  "reset status %d\n",
 			  channel->center_freq, r);
 			  channel->center_freq, r);
 	}
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_phy_disable(ah);
 
 
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	ath9k_hw_configpcipowersave(ah, 1, 1);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
+
+	spin_unlock_bh(&sc->sc_pcu_lock);
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
+
 	ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
 	ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
 }
 }
 
 
@@ -983,29 +977,25 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	/* Stop ANI */
 	/* Stop ANI */
 	del_timer_sync(&common->ani.timer);
 	del_timer_sync(&common->ani.timer);
 
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	ieee80211_stop_queues(hw);
 	ieee80211_stop_queues(hw);
 
 
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 	ath_drain_all_txq(sc, retry_tx);
 	ath_drain_all_txq(sc, retry_tx);
 
 
-	spin_lock_bh(&sc->rx.pcu_lock);
-
 	ath_stoprecv(sc);
 	ath_stoprecv(sc);
 	ath_flushrecv(sc);
 	ath_flushrecv(sc);
 
 
-	spin_lock_bh(&sc->sc_resetlock);
 	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 	r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 	if (r)
 	if (r)
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to reset hardware; reset status %d\n", r);
 			  "Unable to reset hardware; reset status %d\n", r);
-	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	if (ath_startrecv(sc) != 0)
 	if (ath_startrecv(sc) != 0)
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to start recv logic\n");
 			  "Unable to start recv logic\n");
 
 
-	spin_unlock_bh(&sc->rx.pcu_lock);
-
 	/*
 	/*
 	 * We may be doing a reset in response to a request
 	 * We may be doing a reset in response to a request
 	 * that changes the channel so update any state that
 	 * that changes the channel so update any state that
@@ -1030,6 +1020,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	}
 	}
 
 
 	ieee80211_wake_queues(hw);
 	ieee80211_wake_queues(hw);
+	spin_unlock_bh(&sc->sc_pcu_lock);
 
 
 	/* Start ANI */
 	/* Start ANI */
 	ath_start_ani(common);
 	ath_start_ani(common);
@@ -1037,56 +1028,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
 	return r;
 	return r;
 }
 }
 
 
-static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case 0:
-		qnum = sc->tx.hwq_map[WME_AC_VO];
-		break;
-	case 1:
-		qnum = sc->tx.hwq_map[WME_AC_VI];
-		break;
-	case 2:
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		break;
-	case 3:
-		qnum = sc->tx.hwq_map[WME_AC_BK];
-		break;
-	default:
-		qnum = sc->tx.hwq_map[WME_AC_BE];
-		break;
-	}
-
-	return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
-	int qnum;
-
-	switch (queue) {
-	case WME_AC_VO:
-		qnum = 0;
-		break;
-	case WME_AC_VI:
-		qnum = 1;
-		break;
-	case WME_AC_BE:
-		qnum = 2;
-		break;
-	case WME_AC_BK:
-		qnum = 3;
-		break;
-	default:
-		qnum = -1;
-		break;
-	}
-
-	return qnum;
-}
-
 /* XXX: Remove me once we don't depend on ath9k_channel for all
 /* XXX: Remove me once we don't depend on ath9k_channel for all
  * this redundant data */
  * this redundant data */
 void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
 void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
@@ -1168,19 +1109,16 @@ static int ath9k_start(struct ieee80211_hw *hw)
 	 * be followed by initialization of the appropriate bits
 	 * be followed by initialization of the appropriate bits
 	 * and then setup of the interrupt mask.
 	 * and then setup of the interrupt mask.
 	 */
 	 */
-	spin_lock_bh(&sc->rx.pcu_lock);
-	spin_lock_bh(&sc->sc_resetlock);
+	spin_lock_bh(&sc->sc_pcu_lock);
 	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 	r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
 	if (r) {
 	if (r) {
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to reset hardware; reset status %d "
 			  "Unable to reset hardware; reset status %d "
 			  "(freq %u MHz)\n", r,
 			  "(freq %u MHz)\n", r,
 			  curchan->center_freq);
 			  curchan->center_freq);
-		spin_unlock_bh(&sc->sc_resetlock);
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		goto mutex_unlock;
 		goto mutex_unlock;
 	}
 	}
-	spin_unlock_bh(&sc->sc_resetlock);
 
 
 	/*
 	/*
 	 * This is needed only to setup initial state
 	 * This is needed only to setup initial state
@@ -1199,10 +1137,10 @@ static int ath9k_start(struct ieee80211_hw *hw)
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Unable to start recv logic\n");
 			  "Unable to start recv logic\n");
 		r = -EIO;
 		r = -EIO;
-		spin_unlock_bh(&sc->rx.pcu_lock);
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		goto mutex_unlock;
 		goto mutex_unlock;
 	}
 	}
-	spin_unlock_bh(&sc->rx.pcu_lock);
+	spin_unlock_bh(&sc->sc_pcu_lock);
 
 
 	/* Setup our intr mask. */
 	/* Setup our intr mask. */
 	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
 	ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL |
@@ -1262,7 +1200,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
 	struct ath_tx_control txctl;
 	struct ath_tx_control txctl;
 	int padpos, padsize;
 	int padpos, padsize;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-	int qnum;
 
 
 	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
 	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
 		ath_print(common, ATH_DBG_XMIT,
 		ath_print(common, ATH_DBG_XMIT,
@@ -1335,8 +1272,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
 		memmove(skb->data, skb->data + padsize, padpos);
 		memmove(skb->data, skb->data + padsize, padpos);
 	}
 	}
 
 
-	qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
-	txctl.txq = &sc->tx.txq[qnum];
+	txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
 
 
 	ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
 	ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
 
 
@@ -1400,22 +1336,25 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 			ath9k_btcoex_timer_pause(sc);
 			ath9k_btcoex_timer_pause(sc);
 	}
 	}
 
 
+	spin_lock_bh(&sc->sc_pcu_lock);
+
 	/* make sure h/w will not generate any interrupt
 	/* make sure h/w will not generate any interrupt
 	 * before setting the invalid flag. */
 	 * before setting the invalid flag. */
-	ath9k_hw_set_interrupts(ah, 0);
+	ath9k_hw_disable_interrupts(ah);
 
 
-	spin_lock_bh(&sc->rx.pcu_lock);
 	if (!(sc->sc_flags & SC_OP_INVALID)) {
 	if (!(sc->sc_flags & SC_OP_INVALID)) {
 		ath_drain_all_txq(sc, false);
 		ath_drain_all_txq(sc, false);
 		ath_stoprecv(sc);
 		ath_stoprecv(sc);
 		ath9k_hw_phy_disable(ah);
 		ath9k_hw_phy_disable(ah);
 	} else
 	} else
 		sc->rx.rxlink = NULL;
 		sc->rx.rxlink = NULL;
-	spin_unlock_bh(&sc->rx.pcu_lock);
 
 
 	/* disable HAL and put h/w to sleep */
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(ah);
 	ath9k_hw_disable(ah);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
+
+	spin_unlock_bh(&sc->sc_pcu_lock);
+
 	ath9k_ps_restore(sc);
 	ath9k_ps_restore(sc);
 
 
 	/* Finally, put the chip in FULL SLEEP mode */
 	/* Finally, put the chip in FULL SLEEP mode */
@@ -1822,12 +1761,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_txq *txq;
 	struct ath9k_tx_queue_info qi;
 	struct ath9k_tx_queue_info qi;
-	int ret = 0, qnum;
+	int ret = 0;
 
 
 	if (queue >= WME_NUM_AC)
 	if (queue >= WME_NUM_AC)
 		return 0;
 		return 0;
 
 
+	txq = sc->tx.txq_map[queue];
+
 	mutex_lock(&sc->mutex);
 	mutex_lock(&sc->mutex);
 
 
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1836,20 +1778,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 	qi.tqi_cwmin = params->cw_min;
 	qi.tqi_cwmin = params->cw_min;
 	qi.tqi_cwmax = params->cw_max;
 	qi.tqi_cwmax = params->cw_max;
 	qi.tqi_burstTime = params->txop;
 	qi.tqi_burstTime = params->txop;
-	qnum = ath_get_hal_qnum(queue, sc);
 
 
 	ath_print(common, ATH_DBG_CONFIG,
 	ath_print(common, ATH_DBG_CONFIG,
 		  "Configure tx [queue/halq] [%d/%d],  "
 		  "Configure tx [queue/halq] [%d/%d],  "
 		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
 		  "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
-		  queue, qnum, params->aifs, params->cw_min,
+		  queue, txq->axq_qnum, params->aifs, params->cw_min,
 		  params->cw_max, params->txop);
 		  params->cw_max, params->txop);
 
 
-	ret = ath_txq_update(sc, qnum, &qi);
+	ret = ath_txq_update(sc, txq->axq_qnum, &qi);
 	if (ret)
 	if (ret)
 		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
 		ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
 
 
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
 	if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
-		if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret)
+		if (queue == WME_AC_BE && !ret)
 			ath_beaconq_config(sc);
 			ath_beaconq_config(sc);
 
 
 	mutex_unlock(&sc->mutex);
 	mutex_unlock(&sc->mutex);
@@ -2011,7 +1952,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 	if (changed & BSS_CHANGED_ASSOC) {
 	if (changed & BSS_CHANGED_ASSOC) {
 		ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
 		ath_print(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
 			bss_conf->assoc);
 			bss_conf->assoc);
-		ath9k_bss_assoc_info(sc, vif, bss_conf);
+		ath9k_bss_assoc_info(sc, hw, vif, bss_conf);
 	}
 	}
 
 
 	mutex_unlock(&sc->mutex);
 	mutex_unlock(&sc->mutex);

+ 22 - 18
drivers/net/wireless/ath/ath9k/pci.c

@@ -247,34 +247,25 @@ static void ath_pci_remove(struct pci_dev *pdev)
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 
 
-static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int ath_pci_suspend(struct device *device)
 {
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_softc *sc = aphy->sc;
 
 
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
 
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
 	return 0;
 	return 0;
 }
 }
 
 
-static int ath_pci_resume(struct pci_dev *pdev)
+static int ath_pci_resume(struct device *device)
 {
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_softc *sc = aphy->sc;
 	struct ath_softc *sc = aphy->sc;
 	u32 val;
 	u32 val;
-	int err;
-
-	pci_restore_state(pdev);
-
-	err = pci_enable_device(pdev);
-	if (err)
-		return err;
 
 
 	/*
 	/*
 	 * Suspend/Resume resets the PCI configuration space, so we have to
 	 * Suspend/Resume resets the PCI configuration space, so we have to
@@ -293,7 +284,23 @@ static int ath_pci_resume(struct pci_dev *pdev)
 	return 0;
 	return 0;
 }
 }
 
 
-#endif /* CONFIG_PM */
+static const struct dev_pm_ops ath9k_pm_ops = {
+	.suspend = ath_pci_suspend,
+	.resume = ath_pci_resume,
+	.freeze = ath_pci_suspend,
+	.thaw = ath_pci_resume,
+	.poweroff = ath_pci_suspend,
+	.restore = ath_pci_resume,
+};
+
+#define ATH9K_PM_OPS	(&ath9k_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define ATH9K_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
+
 
 
 MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
 MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
 
 
@@ -302,10 +309,7 @@ static struct pci_driver ath_pci_driver = {
 	.id_table   = ath_pci_id_table,
 	.id_table   = ath_pci_id_table,
 	.probe      = ath_pci_probe,
 	.probe      = ath_pci_probe,
 	.remove     = ath_pci_remove,
 	.remove     = ath_pci_remove,
-#ifdef CONFIG_PM
-	.suspend    = ath_pci_suspend,
-	.resume     = ath_pci_resume,
-#endif /* CONFIG_PM */
+	.driver.pm  = ATH9K_PM_OPS,
 };
 };
 
 
 int ath_pci_init(void)
 int ath_pci_init(void)

+ 5 - 26
drivers/net/wireless/ath/ath9k/rc.c

@@ -381,25 +381,6 @@ static const struct ath_rate_table ar5416_11g_ratetable = {
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
 				struct ieee80211_tx_rate *rate);
 				struct ieee80211_tx_rate *rate);
 
 
-static inline int8_t median(int8_t a, int8_t b, int8_t c)
-{
-	if (a >= b) {
-		if (b >= c)
-			return b;
-		else if (a > c)
-			return c;
-		else
-			return a;
-	} else {
-		if (a >= c)
-			return a;
-		else if (b >= c)
-			return c;
-		else
-			return b;
-	}
-}
-
 static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
 static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
 				   struct ath_rate_priv *ath_rc_priv)
 				   struct ath_rate_priv *ath_rc_priv)
 {
 {
@@ -1444,12 +1425,12 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
 		ath_rc_priv->neg_ht_rates.rs_nrates = j;
 		ath_rc_priv->neg_ht_rates.rs_nrates = j;
 	}
 	}
 
 
-	is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+	is_cw40 = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
 
 
 	if (is_cw40)
 	if (is_cw40)
-		is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40;
+		is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40);
 	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
 	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_SGI_20)
-		is_sgi = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20;
+		is_sgi = !!(sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20);
 
 
 	/* Choose rate table first */
 	/* Choose rate table first */
 
 
@@ -1468,10 +1449,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
 	struct ath_rate_priv *ath_rc_priv = priv_sta;
 	struct ath_rate_priv *ath_rc_priv = priv_sta;
 	const struct ath_rate_table *rate_table = NULL;
 	const struct ath_rate_table *rate_table = NULL;
 	bool oper_cw40 = false, oper_sgi;
 	bool oper_cw40 = false, oper_sgi;
-	bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ?
-		true : false;
-	bool local_sgi = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ?
-		true : false;
+	bool local_cw40 = !!(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
+	bool local_sgi = !!(ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG);
 
 
 	/* FIXME: Handle AP mode later when we support CWM */
 	/* FIXME: Handle AP mode later when we support CWM */
 
 

+ 15 - 27
drivers/net/wireless/ath/ath9k/recv.c

@@ -317,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
 	struct ath_buf *bf;
 	struct ath_buf *bf;
 	int error = 0;
 	int error = 0;
 
 
-	spin_lock_init(&sc->rx.pcu_lock);
+	spin_lock_init(&sc->sc_pcu_lock);
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	spin_lock_init(&sc->rx.rxbuflock);
 	spin_lock_init(&sc->rx.rxbuflock);
 
 
@@ -528,6 +528,8 @@ bool ath_stoprecv(struct ath_softc *sc)
 		sc->rx.rxlink = NULL;
 		sc->rx.rxlink = NULL;
 	spin_unlock_bh(&sc->rx.rxbuflock);
 	spin_unlock_bh(&sc->rx.rxbuflock);
 
 
+	ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
+		     "confusing the DMA engine when we start RX up\n");
 	return stopped;
 	return stopped;
 }
 }
 
 
@@ -962,36 +964,23 @@ static void ath9k_process_rssi(struct ath_common *common,
 			       struct ieee80211_hdr *hdr,
 			       struct ieee80211_hdr *hdr,
 			       struct ath_rx_status *rx_stats)
 			       struct ath_rx_status *rx_stats)
 {
 {
+	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = common->ah;
 	struct ath_hw *ah = common->ah;
-	struct ieee80211_sta *sta;
-	struct ath_node *an;
-	int last_rssi = ATH_RSSI_DUMMY_MARKER;
+	int last_rssi;
 	__le16 fc;
 	__le16 fc;
 
 
+	if (ah->opmode != NL80211_IFTYPE_STATION)
+		return;
+
 	fc = hdr->frame_control;
 	fc = hdr->frame_control;
+	if (!ieee80211_is_beacon(fc) ||
+	    compare_ether_addr(hdr->addr3, common->curbssid))
+		return;
 
 
-	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.
-	 */
-	if (is_multicast_ether_addr(hdr->addr1))
-		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
-	else
-		sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
-
-	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 (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+		ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
 
 
+	last_rssi = aphy->last_rssi;
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
 		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
 		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
 					      ATH_RSSI_EP_MULTIPLIER);
 					      ATH_RSSI_EP_MULTIPLIER);
@@ -999,8 +988,7 @@ static void ath9k_process_rssi(struct ath_common *common,
 		rx_stats->rs_rssi = 0;
 		rx_stats->rs_rssi = 0;
 
 
 	/* Update Beacon RSSI, this is used by ANI. */
 	/* Update Beacon RSSI, this is used by ANI. */
-	if (ieee80211_is_beacon(fc))
-		ah->stats.avgbrssi = rx_stats->rs_rssi;
+	ah->stats.avgbrssi = rx_stats->rs_rssi;
 }
 }
 
 
 /*
 /*

+ 2 - 1
drivers/net/wireless/ath/ath9k/virtual.c

@@ -107,6 +107,7 @@ int ath9k_wiphy_add(struct ath_softc *sc)
 	aphy->sc = sc;
 	aphy->sc = sc;
 	aphy->hw = hw;
 	aphy->hw = hw;
 	sc->sec_wiphy[i] = aphy;
 	sc->sec_wiphy[i] = aphy;
+	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
 	spin_unlock_bh(&sc->wiphy_lock);
 	spin_unlock_bh(&sc->wiphy_lock);
 
 
 	memcpy(addr, common->macaddr, ETH_ALEN);
 	memcpy(addr, common->macaddr, ETH_ALEN);
@@ -186,7 +187,7 @@ static int ath9k_send_nullfunc(struct ath_wiphy *aphy,
 	info->control.rates[1].idx = -1;
 	info->control.rates[1].idx = -1;
 
 
 	memset(&txctl, 0, sizeof(struct ath_tx_control));
 	memset(&txctl, 0, sizeof(struct ath_tx_control));
-	txctl.txq = &sc->tx.txq[sc->tx.hwq_map[WME_AC_VO]];
+	txctl.txq = sc->tx.txq_map[WME_AC_VO];
 	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
 	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_UNPAUSE;
 
 
 	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)
 	if (ath_tx_start(aphy->hw, skb, &txctl) != 0)

+ 45 - 57
drivers/net/wireless/ath/ath9k/xmit.c

@@ -124,7 +124,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
 
 
 static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
 {
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+	struct ath_txq *txq = tid->ac->txq;
 
 
 	WARN_ON(!tid->paused);
 	WARN_ON(!tid->paused);
 
 
@@ -142,7 +142,7 @@ unlock:
 
 
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
 {
 {
-	struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
+	struct ath_txq *txq = tid->ac->txq;
 	struct ath_buf *bf;
 	struct ath_buf *bf;
 	struct list_head bf_head;
 	struct list_head bf_head;
 	struct ath_tx_status ts;
 	struct ath_tx_status ts;
@@ -817,7 +817,7 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
 {
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
 	struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
-	struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
+	struct ath_txq *txq = txtid->ac->txq;
 
 
 	if (txtid->state & AGGR_CLEANUP)
 	if (txtid->state & AGGR_CLEANUP)
 		return;
 		return;
@@ -888,10 +888,16 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 	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 ath9k_tx_queue_info qi;
 	struct ath9k_tx_queue_info qi;
+	static const int subtype_txq_to_hwq[] = {
+		[WME_AC_BE] = ATH_TXQ_AC_BE,
+		[WME_AC_BK] = ATH_TXQ_AC_BK,
+		[WME_AC_VI] = ATH_TXQ_AC_VI,
+		[WME_AC_VO] = ATH_TXQ_AC_VO,
+	};
 	int qnum, i;
 	int qnum, i;
 
 
 	memset(&qi, 0, sizeof(qi));
 	memset(&qi, 0, sizeof(qi));
-	qi.tqi_subtype = subtype;
+	qi.tqi_subtype = subtype_txq_to_hwq[subtype];
 	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
 	qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT;
@@ -940,7 +946,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
 	if (!ATH_TXQ_SETUP(sc, qnum)) {
 	if (!ATH_TXQ_SETUP(sc, qnum)) {
 		struct ath_txq *txq = &sc->tx.txq[qnum];
 		struct ath_txq *txq = &sc->tx.txq[qnum];
 
 
-		txq->axq_class = subtype;
 		txq->axq_qnum = qnum;
 		txq->axq_qnum = qnum;
 		txq->axq_link = NULL;
 		txq->axq_link = NULL;
 		INIT_LIST_HEAD(&txq->axq_q);
 		INIT_LIST_HEAD(&txq->axq_q);
@@ -1148,13 +1153,11 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 		ath_print(common, ATH_DBG_FATAL,
 		ath_print(common, ATH_DBG_FATAL,
 			  "Failed to stop TX DMA. Resetting hardware!\n");
 			  "Failed to stop TX DMA. Resetting hardware!\n");
 
 
-		spin_lock_bh(&sc->sc_resetlock);
 		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
 		if (r)
 		if (r)
 			ath_print(common, ATH_DBG_FATAL,
 			ath_print(common, ATH_DBG_FATAL,
 				  "Unable to reset hardware; reset status %d\n",
 				  "Unable to reset hardware; reset status %d\n",
 				  r);
 				  r);
-		spin_unlock_bh(&sc->sc_resetlock);
 	}
 	}
 
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
@@ -1212,24 +1215,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 	}
 	}
 }
 }
 
 
-int ath_tx_setup(struct ath_softc *sc, int haltype)
-{
-	struct ath_txq *txq;
-
-	if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
-		ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
-			  "HAL AC %u out of range, max %zu!\n",
-			 haltype, ARRAY_SIZE(sc->tx.hwq_map));
-		return 0;
-	}
-	txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
-	if (txq != NULL) {
-		sc->tx.hwq_map[haltype] = txq->axq_qnum;
-		return 1;
-	} else
-		return 0;
-}
-
 /***********/
 /***********/
 /* TX, DMA */
 /* TX, DMA */
 /***********/
 /***********/
@@ -1710,6 +1695,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
 			goto tx_done;
 			goto tx_done;
 		}
 		}
 
 
+		WARN_ON(tid->ac->txq != txctl->txq);
 		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
 		if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
 			/*
 			/*
 			 * Try aggregation if it's a unicast data frame
 			 * Try aggregation if it's a unicast data frame
@@ -1749,6 +1735,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		return -1;
 		return -1;
 	}
 	}
 
 
+	q = skb_get_queue_mapping(skb);
 	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
 	r = ath_tx_setup_buffer(hw, bf, skb, txctl);
 	if (unlikely(r)) {
 	if (unlikely(r)) {
 		ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
 		ath_print(common, ATH_DBG_FATAL, "TX mem alloc failure\n");
@@ -1758,8 +1745,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		 * we will at least have to run TX completionon one buffer
 		 * we will at least have to run TX completionon one buffer
 		 * on the queue */
 		 * on the queue */
 		spin_lock_bh(&txq->axq_lock);
 		spin_lock_bh(&txq->axq_lock);
-		if (!txq->stopped && txq->axq_depth > 1) {
-			ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
+		if (txq == sc->tx.txq_map[q] && !txq->stopped &&
+		    txq->axq_depth > 1) {
+			ath_mac80211_stop_queue(sc, q);
 			txq->stopped = 1;
 			txq->stopped = 1;
 		}
 		}
 		spin_unlock_bh(&txq->axq_lock);
 		spin_unlock_bh(&txq->axq_lock);
@@ -1769,13 +1757,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
 		return r;
 		return r;
 	}
 	}
 
 
-	q = skb_get_queue_mapping(skb);
-	if (q >= 4)
-		q = 0;
-
 	spin_lock_bh(&txq->axq_lock);
 	spin_lock_bh(&txq->axq_lock);
-	if (++sc->tx.pending_frames[q] > ATH_MAX_QDEPTH && !txq->stopped) {
-		ath_mac80211_stop_queue(sc, skb_get_queue_mapping(skb));
+	if (txq == sc->tx.txq_map[q] &&
+	    ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
+		ath_mac80211_stop_queue(sc, q);
 		txq->stopped = 1;
 		txq->stopped = 1;
 	}
 	}
 	spin_unlock_bh(&txq->axq_lock);
 	spin_unlock_bh(&txq->axq_lock);
@@ -1843,7 +1828,8 @@ exit:
 /*****************/
 /*****************/
 
 
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-			    struct ath_wiphy *aphy, int tx_flags)
+			    struct ath_wiphy *aphy, int tx_flags,
+			    struct ath_txq *txq)
 {
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1890,11 +1876,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 		ath9k_tx_status(hw, skb);
 		ath9k_tx_status(hw, skb);
 	else {
 	else {
 		q = skb_get_queue_mapping(skb);
 		q = skb_get_queue_mapping(skb);
-		if (q >= 4)
-			q = 0;
-
-		if (--sc->tx.pending_frames[q] < 0)
-			sc->tx.pending_frames[q] = 0;
+		if (txq == sc->tx.txq_map[q]) {
+			spin_lock_bh(&txq->axq_lock);
+			if (WARN_ON(--txq->pending_frames < 0))
+				txq->pending_frames = 0;
+			spin_unlock_bh(&txq->axq_lock);
+		}
 
 
 		ieee80211_tx_status(hw, skb);
 		ieee80211_tx_status(hw, skb);
 	}
 	}
@@ -1929,8 +1916,8 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 		else
 		else
 			complete(&sc->paprd_complete);
 			complete(&sc->paprd_complete);
 	} else {
 	} else {
-		ath_debug_stat_tx(sc, txq, bf, ts);
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
+		ath_debug_stat_tx(sc, bf, ts);
+		ath_tx_complete(sc, skb, bf->aphy, tx_flags, txq);
 	}
 	}
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
 	 * accidentally reference it later.
 	 * accidentally reference it later.
@@ -2020,16 +2007,13 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 }
 
 
-static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
+static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
 {
 {
-	int qnum;
-
-	qnum = ath_get_mac80211_qnum(txq->axq_class, sc);
-	if (qnum == -1)
-		return;
+	struct ath_txq *txq;
 
 
+	txq = sc->tx.txq_map[qnum];
 	spin_lock_bh(&txq->axq_lock);
 	spin_lock_bh(&txq->axq_lock);
-	if (txq->stopped && sc->tx.pending_frames[qnum] < ATH_MAX_QDEPTH) {
+	if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
 		if (ath_mac80211_start_queue(sc, qnum))
 		if (ath_mac80211_start_queue(sc, qnum))
 			txq->stopped = 0;
 			txq->stopped = 0;
 	}
 	}
@@ -2046,6 +2030,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 	struct ath_tx_status ts;
 	struct ath_tx_status ts;
 	int txok;
 	int txok;
 	int status;
 	int status;
+	int qnum;
 
 
 	ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 	ath_print(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 		  txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
 		  txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
@@ -2121,12 +2106,15 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 			ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
 			ath_tx_rc_status(bf, &ts, txok ? 0 : 1, txok, true);
 		}
 		}
 
 
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
 		if (bf_isampdu(bf))
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok);
 		else
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 
 
-		ath_wake_mac80211_queue(sc, txq);
+		if (txq == sc->tx.txq_map[qnum])
+			ath_wake_mac80211_queue(sc, qnum);
 
 
 		spin_lock_bh(&txq->axq_lock);
 		spin_lock_bh(&txq->axq_lock);
 		if (sc->sc_flags & SC_OP_TXAGGR)
 		if (sc->sc_flags & SC_OP_TXAGGR)
@@ -2196,6 +2184,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 	struct list_head bf_head;
 	struct list_head bf_head;
 	int status;
 	int status;
 	int txok;
 	int txok;
+	int qnum;
 
 
 	for (;;) {
 	for (;;) {
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
@@ -2239,13 +2228,16 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 			ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
 			ath_tx_rc_status(bf, &txs, txok ? 0 : 1, txok, true);
 		}
 		}
 
 
+		qnum = skb_get_queue_mapping(bf->bf_mpdu);
+
 		if (bf_isampdu(bf))
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs, txok);
 		else
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 					    &txs, txok, 0);
 					    &txs, txok, 0);
 
 
-		ath_wake_mac80211_queue(sc, txq);
+		if (txq == sc->tx.txq_map[qnum])
+			ath_wake_mac80211_queue(sc, qnum);
 
 
 		spin_lock_bh(&txq->axq_lock);
 		spin_lock_bh(&txq->axq_lock);
 		if (!list_empty(&txq->txq_fifo_pending)) {
 		if (!list_empty(&txq->txq_fifo_pending)) {
@@ -2377,7 +2369,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
 	for (acno = 0, ac = &an->ac[acno];
 	for (acno = 0, ac = &an->ac[acno];
 	     acno < WME_NUM_AC; acno++, ac++) {
 	     acno < WME_NUM_AC; acno++, ac++) {
 		ac->sched    = false;
 		ac->sched    = false;
-		ac->qnum = sc->tx.hwq_map[acno];
+		ac->txq = sc->tx.txq_map[acno];
 		INIT_LIST_HEAD(&ac->tid_q);
 		INIT_LIST_HEAD(&ac->tid_q);
 	}
 	}
 }
 }
@@ -2387,17 +2379,13 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
 	struct ath_atx_ac *ac;
 	struct ath_atx_ac *ac;
 	struct ath_atx_tid *tid;
 	struct ath_atx_tid *tid;
 	struct ath_txq *txq;
 	struct ath_txq *txq;
-	int i, tidno;
+	int tidno;
 
 
 	for (tidno = 0, tid = &an->tid[tidno];
 	for (tidno = 0, tid = &an->tid[tidno];
 	     tidno < WME_NUM_TID; tidno++, tid++) {
 	     tidno < WME_NUM_TID; tidno++, tid++) {
-		i = tid->ac->qnum;
-
-		if (!ATH_TXQ_SETUP(sc, i))
-			continue;
 
 
-		txq = &sc->tx.txq[i];
 		ac = tid->ac;
 		ac = tid->ac;
+		txq = ac->txq;
 
 
 		spin_lock_bh(&txq->axq_lock);
 		spin_lock_bh(&txq->axq_lock);
 
 

+ 3 - 2
drivers/net/wireless/ath/carl9170/carl9170.h

@@ -48,7 +48,7 @@
 #include <linux/usb.h>
 #include <linux/usb.h>
 #ifdef CONFIG_CARL9170_LEDS
 #ifdef CONFIG_CARL9170_LEDS
 #include <linux/leds.h>
 #include <linux/leds.h>
-#endif /* CONFIG_CARL170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
 #ifdef CONFIG_CARL9170_WPC
 #ifdef CONFIG_CARL9170_WPC
 #include <linux/input.h>
 #include <linux/input.h>
 #endif /* CONFIG_CARL9170_WPC */
 #endif /* CONFIG_CARL9170_WPC */
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
 	CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
 	CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
 	CARL9170_RR_WATCHDOG,
 	CARL9170_RR_WATCHDOG,
 	CARL9170_RR_STUCK_TX,
 	CARL9170_RR_STUCK_TX,
-	CARL9170_RR_SLOW_SYSTEM,
+	CARL9170_RR_UNRESPONSIVE_DEVICE,
 	CARL9170_RR_COMMAND_TIMEOUT,
 	CARL9170_RR_COMMAND_TIMEOUT,
 	CARL9170_RR_TOO_MANY_PHY_ERRORS,
 	CARL9170_RR_TOO_MANY_PHY_ERRORS,
 	CARL9170_RR_LOST_RSP,
 	CARL9170_RR_LOST_RSP,
@@ -287,6 +287,7 @@ struct ar9170 {
 
 
 	/* reset / stuck frames/queue detection */
 	/* reset / stuck frames/queue detection */
 	struct work_struct restart_work;
 	struct work_struct restart_work;
+	struct work_struct ping_work;
 	unsigned int restart_counter;
 	unsigned int restart_counter;
 	unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
 	unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
 	unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
 	unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];

+ 9 - 4
drivers/net/wireless/ath/carl9170/fwcmd.h

@@ -97,13 +97,13 @@ struct carl9170_set_key_cmd {
 	__le16		type;
 	__le16		type;
 	u8		macAddr[6];
 	u8		macAddr[6];
 	u32		key[4];
 	u32		key[4];
-} __packed;
+} __packed __aligned(4);
 #define CARL9170_SET_KEY_CMD_SIZE		28
 #define CARL9170_SET_KEY_CMD_SIZE		28
 
 
 struct carl9170_disable_key_cmd {
 struct carl9170_disable_key_cmd {
 	__le16		user;
 	__le16		user;
 	__le16		padding;
 	__le16		padding;
-} __packed;
+} __packed __aligned(4);
 #define CARL9170_DISABLE_KEY_CMD_SIZE		4
 #define CARL9170_DISABLE_KEY_CMD_SIZE		4
 
 
 struct carl9170_u32_list {
 struct carl9170_u32_list {
@@ -206,7 +206,7 @@ struct carl9170_cmd {
 		struct carl9170_rx_filter_cmd	rx_filter;
 		struct carl9170_rx_filter_cmd	rx_filter;
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 	} __packed;
 	} __packed;
-} __packed;
+} __packed __aligned(4);
 
 
 #define	CARL9170_TX_STATUS_QUEUE	3
 #define	CARL9170_TX_STATUS_QUEUE	3
 #define	CARL9170_TX_STATUS_QUEUE_S	0
 #define	CARL9170_TX_STATUS_QUEUE_S	0
@@ -216,6 +216,7 @@ struct carl9170_cmd {
 #define	CARL9170_TX_STATUS_TRIES	(7 << CARL9170_TX_STATUS_TRIES_S)
 #define	CARL9170_TX_STATUS_TRIES	(7 << CARL9170_TX_STATUS_TRIES_S)
 #define	CARL9170_TX_STATUS_SUCCESS	0x80
 #define	CARL9170_TX_STATUS_SUCCESS	0x80
 
 
+#ifdef __CARL9170FW__
 /*
 /*
  * NOTE:
  * NOTE:
  * Both structs [carl9170_tx_status and _carl9170_tx_status]
  * Both structs [carl9170_tx_status and _carl9170_tx_status]
@@ -232,6 +233,8 @@ struct carl9170_tx_status {
 	u8 tries:3;
 	u8 tries:3;
 	u8 success:1;
 	u8 success:1;
 } __packed;
 } __packed;
+#endif /* __CARL9170FW__ */
+
 struct _carl9170_tx_status {
 struct _carl9170_tx_status {
 	/*
 	/*
 	 * This version should be immune to all alignment bugs.
 	 * This version should be immune to all alignment bugs.
@@ -272,13 +275,15 @@ struct carl9170_rsp {
 		struct carl9170_rf_init_result	rf_init_res;
 		struct carl9170_rf_init_result	rf_init_res;
 		struct carl9170_u32_list	rreg_res;
 		struct carl9170_u32_list	rreg_res;
 		struct carl9170_u32_list	echo;
 		struct carl9170_u32_list	echo;
+#ifdef __CARL9170FW__
 		struct carl9170_tx_status	tx_status[0];
 		struct carl9170_tx_status	tx_status[0];
+#endif /* __CARL9170FW__ */
 		struct _carl9170_tx_status	_tx_status[0];
 		struct _carl9170_tx_status	_tx_status[0];
 		struct carl9170_gpio		gpio;
 		struct carl9170_gpio		gpio;
 		struct carl9170_tsf_rsp		tsf;
 		struct carl9170_tsf_rsp		tsf;
 		struct carl9170_psm		psm;
 		struct carl9170_psm		psm;
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 		u8 data[CARL9170_MAX_CMD_PAYLOAD_LEN];
 	} __packed;
 	} __packed;
-} __packed;
+} __packed __aligned(4);
 
 
 #endif /* __CARL9170_SHARED_FWCMD_H */
 #endif /* __CARL9170_SHARED_FWCMD_H */

+ 6 - 1
drivers/net/wireless/ath/carl9170/hw.h

@@ -712,7 +712,8 @@ struct ar9170_stream {
 	__le16 tag;
 	__le16 tag;
 
 
 	u8 payload[0];
 	u8 payload[0];
-};
+} __packed __aligned(4);
+#define AR9170_STREAM_LEN				4
 
 
 #define AR9170_MAX_ACKTABLE_ENTRIES			8
 #define AR9170_MAX_ACKTABLE_ENTRIES			8
 #define AR9170_MAX_VIRTUAL_MAC				7
 #define AR9170_MAX_VIRTUAL_MAC				7
@@ -736,4 +737,8 @@ struct ar9170_stream {
 
 
 #define MOD_VAL(reg, value, newvalue)					\
 #define MOD_VAL(reg, value, newvalue)					\
 	(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
 	(((value) & ~reg) | (((newvalue) << reg##_S) & reg))
+
+#define GET_VAL(reg, value)						\
+	(((value) & reg) >> reg##_S)
+
 #endif	/* __CARL9170_SHARED_HW_H */
 #endif	/* __CARL9170_SHARED_HW_H */

+ 34 - 22
drivers/net/wireless/ath/carl9170/mac.c

@@ -205,8 +205,8 @@ int carl9170_init_mac(struct ar9170 *ar)
 	carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
 	carl9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105);
 
 
 	/* Aggregation MAX number and timeout */
 	/* Aggregation MAX number and timeout */
-	carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0xa);
-	carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a00);
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_FACTOR, 0x8000a);
+	carl9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, 0x140a07);
 
 
 	carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
 	carl9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER,
 			  AR9170_MAC_FTF_DEFAULTS);
 			  AR9170_MAC_FTF_DEFAULTS);
@@ -457,8 +457,9 @@ int carl9170_set_beacon_timers(struct ar9170 *ar)
 
 
 int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
 int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
 {
 {
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
 	struct carl9170_vif_info *cvif;
 	struct carl9170_vif_info *cvif;
+	struct ieee80211_tx_info *txinfo;
 	__le32 *data, *old = NULL;
 	__le32 *data, *old = NULL;
 	u32 word, off, addr, len;
 	u32 word, off, addr, len;
 	int i = 0, err = 0;
 	int i = 0, err = 0;
@@ -487,7 +488,13 @@ found:
 
 
 	if (!skb) {
 	if (!skb) {
 		err = -ENOMEM;
 		err = -ENOMEM;
-		goto out_unlock;
+		goto err_free;
+	}
+
+	txinfo = IEEE80211_SKB_CB(skb);
+	if (txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS) {
+		err = -EINVAL;
+		goto err_free;
 	}
 	}
 
 
 	spin_lock_bh(&ar->beacon_lock);
 	spin_lock_bh(&ar->beacon_lock);
@@ -504,11 +511,8 @@ found:
 			wiphy_err(ar->hw->wiphy, "beacon does not "
 			wiphy_err(ar->hw->wiphy, "beacon does not "
 				  "fit into device memory!\n");
 				  "fit into device memory!\n");
 		}
 		}
-
-		spin_unlock_bh(&ar->beacon_lock);
-		dev_kfree_skb_any(skb);
 		err = -EINVAL;
 		err = -EINVAL;
-		goto out_unlock;
+		goto err_unlock;
 	}
 	}
 
 
 	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
 	if (len > AR9170_MAC_BCN_LENGTH_MAX) {
@@ -518,22 +522,22 @@ found:
 				 AR9170_MAC_BCN_LENGTH_MAX, len);
 				 AR9170_MAC_BCN_LENGTH_MAX, len);
 		}
 		}
 
 
-		spin_unlock_bh(&ar->beacon_lock);
-		dev_kfree_skb_any(skb);
 		err = -EMSGSIZE;
 		err = -EMSGSIZE;
-		goto out_unlock;
+		goto err_unlock;
 	}
 	}
 
 
-	carl9170_async_regwrite_begin(ar);
+	i = txinfo->control.rates[0].idx;
+	if (txinfo->band != IEEE80211_BAND_2GHZ)
+		i += 4;
 
 
-	/* XXX: use skb->cb info */
-	if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) {
-		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + FCS_LEN) << (3 + 16)) + 0x0400);
-	} else {
-		carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP,
-				((skb->len + FCS_LEN) << 16) + 0x001b);
-	}
+	word = __carl9170_ratetable[i].hw_value & 0xf;
+	if (i < 4)
+		word |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
+	else
+		word |= ((skb->len + FCS_LEN) << 16) + 0x0010;
+
+	carl9170_async_regwrite_begin(ar);
+	carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, word);
 
 
 	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
 	for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
 		/*
 		/*
@@ -557,7 +561,7 @@ found:
 		cvif->beacon = skb;
 		cvif->beacon = skb;
 	spin_unlock_bh(&ar->beacon_lock);
 	spin_unlock_bh(&ar->beacon_lock);
 	if (err)
 	if (err)
-		goto out_unlock;
+		goto err_free;
 
 
 	if (submit) {
 	if (submit) {
 		err = carl9170_bcn_ctrl(ar, cvif->id,
 		err = carl9170_bcn_ctrl(ar, cvif->id,
@@ -565,10 +569,18 @@ found:
 					addr, skb->len + FCS_LEN);
 					addr, skb->len + FCS_LEN);
 
 
 		if (err)
 		if (err)
-			goto out_unlock;
+			goto err_free;
 	}
 	}
 out_unlock:
 out_unlock:
 	rcu_read_unlock();
 	rcu_read_unlock();
+	return 0;
+
+err_unlock:
+	spin_unlock_bh(&ar->beacon_lock);
+
+err_free:
+	rcu_read_unlock();
+	dev_kfree_skb_any(skb);
 	return err;
 	return err;
 }
 }
 
 

+ 18 - 1
drivers/net/wireless/ath/carl9170/main.c

@@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar)
 	cancel_delayed_work_sync(&ar->led_work);
 	cancel_delayed_work_sync(&ar->led_work);
 #endif /* CONFIG_CARL9170_LEDS */
 #endif /* CONFIG_CARL9170_LEDS */
 	cancel_work_sync(&ar->ps_work);
 	cancel_work_sync(&ar->ps_work);
+	cancel_work_sync(&ar->ping_work);
 	cancel_work_sync(&ar->ampdu_work);
 	cancel_work_sync(&ar->ampdu_work);
 }
 }
 
 
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
 	 */
 	 */
 }
 }
 
 
+static void carl9170_ping_work(struct work_struct *work)
+{
+	struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
+	int err;
+
+	if (!IS_STARTED(ar))
+		return;
+
+	mutex_lock(&ar->mutex);
+	err = carl9170_echo_test(ar, 0xdeadbeef);
+	if (err)
+		carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
+	mutex_unlock(&ar->mutex);
+}
+
 static int carl9170_init_interface(struct ar9170 *ar,
 static int carl9170_init_interface(struct ar9170 *ar,
 				   struct ieee80211_vif *vif)
 				   struct ieee80211_vif *vif)
 {
 {
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
 		skb_queue_head_init(&ar->tx_pending[i]);
 		skb_queue_head_init(&ar->tx_pending[i]);
 	}
 	}
 	INIT_WORK(&ar->ps_work, carl9170_ps_work);
 	INIT_WORK(&ar->ps_work, carl9170_ps_work);
+	INIT_WORK(&ar->ping_work, carl9170_ping_work);
 	INIT_WORK(&ar->restart_work, carl9170_restart_work);
 	INIT_WORK(&ar->restart_work, carl9170_restart_work);
 	INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
 	INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
 	INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
 	INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
@@ -1828,7 +1845,7 @@ int carl9170_register(struct ar9170 *ar)
 	err = carl9170_led_register(ar);
 	err = carl9170_led_register(ar);
 	if (err)
 	if (err)
 		goto err_unreg;
 		goto err_unreg;
-#endif /* CONFIG_CAR9L170_LEDS */
+#endif /* CONFIG_CARL9170_LEDS */
 
 
 #ifdef CONFIG_CARL9170_WPC
 #ifdef CONFIG_CARL9170_WPC
 	err = carl9170_register_wps_button(ar);
 	err = carl9170_register_wps_button(ar);

+ 4 - 13
drivers/net/wireless/ath/carl9170/phy.c

@@ -1554,15 +1554,6 @@ static int carl9170_set_power_cal(struct ar9170 *ar, u32 freq,
 	return carl9170_regwrite_result();
 	return carl9170_regwrite_result();
 }
 }
 
 
-/* TODO: replace this with sign_extend32(noise, 8) */
-static int carl9170_calc_noise_dbm(u32 raw_noise)
-{
-	if (raw_noise & 0x100)
-		return ~0x1ff | raw_noise;
-	else
-		return raw_noise;
-}
-
 int carl9170_get_noisefloor(struct ar9170 *ar)
 int carl9170_get_noisefloor(struct ar9170 *ar)
 {
 {
 	static const u32 phy_regs[] = {
 	static const u32 phy_regs[] = {
@@ -1578,11 +1569,11 @@ int carl9170_get_noisefloor(struct ar9170 *ar)
 		return err;
 		return err;
 
 
 	for (i = 0; i < 2; i++) {
 	for (i = 0; i < 2; i++) {
-		ar->noise[i] = carl9170_calc_noise_dbm(
-			(phy_res[i] >> 19) & 0x1ff);
+		ar->noise[i] = sign_extend32(GET_VAL(
+			AR9170_PHY_CCA_MIN_PWR, phy_res[i]), 8);
 
 
-		ar->noise[i + 2] = carl9170_calc_noise_dbm(
-			(phy_res[i + 2] >> 23) & 0x1ff);
+		ar->noise[i + 2] = sign_extend32(GET_VAL(
+			AR9170_PHY_EXT_CCA_MIN_PWR, phy_res[i + 2]), 8);
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 12 - 12
drivers/net/wireless/ath/carl9170/phy.h

@@ -139,8 +139,8 @@
 #define		AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF	0x00020000
 #define		AR9170_PHY_AGC_CONTROL_NO_UPDATE_NF	0x00020000
 
 
 #define	AR9170_PHY_REG_CCA			(AR9170_PHY_REG_BASE + 0x0064)
 #define	AR9170_PHY_REG_CCA			(AR9170_PHY_REG_BASE + 0x0064)
-#define		AR9170_PHY_CCA_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CCA_MINCCA_PWR_S		19
+#define		AR9170_PHY_CCA_MIN_PWR			0x0ff80000
+#define		AR9170_PHY_CCA_MIN_PWR_S		19
 #define		AR9170_PHY_CCA_THRESH62			0x0007f000
 #define		AR9170_PHY_CCA_THRESH62			0x0007f000
 #define		AR9170_PHY_CCA_THRESH62_S		12
 #define		AR9170_PHY_CCA_THRESH62_S		12
 
 
@@ -338,8 +338,8 @@
 #define		AR9170_PHY_EXT_CCA_CYCPWR_THR1_S	9
 #define		AR9170_PHY_EXT_CCA_CYCPWR_THR1_S	9
 #define		AR9170_PHY_EXT_CCA_THRESH62		0x007f0000
 #define		AR9170_PHY_EXT_CCA_THRESH62		0x007f0000
 #define		AR9170_PHY_EXT_CCA_THRESH62_S		16
 #define		AR9170_PHY_EXT_CCA_THRESH62_S		16
-#define		AR9170_PHY_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_EXT_CCA_MIN_PWR_S		23
 
 
 #define	AR9170_PHY_REG_SFCORR_EXT		(AR9170_PHY_REG_BASE + 0x01c0)
 #define	AR9170_PHY_REG_SFCORR_EXT		(AR9170_PHY_REG_BASE + 0x01c0)
 #define		AR9170_PHY_SFCORR_EXT_M1_THRESH		0x0000007f
 #define		AR9170_PHY_SFCORR_EXT_M1_THRESH		0x0000007f
@@ -546,19 +546,19 @@
 #define		AR9170_PHY_FORCE_XPA_CFG_S		0
 #define		AR9170_PHY_FORCE_XPA_CFG_S		0
 
 
 #define	AR9170_PHY_REG_CH1_CCA			(AR9170_PHY_REG_BASE + 0x1064)
 #define	AR9170_PHY_REG_CH1_CCA			(AR9170_PHY_REG_BASE + 0x1064)
-#define		AR9170_PHY_CH1_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CH1_MINCCA_PWR_S		19
+#define		AR9170_PHY_CH1_CCA_MIN_PWR		0x0ff80000
+#define		AR9170_PHY_CH1_CCA_MIN_PWR_S		19
 
 
 #define	AR9170_PHY_REG_CH2_CCA			(AR9170_PHY_REG_BASE + 0x2064)
 #define	AR9170_PHY_REG_CH2_CCA			(AR9170_PHY_REG_BASE + 0x2064)
-#define		AR9170_PHY_CH2_MINCCA_PWR		0x0ff80000
-#define		AR9170_PHY_CH2_MINCCA_PWR_S		19
+#define		AR9170_PHY_CH2_CCA_MIN_PWR		0x0ff80000
+#define		AR9170_PHY_CH2_CCA_MIN_PWR_S		19
 
 
 #define	AR9170_PHY_REG_CH1_EXT_CCA		(AR9170_PHY_REG_BASE + 0x11bc)
 #define	AR9170_PHY_REG_CH1_EXT_CCA		(AR9170_PHY_REG_BASE + 0x11bc)
-#define		AR9170_PHY_CH1_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_CH1_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_CH1_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_CH1_EXT_CCA_MIN_PWR_S	23
 
 
 #define	AR9170_PHY_REG_CH2_EXT_CCA		(AR9170_PHY_REG_BASE + 0x21bc)
 #define	AR9170_PHY_REG_CH2_EXT_CCA		(AR9170_PHY_REG_BASE + 0x21bc)
-#define		AR9170_PHY_CH2_EXT_MINCCA_PWR		0xff800000
-#define		AR9170_PHY_CH2_EXT_MINCCA_PWR_S		23
+#define		AR9170_PHY_CH2_EXT_CCA_MIN_PWR		0xff800000
+#define		AR9170_PHY_CH2_EXT_CCA_MIN_PWR_S	23
 
 
 #endif	/* __CARL9170_SHARED_PHY_H */
 #endif	/* __CARL9170_SHARED_PHY_H */

+ 67 - 13
drivers/net/wireless/ath/carl9170/tx.c

@@ -242,9 +242,11 @@ static void carl9170_tx_release(struct kref *ref)
 			ar->tx_ampdu_schedule = true;
 			ar->tx_ampdu_schedule = true;
 
 
 		if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
 		if (txinfo->flags & IEEE80211_TX_STAT_AMPDU) {
-			txinfo->status.ampdu_len = txinfo->pad[0];
-			txinfo->status.ampdu_ack_len = txinfo->pad[1];
-			txinfo->pad[0] = txinfo->pad[1] = 0;
+			struct _carl9170_tx_superframe *super;
+
+			super = (void *)skb->data;
+			txinfo->status.ampdu_len = super->s.rix;
+			txinfo->status.ampdu_ack_len = super->s.cnt;
 		} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
 		} else if (txinfo->flags & IEEE80211_TX_STAT_ACK) {
 			/*
 			/*
 			 * drop redundant tx_status reports:
 			 * drop redundant tx_status reports:
@@ -337,7 +339,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
 	u8 tid;
 	u8 tid;
 
 
 	if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
 	if (!(txinfo->flags & IEEE80211_TX_CTL_AMPDU) ||
-	    txinfo->flags & IEEE80211_TX_CTL_INJECTED)
+	    txinfo->flags & IEEE80211_TX_CTL_INJECTED ||
+	   (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR))))
 		return;
 		return;
 
 
 	tx_info = IEEE80211_SKB_CB(skb);
 	tx_info = IEEE80211_SKB_CB(skb);
@@ -389,8 +392,8 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar,
 		sta_info->stats[tid].ampdu_ack_len++;
 		sta_info->stats[tid].ampdu_ack_len++;
 
 
 	if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
 	if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
-		txinfo->pad[0] = sta_info->stats[tid].ampdu_len;
-		txinfo->pad[1] = sta_info->stats[tid].ampdu_ack_len;
+		super->s.rix = sta_info->stats[tid].ampdu_len;
+		super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
 		txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
 		txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
 		sta_info->stats[tid].clear = true;
 		sta_info->stats[tid].clear = true;
 	}
 	}
@@ -524,6 +527,59 @@ next:
 	}
 	}
 }
 }
 
 
+static void carl9170_tx_ampdu_timeout(struct ar9170 *ar)
+{
+	struct carl9170_sta_tid *iter;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *txinfo;
+	struct carl9170_tx_info *arinfo;
+	struct _carl9170_tx_superframe *super;
+	struct ieee80211_sta *sta;
+	struct ieee80211_vif *vif;
+	struct ieee80211_hdr *hdr;
+	unsigned int vif_id;
+
+	rcu_read_lock();
+	list_for_each_entry_rcu(iter, &ar->tx_ampdu_list, list) {
+		if (iter->state < CARL9170_TID_STATE_IDLE)
+			continue;
+
+		spin_lock_bh(&iter->lock);
+		skb = skb_peek(&iter->queue);
+		if (!skb)
+			goto unlock;
+
+		txinfo = IEEE80211_SKB_CB(skb);
+		arinfo = (void *)txinfo->rate_driver_data;
+		if (time_is_after_jiffies(arinfo->timeout +
+		    msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)))
+			goto unlock;
+
+		super = (void *) skb->data;
+		hdr = (void *) super->frame_data;
+
+		vif_id = (super->s.misc & CARL9170_TX_SUPER_MISC_VIF_ID) >>
+			 CARL9170_TX_SUPER_MISC_VIF_ID_S;
+
+		if (WARN_ON(vif_id >= AR9170_MAX_VIRTUAL_MAC))
+			goto unlock;
+
+		vif = rcu_dereference(ar->vif_priv[vif_id].vif);
+		if (WARN_ON(!vif))
+			goto unlock;
+
+		sta = ieee80211_find_sta(vif, hdr->addr1);
+		if (WARN_ON(!sta))
+			goto unlock;
+
+		ieee80211_stop_tx_ba_session(sta, iter->tid);
+unlock:
+		spin_unlock_bh(&iter->lock);
+
+	}
+	rcu_read_unlock();
+}
+
 void carl9170_tx_janitor(struct work_struct *work)
 void carl9170_tx_janitor(struct work_struct *work)
 {
 {
 	struct ar9170 *ar = container_of(work, struct ar9170,
 	struct ar9170 *ar = container_of(work, struct ar9170,
@@ -534,6 +590,7 @@ void carl9170_tx_janitor(struct work_struct *work)
 	ar->tx_janitor_last_run = jiffies;
 	ar->tx_janitor_last_run = jiffies;
 
 
 	carl9170_check_queue_stop_timeout(ar);
 	carl9170_check_queue_stop_timeout(ar);
+	carl9170_tx_ampdu_timeout(ar);
 
 
 	if (!atomic_read(&ar->tx_total_queued))
 	if (!atomic_read(&ar->tx_total_queued))
 		return;
 		return;
@@ -842,10 +899,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
 		if (unlikely(!sta || !cvif))
 		if (unlikely(!sta || !cvif))
 			goto err_out;
 			goto err_out;
 
 
-		factor = min_t(unsigned int, 1u,
-			 info->control.sta->ht_cap.ampdu_factor);
-
-		density = info->control.sta->ht_cap.ampdu_density;
+		factor = min_t(unsigned int, 1u, sta->ht_cap.ampdu_factor);
+		density = sta->ht_cap.ampdu_density;
 
 
 		if (density) {
 		if (density) {
 			/*
 			/*
@@ -1206,6 +1261,7 @@ static void carl9170_tx(struct ar9170 *ar)
 static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
 static bool carl9170_tx_ampdu_queue(struct ar9170 *ar,
 	struct ieee80211_sta *sta, struct sk_buff *skb)
 	struct ieee80211_sta *sta, struct sk_buff *skb)
 {
 {
+	struct _carl9170_tx_superframe *super = (void *) super;
 	struct carl9170_sta_info *sta_info;
 	struct carl9170_sta_info *sta_info;
 	struct carl9170_sta_tid *agg;
 	struct carl9170_sta_tid *agg;
 	struct sk_buff *iter;
 	struct sk_buff *iter;
@@ -1274,6 +1330,7 @@ err_unlock:
 
 
 err_unlock_rcu:
 err_unlock_rcu:
 	rcu_read_unlock();
 	rcu_read_unlock();
+	super->f.mac_control &= ~cpu_to_le16(AR9170_TX_MAC_AGGR);
 	carl9170_tx_status(ar, skb, false);
 	carl9170_tx_status(ar, skb, false);
 	ar->tx_dropped++;
 	ar->tx_dropped++;
 	return false;
 	return false;
@@ -1302,9 +1359,6 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 */
 	 */
 
 
 	if (info->flags & IEEE80211_TX_CTL_AMPDU) {
 	if (info->flags & IEEE80211_TX_CTL_AMPDU) {
-		if (WARN_ON_ONCE(!sta))
-			goto err_free;
-
 		run = carl9170_tx_ampdu_queue(ar, sta, skb);
 		run = carl9170_tx_ampdu_queue(ar, sta, skb);
 		if (run)
 		if (run)
 			carl9170_tx_ampdu(ar);
 			carl9170_tx_ampdu(ar);

+ 1 - 1
drivers/net/wireless/ath/carl9170/usb.c

@@ -433,7 +433,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
 			 * device.
 			 * device.
 			 */
 			 */
 
 
-			carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
+			ieee80211_queue_work(ar->hw, &ar->ping_work);
 		}
 		}
 	} else {
 	} else {
 		/*
 		/*

+ 3 - 3
drivers/net/wireless/ath/carl9170/version.h

@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
 #define CARL9170FW_VERSION_YEAR 10
 #define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 9
-#define CARL9170FW_VERSION_DAY 28
-#define CARL9170FW_VERSION_GIT "1.8.8.3"
+#define CARL9170FW_VERSION_MONTH 10
+#define CARL9170FW_VERSION_DAY 29
+#define CARL9170FW_VERSION_GIT "1.9.0"
 #endif /* __CARL9170_SHARED_VERSION_H */
 #endif /* __CARL9170_SHARED_VERSION_H */

+ 2 - 0
drivers/net/wireless/ath/debug.h

@@ -70,11 +70,13 @@ enum ATH_DEBUG {
 #ifdef CONFIG_ATH_DEBUG
 #ifdef CONFIG_ATH_DEBUG
 void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
 void ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
 	__attribute__ ((format (printf, 3, 4)));
 	__attribute__ ((format (printf, 3, 4)));
+#define ATH_DBG_WARN(foo, arg...) WARN(foo, arg)
 #else
 #else
 static inline void __attribute__ ((format (printf, 3, 4)))
 static inline void __attribute__ ((format (printf, 3, 4)))
 ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
 ath_print(struct ath_common *common, int dbg_mask, const char *fmt, ...)
 {
 {
 }
 }
+#define ATH_DBG_WARN(foo, arg)
 #endif /* CONFIG_ATH_DEBUG */
 #endif /* CONFIG_ATH_DEBUG */
 
 
 /** Returns string describing opmode, or NULL if unknown mode. */
 /** Returns string describing opmode, or NULL if unknown mode. */

+ 5 - 4
drivers/net/wireless/ath/key.c

@@ -67,7 +67,8 @@ bool ath_hw_keyreset(struct ath_common *common, u16 entry)
 }
 }
 EXPORT_SYMBOL(ath_hw_keyreset);
 EXPORT_SYMBOL(ath_hw_keyreset);
 
 
-bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
+static bool ath_hw_keysetmac(struct ath_common *common,
+			     u16 entry, const u8 *mac)
 {
 {
 	u32 macHi, macLo;
 	u32 macHi, macLo;
 	u32 unicast_flag = AR_KEYTABLE_VALID;
 	u32 unicast_flag = AR_KEYTABLE_VALID;
@@ -107,9 +108,9 @@ bool ath_hw_keysetmac(struct ath_common *common, u16 entry, const u8 *mac)
 	return true;
 	return true;
 }
 }
 
 
-bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
-				 const struct ath_keyval *k,
-				 const u8 *mac)
+static bool ath_hw_set_keycache_entry(struct ath_common *common, u16 entry,
+				      const struct ath_keyval *k,
+				      const u8 *mac)
 {
 {
 	void *ah = common->ah;
 	void *ah = common->ah;
 	u32 key0, key1, key2, key3, key4;
 	u32 key0, key1, key2, key3, key4;

+ 13 - 0
drivers/net/wireless/b43/b43.h

@@ -153,6 +153,19 @@
 #define B43_BFH_FEM_BT			0x0040	/* has FEM and switch to share antenna
 #define B43_BFH_FEM_BT			0x0040	/* has FEM and switch to share antenna
 						 * with bluetooth */
 						 * with bluetooth */
 
 
+/* SPROM boardflags2_lo values */
+#define B43_BFL2_RXBB_INT_REG_DIS	0x0001	/* external RX BB regulator present */
+#define B43_BFL2_APLL_WAR		0x0002	/* alternative A-band PLL settings implemented */
+#define B43_BFL2_TXPWRCTRL_EN 		0x0004	/* permits enabling TX Power Control */
+#define B43_BFL2_2X4_DIV		0x0008	/* 2x4 diversity switch */
+#define B43_BFL2_5G_PWRGAIN		0x0010	/* supports 5G band power gain */
+#define B43_BFL2_PCIEWAR_OVR		0x0020	/* overrides ASPM and Clkreq settings */
+#define B43_BFL2_CAESERS_BRD		0x0040	/* is Caesers board (unused) */
+#define B43_BFL2_BTC3WIRE		0x0080	/* used 3-wire bluetooth coexist */
+#define B43_BFL2_SKWRKFEM_BRD		0x0100	/* 4321mcm93 uses Skyworks FEM */
+#define B43_BFL2_SPUR_WAR		0x0200	/* has a workaround for clock-harmonic spurs */
+#define B43_BFL2_GPLL_WAR		0x0400	/* altenative G-band PLL settings implemented */
+
 /* GPIO register offset, in both ChipCommon and PCI core. */
 /* GPIO register offset, in both ChipCommon and PCI core. */
 #define B43_GPIO_CONTROL		0x6c
 #define B43_GPIO_CONTROL		0x6c
 
 

+ 0 - 5
drivers/net/wireless/b43/dma.c

@@ -415,11 +415,6 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
 
 
 static void free_ringmemory(struct b43_dmaring *ring)
 static void free_ringmemory(struct b43_dmaring *ring)
 {
 {
-	gfp_t flags = GFP_KERNEL;
-
-	if (ring->type == B43_DMA_64BIT)
-		flags |= GFP_DMA;
-
 	dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
 	dma_free_coherent(ring->dev->dev->dma_dev, B43_DMA_RINGMEMSIZE,
 			  ring->descbase, ring->dmabase);
 			  ring->descbase, ring->dmabase);
 }
 }

+ 9 - 5
drivers/net/wireless/b43/phy_n.c

@@ -191,7 +191,8 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
 				binfo->type != 0x46D ||
 				binfo->type != 0x46D ||
 				binfo->rev < 0x41);
 				binfo->rev < 0x41);
 	else
 	else
-		workaround = ((sprom->boardflags_hi & B43_BFH_NOPA) == 0);
+		workaround =
+			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
 
 
 	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
 	b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
 	if (workaround) {
 	if (workaround) {
@@ -240,10 +241,13 @@ static void b43_radio_init2055_post(struct b43_wldev *dev)
 static void b43_radio_init2055(struct b43_wldev *dev)
 static void b43_radio_init2055(struct b43_wldev *dev)
 {
 {
 	b43_radio_init2055_pre(dev);
 	b43_radio_init2055_pre(dev);
-	if (b43_status(dev) < B43_STAT_INITIALIZED)
-		b2055_upload_inittab(dev, 0, 1);
-	else
-		b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0);
+	if (b43_status(dev) < B43_STAT_INITIALIZED) {
+		/* Follow wl, not specs. Do not force uploading all regs */
+		b2055_upload_inittab(dev, 0, 0);
+	} else {
+		bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
+		b2055_upload_inittab(dev, ghz5, 0);
+	}
 	b43_radio_init2055_post(dev);
 	b43_radio_init2055_post(dev);
 }
 }
 
 

+ 5 - 3
drivers/net/wireless/b43/radio_2055.c

@@ -244,7 +244,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = {
   [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xCB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xCC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C1_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xCE]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xCE]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
   [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xCF]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD0]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
   [0xD1]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
@@ -256,7 +256,7 @@ static const struct b2055_inittab_entry b2055_inittab [] = {
   [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD7]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xD8]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [B2055_C2_LNA_GAINBST]	= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
-  [0xDA]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
+  [0xDA]			= { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, },
   [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDB]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDC]			= { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, },
   [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
   [0xDD]			= { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, },
@@ -1299,7 +1299,7 @@ void b2055_upload_inittab(struct b43_wldev *dev,
 			  bool ghz5, bool ignore_uploadflag)
 			  bool ghz5, bool ignore_uploadflag)
 {
 {
 	const struct b2055_inittab_entry *e;
 	const struct b2055_inittab_entry *e;
-	unsigned int i;
+	unsigned int i, writes = 0;
 	u16 value;
 	u16 value;
 
 
 	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
 	for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) {
@@ -1312,6 +1312,8 @@ void b2055_upload_inittab(struct b43_wldev *dev,
 			else
 			else
 				value = e->ghz2;
 				value = e->ghz2;
 			b43_radio_write16(dev, i, value);
 			b43_radio_write16(dev, i, value);
+			if (++writes % 4 == 0)
+				b43_read32(dev, B43_MMIO_MACCTL); /* flush */
 		}
 		}
 	}
 	}
 }
 }

+ 51 - 0
drivers/net/wireless/b43/radio_2056.c

@@ -24,9 +24,60 @@
 #include "radio_2056.h"
 #include "radio_2056.h"
 #include "phy_common.h"
 #include "phy_common.h"
 
 
+#define RADIOREGS3(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
+		   r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
+		   r20, r21, r22, r23, r24, r25, r26, r27, r28, r29, \
+		   r30, r31, r32, r33, r34, r35, r36) \
+	.radio_syn_pll_vcocal1		= r00,	\
+	.radio_syn_pll_vcocal2		= r01,	\
+	.radio_syn_pll_refdiv		= r02,	\
+	.radio_syn_pll_mmd2		= r03,	\
+	.radio_syn_pll_mmd1		= r04,	\
+	.radio_syn_pll_loopfilter1	= r05,	\
+	.radio_syn_pll_loopfilter2	= r06,	\
+	.radio_syn_pll_loopfilter3	= r07,	\
+	.radio_syn_pll_loopfilter4	= r08,	\
+	.radio_syn_pll_loopfilter5	= r09,	\
+	.radio_syn_reserved_addr27	= r10,	\
+	.radio_syn_reserved_addr28	= r11,	\
+	.radio_syn_reserved_addr29	= r12,	\
+	.radio_syn_logen_vcobuf1	= r13,	\
+	.radio_syn_logen_mixer2		= r14,	\
+	.radio_syn_logen_buf3		= r15,	\
+	.radio_syn_logen_buf4		= r16,	\
+	.radio_rx0_lnaa_tune		= r17,	\
+	.radio_rx0_lnag_tune		= r18,	\
+	.radio_tx0_intpaa_boost_tune	= r19,	\
+	.radio_tx0_intpag_boost_tune	= r20,	\
+	.radio_tx0_pada_boost_tune	= r21,	\
+	.radio_tx0_padg_boost_tune	= r22,	\
+	.radio_tx0_pgaa_boost_tune	= r23,	\
+	.radio_tx0_pgag_boost_tune	= r24,	\
+	.radio_tx0_mixa_boost_tune	= r25,	\
+	.radio_tx0_mixg_boost_tune	= r26,	\
+	.radio_rx1_lnaa_tune		= r27,	\
+	.radio_rx1_lnag_tune		= r28,	\
+	.radio_tx1_intpaa_boost_tune	= r29,	\
+	.radio_tx1_intpag_boost_tune	= r30,	\
+	.radio_tx1_pada_boost_tune	= r31,	\
+	.radio_tx1_padg_boost_tune	= r32,	\
+	.radio_tx1_pgaa_boost_tune	= r33,	\
+	.radio_tx1_pgag_boost_tune	= r34,	\
+	.radio_tx1_mixa_boost_tune	= r35,	\
+	.radio_tx1_mixg_boost_tune	= r36
+
+#define PHYREGS(r0, r1, r2, r3, r4, r5)	\
+	.phy_regs.phy_bw1a	= r0,	\
+	.phy_regs.phy_bw2	= r1,	\
+	.phy_regs.phy_bw3	= r2,	\
+	.phy_regs.phy_bw4	= r3,	\
+	.phy_regs.phy_bw5	= r4,	\
+	.phy_regs.phy_bw6	= r5
+
 static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
 static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_rev3[] = {
 };
 };
 
 
+/* TODO: add support for rev4+ devices by searching in rev4+ tables */
 const struct b43_nphy_channeltab_entry_rev3 *
 const struct b43_nphy_channeltab_entry_rev3 *
 b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
 b43_nphy_get_chantabent_rev3(struct b43_wldev *dev, u16 freq)
 {
 {

+ 1078 - 3
drivers/net/wireless/b43/radio_2056.h

@@ -4,6 +4,9 @@
 
 
   Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
   Copyright (c) 2010 Rafał Miłecki <zajec5@gmail.com>
 
 
+  Some parts of the code in this file are derived from the brcm80211
+  driver  Copyright (c) 2010 Broadcom Corporation
+
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   the Free Software Foundation; either version 2 of the License, or
@@ -28,13 +31,1085 @@
 
 
 #include "tables_nphy.h"
 #include "tables_nphy.h"
 
 
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
+#define B2056_SYN			(0x0 << 12)
+#define B2056_TX0			(0x2 << 12)
+#define B2056_TX1			(0x3 << 12)
+#define B2056_RX0			(0x6 << 12)
+#define B2056_RX1			(0x7 << 12)
+#define B2056_ALLTX			(0xE << 12)
+#define B2056_ALLRX			(0xF << 12)
+
+#define B2056_SYN_RESERVED_ADDR0	0x00
+#define B2056_SYN_IDCODE		0x01
+#define B2056_SYN_RESERVED_ADDR2	0x02
+#define B2056_SYN_RESERVED_ADDR3	0x03
+#define B2056_SYN_RESERVED_ADDR4	0x04
+#define B2056_SYN_RESERVED_ADDR5	0x05
+#define B2056_SYN_RESERVED_ADDR6	0x06
+#define B2056_SYN_RESERVED_ADDR7	0x07
+#define B2056_SYN_COM_CTRL		0x08
+#define B2056_SYN_COM_PU		0x09
+#define B2056_SYN_COM_OVR		0x0A
+#define B2056_SYN_COM_RESET		0x0B
+#define B2056_SYN_COM_RCAL		0x0C
+#define B2056_SYN_COM_RC_RXLPF		0x0D
+#define B2056_SYN_COM_RC_TXLPF		0x0E
+#define B2056_SYN_COM_RC_RXHPF		0x0F
+#define B2056_SYN_RESERVED_ADDR16	0x10
+#define B2056_SYN_RESERVED_ADDR17	0x11
+#define B2056_SYN_RESERVED_ADDR18	0x12
+#define B2056_SYN_RESERVED_ADDR19	0x13
+#define B2056_SYN_RESERVED_ADDR20	0x14
+#define B2056_SYN_RESERVED_ADDR21	0x15
+#define B2056_SYN_RESERVED_ADDR22	0x16
+#define B2056_SYN_RESERVED_ADDR23	0x17
+#define B2056_SYN_RESERVED_ADDR24	0x18
+#define B2056_SYN_RESERVED_ADDR25	0x19
+#define B2056_SYN_RESERVED_ADDR26	0x1A
+#define B2056_SYN_RESERVED_ADDR27	0x1B
+#define B2056_SYN_RESERVED_ADDR28	0x1C
+#define B2056_SYN_RESERVED_ADDR29	0x1D
+#define B2056_SYN_RESERVED_ADDR30	0x1E
+#define B2056_SYN_RESERVED_ADDR31	0x1F
+#define B2056_SYN_GPIO_MASTER1		0x20
+#define B2056_SYN_GPIO_MASTER2		0x21
+#define B2056_SYN_TOPBIAS_MASTER	0x22
+#define B2056_SYN_TOPBIAS_RCAL		0x23
+#define B2056_SYN_AFEREG		0x24
+#define B2056_SYN_TEMPPROCSENSE		0x25
+#define B2056_SYN_TEMPPROCSENSEIDAC	0x26
+#define B2056_SYN_TEMPPROCSENSERCAL	0x27
+#define B2056_SYN_LPO			0x28
+#define B2056_SYN_VDDCAL_MASTER		0x29
+#define B2056_SYN_VDDCAL_IDAC		0x2A
+#define B2056_SYN_VDDCAL_STATUS		0x2B
+#define B2056_SYN_RCAL_MASTER		0x2C
+#define B2056_SYN_RCAL_CODE_OUT		0x2D
+#define B2056_SYN_RCCAL_CTRL0		0x2E
+#define B2056_SYN_RCCAL_CTRL1		0x2F
+#define B2056_SYN_RCCAL_CTRL2		0x30
+#define B2056_SYN_RCCAL_CTRL3		0x31
+#define B2056_SYN_RCCAL_CTRL4		0x32
+#define B2056_SYN_RCCAL_CTRL5		0x33
+#define B2056_SYN_RCCAL_CTRL6		0x34
+#define B2056_SYN_RCCAL_CTRL7		0x35
+#define B2056_SYN_RCCAL_CTRL8		0x36
+#define B2056_SYN_RCCAL_CTRL9		0x37
+#define B2056_SYN_RCCAL_CTRL10		0x38
+#define B2056_SYN_RCCAL_CTRL11		0x39
+#define B2056_SYN_ZCAL_SPARE1		0x3A
+#define B2056_SYN_ZCAL_SPARE2		0x3B
+#define B2056_SYN_PLL_MAST1		0x3C
+#define B2056_SYN_PLL_MAST2		0x3D
+#define B2056_SYN_PLL_MAST3		0x3E
+#define B2056_SYN_PLL_BIAS_RESET	0x3F
+#define B2056_SYN_PLL_XTAL0		0x40
+#define B2056_SYN_PLL_XTAL1		0x41
+#define B2056_SYN_PLL_XTAL3		0x42
+#define B2056_SYN_PLL_XTAL4		0x43
+#define B2056_SYN_PLL_XTAL5		0x44
+#define B2056_SYN_PLL_XTAL6		0x45
+#define B2056_SYN_PLL_REFDIV		0x46
+#define B2056_SYN_PLL_PFD		0x47
+#define B2056_SYN_PLL_CP1		0x48
+#define B2056_SYN_PLL_CP2		0x49
+#define B2056_SYN_PLL_CP3		0x4A
+#define B2056_SYN_PLL_LOOPFILTER1	0x4B
+#define B2056_SYN_PLL_LOOPFILTER2	0x4C
+#define B2056_SYN_PLL_LOOPFILTER3	0x4D
+#define B2056_SYN_PLL_LOOPFILTER4	0x4E
+#define B2056_SYN_PLL_LOOPFILTER5	0x4F
+#define B2056_SYN_PLL_MMD1		0x50
+#define B2056_SYN_PLL_MMD2		0x51
+#define B2056_SYN_PLL_VCO1		0x52
+#define B2056_SYN_PLL_VCO2		0x53
+#define B2056_SYN_PLL_MONITOR1		0x54
+#define B2056_SYN_PLL_MONITOR2		0x55
+#define B2056_SYN_PLL_VCOCAL1		0x56
+#define B2056_SYN_PLL_VCOCAL2		0x57
+#define B2056_SYN_PLL_VCOCAL4		0x58
+#define B2056_SYN_PLL_VCOCAL5		0x59
+#define B2056_SYN_PLL_VCOCAL6		0x5A
+#define B2056_SYN_PLL_VCOCAL7		0x5B
+#define B2056_SYN_PLL_VCOCAL8		0x5C
+#define B2056_SYN_PLL_VCOCAL9		0x5D
+#define B2056_SYN_PLL_VCOCAL10		0x5E
+#define B2056_SYN_PLL_VCOCAL11		0x5F
+#define B2056_SYN_PLL_VCOCAL12		0x60
+#define B2056_SYN_PLL_VCOCAL13		0x61
+#define B2056_SYN_PLL_VREG		0x62
+#define B2056_SYN_PLL_STATUS1		0x63
+#define B2056_SYN_PLL_STATUS2		0x64
+#define B2056_SYN_PLL_STATUS3		0x65
+#define B2056_SYN_LOGEN_PU0		0x66
+#define B2056_SYN_LOGEN_PU1		0x67
+#define B2056_SYN_LOGEN_PU2		0x68
+#define B2056_SYN_LOGEN_PU3		0x69
+#define B2056_SYN_LOGEN_PU5		0x6A
+#define B2056_SYN_LOGEN_PU6		0x6B
+#define B2056_SYN_LOGEN_PU7		0x6C
+#define B2056_SYN_LOGEN_PU8		0x6D
+#define B2056_SYN_LOGEN_BIAS_RESET	0x6E
+#define B2056_SYN_LOGEN_RCCR1		0x6F
+#define B2056_SYN_LOGEN_VCOBUF1		0x70
+#define B2056_SYN_LOGEN_MIXER1		0x71
+#define B2056_SYN_LOGEN_MIXER2		0x72
+#define B2056_SYN_LOGEN_BUF1		0x73
+#define B2056_SYN_LOGENBUF2		0x74
+#define B2056_SYN_LOGEN_BUF3		0x75
+#define B2056_SYN_LOGEN_BUF4		0x76
+#define B2056_SYN_LOGEN_DIV1		0x77
+#define B2056_SYN_LOGEN_DIV2		0x78
+#define B2056_SYN_LOGEN_DIV3		0x79
+#define B2056_SYN_LOGEN_ACL1		0x7A
+#define B2056_SYN_LOGEN_ACL2		0x7B
+#define B2056_SYN_LOGEN_ACL3		0x7C
+#define B2056_SYN_LOGEN_ACL4		0x7D
+#define B2056_SYN_LOGEN_ACL5		0x7E
+#define B2056_SYN_LOGEN_ACL6		0x7F
+#define B2056_SYN_LOGEN_ACLOUT		0x80
+#define B2056_SYN_LOGEN_ACLCAL1		0x81
+#define B2056_SYN_LOGEN_ACLCAL2		0x82
+#define B2056_SYN_LOGEN_ACLCAL3		0x83
+#define B2056_SYN_CALEN			0x84
+#define B2056_SYN_LOGEN_PEAKDET1	0x85
+#define B2056_SYN_LOGEN_CORE_ACL_OVR	0x86
+#define B2056_SYN_LOGEN_RX_DIFF_ACL_OVR	0x87
+#define B2056_SYN_LOGEN_TX_DIFF_ACL_OVR	0x88
+#define B2056_SYN_LOGEN_RX_CMOS_ACL_OVR	0x89
+#define B2056_SYN_LOGEN_TX_CMOS_ACL_OVR	0x8A
+#define B2056_SYN_LOGEN_VCOBUF2		0x8B
+#define B2056_SYN_LOGEN_MIXER3		0x8C
+#define B2056_SYN_LOGEN_BUF5		0x8D
+#define B2056_SYN_LOGEN_BUF6		0x8E
+#define B2056_SYN_LOGEN_CBUFRX1		0x8F
+#define B2056_SYN_LOGEN_CBUFRX2		0x90
+#define B2056_SYN_LOGEN_CBUFRX3		0x91
+#define B2056_SYN_LOGEN_CBUFRX4		0x92
+#define B2056_SYN_LOGEN_CBUFTX1		0x93
+#define B2056_SYN_LOGEN_CBUFTX2		0x94
+#define B2056_SYN_LOGEN_CBUFTX3		0x95
+#define B2056_SYN_LOGEN_CBUFTX4		0x96
+#define B2056_SYN_LOGEN_CMOSRX1		0x97
+#define B2056_SYN_LOGEN_CMOSRX2		0x98
+#define B2056_SYN_LOGEN_CMOSRX3		0x99
+#define B2056_SYN_LOGEN_CMOSRX4		0x9A
+#define B2056_SYN_LOGEN_CMOSTX1		0x9B
+#define B2056_SYN_LOGEN_CMOSTX2		0x9C
+#define B2056_SYN_LOGEN_CMOSTX3		0x9D
+#define B2056_SYN_LOGEN_CMOSTX4		0x9E
+#define B2056_SYN_LOGEN_VCOBUF2_OVRVAL	0x9F
+#define B2056_SYN_LOGEN_MIXER3_OVRVAL	0xA0
+#define B2056_SYN_LOGEN_BUF5_OVRVAL	0xA1
+#define B2056_SYN_LOGEN_BUF6_OVRVAL	0xA2
+#define B2056_SYN_LOGEN_CBUFRX1_OVRVAL	0xA3
+#define B2056_SYN_LOGEN_CBUFRX2_OVRVAL	0xA4
+#define B2056_SYN_LOGEN_CBUFRX3_OVRVAL	0xA5
+#define B2056_SYN_LOGEN_CBUFRX4_OVRVAL	0xA6
+#define B2056_SYN_LOGEN_CBUFTX1_OVRVAL	0xA7
+#define B2056_SYN_LOGEN_CBUFTX2_OVRVAL	0xA8
+#define B2056_SYN_LOGEN_CBUFTX3_OVRVAL	0xA9
+#define B2056_SYN_LOGEN_CBUFTX4_OVRVAL	0xAA
+#define B2056_SYN_LOGEN_CMOSRX1_OVRVAL	0xAB
+#define B2056_SYN_LOGEN_CMOSRX2_OVRVAL	0xAC
+#define B2056_SYN_LOGEN_CMOSRX3_OVRVAL	0xAD
+#define B2056_SYN_LOGEN_CMOSRX4_OVRVAL	0xAE
+#define B2056_SYN_LOGEN_CMOSTX1_OVRVAL	0xAF
+#define B2056_SYN_LOGEN_CMOSTX2_OVRVAL	0xB0
+#define B2056_SYN_LOGEN_CMOSTX3_OVRVAL	0xB1
+#define B2056_SYN_LOGEN_CMOSTX4_OVRVAL	0xB2
+#define B2056_SYN_LOGEN_ACL_WAITCNT	0xB3
+#define B2056_SYN_LOGEN_CORE_CALVALID	0xB4
+#define B2056_SYN_LOGEN_RX_CMOS_CALVALID	0xB5
+#define B2056_SYN_LOGEN_TX_CMOS_VALID	0xB6
+
+#define B2056_TX_RESERVED_ADDR0		0x00
+#define B2056_TX_IDCODE			0x01
+#define B2056_TX_RESERVED_ADDR2		0x02
+#define B2056_TX_RESERVED_ADDR3		0x03
+#define B2056_TX_RESERVED_ADDR4		0x04
+#define B2056_TX_RESERVED_ADDR5		0x05
+#define B2056_TX_RESERVED_ADDR6		0x06
+#define B2056_TX_RESERVED_ADDR7		0x07
+#define B2056_TX_COM_CTRL		0x08
+#define B2056_TX_COM_PU			0x09
+#define B2056_TX_COM_OVR		0x0A
+#define B2056_TX_COM_RESET		0x0B
+#define B2056_TX_COM_RCAL		0x0C
+#define B2056_TX_COM_RC_RXLPF		0x0D
+#define B2056_TX_COM_RC_TXLPF		0x0E
+#define B2056_TX_COM_RC_RXHPF		0x0F
+#define B2056_TX_RESERVED_ADDR16	0x10
+#define B2056_TX_RESERVED_ADDR17	0x11
+#define B2056_TX_RESERVED_ADDR18	0x12
+#define B2056_TX_RESERVED_ADDR19	0x13
+#define B2056_TX_RESERVED_ADDR20	0x14
+#define B2056_TX_RESERVED_ADDR21	0x15
+#define B2056_TX_RESERVED_ADDR22	0x16
+#define B2056_TX_RESERVED_ADDR23	0x17
+#define B2056_TX_RESERVED_ADDR24	0x18
+#define B2056_TX_RESERVED_ADDR25	0x19
+#define B2056_TX_RESERVED_ADDR26	0x1A
+#define B2056_TX_RESERVED_ADDR27	0x1B
+#define B2056_TX_RESERVED_ADDR28	0x1C
+#define B2056_TX_RESERVED_ADDR29	0x1D
+#define B2056_TX_RESERVED_ADDR30	0x1E
+#define B2056_TX_RESERVED_ADDR31	0x1F
+#define B2056_TX_IQCAL_GAIN_BW		0x20
+#define B2056_TX_LOFT_FINE_I		0x21
+#define B2056_TX_LOFT_FINE_Q		0x22
+#define B2056_TX_LOFT_COARSE_I		0x23
+#define B2056_TX_LOFT_COARSE_Q		0x24
+#define B2056_TX_TX_COM_MASTER1		0x25
+#define B2056_TX_TX_COM_MASTER2		0x26
+#define B2056_TX_RXIQCAL_TXMUX		0x27
+#define B2056_TX_TX_SSI_MASTER		0x28
+#define B2056_TX_IQCAL_VCM_HG		0x29
+#define B2056_TX_IQCAL_IDAC		0x2A
+#define B2056_TX_TSSI_VCM		0x2B
+#define B2056_TX_TX_AMP_DET		0x2C
+#define B2056_TX_TX_SSI_MUX		0x2D
+#define B2056_TX_TSSIA			0x2E
+#define B2056_TX_TSSIG			0x2F
+#define B2056_TX_TSSI_MISC1		0x30
+#define B2056_TX_TSSI_MISC2		0x31
+#define B2056_TX_TSSI_MISC3		0x32
+#define B2056_TX_PA_SPARE1		0x33
+#define B2056_TX_PA_SPARE2		0x34
+#define B2056_TX_INTPAA_MASTER		0x35
+#define B2056_TX_INTPAA_GAIN		0x36
+#define B2056_TX_INTPAA_BOOST_TUNE	0x37
+#define B2056_TX_INTPAA_IAUX_STAT	0x38
+#define B2056_TX_INTPAA_IAUX_DYN	0x39
+#define B2056_TX_INTPAA_IMAIN_STAT	0x3A
+#define B2056_TX_INTPAA_IMAIN_DYN	0x3B
+#define B2056_TX_INTPAA_CASCBIAS	0x3C
+#define B2056_TX_INTPAA_PASLOPE		0x3D
+#define B2056_TX_INTPAA_PA_MISC		0x3E
+#define B2056_TX_INTPAG_MASTER		0x3F
+#define B2056_TX_INTPAG_GAIN		0x40
+#define B2056_TX_INTPAG_BOOST_TUNE	0x41
+#define B2056_TX_INTPAG_IAUX_STAT	0x42
+#define B2056_TX_INTPAG_IAUX_DYN	0x43
+#define B2056_TX_INTPAG_IMAIN_STAT	0x44
+#define B2056_TX_INTPAG_IMAIN_DYN	0x45
+#define B2056_TX_INTPAG_CASCBIAS	0x46
+#define B2056_TX_INTPAG_PASLOPE		0x47
+#define B2056_TX_INTPAG_PA_MISC		0x48
+#define B2056_TX_PADA_MASTER		0x49
+#define B2056_TX_PADA_IDAC		0x4A
+#define B2056_TX_PADA_CASCBIAS		0x4B
+#define B2056_TX_PADA_GAIN		0x4C
+#define B2056_TX_PADA_BOOST_TUNE	0x4D
+#define B2056_TX_PADA_SLOPE		0x4E
+#define B2056_TX_PADG_MASTER		0x4F
+#define B2056_TX_PADG_IDAC		0x50
+#define B2056_TX_PADG_CASCBIAS		0x51
+#define B2056_TX_PADG_GAIN		0x52
+#define B2056_TX_PADG_BOOST_TUNE	0x53
+#define B2056_TX_PADG_SLOPE		0x54
+#define B2056_TX_PGAA_MASTER		0x55
+#define B2056_TX_PGAA_IDAC		0x56
+#define B2056_TX_PGAA_GAIN		0x57
+#define B2056_TX_PGAA_BOOST_TUNE	0x58
+#define B2056_TX_PGAA_SLOPE		0x59
+#define B2056_TX_PGAA_MISC		0x5A
+#define B2056_TX_PGAG_MASTER		0x5B
+#define B2056_TX_PGAG_IDAC		0x5C
+#define B2056_TX_PGAG_GAIN		0x5D
+#define B2056_TX_PGAG_BOOST_TUNE	0x5E
+#define B2056_TX_PGAG_SLOPE		0x5F
+#define B2056_TX_PGAG_MISC		0x60
+#define B2056_TX_MIXA_MASTER		0x61
+#define B2056_TX_MIXA_BOOST_TUNE	0x62
+#define B2056_TX_MIXG			0x63
+#define B2056_TX_MIXG_BOOST_TUNE	0x64
+#define B2056_TX_BB_GM_MASTER		0x65
+#define B2056_TX_GMBB_GM		0x66
+#define B2056_TX_GMBB_IDAC		0x67
+#define B2056_TX_TXLPF_MASTER		0x68
+#define B2056_TX_TXLPF_RCCAL		0x69
+#define B2056_TX_TXLPF_RCCAL_OFF0	0x6A
+#define B2056_TX_TXLPF_RCCAL_OFF1	0x6B
+#define B2056_TX_TXLPF_RCCAL_OFF2	0x6C
+#define B2056_TX_TXLPF_RCCAL_OFF3	0x6D
+#define B2056_TX_TXLPF_RCCAL_OFF4	0x6E
+#define B2056_TX_TXLPF_RCCAL_OFF5	0x6F
+#define B2056_TX_TXLPF_RCCAL_OFF6	0x70
+#define B2056_TX_TXLPF_BW		0x71
+#define B2056_TX_TXLPF_GAIN		0x72
+#define B2056_TX_TXLPF_IDAC		0x73
+#define B2056_TX_TXLPF_IDAC_0		0x74
+#define B2056_TX_TXLPF_IDAC_1		0x75
+#define B2056_TX_TXLPF_IDAC_2		0x76
+#define B2056_TX_TXLPF_IDAC_3		0x77
+#define B2056_TX_TXLPF_IDAC_4		0x78
+#define B2056_TX_TXLPF_IDAC_5		0x79
+#define B2056_TX_TXLPF_IDAC_6		0x7A
+#define B2056_TX_TXLPF_OPAMP_IDAC	0x7B
+#define B2056_TX_TXLPF_MISC		0x7C
+#define B2056_TX_TXSPARE1		0x7D
+#define B2056_TX_TXSPARE2		0x7E
+#define B2056_TX_TXSPARE3		0x7F
+#define B2056_TX_TXSPARE4		0x80
+#define B2056_TX_TXSPARE5		0x81
+#define B2056_TX_TXSPARE6		0x82
+#define B2056_TX_TXSPARE7		0x83
+#define B2056_TX_TXSPARE8		0x84
+#define B2056_TX_TXSPARE9		0x85
+#define B2056_TX_TXSPARE10		0x86
+#define B2056_TX_TXSPARE11		0x87
+#define B2056_TX_TXSPARE12		0x88
+#define B2056_TX_TXSPARE13		0x89
+#define B2056_TX_TXSPARE14		0x8A
+#define B2056_TX_TXSPARE15		0x8B
+#define B2056_TX_TXSPARE16		0x8C
+#define B2056_TX_STATUS_INTPA_GAIN	0x8D
+#define B2056_TX_STATUS_PAD_GAIN	0x8E
+#define B2056_TX_STATUS_PGA_GAIN	0x8F
+#define B2056_TX_STATUS_GM_TXLPF_GAIN	0x90
+#define B2056_TX_STATUS_TXLPF_BW	0x91
+#define B2056_TX_STATUS_TXLPF_RC	0x92
+#define B2056_TX_GMBB_IDAC0		0x93
+#define B2056_TX_GMBB_IDAC1		0x94
+#define B2056_TX_GMBB_IDAC2		0x95
+#define B2056_TX_GMBB_IDAC3		0x96
+#define B2056_TX_GMBB_IDAC4		0x97
+#define B2056_TX_GMBB_IDAC5		0x98
+#define B2056_TX_GMBB_IDAC6		0x99
+#define B2056_TX_GMBB_IDAC7		0x9A
+
+#define B2056_RX_RESERVED_ADDR0		0x00
+#define B2056_RX_IDCODE			0x01
+#define B2056_RX_RESERVED_ADDR2		0x02
+#define B2056_RX_RESERVED_ADDR3		0x03
+#define B2056_RX_RESERVED_ADDR4		0x04
+#define B2056_RX_RESERVED_ADDR5		0x05
+#define B2056_RX_RESERVED_ADDR6		0x06
+#define B2056_RX_RESERVED_ADDR7		0x07
+#define B2056_RX_COM_CTRL		0x08
+#define B2056_RX_COM_PU			0x09
+#define B2056_RX_COM_OVR		0x0A
+#define B2056_RX_COM_RESET		0x0B
+#define B2056_RX_COM_RCAL		0x0C
+#define B2056_RX_COM_RC_RXLPF		0x0D
+#define B2056_RX_COM_RC_TXLPF		0x0E
+#define B2056_RX_COM_RC_RXHPF		0x0F
+#define B2056_RX_RESERVED_ADDR16	0x10
+#define B2056_RX_RESERVED_ADDR17	0x11
+#define B2056_RX_RESERVED_ADDR18	0x12
+#define B2056_RX_RESERVED_ADDR19	0x13
+#define B2056_RX_RESERVED_ADDR20	0x14
+#define B2056_RX_RESERVED_ADDR21	0x15
+#define B2056_RX_RESERVED_ADDR22	0x16
+#define B2056_RX_RESERVED_ADDR23	0x17
+#define B2056_RX_RESERVED_ADDR24	0x18
+#define B2056_RX_RESERVED_ADDR25	0x19
+#define B2056_RX_RESERVED_ADDR26	0x1A
+#define B2056_RX_RESERVED_ADDR27	0x1B
+#define B2056_RX_RESERVED_ADDR28	0x1C
+#define B2056_RX_RESERVED_ADDR29	0x1D
+#define B2056_RX_RESERVED_ADDR30	0x1E
+#define B2056_RX_RESERVED_ADDR31	0x1F
+#define B2056_RX_RXIQCAL_RXMUX		0x20
+#define B2056_RX_RSSI_PU		0x21
+#define B2056_RX_RSSI_SEL		0x22
+#define B2056_RX_RSSI_GAIN		0x23
+#define B2056_RX_RSSI_NB_IDAC		0x24
+#define B2056_RX_RSSI_WB2I_IDAC_1	0x25
+#define B2056_RX_RSSI_WB2I_IDAC_2	0x26
+#define B2056_RX_RSSI_WB2Q_IDAC_1	0x27
+#define B2056_RX_RSSI_WB2Q_IDAC_2	0x28
+#define B2056_RX_RSSI_POLE		0x29
+#define B2056_RX_RSSI_WB1_IDAC		0x2A
+#define B2056_RX_RSSI_MISC		0x2B
+#define B2056_RX_LNAA_MASTER		0x2C
+#define B2056_RX_LNAA_TUNE		0x2D
+#define B2056_RX_LNAA_GAIN		0x2E
+#define B2056_RX_LNA_A_SLOPE		0x2F
+#define B2056_RX_BIASPOLE_LNAA1_IDAC	0x30
+#define B2056_RX_LNAA2_IDAC		0x31
+#define B2056_RX_LNA1A_MISC		0x32
+#define B2056_RX_LNAG_MASTER		0x33
+#define B2056_RX_LNAG_TUNE		0x34
+#define B2056_RX_LNAG_GAIN		0x35
+#define B2056_RX_LNA_G_SLOPE		0x36
+#define B2056_RX_BIASPOLE_LNAG1_IDAC	0x37
+#define B2056_RX_LNAG2_IDAC		0x38
+#define B2056_RX_LNA1G_MISC		0x39
+#define B2056_RX_MIXA_MASTER		0x3A
+#define B2056_RX_MIXA_VCM		0x3B
+#define B2056_RX_MIXA_CTRLPTAT		0x3C
+#define B2056_RX_MIXA_LOB_BIAS		0x3D
+#define B2056_RX_MIXA_CORE_IDAC		0x3E
+#define B2056_RX_MIXA_CMFB_IDAC		0x3F
+#define B2056_RX_MIXA_BIAS_AUX		0x40
+#define B2056_RX_MIXA_BIAS_MAIN		0x41
+#define B2056_RX_MIXA_BIAS_MISC		0x42
+#define B2056_RX_MIXA_MAST_BIAS		0x43
+#define B2056_RX_MIXG_MASTER		0x44
+#define B2056_RX_MIXG_VCM		0x45
+#define B2056_RX_MIXG_CTRLPTAT		0x46
+#define B2056_RX_MIXG_LOB_BIAS		0x47
+#define B2056_RX_MIXG_CORE_IDAC		0x48
+#define B2056_RX_MIXG_CMFB_IDAC		0x49
+#define B2056_RX_MIXG_BIAS_AUX		0x4A
+#define B2056_RX_MIXG_BIAS_MAIN		0x4B
+#define B2056_RX_MIXG_BIAS_MISC		0x4C
+#define B2056_RX_MIXG_MAST_BIAS		0x4D
+#define B2056_RX_TIA_MASTER		0x4E
+#define B2056_RX_TIA_IOPAMP		0x4F
+#define B2056_RX_TIA_QOPAMP		0x50
+#define B2056_RX_TIA_IMISC		0x51
+#define B2056_RX_TIA_QMISC		0x52
+#define B2056_RX_TIA_GAIN		0x53
+#define B2056_RX_TIA_SPARE1		0x54
+#define B2056_RX_TIA_SPARE2		0x55
+#define B2056_RX_BB_LPF_MASTER		0x56
+#define B2056_RX_AACI_MASTER		0x57
+#define B2056_RX_RXLPF_IDAC		0x58
+#define B2056_RX_RXLPF_OPAMPBIAS_LOWQ	0x59
+#define B2056_RX_RXLPF_OPAMPBIAS_HIGHQ	0x5A
+#define B2056_RX_RXLPF_BIAS_DCCANCEL	0x5B
+#define B2056_RX_RXLPF_OUTVCM		0x5C
+#define B2056_RX_RXLPF_INVCM_BODY	0x5D
+#define B2056_RX_RXLPF_CC_OP		0x5E
+#define B2056_RX_RXLPF_GAIN		0x5F
+#define B2056_RX_RXLPF_Q_BW		0x60
+#define B2056_RX_RXLPF_HP_CORNER_BW	0x61
+#define B2056_RX_RXLPF_RCCAL_HPC	0x62
+#define B2056_RX_RXHPF_OFF0		0x63
+#define B2056_RX_RXHPF_OFF1		0x64
+#define B2056_RX_RXHPF_OFF2		0x65
+#define B2056_RX_RXHPF_OFF3		0x66
+#define B2056_RX_RXHPF_OFF4		0x67
+#define B2056_RX_RXHPF_OFF5		0x68
+#define B2056_RX_RXHPF_OFF6		0x69
+#define B2056_RX_RXHPF_OFF7		0x6A
+#define B2056_RX_RXLPF_RCCAL_LPC	0x6B
+#define B2056_RX_RXLPF_OFF_0		0x6C
+#define B2056_RX_RXLPF_OFF_1		0x6D
+#define B2056_RX_RXLPF_OFF_2		0x6E
+#define B2056_RX_RXLPF_OFF_3		0x6F
+#define B2056_RX_RXLPF_OFF_4		0x70
+#define B2056_RX_UNUSED			0x71
+#define B2056_RX_VGA_MASTER		0x72
+#define B2056_RX_VGA_BIAS		0x73
+#define B2056_RX_VGA_BIAS_DCCANCEL	0x74
+#define B2056_RX_VGA_GAIN		0x75
+#define B2056_RX_VGA_HP_CORNER_BW	0x76
+#define B2056_RX_VGABUF_BIAS		0x77
+#define B2056_RX_VGABUF_GAIN_BW		0x78
+#define B2056_RX_TXFBMIX_A		0x79
+#define B2056_RX_TXFBMIX_G		0x7A
+#define B2056_RX_RXSPARE1		0x7B
+#define B2056_RX_RXSPARE2		0x7C
+#define B2056_RX_RXSPARE3		0x7D
+#define B2056_RX_RXSPARE4		0x7E
+#define B2056_RX_RXSPARE5		0x7F
+#define B2056_RX_RXSPARE6		0x80
+#define B2056_RX_RXSPARE7		0x81
+#define B2056_RX_RXSPARE8		0x82
+#define B2056_RX_RXSPARE9		0x83
+#define B2056_RX_RXSPARE10		0x84
+#define B2056_RX_RXSPARE11		0x85
+#define B2056_RX_RXSPARE12		0x86
+#define B2056_RX_RXSPARE13		0x87
+#define B2056_RX_RXSPARE14		0x88
+#define B2056_RX_RXSPARE15		0x89
+#define B2056_RX_RXSPARE16		0x8A
+#define B2056_RX_STATUS_LNAA_GAIN	0x8B
+#define B2056_RX_STATUS_LNAG_GAIN	0x8C
+#define B2056_RX_STATUS_MIXTIA_GAIN	0x8D
+#define B2056_RX_STATUS_RXLPF_GAIN	0x8E
+#define B2056_RX_STATUS_VGA_BUF_GAIN	0x8F
+#define B2056_RX_STATUS_RXLPF_Q		0x90
+#define B2056_RX_STATUS_RXLPF_BUF_BW	0x91
+#define B2056_RX_STATUS_RXLPF_VGA_HPC	0x92
+#define B2056_RX_STATUS_RXLPF_RC	0x93
+#define B2056_RX_STATUS_HPC_RC		0x94
+
+#define B2056_LNA1_A_PU			0x01
+#define B2056_LNA2_A_PU			0x02
+#define B2056_LNA1_G_PU			0x01
+#define B2056_LNA2_G_PU			0x02
+#define B2056_MIXA_PU_I			0x01
+#define B2056_MIXA_PU_Q			0x02
+#define B2056_MIXA_PU_GM		0x10
+#define B2056_MIXG_PU_I			0x01
+#define B2056_MIXG_PU_Q			0x02
+#define B2056_MIXG_PU_GM		0x10
+#define B2056_TIA_PU			0x01
+#define B2056_BB_LPF_PU			0x20
+#define B2056_W1_PU			0x02
+#define B2056_W2_PU			0x04
+#define B2056_NB_PU			0x08
+#define B2056_RSSI_W1_SEL		0x02
+#define B2056_RSSI_W2_SEL		0x04
+#define B2056_RSSI_NB_SEL		0x08
+#define B2056_VCM_MASK			0x1C
+#define B2056_RSSI_VCM_SHIFT		0x02
+
 struct b43_nphy_channeltab_entry_rev3 {
 struct b43_nphy_channeltab_entry_rev3 {
-	/* The channel number */
-	u8 channel;
 	/* The channel frequency in MHz */
 	/* The channel frequency in MHz */
 	u16 freq;
 	u16 freq;
 	/* Radio register values on channelswitch */
 	/* Radio register values on channelswitch */
-	/* TODO */
+	u8 radio_syn_pll_vcocal1;
+	u8 radio_syn_pll_vcocal2;
+	u8 radio_syn_pll_refdiv;
+	u8 radio_syn_pll_mmd2;
+	u8 radio_syn_pll_mmd1;
+	u8 radio_syn_pll_loopfilter1;
+	u8 radio_syn_pll_loopfilter2;
+	u8 radio_syn_pll_loopfilter3;
+	u8 radio_syn_pll_loopfilter4;
+	u8 radio_syn_pll_loopfilter5;
+	u8 radio_syn_reserved_addr27;
+	u8 radio_syn_reserved_addr28;
+	u8 radio_syn_reserved_addr29;
+	u8 radio_syn_logen_vcobuf1;
+	u8 radio_syn_logen_mixer2;
+	u8 radio_syn_logen_buf3;
+	u8 radio_syn_logen_buf4;
+	u8 radio_rx0_lnaa_tune;
+	u8 radio_rx0_lnag_tune;
+	u8 radio_tx0_intpaa_boost_tune;
+	u8 radio_tx0_intpag_boost_tune;
+	u8 radio_tx0_pada_boost_tune;
+	u8 radio_tx0_padg_boost_tune;
+	u8 radio_tx0_pgaa_boost_tune;
+	u8 radio_tx0_pgag_boost_tune;
+	u8 radio_tx0_mixa_boost_tune;
+	u8 radio_tx0_mixg_boost_tune;
+	u8 radio_rx1_lnaa_tune;
+	u8 radio_rx1_lnag_tune;
+	u8 radio_tx1_intpaa_boost_tune;
+	u8 radio_tx1_intpag_boost_tune;
+	u8 radio_tx1_pada_boost_tune;
+	u8 radio_tx1_padg_boost_tune;
+	u8 radio_tx1_pgaa_boost_tune;
+	u8 radio_tx1_pgag_boost_tune;
+	u8 radio_tx1_mixa_boost_tune;
+	u8 radio_tx1_mixg_boost_tune;
 	/* PHY register values on channelswitch */
 	/* PHY register values on channelswitch */
 	struct b43_phy_n_sfo_cfg phy_regs;
 	struct b43_phy_n_sfo_cfg phy_regs;
 };
 };

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

@@ -29,7 +29,7 @@
 /* Returns TRUE, if the radio is enabled in hardware. */
 /* Returns TRUE, if the radio is enabled in hardware. */
 bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
 bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
 {
 {
-	if (dev->phy.rev >= 3) {
+	if (dev->dev->id.revision >= 3) {
 		if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
 		if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI)
 		      & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
 		      & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
 			return 1;
 			return 1;

+ 3 - 0
drivers/net/wireless/iwlwifi/Kconfig

@@ -106,6 +106,9 @@ config IWL5000
 		Intel WiFi Link 1000BGN
 		Intel WiFi Link 1000BGN
 		Intel Wireless WiFi 5150AGN
 		Intel Wireless WiFi 5150AGN
 		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
 		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+		Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B)
+		Intel WIreless WiFi Link 6050BGN Gen 2 Adapter
+		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
 
 
 config IWL3945
 config IWL3945
 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"

+ 5 - 2
drivers/net/wireless/iwlwifi/Makefile

@@ -2,6 +2,8 @@ obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
 iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
 iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
 iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
 iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
 iwlcore-objs 		+= iwl-scan.o iwl-led.o
 iwlcore-objs 		+= iwl-scan.o iwl-led.o
+iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
+iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
 
 
@@ -9,13 +11,14 @@ CFLAGS_iwl-devtrace.o := -I$(src)
 
 
 # AGN
 # AGN
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
-iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
-iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
+iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
+iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
 iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
+iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
 iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
 iwlagn-$(CONFIG_IWL5000) += iwl-1000.o

+ 8 - 5
drivers/net/wireless/iwlwifi/iwl-1000.c

@@ -211,14 +211,16 @@ static struct iwl_lib_ops iwl1000_lib = {
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 		.temperature = iwlagn_temperature,
 	 },
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -243,6 +245,7 @@ static const struct iwl_ops iwl1000_ops = {
 	.hcmd = &iwlagn_hcmd,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static struct iwl_base_params iwl1000_base_params = {
 static struct iwl_base_params iwl1000_base_params = {

+ 17 - 5
drivers/net/wireless/iwlwifi/iwl-3945.c

@@ -51,6 +51,7 @@
 #include "iwl-led.h"
 #include "iwl-led.h"
 #include "iwl-3945-led.h"
 #include "iwl-3945-led.h"
 #include "iwl-3945-debugfs.h"
 #include "iwl-3945-debugfs.h"
+#include "iwl-legacy.h"
 
 
 #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
 #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
 	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
 	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
@@ -1451,6 +1452,10 @@ static int iwl3945_send_tx_power(struct iwl_priv *priv)
 	};
 	};
 	u16 chan;
 	u16 chan;
 
 
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
 	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
 	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
 
 
 	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
 	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
@@ -2722,10 +2727,9 @@ static struct iwl_lib_ops iwl3945_lib = {
 	},
 	},
 	.send_tx_power	= iwl3945_send_tx_power,
 	.send_tx_power	= iwl3945_send_tx_power,
 	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
 	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
-	.post_associate = iwl3945_post_associate,
-	.isr = iwl_isr_legacy,
-	.config_ap = iwl3945_config_ap,
-	.manage_ibss_station = iwl3945_manage_ibss_station,
+	.isr_ops = {
+		.isr = iwl_isr_legacy,
+	},
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.recover_from_tx_stall = iwl_bg_monitor_recover,
 	.check_plcp_health = iwl3945_good_plcp_health,
 	.check_plcp_health = iwl3945_good_plcp_health,
 
 
@@ -2736,10 +2740,16 @@ static struct iwl_lib_ops iwl3945_lib = {
 	},
 	},
 };
 };
 
 
+static const struct iwl_legacy_ops iwl3945_legacy_ops = {
+	.post_associate = iwl3945_post_associate,
+	.config_ap = iwl3945_config_ap,
+	.manage_ibss_station = iwl3945_manage_ibss_station,
+};
+
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 	.get_hcmd_size = iwl3945_get_hcmd_size,
 	.get_hcmd_size = iwl3945_get_hcmd_size,
 	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
 	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-	.tx_cmd_protection = iwlcore_tx_cmd_protection,
+	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
 	.request_scan = iwl3945_request_scan,
 	.request_scan = iwl3945_request_scan,
 	.post_scan = iwl3945_post_scan,
 	.post_scan = iwl3945_post_scan,
 };
 };
@@ -2749,6 +2759,8 @@ static const struct iwl_ops iwl3945_ops = {
 	.hcmd = &iwl3945_hcmd,
 	.hcmd = &iwl3945_hcmd,
 	.utils = &iwl3945_hcmd_utils,
 	.utils = &iwl3945_hcmd_utils,
 	.led = &iwl3945_led_ops,
 	.led = &iwl3945_led_ops,
+	.legacy = &iwl3945_legacy_ops,
+	.ieee80211_ops = &iwl3945_hw_ops,
 };
 };
 
 
 static struct iwl_base_params iwl3945_base_params = {
 static struct iwl_base_params iwl3945_base_params = {

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

@@ -264,10 +264,8 @@ void iwl3945_reply_statistics(struct iwl_priv *priv,
 			      struct iwl_rx_mem_buffer *rxb);
 			      struct iwl_rx_mem_buffer *rxb);
 extern void iwl3945_disable_events(struct iwl_priv *priv);
 extern void iwl3945_disable_events(struct iwl_priv *priv);
 extern int iwl4965_get_temperature(const struct iwl_priv *priv);
 extern int iwl4965_get_temperature(const struct iwl_priv *priv);
-extern void iwl3945_post_associate(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif);
-extern void iwl3945_config_ap(struct iwl_priv *priv,
-			      struct ieee80211_vif *vif);
+extern void iwl3945_post_associate(struct iwl_priv *priv);
+extern void iwl3945_config_ap(struct iwl_priv *priv);
 
 
 extern int iwl3945_commit_rxon(struct iwl_priv *priv,
 extern int iwl3945_commit_rxon(struct iwl_priv *priv,
 			       struct iwl_rxon_context *ctx);
 			       struct iwl_rxon_context *ctx);
@@ -282,6 +280,8 @@ extern int iwl3945_commit_rxon(struct iwl_priv *priv,
  */
  */
 extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
 extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
 
 
+extern struct ieee80211_ops iwl3945_hw_ops;
+
 /*
 /*
  * Forward declare iwl-3945.c functions for iwl-base.c
  * Forward declare iwl-3945.c functions for iwl-base.c
  */
  */

+ 321 - 31
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -48,6 +48,7 @@
 #include "iwl-agn-led.h"
 #include "iwl-agn-led.h"
 #include "iwl-agn.h"
 #include "iwl-agn.h"
 #include "iwl-agn-debugfs.h"
 #include "iwl-agn-debugfs.h"
+#include "iwl-legacy.h"
 
 
 static int iwl4965_send_tx_power(struct iwl_priv *priv);
 static int iwl4965_send_tx_power(struct iwl_priv *priv);
 static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
 static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
@@ -1377,13 +1378,9 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
 	u8 ctrl_chan_high = 0;
 	u8 ctrl_chan_high = 0;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 
-	if (test_bit(STATUS_SCANNING, &priv->status)) {
-		/* If this gets hit a lot, switch it to a BUG() and catch
-		 * the stack trace to find out who is calling this during
-		 * a scan. */
-		IWL_WARN(priv, "TX Power requested while scanning!\n");
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
 		return -EAGAIN;
 		return -EAGAIN;
-	}
 
 
 	band = priv->band == IEEE80211_BAND_2GHZ;
 	band = priv->band == IEEE80211_BAND_2GHZ;
 
 
@@ -1447,6 +1444,142 @@ static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
 	return ret;
 	return ret;
 }
 }
 
 
+static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
+	int ret;
+	bool new_assoc =
+		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_is_alive(priv))
+		return -EBUSY;
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	ret = iwl_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		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 != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_chswitch_done(priv, false);
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_full_rxon_required(priv, ctx)) {
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_print_rx_config_cmd(priv, ctx);
+		return 0;
+	}
+
+	/* If we are currently associated and the new config requires
+	 * an RXON_ASSOC and the new config wants the associated mask enabled,
+	 * we must clear the associated from the active configuration
+	 * before we apply the new config */
+	if (iwl_is_associated_ctx(ctx) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+				       sizeof(struct iwl_rxon_cmd),
+				       active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (ret) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
+			return ret;
+		}
+		iwl_clear_ucode_stations(priv, ctx);
+		iwl_restore_stations(priv, ctx);
+		ret = iwl_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "Sending RXON\n"
+		       "* with%s RXON_FILTER_ASSOC_MSK\n"
+		       "* channel = %d\n"
+		       "* bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
+
+	/* Apply the new configuration
+	 * RXON unassoc clears the station table in uCode so restoration of
+	 * stations is needed after it (the RXON command) completes
+	 */
+	if (!new_assoc) {
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_clear_ucode_stations(priv, ctx);
+		iwl_restore_stations(priv, ctx);
+		ret = iwl_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+	if (new_assoc) {
+		priv->start_calib = 0;
+		/* Apply the new configuration
+		 * RXON assoc doesn't clear the station table in uCode,
+		 */
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+	}
+	iwl_print_rx_config_cmd(priv, ctx);
+
+	iwl_init_sensitivity(priv);
+
+	/* If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames */
+	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
 static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
 				     struct ieee80211_channel_switch *ch_switch)
 				     struct ieee80211_channel_switch *ch_switch)
 {
 {
@@ -1553,22 +1686,6 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
 			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
 }
 }
 
 
-/**
- * sign_extend - Sign extend a value using specified bit as sign-bit
- *
- * Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1
- * and bit0..2 is 001b which when sign extended to 1111111111111001b is -7.
- *
- * @param oper value to sign extend
- * @param index 0 based bit index (0<=index<32) to sign bit
- */
-static s32 sign_extend(u32 oper, int index)
-{
-	u8 shift = 31 - index;
-
-	return (s32)(oper << shift) >> shift;
-}
-
 /**
 /**
  * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
  * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
  * @statistics: Provides the temperature reading from the uCode
  * @statistics: Provides the temperature reading from the uCode
@@ -1606,9 +1723,9 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	 * "initialize" ALIVE response.
 	 * "initialize" ALIVE response.
 	 */
 	 */
 	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
 	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
-		vt = sign_extend(R4, 23);
+		vt = sign_extend32(R4, 23);
 	else
 	else
-		vt = sign_extend(le32_to_cpu(priv->_agn.statistics.
+		vt = sign_extend32(le32_to_cpu(priv->_agn.statistics.
 				 general.common.temperature), 23);
 				 general.common.temperature), 23);
 
 
 	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
@@ -2216,7 +2333,7 @@ static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
 
 
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 static struct iwl_hcmd_ops iwl4965_hcmd = {
 	.rxon_assoc = iwl4965_send_rxon_assoc,
 	.rxon_assoc = iwl4965_send_rxon_assoc,
-	.commit_rxon = iwlagn_commit_rxon,
+	.commit_rxon = iwl4965_commit_rxon,
 	.set_rxon_chain = iwlagn_set_rxon_chain,
 	.set_rxon_chain = iwlagn_set_rxon_chain,
 	.send_bt_config = iwl_send_bt_config,
 	.send_bt_config = iwl_send_bt_config,
 };
 };
@@ -2233,12 +2350,155 @@ static void iwl4965_post_scan(struct iwl_priv *priv)
 		iwlcore_commit_rxon(priv, ctx);
 		iwlcore_commit_rxon(priv, ctx);
 }
 }
 
 
+static void iwl4965_post_associate(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	struct ieee80211_conf *conf = NULL;
+	int ret = 0;
+
+	if (!vif || !priv->is_open)
+		return;
+
+	if (vif->type == NL80211_IFTYPE_AP) {
+		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
+		return;
+	}
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_scan_cancel_timeout(priv, 200);
+
+	conf = ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
+
+	ret = iwl_send_rxon_timing(priv, ctx);
+	if (ret)
+		IWL_WARN(priv, "RXON timing - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	iwl_set_rxon_ht(priv, &priv->current_ht_config);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwlcore_commit_rxon(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwlagn_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			  __func__, vif->type);
+		break;
+	}
+
+	/* the chain noise calibration will enabled PM upon completion
+	 * If chain noise has already been run, then we need to enable
+	 * power management here */
+	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+		iwl_power_update_mode(priv, false);
+
+	/* Enable Rx differential gain and sensitivity calibrations */
+	iwl_chain_noise_reset(priv);
+	priv->start_calib = 1;
+}
+
+static void iwl4965_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int ret = 0;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!iwl_is_associated_ctx(ctx)) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		ret = iwl_send_rxon_timing(priv, ctx);
+		if (ret)
+			IWL_WARN(priv, "RXON timing failed - "
+					"Attempting to continue.\n");
+
+		/* AP has all antennas */
+		priv->chain_noise_data.active_chains =
+			priv->hw_params.valid_rx_ant;
+		iwl_set_rxon_ht(priv, &priv->current_ht_config);
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* need to send beacon cmd before committing assoc RXON! */
+		iwlagn_send_beacon_cmd(priv);
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwlcore_commit_rxon(priv, ctx);
+	}
+	iwlagn_send_beacon_cmd(priv);
+
+	/* FIXME - we need to add code here to detect a totally new
+	 * configuration, reset the AP, unassoc, rxon timing, assoc,
+	 * clear sta table, add BCAST sta... */
+}
+
 static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
 	.get_hcmd_size = iwl4965_get_hcmd_size,
 	.get_hcmd_size = iwl4965_get_hcmd_size,
 	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
 	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
 	.chain_noise_reset = iwl4965_chain_noise_reset,
 	.chain_noise_reset = iwl4965_chain_noise_reset,
 	.gain_computation = iwl4965_gain_computation,
 	.gain_computation = iwl4965_gain_computation,
-	.tx_cmd_protection = iwlcore_tx_cmd_protection,
+	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
 	.calc_rssi = iwl4965_calc_rssi,
 	.calc_rssi = iwl4965_calc_rssi,
 	.request_scan = iwlagn_request_scan,
 	.request_scan = iwlagn_request_scan,
 	.post_scan = iwl4965_post_scan,
 	.post_scan = iwl4965_post_scan,
@@ -2285,14 +2545,12 @@ static struct iwl_lib_ops iwl4965_lib = {
 	},
 	},
 	.send_tx_power	= iwl4965_send_tx_power,
 	.send_tx_power	= iwl4965_send_tx_power,
 	.update_chain_flags = iwl_update_chain_flags,
 	.update_chain_flags = iwl_update_chain_flags,
-	.post_associate = iwl_post_associate,
-	.config_ap = iwl_config_ap,
-	.isr = iwl_isr_legacy,
+	.isr_ops = {
+		.isr = iwl_isr_legacy,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwl4965_temperature_calib,
 		.temperature = iwl4965_temperature_calib,
 	},
 	},
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -2304,11 +2562,43 @@ static struct iwl_lib_ops iwl4965_lib = {
 	.check_plcp_health = iwl_good_plcp_health,
 	.check_plcp_health = iwl_good_plcp_health,
 };
 };
 
 
+static const struct iwl_legacy_ops iwl4965_legacy_ops = {
+	.post_associate = iwl4965_post_associate,
+	.config_ap = iwl4965_config_ap,
+	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_stations = iwl_update_bcast_stations,
+};
+
+struct ieee80211_ops iwl4965_hw_ops = {
+	.tx = iwlagn_mac_tx,
+	.start = iwlagn_mac_start,
+	.stop = iwlagn_mac_stop,
+	.add_interface = iwl_mac_add_interface,
+	.remove_interface = iwl_mac_remove_interface,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwlagn_configure_filter,
+	.set_key = iwlagn_mac_set_key,
+	.update_tkip_key = iwlagn_mac_update_tkip_key,
+	.conf_tx = iwl_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.ampdu_action = iwlagn_mac_ampdu_action,
+	.hw_scan = iwl_mac_hw_scan,
+	.sta_add = iwlagn_mac_sta_add,
+	.sta_remove = iwl_mac_sta_remove,
+	.channel_switch = iwlagn_mac_channel_switch,
+	.flush = iwlagn_mac_flush,
+	.tx_last_beacon = iwl_mac_tx_last_beacon,
+};
+
 static const struct iwl_ops iwl4965_ops = {
 static const struct iwl_ops iwl4965_ops = {
 	.lib = &iwl4965_lib,
 	.lib = &iwl4965_lib,
 	.hcmd = &iwl4965_hcmd,
 	.hcmd = &iwl4965_hcmd,
 	.utils = &iwl4965_hcmd_utils,
 	.utils = &iwl4965_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.legacy = &iwl4965_legacy_ops,
+	.ieee80211_ops = &iwl4965_hw_ops,
 };
 };
 
 
 static struct iwl_base_params iwl4965_base_params = {
 static struct iwl_base_params iwl4965_base_params = {

+ 16 - 10
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -385,14 +385,16 @@ static struct iwl_lib_ops iwl5000_lib = {
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 		.temperature = iwlagn_temperature,
 	 },
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -453,14 +455,16 @@ static struct iwl_lib_ops iwl5150_lib = {
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.calib_version	= iwlagn_eeprom_calib_version,
 		.query_addr = iwlagn_eeprom_query_addr,
 		.query_addr = iwlagn_eeprom_query_addr,
 	},
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwl5150_temperature,
 		.temperature = iwl5150_temperature,
 	 },
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -485,6 +489,7 @@ static const struct iwl_ops iwl5000_ops = {
 	.hcmd = &iwlagn_hcmd,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static const struct iwl_ops iwl5150_ops = {
 static const struct iwl_ops iwl5150_ops = {
@@ -492,6 +497,7 @@ static const struct iwl_ops iwl5150_ops = {
 	.hcmd = &iwlagn_hcmd,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static struct iwl_base_params iwl5000_base_params = {
 static struct iwl_base_params iwl5000_base_params = {

+ 25 - 21
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -53,13 +53,11 @@
 #define IWL6000_UCODE_API_MAX 4
 #define IWL6000_UCODE_API_MAX 4
 #define IWL6050_UCODE_API_MAX 5
 #define IWL6050_UCODE_API_MAX 5
 #define IWL6000G2_UCODE_API_MAX 5
 #define IWL6000G2_UCODE_API_MAX 5
-#define IWL130_UCODE_API_MAX 5
 
 
 /* Lowest firmware API version supported */
 /* Lowest firmware API version supported */
 #define IWL6000_UCODE_API_MIN 4
 #define IWL6000_UCODE_API_MIN 4
 #define IWL6050_UCODE_API_MIN 4
 #define IWL6050_UCODE_API_MIN 4
 #define IWL6000G2_UCODE_API_MIN 4
 #define IWL6000G2_UCODE_API_MIN 4
-#define IWL130_UCODE_API_MIN 5
 
 
 #define IWL6000_FW_PRE "iwlwifi-6000-"
 #define IWL6000_FW_PRE "iwlwifi-6000-"
 #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
 #define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode"
@@ -77,10 +75,6 @@
 #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
 #define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE #api ".ucode"
 #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
 #define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
 
 
-#define IWL130_FW_PRE "iwlwifi-130-"
-#define _IWL130_MODULE_FIRMWARE(api) IWL130_FW_PRE #api ".ucode"
-#define IWL130_MODULE_FIRMWARE(api) _IWL130_MODULE_FIRMWARE(api)
-
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
 {
 	/* want Celsius */
 	/* want Celsius */
@@ -328,14 +322,16 @@ static struct iwl_lib_ops iwl6000_lib = {
 		.query_addr = iwlagn_eeprom_query_addr,
 		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 		.temperature = iwlagn_temperature,
 	 },
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -399,14 +395,16 @@ static struct iwl_lib_ops iwl6000g2b_lib = {
 		.query_addr = iwlagn_eeprom_query_addr,
 		.query_addr = iwlagn_eeprom_query_addr,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
 	},
 	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
 	.temp_ops = {
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 		.temperature = iwlagn_temperature,
 	 },
 	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
 	.debugfs_ops = {
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -439,6 +437,7 @@ static const struct iwl_ops iwl6000_ops = {
 	.hcmd = &iwlagn_hcmd,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static const struct iwl_ops iwl6050_ops = {
 static const struct iwl_ops iwl6050_ops = {
@@ -447,6 +446,7 @@ static const struct iwl_ops iwl6050_ops = {
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
 	.nic = &iwl6050_nic_ops,
 	.nic = &iwl6050_nic_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static const struct iwl_ops iwl6050g2_ops = {
 static const struct iwl_ops iwl6050g2_ops = {
@@ -455,6 +455,7 @@ static const struct iwl_ops iwl6050g2_ops = {
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
 	.nic = &iwl6050g2_nic_ops,
 	.nic = &iwl6050g2_nic_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static const struct iwl_ops iwl6000g2b_ops = {
 static const struct iwl_ops iwl6000g2b_ops = {
@@ -462,6 +463,7 @@ static const struct iwl_ops iwl6000g2b_ops = {
 	.hcmd = &iwlagn_bt_hcmd,
 	.hcmd = &iwlagn_bt_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
 	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
 };
 };
 
 
 static struct iwl_base_params iwl6000_base_params = {
 static struct iwl_base_params iwl6000_base_params = {
@@ -485,6 +487,7 @@ static struct iwl_base_params iwl6000_base_params = {
 	.ucode_tracing = true,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
 };
 
 
 static struct iwl_base_params iwl6050_base_params = {
 static struct iwl_base_params iwl6050_base_params = {
@@ -508,6 +511,7 @@ static struct iwl_base_params iwl6050_base_params = {
 	.ucode_tracing = true,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
 };
 static struct iwl_base_params iwl6000_coex_base_params = {
 static struct iwl_base_params iwl6000_coex_base_params = {
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
@@ -530,6 +534,7 @@ static struct iwl_base_params iwl6000_coex_base_params = {
 	.ucode_tracing = true,
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
 };
 };
 
 
 static struct iwl_ht_params iwl6000_ht_params = {
 static struct iwl_ht_params iwl6000_ht_params = {
@@ -842,8 +847,8 @@ struct iwl_cfg iwl6000_3agn_cfg = {
 struct iwl_cfg iwl130_bgn_cfg = {
 struct iwl_cfg iwl130_bgn_cfg = {
 	.name = "Intel(R) 130 Series 1x1 BGN",
 	.name = "Intel(R) 130 Series 1x1 BGN",
 	.fw_name_pre = IWL6000G2B_FW_PRE,
 	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL130_UCODE_API_MAX,
-	.ucode_api_min = IWL130_UCODE_API_MIN,
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G|IWL_SKU_N,
 	.sku = IWL_SKU_G|IWL_SKU_N,
 	.valid_tx_ant = ANT_A,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_A,
 	.valid_rx_ant = ANT_A,
@@ -862,8 +867,8 @@ struct iwl_cfg iwl130_bgn_cfg = {
 struct iwl_cfg iwl130_bg_cfg = {
 struct iwl_cfg iwl130_bg_cfg = {
 	.name = "Intel(R) 130 Series 1x2 BG",
 	.name = "Intel(R) 130 Series 1x2 BG",
 	.fw_name_pre = IWL6000G2B_FW_PRE,
 	.fw_name_pre = IWL6000G2B_FW_PRE,
-	.ucode_api_max = IWL130_UCODE_API_MAX,
-	.ucode_api_min = IWL130_UCODE_API_MIN,
+	.ucode_api_max = IWL6000G2_UCODE_API_MAX,
+	.ucode_api_min = IWL6000G2_UCODE_API_MIN,
 	.sku = IWL_SKU_G,
 	.sku = IWL_SKU_G,
 	.valid_tx_ant = ANT_A,
 	.valid_tx_ant = ANT_A,
 	.valid_rx_ant = ANT_A,
 	.valid_rx_ant = ANT_A,
@@ -882,4 +887,3 @@ MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6000G2A_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
 MODULE_FIRMWARE(IWL6000G2B_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
-MODULE_FIRMWARE(IWL130_MODULE_FIRMWARE(IWL130_UCODE_API_MAX));

+ 124 - 106
drivers/net/wireless/iwlwifi/iwl-agn-calib.c

@@ -732,8 +732,122 @@ static inline u8 find_first_chain(u8 mask)
 	return CHAIN_C;
 	return CHAIN_C;
 }
 }
 
 
+/**
+ * Run disconnected antenna algorithm to find out which antennas are
+ * disconnected.
+ */
+static void iwl_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
+				     struct iwl_chain_noise_data *data)
+{
+	u32 active_chains = 0;
+	u32 max_average_sig;
+	u16 max_average_sig_antenna_i;
+	u8 num_tx_chains;
+	u8 first_chain;
+	u16 i = 0;
+
+	average_sig[0] = data->chain_signal_a /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[1] = data->chain_signal_b /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[2] = data->chain_signal_c /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+
+	if (average_sig[0] >= average_sig[1]) {
+		max_average_sig = average_sig[0];
+		max_average_sig_antenna_i = 0;
+		active_chains = (1 << max_average_sig_antenna_i);
+	} else {
+		max_average_sig = average_sig[1];
+		max_average_sig_antenna_i = 1;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	if (average_sig[2] >= max_average_sig) {
+		max_average_sig = average_sig[2];
+		max_average_sig_antenna_i = 2;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
+		     average_sig[0], average_sig[1], average_sig[2]);
+	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
+		     max_average_sig, max_average_sig_antenna_i);
+
+	/* Compare signal strengths for all 3 receivers. */
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (i != max_average_sig_antenna_i) {
+			s32 rssi_delta = (max_average_sig - average_sig[i]);
+
+			/* If signal is very weak, compared with
+			 * strongest, mark it as disconnected. */
+			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
+				data->disconn_array[i] = 1;
+			else
+				active_chains |= (1 << i);
+			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
+			     "disconn_array[i] = %d\n",
+			     i, rssi_delta, data->disconn_array[i]);
+		}
+	}
+
+	/*
+	 * The above algorithm sometimes fails when the ucode
+	 * reports 0 for all chains. It's not clear why that
+	 * happens to start with, but it is then causing trouble
+	 * because this can make us enable more chains than the
+	 * hardware really has.
+	 *
+	 * To be safe, simply mask out any chains that we know
+	 * are not on the device.
+	 */
+	active_chains &= priv->hw_params.valid_rx_ant;
+
+	num_tx_chains = 0;
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		/* loops on all the bits of
+		 * priv->hw_setting.valid_tx_ant */
+		u8 ant_msk = (1 << i);
+		if (!(priv->hw_params.valid_tx_ant & ant_msk))
+			continue;
+
+		num_tx_chains++;
+		if (data->disconn_array[i] == 0)
+			/* there is a Tx antenna connected */
+			break;
+		if (num_tx_chains == priv->hw_params.tx_chains_num &&
+		    data->disconn_array[i]) {
+			/*
+			 * If all chains are disconnected
+			 * connect the first valid tx chain
+			 */
+			first_chain =
+				find_first_chain(priv->cfg->valid_tx_ant);
+			data->disconn_array[first_chain] = 0;
+			active_chains |= BIT(first_chain);
+			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \
+					W/A - declare %d as connected\n",
+					first_chain);
+			break;
+		}
+	}
+
+	if (active_chains != priv->hw_params.valid_rx_ant &&
+	    active_chains != priv->chain_noise_data.active_chains)
+		IWL_DEBUG_CALIB(priv,
+				"Detected that not all antennas are connected! "
+				"Connected: %#x, valid: %#x.\n",
+				active_chains, priv->hw_params.valid_rx_ant);
+
+	/* Save for use within RXON, TX, SCAN commands, etc. */
+	data->active_chains = active_chains;
+	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
+			active_chains);
+}
+
+
 /*
 /*
- * Accumulate 20 beacons of signal and noise statistics for each of
+ * Accumulate 16 beacons of signal and noise statistics for each of
  *   3 receivers/antennas/rx-chains, then figure out:
  *   3 receivers/antennas/rx-chains, then figure out:
  * 1)  Which antennas are connected.
  * 1)  Which antennas are connected.
  * 2)  Differential rx gain settings to balance the 3 receivers.
  * 2)  Differential rx gain settings to balance the 3 receivers.
@@ -750,8 +864,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 	u32 chain_sig_c;
 	u32 chain_sig_c;
 	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
 	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
 	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
 	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
-	u32 max_average_sig;
-	u16 max_average_sig_antenna_i;
 	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
 	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
 	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
 	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
 	u16 i = 0;
 	u16 i = 0;
@@ -759,11 +871,9 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 	u16 stat_chnum = INITIALIZATION_VALUE;
 	u16 stat_chnum = INITIALIZATION_VALUE;
 	u8 rxon_band24;
 	u8 rxon_band24;
 	u8 stat_band24;
 	u8 stat_band24;
-	u32 active_chains = 0;
-	u8 num_tx_chains;
 	unsigned long flags;
 	unsigned long flags;
 	struct statistics_rx_non_phy *rx_info;
 	struct statistics_rx_non_phy *rx_info;
-	u8 first_chain;
+
 	/*
 	/*
 	 * MULTI-FIXME:
 	 * MULTI-FIXME:
 	 * When we support multiple interfaces on different channels,
 	 * When we support multiple interfaces on different channels,
@@ -869,108 +979,16 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
 		return;
 		return;
 
 
 	/* Analyze signal for disconnected antenna */
 	/* Analyze signal for disconnected antenna */
-	average_sig[0] = data->chain_signal_a /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-	average_sig[1] = data->chain_signal_b /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-	average_sig[2] = data->chain_signal_c /
-			 priv->cfg->base_params->chain_noise_num_beacons;
-
-	if (average_sig[0] >= average_sig[1]) {
-		max_average_sig = average_sig[0];
-		max_average_sig_antenna_i = 0;
-		active_chains = (1 << max_average_sig_antenna_i);
-	} else {
-		max_average_sig = average_sig[1];
-		max_average_sig_antenna_i = 1;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	if (average_sig[2] >= max_average_sig) {
-		max_average_sig = average_sig[2];
-		max_average_sig_antenna_i = 2;
-		active_chains = (1 << max_average_sig_antenna_i);
-	}
-
-	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
-		     average_sig[0], average_sig[1], average_sig[2]);
-	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
-		     max_average_sig, max_average_sig_antenna_i);
-
-	/* Compare signal strengths for all 3 receivers. */
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		if (i != max_average_sig_antenna_i) {
-			s32 rssi_delta = (max_average_sig - average_sig[i]);
-
-			/* If signal is very weak, compared with
-			 * strongest, mark it as disconnected. */
-			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
-				data->disconn_array[i] = 1;
-			else
-				active_chains |= (1 << i);
-			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
-			     "disconn_array[i] = %d\n",
-			     i, rssi_delta, data->disconn_array[i]);
-		}
-	}
-
-	/*
-	 * The above algorithm sometimes fails when the ucode
-	 * reports 0 for all chains. It's not clear why that
-	 * happens to start with, but it is then causing trouble
-	 * because this can make us enable more chains than the
-	 * hardware really has.
-	 *
-	 * To be safe, simply mask out any chains that we know
-	 * are not on the device.
-	 */
 	if (priv->cfg->bt_params &&
 	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
-	    priv->bt_full_concurrent) {
-		/* operated as 1x1 in full concurrency mode */
-		active_chains &= first_antenna(priv->hw_params.valid_rx_ant);
+	    priv->cfg->bt_params->advanced_bt_coexist) {
+		/* Disable disconnected antenna algorithm for advanced
+		   bt coex, assuming valid antennas are connected */
+		data->active_chains = priv->hw_params.valid_rx_ant;
+		for (i = 0; i < NUM_RX_CHAINS; i++)
+			if (!(data->active_chains & (1<<i)))
+				data->disconn_array[i] = 1;
 	} else
 	} else
-		active_chains &= priv->hw_params.valid_rx_ant;
-
-	num_tx_chains = 0;
-	for (i = 0; i < NUM_RX_CHAINS; i++) {
-		/* loops on all the bits of
-		 * priv->hw_setting.valid_tx_ant */
-		u8 ant_msk = (1 << i);
-		if (!(priv->hw_params.valid_tx_ant & ant_msk))
-			continue;
-
-		num_tx_chains++;
-		if (data->disconn_array[i] == 0)
-			/* there is a Tx antenna connected */
-			break;
-		if (num_tx_chains == priv->hw_params.tx_chains_num &&
-		    data->disconn_array[i]) {
-			/*
-			 * If all chains are disconnected
-			 * connect the first valid tx chain
-			 */
-			first_chain =
-				find_first_chain(priv->cfg->valid_tx_ant);
-			data->disconn_array[first_chain] = 0;
-			active_chains |= BIT(first_chain);
-			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - declare %d as connected\n",
-					first_chain);
-			break;
-		}
-	}
-
-	if (active_chains != priv->hw_params.valid_rx_ant &&
-	    active_chains != priv->chain_noise_data.active_chains)
-		IWL_DEBUG_CALIB(priv,
-				"Detected that not all antennas are connected! "
-				"Connected: %#x, valid: %#x.\n",
-				active_chains, priv->hw_params.valid_rx_ant);
-
-	/* Save for use within RXON, TX, SCAN commands, etc. */
-	priv->chain_noise_data.active_chains = active_chains;
-	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
-			active_chains);
+		iwl_find_disconn_antenna(priv, average_sig, data);
 
 
 	/* Analyze noise for rx balance */
 	/* Analyze noise for rx balance */
 	average_noise[0] = data->chain_noise_a /
 	average_noise[0] = data->chain_noise_a /

+ 32 - 21
drivers/net/wireless/iwlwifi/iwl-agn-lib.c

@@ -496,6 +496,10 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 	struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
 	struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
 	u8 tx_ant_cfg_cmd;
 	u8 tx_ant_cfg_cmd;
 
 
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
 	/* half dBm need to multiply */
 	/* half dBm need to multiply */
 	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
 	tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
 
 
@@ -522,9 +526,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 	else
 	else
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 		tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
 
 
-	return  iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd,
-				       sizeof(tx_power_cmd), &tx_power_cmd,
-				       NULL);
+	return iwl_send_cmd_pdu(priv, tx_ant_cfg_cmd, sizeof(tx_power_cmd),
+				&tx_power_cmd);
 }
 }
 
 
 void iwlagn_temperature(struct iwl_priv *priv)
 void iwlagn_temperature(struct iwl_priv *priv)
@@ -750,6 +753,12 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv)
 	} else
 	} else
 		iwlagn_txq_ctx_reset(priv);
 		iwlagn_txq_ctx_reset(priv);
 
 
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* enable shadow regs in HW */
+		iwl_set_bit(priv, CSR_MAC_SHADOW_REG_CTRL,
+			0x800FFFFF);
+	}
+
 	set_bit(STATUS_INIT, &priv->status);
 	set_bit(STATUS_INIT, &priv->status);
 
 
 	return 0;
 	return 0;
@@ -1584,22 +1593,6 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 	return ret;
 	return ret;
 }
 }
 
 
-void iwlagn_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx;
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	for_each_context(priv, ctx)
-		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-			iwlagn_commit_rxon(priv, ctx);
-
-	if (priv->cfg->ops->hcmd->set_pan_params)
-		priv->cfg->ops->hcmd->set_pan_params(priv);
-}
-
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 			       struct ieee80211_vif *vif, bool add)
 			       struct ieee80211_vif *vif, bool add)
 {
 {
@@ -1884,12 +1877,20 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 	struct iwl_rxon_context *ctx;
 	struct iwl_rxon_context *ctx;
 	int smps_request = -1;
 	int smps_request = -1;
 
 
+	/*
+	 * Note: bt_traffic_load can be overridden by scan complete and
+	 * coex profile notifications. Ignore that since only bad consequence
+	 * can be not matching debug print with actual state.
+	 */
 	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
 	IWL_DEBUG_INFO(priv, "BT traffic load changes: %d\n",
 		       priv->bt_traffic_load);
 		       priv->bt_traffic_load);
 
 
 	switch (priv->bt_traffic_load) {
 	switch (priv->bt_traffic_load) {
 	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
 	case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
-		smps_request = IEEE80211_SMPS_AUTOMATIC;
+		if (priv->bt_status)
+			smps_request = IEEE80211_SMPS_DYNAMIC;
+		else
+			smps_request = IEEE80211_SMPS_AUTOMATIC;
 		break;
 		break;
 	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
 	case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
 		smps_request = IEEE80211_SMPS_DYNAMIC;
 		smps_request = IEEE80211_SMPS_DYNAMIC;
@@ -1906,6 +1907,16 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 
 
 	mutex_lock(&priv->mutex);
 	mutex_lock(&priv->mutex);
 
 
+	/*
+	 * We can not send command to firmware while scanning. When the scan
+	 * complete we will schedule this work again. We do check with mutex
+	 * locked to prevent new scan request to arrive. We do not check
+	 * STATUS_SCANNING to avoid race when queue_work two times from
+	 * different notifications, but quit and not perform any work at all.
+	 */
+	if (test_bit(STATUS_SCAN_HW, &priv->status))
+		goto out;
+
 	if (priv->cfg->ops->lib->update_chain_flags)
 	if (priv->cfg->ops->lib->update_chain_flags)
 		priv->cfg->ops->lib->update_chain_flags(priv);
 		priv->cfg->ops->lib->update_chain_flags(priv);
 
 
@@ -1915,7 +1926,7 @@ static void iwlagn_bt_traffic_change_work(struct work_struct *work)
 				ieee80211_request_smps(ctx->vif, smps_request);
 				ieee80211_request_smps(ctx->vif, smps_request);
 		}
 		}
 	}
 	}
-
+out:
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 }
 }
 
 

+ 619 - 0
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c

@@ -0,0 +1,619 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-agn.h"
+#include "iwl-sta.h"
+#include "iwl-core.h"
+#include "iwl-agn-calib.h"
+
+static int iwlagn_disable_bss(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_rxon_cmd *send)
+{
+	__le32 old_filter = send->filter_flags;
+	int ret;
+
+	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+
+	send->filter_flags = old_filter;
+
+	if (ret)
+		IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
+
+	return ret;
+}
+
+static int iwlagn_disable_pan(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_rxon_cmd *send)
+{
+	__le32 old_filter = send->filter_flags;
+	u8 old_dev_type = send->dev_type;
+	int ret;
+
+	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	send->dev_type = RXON_DEV_TYPE_P2P;
+	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
+
+	send->filter_flags = old_filter;
+	send->dev_type = old_dev_type;
+
+	if (ret)
+		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
+
+	/* FIXME: WAIT FOR PAN DISABLE */
+	msleep(300);
+
+	return ret;
+}
+
+static int iwlagn_update_beacon(struct iwl_priv *priv,
+				struct ieee80211_vif *vif)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
+	if (!priv->beacon_skb)
+		return -ENOMEM;
+	return iwlagn_send_beacon_cmd(priv);
+}
+
+/**
+ * iwlagn_commit_rxon - commit staging_rxon to hardware
+ *
+ * The RXON command in staging_rxon is committed to the hardware and
+ * the active_rxon structure is updated with the new data.  This
+ * function correctly transitions out of the RXON_ASSOC_MSK state if
+ * a HW tune is required based on the RXON structure changes.
+ */
+int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_rxon_cmd *active = (void *)&ctx->active;
+	bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!iwl_is_alive(priv))
+		return -EBUSY;
+
+	/* This function hardcodes a bunch of dual-mode assumptions */
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
+	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
+		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+	ret = iwl_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
+		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 != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_chswitch_done(priv, false);
+	}
+
+	/*
+	 * If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration.
+	 */
+	if (!iwl_full_rxon_required(priv, ctx)) {
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active, &ctx->staging, sizeof(*active));
+		iwl_print_rx_config_cmd(priv, ctx);
+		return 0;
+	}
+
+	if (priv->cfg->ops->hcmd->set_pan_params) {
+		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
+		if (ret)
+			return ret;
+	}
+
+	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
+
+	IWL_DEBUG_INFO(priv,
+		       "Going to commit RXON\n"
+		       "  * with%s RXON_FILTER_ASSOC_MSK\n"
+		       "  * channel = %d\n"
+		       "  * bssid = %pM\n",
+		       (new_assoc ? "" : "out"),
+		       le16_to_cpu(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	/*
+	 * Always clear associated first, but with the correct config.
+	 * This is required as for example station addition for the
+	 * AP station must be done after the BSSID is set to correctly
+	 * set up filters in the device.
+	 */
+	if (ctx->ctxid == IWL_RXON_CTX_BSS)
+		ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
+	else
+		ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
+	if (ret)
+		return ret;
+
+	memcpy(active, &ctx->staging, sizeof(*active));
+
+	/*
+	 * Un-assoc RXON clears the station table and WEP
+	 * keys, so we have to restore those afterwards.
+	 */
+	iwl_clear_ucode_stations(priv, ctx);
+	iwl_restore_stations(priv, ctx);
+	ret = iwl_restore_default_wep_keys(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+		return ret;
+	}
+
+	/* RXON timing must be before associated RXON */
+	ret = iwl_send_rxon_timing(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
+		return ret;
+	}
+
+	if (new_assoc) {
+		/*
+		 * We'll run into this code path when beaconing is
+		 * enabled, but then we also need to send the beacon
+		 * to the device.
+		 */
+		if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
+			ret = iwlagn_update_beacon(priv, ctx->vif);
+			if (ret) {
+				IWL_ERR(priv,
+					"Error sending required beacon (%d)!\n",
+					ret);
+				return ret;
+			}
+		}
+
+		priv->start_calib = 0;
+		/*
+		 * Apply the new configuration.
+		 *
+		 * Associated RXON doesn't clear the station table in uCode,
+		 * so we don't need to restore stations etc. after this.
+		 */
+		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active, &ctx->staging, sizeof(*active));
+
+		/* IBSS beacon needs to be sent after setting assoc */
+		if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
+			if (iwlagn_update_beacon(priv, ctx->vif))
+				IWL_ERR(priv, "Error sending IBSS beacon\n");
+	}
+
+	iwl_print_rx_config_cmd(priv, ctx);
+
+	iwl_init_sensitivity(priv);
+
+	/*
+	 * If we issue a new RXON command which required a tune then we must
+	 * send a new TXPOWER command or we won't be able to Tx any frames.
+	 *
+	 * FIXME: which RXON requires a tune? Can we optimise this out in
+	 *        some cases?
+	 */
+	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void iwlagn_update_qos(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx)
+{
+	int ret;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm);
+	if (ret)
+		IWL_ERR(priv, "Failed to update QoS\n");
+}
+
+int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = conf->channel;
+	const struct iwl_channel_info *ch_info;
+	int ret = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
+
+	mutex_lock(&priv->mutex);
+
+	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+		goto out;
+	}
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+		unsigned long flags;
+
+		ch_info = iwl_get_channel_info(priv, channel->band,
+					       channel->hw_value);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* if we are switching from ht to 2.4 clear flags
+			 * from any ht related info since 2.4 does not
+			 * support ht */
+			if (le16_to_cpu(ctx->staging.channel) !=
+			    channel->hw_value)
+				ctx->staging.flags = 0;
+
+			iwl_set_rxon_channel(priv, channel, ctx);
+			iwl_set_rxon_ht(priv, &priv->current_ht_config);
+
+			iwl_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		iwl_update_bcast_stations(priv);
+
+		/*
+		 * The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists.
+		 */
+		iwl_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_set_tx_power(priv, conf->power_level, false);
+	}
+
+	for_each_context(priv, ctx) {
+		if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+			continue;
+		iwlagn_commit_rxon(priv, ctx);
+		if (ht_changed[ctx->ctxid])
+			iwlagn_update_qos(priv, ctx);
+	}
+ out:
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+
+static void iwlagn_check_needed_chains(struct iwl_priv *priv,
+				       struct iwl_rxon_context *ctx,
+				       struct ieee80211_bss_conf *bss_conf)
+{
+	struct ieee80211_vif *vif = ctx->vif;
+	struct iwl_rxon_context *tmp;
+	struct ieee80211_sta *sta;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	bool need_multiple;
+
+	lockdep_assert_held(&priv->mutex);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			need_multiple = true;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				need_multiple = false;
+			if (maxstreams <= 1)
+				need_multiple = false;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			need_multiple = false;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		/* currently */
+		need_multiple = false;
+		break;
+	default:
+		/* only AP really */
+		need_multiple = true;
+		break;
+	}
+
+	ctx->ht_need_multiple_chains = need_multiple;
+
+	if (!need_multiple) {
+		/* check all contexts */
+		for_each_context(priv, tmp) {
+			if (!tmp->vif)
+				continue;
+			if (tmp->ht_need_multiple_chains) {
+				need_multiple = true;
+				break;
+			}
+		}
+	}
+
+	ht_conf->single_chain_sufficient = !need_multiple;
+}
+
+void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *bss_conf,
+			     u32 changes)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	int ret;
+	bool force = false;
+
+	mutex_lock(&priv->mutex);
+
+	if (changes & BSS_CHANGED_BEACON_INT)
+		force = true;
+
+	if (changes & BSS_CHANGED_QOS) {
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwlagn_update_qos(priv, ctx);
+	}
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		if (bss_conf->assoc) {
+			iwl_led_associate(priv);
+			priv->timestamp = bss_conf->timestamp;
+			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		} else {
+			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+			iwl_led_disassociate(priv);
+		}
+	}
+
+	if (ctx->ht.enabled) {
+		ctx->ht.protection = bss_conf->ht_operation_mode &
+					IEEE80211_HT_OP_MODE_PROTECTION;
+		ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
+					IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+		iwlagn_check_needed_chains(priv, ctx, bss_conf);
+		iwl_set_rxon_ht(priv, &priv->current_ht_config);
+	}
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+		ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+
+	if (bss_conf->use_cts_prot)
+		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+
+	memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
+
+	if (vif->type == NL80211_IFTYPE_AP ||
+	    vif->type == NL80211_IFTYPE_ADHOC) {
+		if (vif->bss_conf.enable_beacon) {
+			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+			priv->beacon_ctx = ctx;
+		} else {
+			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+			priv->beacon_ctx = NULL;
+		}
+	}
+
+	if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwlagn_commit_rxon(priv, ctx);
+
+	if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
+		/*
+		 * The chain noise calibration will enable PM upon
+		 * completion. If calibration has already been run
+		 * then we need to enable power management here.
+		 */
+		if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
+			iwl_power_update_mode(priv, false);
+
+		/* Enable RX differential gain and sensitivity calibrations */
+		iwl_chain_noise_reset(priv);
+		priv->start_calib = 1;
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = iwlagn_manage_ibss_station(priv, vif,
+						 bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
+	    priv->beacon_ctx) {
+		if (iwlagn_update_beacon(priv, vif))
+			IWL_ERR(priv, "Error sending IBSS beacon\n");
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+void iwlagn_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	for_each_context(priv, ctx)
+		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+			iwlagn_commit_rxon(priv, ctx);
+
+	if (priv->cfg->ops->hcmd->set_pan_params)
+		priv->cfg->ops->hcmd->set_pan_params(priv);
+}

+ 31 - 1
drivers/net/wireless/iwlwifi/iwl-agn-sta.c

@@ -684,7 +684,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 }
 
 
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 
 
@@ -714,3 +714,33 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 
 }
 }
+
+void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   enum sta_notify_cmd cmd,
+			   struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	int sta_id;
+
+	switch (cmd) {
+	case STA_NOTIFY_SLEEP:
+		WARN_ON(!sta_priv->client);
+		sta_priv->asleep = true;
+		if (atomic_read(&sta_priv->pending_frames) > 0)
+			ieee80211_sta_block_awake(hw, sta, true);
+		break;
+	case STA_NOTIFY_AWAKE:
+		WARN_ON(!sta_priv->client);
+		if (!sta_priv->asleep)
+			break;
+		sta_priv->asleep = false;
+		sta_id = iwl_sta_id(sta);
+		if (sta_id != IWL_INVALID_STATION)
+			iwl_sta_modify_ps_wake(priv, sta_id);
+		break;
+	default:
+		break;
+	}
+}

+ 75 - 418
drivers/net/wireless/iwlwifi/iwl-agn.c

@@ -90,170 +90,6 @@ MODULE_ALIAS("iwl4965");
 static int iwlagn_ant_coupling;
 static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
 static bool iwlagn_bt_ch_announce = 1;
 
 
-/**
- * iwlagn_commit_rxon - commit staging_rxon to hardware
- *
- * The RXON command in staging_rxon is committed to the hardware and
- * the active_rxon structure is updated with the new data.  This
- * function correctly transitions out of the RXON_ASSOC_MSK state if
- * a HW tune is required based on the RXON structure changes.
- */
-int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
-	int ret;
-	bool new_assoc =
-		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-	bool old_assoc = !!(ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (!iwl_is_alive(priv))
-		return -EBUSY;
-
-	if (!ctx->is_active)
-		return 0;
-
-	/* always get timestamp with Rx frame */
-	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
-
-	ret = iwl_check_rxon_cmd(priv, ctx);
-	if (ret) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		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 != ctx->staging.channel)) {
-		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-		      le16_to_cpu(priv->switch_rxon.channel));
-		iwl_chswitch_done(priv, false);
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv, ctx)) {
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
-			return ret;
-		}
-
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_print_rx_config_cmd(priv, ctx);
-		return 0;
-	}
-
-	/* If we are currently associated and the new config requires
-	 * an RXON_ASSOC and the new config wants the associated mask enabled,
-	 * we must clear the associated from the active configuration
-	 * before we apply the new config */
-	if (iwl_is_associated_ctx(ctx) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-				       sizeof(struct iwl_rxon_cmd),
-				       active_rxon);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (ret) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
-			return ret;
-		}
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "Sending RXON\n"
-		       "* with%s RXON_FILTER_ASSOC_MSK\n"
-		       "* channel = %d\n"
-		       "* bssid = %pM\n",
-		       (new_assoc ? "" : "out"),
-		       le16_to_cpu(ctx->staging.channel),
-		       ctx->staging.bssid_addr);
-
-	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
-
-	if (!old_assoc) {
-		/*
-		 * First of all, before setting associated, we need to
-		 * send RXON timing so the device knows about the DTIM
-		 * period and other timing values
-		 */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON timing!\n");
-			return ret;
-		}
-	}
-
-	if (priv->cfg->ops->hcmd->set_pan_params) {
-		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
-		if (ret)
-			return ret;
-	}
-
-	/* Apply the new configuration
-	 * RXON unassoc clears the station table in uCode so restoration of
-	 * stations is needed after it (the RXON command) completes
-	 */
-	if (!new_assoc) {
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-	if (new_assoc) {
-		priv->start_calib = 0;
-		/* Apply the new configuration
-		 * RXON assoc doesn't clear the station table in uCode,
-		 */
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-	}
-	iwl_print_rx_config_cmd(priv, ctx);
-
-	iwl_init_sensitivity(priv);
-
-	/* If we issue a new RXON command which required a tune then we must
-	 * send a new TXPOWER command or we won't be able to Tx any frames */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-	if (ret) {
-		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
 void iwl_update_chain_flags(struct iwl_priv *priv)
 void iwl_update_chain_flags(struct iwl_priv *priv)
 {
 {
 	struct iwl_rxon_context *ctx;
 	struct iwl_rxon_context *ctx;
@@ -411,7 +247,8 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
 
 
 	return sizeof(*tx_beacon_cmd) + frame_size;
 	return sizeof(*tx_beacon_cmd) + frame_size;
 }
 }
-static int iwl_send_beacon_cmd(struct iwl_priv *priv)
+
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
 {
 {
 	struct iwl_frame *frame;
 	struct iwl_frame *frame;
 	unsigned int frame_size;
 	unsigned int frame_size;
@@ -661,7 +498,7 @@ static void iwl_bg_beacon_update(struct work_struct *work)
 
 
 	priv->beacon_skb = beacon;
 	priv->beacon_skb = beacon;
 
 
-	iwl_send_beacon_cmd(priv);
+	iwlagn_send_beacon_cmd(priv);
  out:
  out:
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 }
 }
@@ -2978,7 +2815,8 @@ static void __iwl_down(struct iwl_priv *priv)
 				STATUS_EXIT_PENDING;
 				STATUS_EXIT_PENDING;
 
 
 	/* device going down, Stop using ICT table */
 	/* device going down, Stop using ICT table */
-	iwl_disable_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.disable)
+		priv->cfg->ops->lib->isr_ops.disable(priv);
 
 
 	iwlagn_txq_ctx_stop(priv);
 	iwlagn_txq_ctx_stop(priv);
 	iwlagn_rxq_stop(priv);
 	iwlagn_rxq_stop(priv);
@@ -3201,7 +3039,8 @@ static void iwl_bg_alive_start(struct work_struct *data)
 		return;
 		return;
 
 
 	/* enable dram interrupt */
 	/* enable dram interrupt */
-	iwl_reset_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.reset)
+		priv->cfg->ops->lib->isr_ops.reset(priv);
 
 
 	mutex_lock(&priv->mutex);
 	mutex_lock(&priv->mutex);
 	iwl_alive_start(priv);
 	iwl_alive_start(priv);
@@ -3309,92 +3148,6 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 }
 }
 
 
-#define IWL_DELAY_NEXT_SCAN (HZ*2)
-
-void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx;
-	struct ieee80211_conf *conf = NULL;
-	int ret = 0;
-
-	if (!vif || !priv->is_open)
-		return;
-
-	ctx = iwl_rxon_ctx_from_vif(vif);
-
-	if (vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	ret = iwl_send_rxon_timing(priv, ctx);
-	if (ret)
-		IWL_WARN(priv, "RXON timing - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	iwl_set_rxon_ht(priv, &priv->current_ht_config);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
-
-	if (vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwlcore_commit_rxon(priv, ctx);
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwl_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			  __func__, vif->type);
-		break;
-	}
-
-	/* the chain noise calibration will enabled PM upon completion
-	 * If chain noise has already been run, then we need to enable
-	 * power management here */
-	if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
-		iwl_power_update_mode(priv, false);
-
-	/* Enable Rx differential gain and sensitivity calibrations */
-	iwl_chain_noise_reset(priv);
-	priv->start_calib = 1;
-
-}
-
 /*****************************************************************************
 /*****************************************************************************
  *
  *
  * mac80211 entry point functions
  * mac80211 entry point functions
@@ -3474,7 +3227,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
 }
 }
 
 
 
 
-static int iwl_mac_start(struct ieee80211_hw *hw)
+int iwlagn_mac_start(struct ieee80211_hw *hw)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	int ret;
 	int ret;
@@ -3515,7 +3268,7 @@ out:
 	return 0;
 	return 0;
 }
 }
 
 
-static void iwl_mac_stop(struct ieee80211_hw *hw)
+void iwlagn_mac_stop(struct ieee80211_hw *hw)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 
 
@@ -3537,7 +3290,7 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 }
 
 
-static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 
 
@@ -3553,73 +3306,12 @@ static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 
-void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret = 0;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!iwl_is_associated_ctx(ctx)) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret)
-			IWL_WARN(priv, "RXON timing failed - "
-					"Attempting to continue.\n");
-
-		/* AP has all antennas */
-		priv->chain_noise_data.active_chains =
-			priv->hw_params.valid_rx_ant;
-		iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* need to send beacon cmd before committing assoc RXON! */
-		iwl_send_beacon_cmd(priv);
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-	}
-	iwl_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
-				    struct ieee80211_vif *vif,
-				    struct ieee80211_key_conf *keyconf,
-				    struct ieee80211_sta *sta,
-				    u32 iv32, u16 *phase1key)
+void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key)
 {
 {
-
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 
 
@@ -3631,10 +3323,9 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 }
 
 
-static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
-			   struct ieee80211_vif *vif,
-			   struct ieee80211_sta *sta,
-			   struct ieee80211_key_conf *key)
+int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
@@ -3701,10 +3392,10 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	return ret;
 	return ret;
 }
 }
 
 
-static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
-				struct ieee80211_vif *vif,
-				enum ieee80211_ampdu_mlme_action action,
-				struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
 	int ret = -EINVAL;
@@ -3785,39 +3476,9 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 	return ret;
 	return ret;
 }
 }
 
 
-static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       enum sta_notify_cmd cmd,
-			       struct ieee80211_sta *sta)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
-	int sta_id;
-
-	switch (cmd) {
-	case STA_NOTIFY_SLEEP:
-		WARN_ON(!sta_priv->client);
-		sta_priv->asleep = true;
-		if (atomic_read(&sta_priv->pending_frames) > 0)
-			ieee80211_sta_block_awake(hw, sta, true);
-		break;
-	case STA_NOTIFY_AWAKE:
-		WARN_ON(!sta_priv->client);
-		if (!sta_priv->asleep)
-			break;
-		sta_priv->asleep = false;
-		sta_id = iwl_sta_id(sta);
-		if (sta_id != IWL_INVALID_STATION)
-			iwl_sta_modify_ps_wake(priv, sta_id);
-		break;
-	default:
-		break;
-	}
-}
-
-static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      struct ieee80211_sta *sta)
+int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
 	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
@@ -3858,8 +3519,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
 	return 0;
 	return 0;
 }
 }
 
 
-static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
-				   struct ieee80211_channel_switch *ch_switch)
+void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	const struct iwl_channel_info *ch_info;
 	const struct iwl_channel_info *ch_info;
@@ -3956,10 +3617,10 @@ out_exit:
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 }
 
 
-static void iwlagn_configure_filter(struct ieee80211_hw *hw,
-				    unsigned int changed_flags,
-				    unsigned int *total_flags,
-				    u64 multicast)
+void iwlagn_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	__le32 filter_or = 0, filter_nand = 0;
 	__le32 filter_or = 0, filter_nand = 0;
@@ -3986,7 +3647,11 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
 	for_each_context(priv, ctx) {
 	for_each_context(priv, ctx) {
 		ctx->staging.filter_flags &= ~filter_nand;
 		ctx->staging.filter_flags &= ~filter_nand;
 		ctx->staging.filter_flags |= filter_or;
 		ctx->staging.filter_flags |= filter_or;
-		iwlcore_commit_rxon(priv, ctx);
+
+		/*
+		 * Not committing directly because hardware can perform a scan,
+		 * but we'll eventually commit the filter flags change anyway.
+		 */
 	}
 	}
 
 
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
@@ -4001,7 +3666,7 @@ static void iwlagn_configure_filter(struct ieee80211_hw *hw,
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
 }
 
 
-static void iwl_mac_flush(struct ieee80211_hw *hw, bool drop)
+void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 
 
@@ -4179,6 +3844,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
 	 * this value will get overwritten by channel max power avg
 	 * this value will get overwritten by channel max power avg
 	 * from eeprom */
 	 * from eeprom */
 	priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
 	priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
+	priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
 
 
 	ret = iwl_init_channel_map(priv);
 	ret = iwl_init_channel_map(priv);
 	if (ret) {
 	if (ret) {
@@ -4209,28 +3875,30 @@ static void iwl_uninit_drv(struct iwl_priv *priv)
 	kfree(priv->scan_cmd);
 	kfree(priv->scan_cmd);
 }
 }
 
 
-static struct ieee80211_ops iwl_hw_ops = {
-	.tx = iwl_mac_tx,
-	.start = iwl_mac_start,
-	.stop = iwl_mac_stop,
+#ifdef CONFIG_IWL5000
+struct ieee80211_ops iwlagn_hw_ops = {
+	.tx = iwlagn_mac_tx,
+	.start = iwlagn_mac_start,
+	.stop = iwlagn_mac_stop,
 	.add_interface = iwl_mac_add_interface,
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
 	.remove_interface = iwl_mac_remove_interface,
-	.config = iwl_mac_config,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwlagn_mac_config,
 	.configure_filter = iwlagn_configure_filter,
 	.configure_filter = iwlagn_configure_filter,
-	.set_key = iwl_mac_set_key,
-	.update_tkip_key = iwl_mac_update_tkip_key,
+	.set_key = iwlagn_mac_set_key,
+	.update_tkip_key = iwlagn_mac_update_tkip_key,
 	.conf_tx = iwl_mac_conf_tx,
 	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_mac_reset_tsf,
-	.bss_info_changed = iwl_bss_info_changed,
-	.ampdu_action = iwl_mac_ampdu_action,
+	.bss_info_changed = iwlagn_bss_info_changed,
+	.ampdu_action = iwlagn_mac_ampdu_action,
 	.hw_scan = iwl_mac_hw_scan,
 	.hw_scan = iwl_mac_hw_scan,
-	.sta_notify = iwl_mac_sta_notify,
+	.sta_notify = iwlagn_mac_sta_notify,
 	.sta_add = iwlagn_mac_sta_add,
 	.sta_add = iwlagn_mac_sta_add,
 	.sta_remove = iwl_mac_sta_remove,
 	.sta_remove = iwl_mac_sta_remove,
-	.channel_switch = iwl_mac_channel_switch,
-	.flush = iwl_mac_flush,
+	.channel_switch = iwlagn_mac_channel_switch,
+	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwl_mac_tx_last_beacon,
 	.tx_last_beacon = iwl_mac_tx_last_beacon,
 };
 };
+#endif
 
 
 static void iwl_hw_detect(struct iwl_priv *priv)
 static void iwl_hw_detect(struct iwl_priv *priv)
 {
 {
@@ -4298,10 +3966,15 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	if (cfg->mod_params->disable_hw_scan) {
 	if (cfg->mod_params->disable_hw_scan) {
 		dev_printk(KERN_DEBUG, &(pdev->dev),
 		dev_printk(KERN_DEBUG, &(pdev->dev),
 			"sw scan support is deprecated\n");
 			"sw scan support is deprecated\n");
-		iwl_hw_ops.hw_scan = NULL;
+#ifdef CONFIG_IWL5000
+		iwlagn_hw_ops.hw_scan = NULL;
+#endif
+#ifdef CONFIG_IWL4965
+		iwl4965_hw_ops.hw_scan = NULL;
+#endif
 	}
 	}
 
 
-	hw = iwl_alloc_all(cfg, &iwl_hw_ops);
+	hw = iwl_alloc_all(cfg);
 	if (!hw) {
 	if (!hw) {
 		err = -ENOMEM;
 		err = -ENOMEM;
 		goto out;
 		goto out;
@@ -4333,6 +4006,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 		BIT(NL80211_IFTYPE_ADHOC);
 		BIT(NL80211_IFTYPE_ADHOC);
 	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
 	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
 		BIT(NL80211_IFTYPE_STATION);
 		BIT(NL80211_IFTYPE_STATION);
+	priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
 	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
 	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
 	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
 	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
 	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
 	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
@@ -4500,8 +4174,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
 
 	pci_enable_msi(priv->pci_dev);
 	pci_enable_msi(priv->pci_dev);
 
 
-	iwl_alloc_isr_ict(priv);
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+	if (priv->cfg->ops->lib->isr_ops.alloc)
+		priv->cfg->ops->lib->isr_ops.alloc(priv);
+
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
 			  IRQF_SHARED, DRV_NAME, priv);
 			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -4548,7 +4224,8 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 	destroy_workqueue(priv->workqueue);
 	destroy_workqueue(priv->workqueue);
 	priv->workqueue = NULL;
 	priv->workqueue = NULL;
 	free_irq(priv->pci_dev->irq, priv);
 	free_irq(priv->pci_dev->irq, priv);
-	iwl_free_isr_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.free)
+		priv->cfg->ops->lib->isr_ops.free(priv);
  out_disable_msi:
  out_disable_msi:
 	pci_disable_msi(priv->pci_dev);
 	pci_disable_msi(priv->pci_dev);
 	iwl_uninit_drv(priv);
 	iwl_uninit_drv(priv);
@@ -4643,7 +4320,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
 
 
 	iwl_uninit_drv(priv);
 	iwl_uninit_drv(priv);
 
 
-	iwl_free_isr_ict(priv);
+	if (priv->cfg->ops->lib->isr_ops.free)
+		priv->cfg->ops->lib->isr_ops.free(priv);
 
 
 	dev_kfree_skb(priv->beacon_skb);
 	dev_kfree_skb(priv->beacon_skb);
 
 
@@ -4735,13 +4413,6 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)},
 
 
 /* 6x00 Series Gen2a */
 /* 6x00 Series Gen2a */
-	{IWL_PCI_DEVICE(0x0082, 0x1201, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1211, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1221, iwl6000g2a_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1206, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0085, 0x1216, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1226, iwl6000g2a_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0082, 0x1207, iwl6000g2a_2bg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1301, iwl6000g2a_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1306, iwl6000g2a_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)},
 	{IWL_PCI_DEVICE(0x0082, 0x1307, iwl6000g2a_2bg_cfg)},
@@ -4751,24 +4422,12 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0085, 0x1316, iwl6000g2a_2abg_cfg)},
 
 
 /* 6x00 Series Gen2b */
 /* 6x00 Series Gen2b */
-	{IWL_PCI_DEVICE(0x008F, 0x5105, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5115, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5125, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5107, iwl6000g2b_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5201, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5221, iwl6000g2b_2agn_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5206, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5226, iwl6000g2b_2abg_cfg)},
-	{IWL_PCI_DEVICE(0x008F, 0x5207, iwl6000g2b_2bg_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5301, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5305, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5307, iwl6000g2b_bg_cfg)},
-	{IWL_PCI_DEVICE(0x008A, 0x5321, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008A, 0x5325, iwl6000g2b_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x008B, 0x5311, iwl6000g2b_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008A, 0x5327, iwl6000g2b_bg_cfg)},
 	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x008B, 0x5315, iwl6000g2b_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x008B, 0x5317, iwl6000g2b_bg_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5211, iwl6000g2b_2agn_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5215, iwl6000g2b_2bgn_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
 	{IWL_PCI_DEVICE(0x0090, 0x5216, iwl6000g2b_2abg_cfg)},
@@ -4812,10 +4471,11 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
 
 
 /* 100 Series WiFi */
 /* 100 Series WiFi */
 	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x08AE, 0x1005, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
 	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x08AF, 0x1015, iwl100_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x08AF, 0x1017, iwl100_bg_cfg)},
 	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x08AE, 0x1025, iwl100_bgn_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1007, iwl100_bg_cfg)},
-	{IWL_PCI_DEVICE(0x08AE, 0x1017, iwl100_bg_cfg)},
+	{IWL_PCI_DEVICE(0x08AE, 0x1027, iwl100_bg_cfg)},
 
 
 /* 130 Series WiFi */
 /* 130 Series WiFi */
 	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x0896, 0x5005, iwl130_bgn_cfg)},
@@ -4836,10 +4496,7 @@ static struct pci_driver iwl_driver = {
 	.id_table = iwl_hw_card_ids,
 	.id_table = iwl_hw_card_ids,
 	.probe = iwl_pci_probe,
 	.probe = iwl_pci_probe,
 	.remove = __devexit_p(iwl_pci_remove),
 	.remove = __devexit_p(iwl_pci_remove),
-#ifdef CONFIG_PM
-	.suspend = iwl_pci_suspend,
-	.resume = iwl_pci_resume,
-#endif
+	.driver.pm = IWL_PM_OPS,
 };
 };
 
 
 static int __init iwl_init(void)
 static int __init iwl_init(void)

+ 40 - 1
drivers/net/wireless/iwlwifi/iwl-agn.h

@@ -102,6 +102,9 @@ extern struct iwl_hcmd_ops iwlagn_hcmd;
 extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
 extern struct iwl_hcmd_ops iwlagn_bt_hcmd;
 extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
 extern struct iwl_hcmd_utils_ops iwlagn_hcmd_utils;
 
 
+extern struct ieee80211_ops iwlagn_hw_ops;
+extern struct ieee80211_ops iwl4965_hw_ops;
+
 int iwl_reset_ict(struct iwl_priv *priv);
 int iwl_reset_ict(struct iwl_priv *priv);
 void iwl_disable_ict(struct iwl_priv *priv);
 void iwl_disable_ict(struct iwl_priv *priv);
 int iwl_alloc_isr_ict(struct iwl_priv *priv);
 int iwl_alloc_isr_ict(struct iwl_priv *priv);
@@ -132,6 +135,11 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
 /* RXON */
 /* RXON */
 int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
 void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_bss_conf *bss_conf,
+			     u32 changes);
 
 
 /* uCode */
 /* uCode */
 int iwlagn_load_ucode(struct iwl_priv *priv);
 int iwlagn_load_ucode(struct iwl_priv *priv);
@@ -249,6 +257,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv,
 int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
 int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
 			   struct iwl_rxon_context *ctx);
 			   struct iwl_rxon_context *ctx);
 int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
 int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant);
+int iwlagn_send_beacon_cmd(struct iwl_priv *priv);
 
 
 /* bt coex */
 /* bt coex */
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv);
@@ -292,9 +301,12 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			 int tid, u16 ssn);
 			 int tid, u16 ssn);
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid);
 			int tid);
-void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id);
 void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
 void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt);
 int iwl_update_bcast_stations(struct iwl_priv *priv);
 int iwl_update_bcast_stations(struct iwl_priv *priv);
+void iwlagn_mac_sta_notify(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif,
+			   enum sta_notify_cmd cmd,
+			   struct ieee80211_sta *sta);
 
 
 /* rate */
 /* rate */
 static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
 static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
@@ -318,4 +330,31 @@ void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
 int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
 int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
 void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
 void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
 
 
+/* mac80211 handlers (for 4965) */
+int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int iwlagn_mac_start(struct ieee80211_hw *hw);
+void iwlagn_mac_stop(struct ieee80211_hw *hw);
+void iwlagn_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast);
+int iwlagn_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key);
+void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key);
+int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta);
+void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
+void iwlagn_mac_flush(struct ieee80211_hw *hw, bool drop);
+
 #endif /* __iwl_agn_h__ */
 #endif /* __iwl_agn_h__ */

+ 153 - 688
drivers/net/wireless/iwlwifi/iwl-core.c

@@ -77,15 +77,15 @@ EXPORT_SYMBOL(iwl_bcast_addr);
 
 
 
 
 /* This function both allocates and initializes hw and priv. */
 /* This function both allocates and initializes hw and priv. */
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-		struct ieee80211_ops *hw_ops)
+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
 {
 {
 	struct iwl_priv *priv;
 	struct iwl_priv *priv;
-
 	/* mac80211 allocates memory for this device instance, including
 	/* mac80211 allocates memory for this device instance, including
 	 *   space for this driver's private structure */
 	 *   space for this driver's private structure */
-	struct ieee80211_hw *hw =
-		ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
+	struct ieee80211_hw *hw;
+
+	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
+				cfg->ops->ieee80211_ops);
 	if (hw == NULL) {
 	if (hw == NULL) {
 		pr_err("%s: Can not allocate network device\n",
 		pr_err("%s: Can not allocate network device\n",
 		       cfg->name);
 		       cfg->name);
@@ -100,35 +100,6 @@ out:
 }
 }
 EXPORT_SYMBOL(iwl_alloc_all);
 EXPORT_SYMBOL(iwl_alloc_all);
 
 
-/*
- * QoS  support
-*/
-static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!ctx->is_active)
-		return;
-
-	ctx->qos_data.def_qos_parm.qos_flags = 0;
-
-	if (ctx->qos_data.qos_active)
-		ctx->qos_data.def_qos_parm.qos_flags |=
-			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
-
-	if (ctx->ht.enabled)
-		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
-
-	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-		      ctx->qos_data.qos_active,
-		      ctx->qos_data.def_qos_parm.qos_flags);
-
-	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
-			       sizeof(struct iwl_qosparam_cmd),
-			       &ctx->qos_data.def_qos_parm, NULL);
-}
-
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
 static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
 static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
@@ -317,40 +288,6 @@ void iwlcore_free_geos(struct iwl_priv *priv)
 }
 }
 EXPORT_SYMBOL(iwlcore_free_geos);
 EXPORT_SYMBOL(iwlcore_free_geos);
 
 
-/*
- *  iwlcore_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
- *  function.
- */
-void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags)
-{
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		*tx_flags |= TX_CMD_FLG_RTS_MSK;
-		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
-		if (!ieee80211_is_mgmt(fc))
-			return;
-
-		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-		case cpu_to_le16(IEEE80211_STYPE_AUTH):
-		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-			*tx_flags |= TX_CMD_FLG_CTS_MSK;
-			break;
-		}
-	} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
-		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-		*tx_flags |= TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-	}
-}
-EXPORT_SYMBOL(iwlcore_tx_cmd_protection);
-
-
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
 				     enum ieee80211_band band,
 				     enum ieee80211_band band,
 				     u16 channel, u8 extension_chan_offset)
 				     u16 channel, u8 extension_chan_offset)
@@ -1206,8 +1143,16 @@ EXPORT_SYMBOL(iwl_apm_init);
 
 
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
 {
-	int ret = 0;
-	s8 prev_tx_power = priv->tx_power_user_lmt;
+	int ret;
+	s8 prev_tx_power;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->tx_power_user_lmt == tx_power && !force)
+		return 0;
+
+	if (!priv->cfg->ops->lib->send_tx_power)
+		return -EOPNOTSUPP;
 
 
 	if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
 	if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
 		IWL_WARN(priv,
 		IWL_WARN(priv,
@@ -1224,93 +1169,29 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (priv->tx_power_user_lmt != tx_power)
-		force = true;
+	if (!iwl_is_ready_rf(priv))
+		return -EIO;
 
 
-	/* if nic is not up don't send command */
-	if (iwl_is_ready_rf(priv)) {
-		priv->tx_power_user_lmt = tx_power;
-		if (force && priv->cfg->ops->lib->send_tx_power)
-			ret = priv->cfg->ops->lib->send_tx_power(priv);
-		else if (!priv->cfg->ops->lib->send_tx_power)
-			ret = -EOPNOTSUPP;
-		/*
-		 * if fail to set tx_power, restore the orig. tx power
-		 */
-		if (ret)
-			priv->tx_power_user_lmt = prev_tx_power;
+	/* scan complete use tx_power_next, need to be updated */
+	priv->tx_power_next = tx_power;
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+		return 0;
 	}
 	}
 
 
-	/*
-	 * Even this is an async host command, the command
-	 * will always report success from uCode
-	 * So once driver can placing the command into the queue
-	 * successfully, driver can use priv->tx_power_user_lmt
-	 * to reflect the current tx power
-	 */
-	return ret;
-}
-EXPORT_SYMBOL(iwl_set_tx_power);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	u32 inta_fh;
-	unsigned long flags;
-	if (!priv)
-		return IRQ_NONE;
+	prev_tx_power = priv->tx_power_user_lmt;
+	priv->tx_power_user_lmt = tx_power;
 
 
-	spin_lock_irqsave(&priv->lock, flags);
+	ret = priv->cfg->ops->lib->send_tx_power(priv);
 
 
-	/* Disable (but don't clear!) interrupts here to avoid
-	 *    back-to-back ISRs and sporadic interrupts from our NIC.
-	 * If we have something to service, the tasklet will re-enable ints.
-	 * If we *don't* have something, we'll re-enable before leaving here. */
-	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
-	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
-	/* Discover which interrupts are active/pending */
-	inta = iwl_read32(priv, CSR_INT);
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-
-	/* Ignore interrupt if there's nothing in NIC to service.
-	 * This may be due to IRQ shared with another device,
-	 * or due to sporadic interrupts thrown from our NIC. */
-	if (!inta && !inta_fh) {
-		IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n");
-		goto none;
+	/* if fail to set tx_power, restore the orig. tx power */
+	if (ret) {
+		priv->tx_power_user_lmt = prev_tx_power;
+		priv->tx_power_next = prev_tx_power;
 	}
 	}
-
-	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
-		/* Hardware disappeared. It might have already raised
-		 * an interrupt */
-		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-		goto unplugged;
-	}
-
-	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-		      inta, inta_mask, inta_fh);
-
-	inta &= ~CSR_INT_BIT_SCD;
-
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta || inta_fh))
-		tasklet_schedule(&priv->irq_tasklet);
-
- unplugged:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_HANDLED;
-
- none:
-	/* re-enable interrupts here since we don't have anything to service. */
-	/* only Re-enable if diabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
+	return ret;
 }
 }
-EXPORT_SYMBOL(iwl_isr_legacy);
+EXPORT_SYMBOL(iwl_set_tx_power);
 
 
 void iwl_send_bt_config(struct iwl_priv *priv)
 void iwl_send_bt_config(struct iwl_priv *priv)
 {
 {
@@ -1452,318 +1333,51 @@ int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
 }
 }
 EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
 EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
 
 
-static void iwl_ht_conf(struct iwl_priv *priv,
-			struct ieee80211_vif *vif)
+static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
 {
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct ieee80211_sta *sta;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	IWL_DEBUG_MAC80211(priv, "enter:\n");
-
-	if (!ctx->ht.enabled)
-		return;
-
-	ctx->ht.protection =
-		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	ctx->ht.non_gf_sta_present =
-		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	ht_conf->single_chain_sufficient = false;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		rcu_read_lock();
-		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				ht_conf->single_chain_sufficient = true;
-			if (maxstreams <= 1)
-				ht_conf->single_chain_sufficient = true;
-		} else {
-			/*
-			 * If at all, this can only happen through a race
-			 * when the AP disconnects us while we're still
-			 * setting up the connection, in that case mac80211
-			 * will soon tell us about that.
-			 */
-			ht_conf->single_chain_sufficient = true;
-		}
-		rcu_read_unlock();
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		ht_conf->single_chain_sufficient = true;
-		break;
-	default:
-		break;
-	}
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
+	iwl_connection_init_rx_config(priv, ctx);
 
 
-static inline void iwl_set_no_assoc(struct iwl_priv *priv,
-				    struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 
 
-	iwl_led_disassociate(priv);
-	/*
-	 * inform the ucode that there is no longer an
-	 * association and that no more packets should be
-	 * sent
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ctx->staging.assoc_id = 0;
-	iwlcore_commit_rxon(priv, ctx);
+	return iwlcore_commit_rxon(priv, ctx);
 }
 }
 
 
-static void iwlcore_beacon_update(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif)
+static int iwl_setup_interface(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
 {
 {
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
-
-	if (!skb)
-		return;
-
-	IWL_DEBUG_ASSOC(priv, "enter\n");
+	struct ieee80211_vif *vif = ctx->vif;
+	int err;
 
 
 	lockdep_assert_held(&priv->mutex);
 	lockdep_assert_held(&priv->mutex);
 
 
-	if (!priv->beacon_ctx) {
-		IWL_ERR(priv, "update beacon but no beacon context!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = skb;
-
-	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
-	priv->timestamp = le64_to_cpu(timestamp);
-
-	IWL_DEBUG_ASSOC(priv, "leave\n");
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return;
-	}
-
-	priv->cfg->ops->lib->post_associate(priv, priv->beacon_ctx->vif);
-}
-
-void iwl_bss_info_changed(struct ieee80211_hw *hw,
-			  struct ieee80211_vif *vif,
-			  struct ieee80211_bss_conf *bss_conf,
-			  u32 changes)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (!iwl_is_alive(priv))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (changes & BSS_CHANGED_QOS) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		ctx->qos_data.qos_active = bss_conf->qos;
-		iwl_update_qos(priv, ctx);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		/*
-		 * the add_interface code must make sure we only ever
-		 * have a single interface that could be beaconing at
-		 * any time.
-		 */
-		if (vif->bss_conf.enable_beacon)
-			priv->beacon_ctx = ctx;
-		else
-			priv->beacon_ctx = NULL;
-	}
-
-	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->beacon_skb);
-		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
-		iwl_send_rxon_timing(priv, ctx);
-
-	if (changes & BSS_CHANGED_BSSID) {
-		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
-
-		/*
-		 * If there is currently a HW scan going on in the
-		 * background then we need to cancel it else the RXON
-		 * below/in post_associate will fail.
-		 */
-		if (iwl_scan_cancel_timeout(priv, 100)) {
-			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-			mutex_unlock(&priv->mutex);
-			return;
-		}
-
-		/* mac80211 only sets assoc when in STATION mode */
-		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-
-			/* currently needed in a few places */
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-		} else {
-			ctx->staging.filter_flags &=
-				~RXON_FILTER_ASSOC_MSK;
-		}
-
-	}
-
 	/*
 	/*
-	 * This needs to be after setting the BSSID in case
-	 * mac80211 decides to do both changes at once because
-	 * it will invoke post_associate.
+	 * This variable will be correct only when there's just
+	 * a single context, but all code using it is for hardware
+	 * that supports only one context.
 	 */
 	 */
-	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
-		iwlcore_beacon_update(hw, vif);
-
-	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
-				   bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-	}
-
-	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
-		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
-		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
-			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-		if (bss_conf->use_cts_prot)
-			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
-	}
-
-	if (changes & BSS_CHANGED_BASIC_RATES) {
-		/* XXX use this information
-		 *
-		 * To do that, remove code from iwl_set_rate() and put something
-		 * like this here:
-		 *
-		if (A-band)
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates;
-		else
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates >> 4;
-			ctx->staging.cck_basic_rates =
-				bss_conf->basic_rates & 0xF;
-		 */
-	}
-
-	if (changes & BSS_CHANGED_HT) {
-		iwl_ht_conf(priv, vif);
-
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		if (bss_conf->assoc) {
-			priv->timestamp = bss_conf->timestamp;
-
-			iwl_led_associate(priv);
-
-			if (!iwl_is_rfkill(priv))
-				priv->cfg->ops->lib->post_associate(priv, vif);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
-		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
-				   changes);
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (!ret) {
-			/* Sync active_rxon with latest change. */
-			memcpy((void *)&ctx->active,
-				&ctx->staging,
-				sizeof(struct iwl_rxon_cmd));
-		}
-	}
+	priv->iw_mode = vif->type;
 
 
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		if (vif->bss_conf.enable_beacon) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-			iwl_led_associate(priv);
-			iwlcore_config_ap(priv, vif);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
+	ctx->is_active = true;
 
 
-	if (changes & BSS_CHANGED_IBSS) {
-		ret = priv->cfg->ops->lib->manage_ibss_station(priv, vif,
-							bss_conf->ibss_joined);
-		if (ret)
-			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
-				bss_conf->ibss_joined ? "add" : "remove",
-				bss_conf->bssid);
+	err = iwl_set_mode(priv, ctx);
+	if (err) {
+		if (!ctx->always_active)
+			ctx->is_active = false;
+		return err;
 	}
 	}
 
 
-	if (changes & BSS_CHANGED_IDLE &&
-	    priv->cfg->ops->hcmd->set_pan_params) {
-		if (priv->cfg->ops->hcmd->set_pan_params(priv))
-			IWL_ERR(priv, "failed to update PAN params\n");
+	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist &&
+	    vif->type == NL80211_IFTYPE_ADHOC) {
+		/*
+		 * pretend to have high BT traffic as long as we
+		 * are operating in IBSS mode, as this will cause
+		 * the rate scaling etc. to behave as intended.
+		 */
+		priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
 	}
 	}
 
 
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_bss_info_changed);
-
-static int iwl_set_mode(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	iwl_connection_init_rx_config(priv, ctx);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	return iwlcore_commit_rxon(priv, ctx);
+	return 0;
 }
 }
 
 
 int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
@@ -1771,7 +1385,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_rxon_context *tmp, *ctx = NULL;
 	struct iwl_rxon_context *tmp, *ctx = NULL;
-	int err = 0;
+	int err;
 
 
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
 			   vif->type, vif->addr);
 			   vif->type, vif->addr);
@@ -1813,36 +1427,11 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 
 
 	vif_priv->ctx = ctx;
 	vif_priv->ctx = ctx;
 	ctx->vif = vif;
 	ctx->vif = vif;
-	/*
-	 * This variable will be correct only when there's just
-	 * a single context, but all code using it is for hardware
-	 * that supports only one context.
-	 */
-	priv->iw_mode = vif->type;
-
-	ctx->is_active = true;
-
-	err = iwl_set_mode(priv, vif);
-	if (err) {
-		if (!ctx->always_active)
-			ctx->is_active = false;
-		goto out_err;
-	}
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
-	    vif->type == NL80211_IFTYPE_ADHOC) {
-		/*
-		 * pretend to have high BT traffic as long as we
-		 * are operating in IBSS mode, as this will cause
-		 * the rate scaling etc. to behave as intended.
-		 */
-		priv->bt_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
-	}
 
 
-	goto out;
+	err = iwl_setup_interface(priv, ctx);
+	if (!err)
+		goto out;
 
 
- out_err:
 	ctx->vif = NULL;
 	ctx->vif = NULL;
 	priv->iw_mode = NL80211_IFTYPE_STATION;
 	priv->iw_mode = NL80211_IFTYPE_STATION;
  out:
  out:
@@ -1853,27 +1442,24 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 }
 }
 EXPORT_SYMBOL(iwl_mac_add_interface);
 EXPORT_SYMBOL(iwl_mac_add_interface);
 
 
-void iwl_mac_remove_interface(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif)
+static void iwl_teardown_interface(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   bool mode_change)
 {
 {
-	struct iwl_priv *priv = hw->priv;
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
 
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	mutex_lock(&priv->mutex);
-
-	WARN_ON(ctx->vif != vif);
-	ctx->vif = NULL;
+	lockdep_assert_held(&priv->mutex);
 
 
 	if (priv->scan_vif == vif) {
 	if (priv->scan_vif == vif) {
 		iwl_scan_cancel_timeout(priv, 200);
 		iwl_scan_cancel_timeout(priv, 200);
 		iwl_force_scan_end(priv);
 		iwl_force_scan_end(priv);
 	}
 	}
-	iwl_set_mode(priv, vif);
 
 
-	if (!ctx->always_active)
-		ctx->is_active = false;
+	if (!mode_change) {
+		iwl_set_mode(priv, ctx);
+		if (!ctx->always_active)
+			ctx->is_active = false;
+	}
 
 
 	/*
 	/*
 	 * When removing the IBSS interface, overwrite the
 	 * When removing the IBSS interface, overwrite the
@@ -1884,210 +1470,30 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 	 */
 	 */
 	if (vif->type == NL80211_IFTYPE_ADHOC)
 	if (vif->type == NL80211_IFTYPE_ADHOC)
 		priv->bt_traffic_load = priv->notif_bt_traffic_load;
 		priv->bt_traffic_load = priv->notif_bt_traffic_load;
-
-	memset(priv->bssid, 0, ETH_ALEN);
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
 }
 }
-EXPORT_SYMBOL(iwl_mac_remove_interface);
-
-/**
- * iwl_mac_config - mac80211 config callback
- */
-int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
-{
-	struct iwl_priv *priv = hw->priv;
-	const struct iwl_channel_info *ch_info;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_channel *channel = conf->channel;
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct iwl_rxon_context *ctx;
-	unsigned long flags = 0;
-	int ret = 0;
-	u16 ch;
-	int scan_active = 0;
-
-	mutex_lock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					channel->hw_value, changed);
-
-	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
-			test_bit(STATUS_SCANNING, &priv->status))) {
-		scan_active = 1;
-		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
-		       IEEE80211_CONF_CHANGE_CHANNEL)) {
-		/* mac80211 uses static for non-HT which is what we want */
-		priv->current_ht_config.smps = conf->smps_mode;
-
-		/*
-		 * Recalculate chain counts.
-		 *
-		 * If monitor mode is enabled then mac80211 will
-		 * set up the SM PS mode to OFF if an HT channel is
-		 * configured.
-		 */
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			for_each_context(priv, ctx)
-				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	/* during scanning mac80211 will delay channel setting until
-	 * scan finish with changed = 0
-	 */
-	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
-		if (scan_active)
-			goto set_ch_out;
-
-		ch = channel->hw_value;
-		ch_info = iwl_get_channel_info(priv, channel->band, ch);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
 
 
-		spin_lock_irqsave(&priv->lock, flags);
-
-		for_each_context(priv, ctx) {
-			/* Configure HT40 channels */
-			ctx->ht.enabled = conf_is_ht(conf);
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			/*
-			 * Default to no protection. Protection mode will
-			 * later be set from BSS config in iwl_ht_conf
-			 */
-			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
-
-			/* if we are switching from ht to 2.4 clear flags
-			 * from any ht related info since 2.4 does not
-			 * support ht */
-			if ((le16_to_cpu(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_set_rxon_channel(priv, channel, ctx);
-			iwl_set_rxon_ht(priv, ht_conf);
-
-			iwl_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-		}
-
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		if (priv->cfg->ops->lib->update_bcast_stations)
-			ret = priv->cfg->ops->lib->update_bcast_stations(priv);
-
- set_ch_out:
-		/* The list of supported rates and rate mask can be different
-		 * for each band; since the band may have changed, reset
-		 * the rate mask to what mac80211 lists */
-		iwl_set_rate(priv);
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_PS |
-			IEEE80211_CONF_CHANGE_IDLE)) {
-		ret = iwl_power_update_mode(priv, false);
-		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
-	}
-
-	if (changed & IEEE80211_CONF_CHANGE_POWER) {
-		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
-			priv->tx_power_user_lmt, conf->power_level);
-
-		iwl_set_tx_power(priv, conf->power_level, false);
-	}
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		goto out;
-	}
-
-	if (scan_active)
-		goto out;
-
-	for_each_context(priv, ctx) {
-		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
-			iwlcore_commit_rxon(priv, ctx);
-		else
-			IWL_DEBUG_INFO(priv,
-				"Not re-sending same RXON configuration.\n");
-	}
-
-out:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-EXPORT_SYMBOL(iwl_mac_config);
-
-void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
+void iwl_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	/* IBSS can only be the IWL_RXON_CTX_BSS context */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
 
 
-	mutex_lock(&priv->mutex);
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 	IWL_DEBUG_MAC80211(priv, "enter\n");
 
 
-	spin_lock_irqsave(&priv->lock, flags);
-	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = NULL;
-
-	priv->timestamp = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_scan_cancel_timeout(priv, 100);
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		mutex_unlock(&priv->mutex);
-		return;
-	}
+	mutex_lock(&priv->mutex);
 
 
-	/* we are restarting association process
-	 * clear RXON_FILTER_ASSOC_MSK bit
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
+	WARN_ON(ctx->vif != vif);
+	ctx->vif = NULL;
 
 
-	iwl_set_rate(priv);
+	iwl_teardown_interface(priv, vif, false);
 
 
+	memset(priv->bssid, 0, ETH_ALEN);
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	IWL_DEBUG_MAC80211(priv, "leave\n");
+
 }
 }
-EXPORT_SYMBOL(iwl_mac_reset_tsf);
+EXPORT_SYMBOL(iwl_mac_remove_interface);
 
 
 int iwl_alloc_txq_mem(struct iwl_priv *priv)
 int iwl_alloc_txq_mem(struct iwl_priv *priv)
 {
 {
@@ -2431,6 +1837,63 @@ int iwl_force_reset(struct iwl_priv *priv, int mode, bool external)
 	return 0;
 	return 0;
 }
 }
 
 
+int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	struct iwl_rxon_context *tmp;
+	u32 interface_modes;
+	int err;
+
+	newtype = ieee80211_iftype_p2p(newtype, newp2p);
+
+	mutex_lock(&priv->mutex);
+
+	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+
+	if (!(interface_modes & BIT(newtype))) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (ctx->exclusive_interface_modes & BIT(newtype)) {
+		for_each_context(priv, tmp) {
+			if (ctx == tmp)
+				continue;
+
+			if (!tmp->vif)
+				continue;
+
+			/*
+			 * The current mode switch would be exclusive, but
+			 * another context is active ... refuse the switch.
+			 */
+			err = -EBUSY;
+			goto out;
+		}
+	}
+
+	/* success */
+	iwl_teardown_interface(priv, vif, true);
+	vif->type = newtype;
+	err = iwl_setup_interface(priv, ctx);
+	WARN_ON(err);
+	/*
+	 * We've switched internally, but submitting to the
+	 * device may have failed for some reason. Mask this
+	 * error, because otherwise mac80211 will not switch
+	 * (and set the interface type back) and we'll be
+	 * out of sync with it.
+	 */
+	err = 0;
+
+ out:
+	mutex_unlock(&priv->mutex);
+	return err;
+}
+EXPORT_SYMBOL(iwl_mac_change_interface);
+
 /**
 /**
  * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
  * iwl_bg_monitor_recover - Timer callback to check for stuck queue and recover
  *
  *
@@ -2584,8 +2047,9 @@ EXPORT_SYMBOL(iwl_add_beacon_time);
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 
 
-int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+int iwl_pci_suspend(struct device *device)
 {
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 
 
 	/*
 	/*
@@ -2597,18 +2061,14 @@ int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 	 */
 	 */
 	iwl_apm_stop(priv);
 	iwl_apm_stop(priv);
 
 
-	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL(iwl_pci_suspend);
 EXPORT_SYMBOL(iwl_pci_suspend);
 
 
-int iwl_pci_resume(struct pci_dev *pdev)
+int iwl_pci_resume(struct device *device)
 {
 {
+	struct pci_dev *pdev = to_pci_dev(device);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	int ret;
 	bool hw_rfkill = false;
 	bool hw_rfkill = false;
 
 
 	/*
 	/*
@@ -2617,11 +2077,6 @@ int iwl_pci_resume(struct pci_dev *pdev)
 	 */
 	 */
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
 
 
-	pci_set_power_state(pdev, PCI_D0);
-	ret = pci_enable_device(pdev);
-	if (ret)
-		return ret;
-	pci_restore_state(pdev);
 	iwl_enable_interrupts(priv);
 	iwl_enable_interrupts(priv);
 
 
 	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
 	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
@@ -2639,4 +2094,14 @@ int iwl_pci_resume(struct pci_dev *pdev)
 }
 }
 EXPORT_SYMBOL(iwl_pci_resume);
 EXPORT_SYMBOL(iwl_pci_resume);
 
 
+const struct dev_pm_ops iwl_pm_ops = {
+	.suspend = iwl_pci_suspend,
+	.resume = iwl_pci_resume,
+	.freeze = iwl_pci_suspend,
+	.thaw = iwl_pci_resume,
+	.poweroff = iwl_pci_suspend,
+	.restore = iwl_pci_resume,
+};
+EXPORT_SYMBOL(iwl_pm_ops);
+
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */

+ 40 - 30
drivers/net/wireless/iwlwifi/iwl-core.h

@@ -120,6 +120,14 @@ struct iwl_apm_ops {
 	void (*config)(struct iwl_priv *priv);
 	void (*config)(struct iwl_priv *priv);
 };
 };
 
 
+struct iwl_isr_ops {
+	irqreturn_t (*isr) (int irq, void *data);
+	void (*free)(struct iwl_priv *priv);
+	int (*alloc)(struct iwl_priv *priv);
+	int (*reset)(struct iwl_priv *priv);
+	void (*disable)(struct iwl_priv *priv);
+};
+
 struct iwl_debugfs_ops {
 struct iwl_debugfs_ops {
 	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
 	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
 				 size_t count, loff_t *ppos);
 				 size_t count, loff_t *ppos);
@@ -193,20 +201,15 @@ struct iwl_lib_ops {
 	/* power */
 	/* power */
 	int (*send_tx_power) (struct iwl_priv *priv);
 	int (*send_tx_power) (struct iwl_priv *priv);
 	void (*update_chain_flags)(struct iwl_priv *priv);
 	void (*update_chain_flags)(struct iwl_priv *priv);
-	void (*post_associate)(struct iwl_priv *priv,
-			       struct ieee80211_vif *vif);
-	void (*config_ap)(struct iwl_priv *priv, struct ieee80211_vif *vif);
-	irqreturn_t (*isr) (int irq, void *data);
+
+	/* isr */
+	struct iwl_isr_ops isr_ops;
 
 
 	/* eeprom operations (as defined in iwl-eeprom.h) */
 	/* eeprom operations (as defined in iwl-eeprom.h) */
 	struct iwl_eeprom_ops eeprom_ops;
 	struct iwl_eeprom_ops eeprom_ops;
 
 
 	/* temperature */
 	/* temperature */
 	struct iwl_temp_ops temp_ops;
 	struct iwl_temp_ops temp_ops;
-	/* station management */
-	int (*manage_ibss_station)(struct iwl_priv *priv,
-				   struct ieee80211_vif *vif, bool add);
-	int (*update_bcast_stations)(struct iwl_priv *priv);
 	/* recover from tx queue stall */
 	/* recover from tx queue stall */
 	void (*recover_from_tx_stall)(unsigned long data);
 	void (*recover_from_tx_stall)(unsigned long data);
 	/* check for plcp health */
 	/* check for plcp health */
@@ -235,12 +238,23 @@ struct iwl_nic_ops {
 	void (*additional_nic_config)(struct iwl_priv *priv);
 	void (*additional_nic_config)(struct iwl_priv *priv);
 };
 };
 
 
+struct iwl_legacy_ops {
+	void (*post_associate)(struct iwl_priv *priv);
+	void (*config_ap)(struct iwl_priv *priv);
+	/* station management */
+	int (*update_bcast_stations)(struct iwl_priv *priv);
+	int (*manage_ibss_station)(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif, bool add);
+};
+
 struct iwl_ops {
 struct iwl_ops {
 	const struct iwl_lib_ops *lib;
 	const struct iwl_lib_ops *lib;
 	const struct iwl_hcmd_ops *hcmd;
 	const struct iwl_hcmd_ops *hcmd;
 	const struct iwl_hcmd_utils_ops *utils;
 	const struct iwl_hcmd_utils_ops *utils;
 	const struct iwl_led_ops *led;
 	const struct iwl_led_ops *led;
 	const struct iwl_nic_ops *nic;
 	const struct iwl_nic_ops *nic;
+	const struct iwl_legacy_ops *legacy;
+	const struct ieee80211_ops *ieee80211_ops;
 };
 };
 
 
 struct iwl_mod_params {
 struct iwl_mod_params {
@@ -276,6 +290,7 @@ struct iwl_mod_params {
  *	sensitivity calibration operation
  *	sensitivity calibration operation
  * @chain_noise_calib_by_driver: driver has the capability to perform
  * @chain_noise_calib_by_driver: driver has the capability to perform
  *	chain noise calibration operation
  *	chain noise calibration operation
+ * @shadow_reg_enable: HW shadhow register bit
 */
 */
 struct iwl_base_params {
 struct iwl_base_params {
 	int eeprom_size;
 	int eeprom_size;
@@ -306,6 +321,7 @@ struct iwl_base_params {
 	const bool ucode_tracing;
 	const bool ucode_tracing;
 	const bool sensitivity_calib_by_driver;
 	const bool sensitivity_calib_by_driver;
 	const bool chain_noise_calib_by_driver;
 	const bool chain_noise_calib_by_driver;
+	const bool shadow_reg_enable;
 };
 };
 /*
 /*
  * @advanced_bt_coexist: support advanced bt coexist
  * @advanced_bt_coexist: support advanced bt coexist
@@ -396,8 +412,7 @@ struct iwl_cfg {
  *   L i b                 *
  *   L i b                 *
  ***************************/
  ***************************/
 
 
-struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
-		struct ieee80211_ops *hw_ops);
+struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg);
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		    const struct ieee80211_tx_queue_params *params);
 		    const struct ieee80211_tx_queue_params *params);
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw);
@@ -425,23 +440,16 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv,
 			   u32 decrypt_res,
 			   u32 decrypt_res,
 			   struct ieee80211_rx_status *stats);
 			   struct ieee80211_rx_status *stats);
 void iwl_irq_handle_error(struct iwl_priv *priv);
 void iwl_irq_handle_error(struct iwl_priv *priv);
-void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes);
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif);
 			  struct ieee80211_vif *vif);
 void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 void iwl_mac_remove_interface(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif);
 			      struct ieee80211_vif *vif);
-int iwl_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl_mac_reset_tsf(struct ieee80211_hw *hw);
+int iwl_mac_change_interface(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p);
 int iwl_alloc_txq_mem(struct iwl_priv *priv);
 int iwl_alloc_txq_mem(struct iwl_priv *priv);
 void iwl_free_txq_mem(struct iwl_priv *priv);
 void iwl_free_txq_mem(struct iwl_priv *priv);
-void iwlcore_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags);
+
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 int iwl_alloc_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
 void iwl_free_traffic_mem(struct iwl_priv *priv);
@@ -598,7 +606,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
 /*****************************************************
 /*****************************************************
  * PCI						     *
  * PCI						     *
  *****************************************************/
  *****************************************************/
-irqreturn_t iwl_isr_legacy(int irq, void *data);
 
 
 static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
 static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
 {
 {
@@ -615,9 +622,17 @@ __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base,
 			   u32 addon, u32 beacon_interval);
 			   u32 addon, u32 beacon_interval);
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state);
-int iwl_pci_resume(struct pci_dev *pdev);
-#endif /* CONFIG_PM */
+int iwl_pci_suspend(struct device *device);
+int iwl_pci_resume(struct device *device);
+extern const struct dev_pm_ops iwl_pm_ops;
+
+#define IWL_PM_OPS	(&iwl_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define IWL_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
 
 
 /*****************************************************
 /*****************************************************
 *  Error Handling Debugging
 *  Error Handling Debugging
@@ -724,11 +739,6 @@ static inline int iwlcore_commit_rxon(struct iwl_priv *priv,
 {
 {
 	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
 	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
 }
 }
-static inline void iwlcore_config_ap(struct iwl_priv *priv,
-				     struct ieee80211_vif *vif)
-{
-	priv->cfg->ops->lib->config_ap(priv, vif);
-}
 static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
 			struct iwl_priv *priv, enum ieee80211_band band)
 			struct iwl_priv *priv, enum ieee80211_band band)
 {
 {

+ 2 - 0
drivers/net/wireless/iwlwifi/iwl-csr.h

@@ -132,6 +132,8 @@
 
 
 #define CSR_LED_REG             (CSR_BASE+0x094)
 #define CSR_LED_REG             (CSR_BASE+0x094)
 #define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
 #define CSR_DRAM_INT_TBL_REG	(CSR_BASE+0x0A0)
+#define CSR_MAC_SHADOW_REG_CTRL	(CSR_BASE+0x0A8) /* 6000 and up */
+
 
 
 /* GIO Chicken Bits (PCI Express bus link power management) */
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
 #define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)

+ 3 - 0
drivers/net/wireless/iwlwifi/iwl-dev.h

@@ -1162,6 +1162,8 @@ struct iwl_rxon_context {
 	 */
 	 */
 	bool always_active, is_active;
 	bool always_active, is_active;
 
 
+	bool ht_need_multiple_chains;
+
 	enum iwl_rxon_context_id ctxid;
 	enum iwl_rxon_context_id ctxid;
 
 
 	u32 interface_modes, exclusive_interface_modes;
 	u32 interface_modes, exclusive_interface_modes;
@@ -1517,6 +1519,7 @@ struct iwl_priv {
 	s8 tx_power_user_lmt;
 	s8 tx_power_user_lmt;
 	s8 tx_power_device_lmt;
 	s8 tx_power_device_lmt;
 	s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
 	s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
+	s8 tx_power_next;
 
 
 
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 #ifdef CONFIG_IWLWIFI_DEBUG

+ 2 - 0
drivers/net/wireless/iwlwifi/iwl-led.c

@@ -134,6 +134,7 @@ int iwl_led_associate(struct iwl_priv *priv)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL(iwl_led_associate);
 
 
 int iwl_led_disassociate(struct iwl_priv *priv)
 int iwl_led_disassociate(struct iwl_priv *priv)
 {
 {
@@ -141,6 +142,7 @@ int iwl_led_disassociate(struct iwl_priv *priv)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL(iwl_led_disassociate);
 
 
 /*
 /*
  * calculate blink rate according to last second Tx/Rx activities
  * calculate blink rate according to last second Tx/Rx activities

+ 662 - 0
drivers/net/wireless/iwlwifi/iwl-legacy.c

@@ -0,0 +1,662 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-legacy.h"
+
+static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm, NULL);
+}
+
+/**
+ * iwl_legacy_mac_config - mac80211 config callback
+ */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = conf->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags = 0;
+	int ret = 0;
+	u16 ch;
+	int scan_active = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
+					channel->hw_value, changed);
+
+	if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
+			test_bit(STATUS_SCANNING, &priv->status))) {
+		scan_active = 1;
+		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* during scanning mac80211 will delay channel setting until
+	 * scan finish with changed = 0
+	 */
+	if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
+		if (scan_active)
+			goto set_ch_out;
+
+		ch = channel->hw_value;
+		ch_info = iwl_get_channel_info(priv, channel->band, ch);
+		if (!is_channel_valid(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* if we are switching from ht to 2.4 clear flags
+			 * from any ht related info since 2.4 does not
+			 * support ht */
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_set_rxon_channel(priv, channel, ctx);
+			iwl_set_rxon_ht(priv, ht_conf);
+
+			iwl_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		if (priv->cfg->ops->legacy->update_bcast_stations)
+			ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
+
+ set_ch_out:
+		/* The list of supported rates and rate mask can be different
+		 * for each band; since the band may have changed, reset
+		 * the rate mask to what mac80211 lists */
+		iwl_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
+	}
+
+	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
+			priv->tx_power_user_lmt, conf->power_level);
+
+		iwl_set_tx_power(priv, conf->power_level, false);
+	}
+
+	if (!iwl_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (scan_active)
+		goto out;
+
+	for_each_context(priv, ctx) {
+		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+			iwlcore_commit_rxon(priv, ctx);
+		else
+			IWL_DEBUG_INFO(priv,
+				"Not re-sending same RXON configuration.\n");
+		if (ht_changed[ctx->ctxid])
+			iwl_update_qos(priv, ctx);
+	}
+
+out:
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_config);
+
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	/* IBSS can only be the IWL_RXON_CTX_BSS context */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	spin_lock_irqsave(&priv->lock, flags);
+	memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* new association get rid of ibss beacon skb */
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = NULL;
+
+	priv->timestamp = 0;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_scan_cancel_timeout(priv, 100);
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	/* we are restarting association process
+	 * clear RXON_FILTER_ASSOC_MSK bit
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwlcore_commit_rxon(priv, ctx);
+
+	iwl_set_rate(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
+
+static void iwl_ht_conf(struct iwl_priv *priv,
+			struct ieee80211_vif *vif)
+{
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_ASSOC(priv, "enter:\n");
+
+	if (!ctx->ht.enabled)
+		return;
+
+	ctx->ht.protection =
+		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	ctx->ht.non_gf_sta_present =
+		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+	ht_conf->single_chain_sufficient = false;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				ht_conf->single_chain_sufficient = true;
+			if (maxstreams <= 1)
+				ht_conf->single_chain_sufficient = true;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			ht_conf->single_chain_sufficient = true;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ht_conf->single_chain_sufficient = true;
+		break;
+	default:
+		break;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "leave\n");
+}
+
+static inline void iwl_set_no_assoc(struct iwl_priv *priv,
+				    struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+
+	iwl_led_disassociate(priv);
+	/*
+	 * inform the ucode that there is no longer an
+	 * association and that no more packets should be
+	 * sent
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ctx->staging.assoc_id = 0;
+	iwlcore_commit_rxon(priv, ctx);
+}
+
+static void iwlcore_beacon_update(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	__le64 timestamp;
+	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb)
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "update beacon but no beacon context!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = skb;
+
+	timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
+	priv->timestamp = le64_to_cpu(timestamp);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!iwl_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return;
+	}
+
+	priv->cfg->ops->legacy->post_associate(priv);
+}
+
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+	int ret;
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
+
+	if (!iwl_is_alive(priv))
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	if (changes & BSS_CHANGED_QOS) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwl_update_qos(priv, ctx);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		/*
+		 * the add_interface code must make sure we only ever
+		 * have a single interface that could be beaconing at
+		 * any time.
+		 */
+		if (vif->bss_conf.enable_beacon)
+			priv->beacon_ctx = ctx;
+		else
+			priv->beacon_ctx = NULL;
+	}
+
+	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
+		dev_kfree_skb(priv->beacon_skb);
+		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
+		iwl_send_rxon_timing(priv, ctx);
+
+	if (changes & BSS_CHANGED_BSSID) {
+		IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
+
+		/*
+		 * If there is currently a HW scan going on in the
+		 * background then we need to cancel it else the RXON
+		 * below/in post_associate will fail.
+		 */
+		if (iwl_scan_cancel_timeout(priv, 100)) {
+			IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
+			IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
+			mutex_unlock(&priv->mutex);
+			return;
+		}
+
+		/* mac80211 only sets assoc when in STATION mode */
+		if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+
+			/* currently needed in a few places */
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+		} else {
+			ctx->staging.filter_flags &=
+				~RXON_FILTER_ASSOC_MSK;
+		}
+
+	}
+
+	/*
+	 * This needs to be after setting the BSSID in case
+	 * mac80211 decides to do both changes at once because
+	 * it will invoke post_associate.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
+		iwlcore_beacon_update(hw, vif);
+
+	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+		IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
+				   bss_conf->use_short_preamble);
+		if (bss_conf->use_short_preamble)
+			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	}
+
+	if (changes & BSS_CHANGED_ERP_CTS_PROT) {
+		IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
+		if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
+			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+		if (bss_conf->use_cts_prot)
+			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+	}
+
+	if (changes & BSS_CHANGED_BASIC_RATES) {
+		/* XXX use this information
+		 *
+		 * To do that, remove code from iwl_set_rate() and put something
+		 * like this here:
+		 *
+		if (A-band)
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates;
+		else
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates >> 4;
+			ctx->staging.cck_basic_rates =
+				bss_conf->basic_rates & 0xF;
+		 */
+	}
+
+	if (changes & BSS_CHANGED_HT) {
+		iwl_ht_conf(priv, vif);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
+		if (bss_conf->assoc) {
+			priv->timestamp = bss_conf->timestamp;
+
+			iwl_led_associate(priv);
+
+			if (!iwl_is_rfkill(priv))
+				priv->cfg->ops->legacy->post_associate(priv);
+		} else
+			iwl_set_no_assoc(priv, vif);
+	}
+
+	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
+		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
+				   changes);
+		ret = iwl_send_rxon_assoc(priv, ctx);
+		if (!ret) {
+			/* Sync active_rxon with latest change. */
+			memcpy((void *)&ctx->active,
+				&ctx->staging,
+				sizeof(struct iwl_rxon_cmd));
+		}
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (vif->bss_conf.enable_beacon) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			iwl_led_associate(priv);
+			priv->cfg->ops->legacy->config_ap(priv);
+		} else
+			iwl_set_no_assoc(priv, vif);
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
+							bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
+
+irqreturn_t iwl_isr_legacy(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 inta_fh;
+	unsigned long flags;
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Disable (but don't clear!) interrupts here to avoid
+	 *    back-to-back ISRs and sporadic interrupts from our NIC.
+	 * If we have something to service, the tasklet will re-enable ints.
+	 * If we *don't* have something, we'll re-enable before leaving here. */
+	inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* Discover which interrupts are active/pending */
+	inta = iwl_read32(priv, CSR_INT);
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+
+	/* Ignore interrupt if there's nothing in NIC to service.
+	 * This may be due to IRQ shared with another device,
+	 * or due to sporadic interrupts thrown from our NIC. */
+	if (!inta && !inta_fh) {
+		IWL_DEBUG_ISR(priv,
+			"Ignore interrupt, inta == 0, inta_fh == 0\n");
+		goto none;
+	}
+
+	if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
+		/* Hardware disappeared. It might have already raised
+		 * an interrupt */
+		IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
+		goto unplugged;
+	}
+
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+		      inta, inta_mask, inta_fh);
+
+	inta &= ~CSR_INT_BIT_SCD;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
+
+unplugged:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL(iwl_isr_legacy);
+
+/*
+ *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
+ *  function.
+ */
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+			       struct ieee80211_tx_info *info,
+			       __le16 fc, __le32 *tx_flags)
+{
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		*tx_flags |= TX_CMD_FLG_RTS_MSK;
+		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+		if (!ieee80211_is_mgmt(fc))
+			return;
+
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+			*tx_flags |= TX_CMD_FLG_CTS_MSK;
+			break;
+		}
+	} else if (info->control.rates[0].flags &
+		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
+		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+		*tx_flags |= TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);

+ 79 - 0
drivers/net/wireless/iwlwifi/iwl-legacy.h

@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name Intel Corporation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_h__
+#define __iwl_legacy_h__
+
+/* mac80211 handlers */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes);
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+				struct ieee80211_tx_info *info,
+				__le16 fc, __le32 *tx_flags);
+
+irqreturn_t iwl_isr_legacy(int irq, void *data);
+
+#endif /* __iwl_legacy_h__ */

+ 60 - 35
drivers/net/wireless/iwlwifi/iwl-power.c

@@ -263,70 +263,95 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
 				sizeof(struct iwl_powertable_cmd), cmd);
 				sizeof(struct iwl_powertable_cmd), cmd);
 }
 }
 
 
-/* priv->mutex must be held */
-int iwl_power_update_mode(struct iwl_priv *priv, bool force)
+static void iwl_power_build_cmd(struct iwl_priv *priv,
+				struct iwl_powertable_cmd *cmd)
 {
 {
-	int ret = 0;
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
 	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
-	bool update_chains;
-	struct iwl_powertable_cmd cmd;
 	int dtimper;
 	int dtimper;
 
 
-	/* Don't update the RX chain when chain noise calibration is running */
-	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
-			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
-
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
 
 
 	if (priv->cfg->base_params->broken_powersave)
 	if (priv->cfg->base_params->broken_powersave)
-		iwl_power_sleep_cam_cmd(priv, &cmd);
+		iwl_power_sleep_cam_cmd(priv, cmd);
 	else if (priv->cfg->base_params->supports_idle &&
 	else if (priv->cfg->base_params->supports_idle &&
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
-		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20);
+		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
 	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
 	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
 		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
 		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
 		 priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
 		 priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) {
 		/* in thermal throttling low power state */
 		/* in thermal throttling low power state */
-		iwl_static_sleep_cmd(priv, &cmd,
+		iwl_static_sleep_cmd(priv, cmd,
 		    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
 		    priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper);
 	} else if (!enabled)
 	} else if (!enabled)
-		iwl_power_sleep_cam_cmd(priv, &cmd);
+		iwl_power_sleep_cam_cmd(priv, cmd);
 	else if (priv->power_data.debug_sleep_level_override >= 0)
 	else if (priv->power_data.debug_sleep_level_override >= 0)
-		iwl_static_sleep_cmd(priv, &cmd,
+		iwl_static_sleep_cmd(priv, cmd,
 				     priv->power_data.debug_sleep_level_override,
 				     priv->power_data.debug_sleep_level_override,
 				     dtimper);
 				     dtimper);
 	else if (no_sleep_autoadjust)
 	else if (no_sleep_autoadjust)
-		iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
+		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
 	else
 	else
-		iwl_power_fill_sleep_cmd(priv, &cmd,
+		iwl_power_fill_sleep_cmd(priv, cmd,
 					 priv->hw->conf.dynamic_ps_timeout,
 					 priv->hw->conf.dynamic_ps_timeout,
 					 priv->hw->conf.max_sleep_period);
 					 priv->hw->conf.max_sleep_period);
+}
+
+int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force)
+{
+	int ret;
+	bool update_chains;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Don't update the RX chain when chain noise calibration is running */
+	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
+			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
+
+	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
+		return 0;
+
+	if (!iwl_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete use sleep_power_next, need to be updated */
+	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
+		return 0;
+	}
+
+	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
+		set_bit(STATUS_POWER_PMI, &priv->status);
 
 
-	if (iwl_is_ready_rf(priv) &&
-	    (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
-		if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
-			set_bit(STATUS_POWER_PMI, &priv->status);
-
-		ret = iwl_set_power(priv, &cmd);
-		if (!ret) {
-			if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
-				clear_bit(STATUS_POWER_PMI, &priv->status);
-
-			if (priv->cfg->ops->lib->update_chain_flags &&
-			    update_chains)
-				priv->cfg->ops->lib->update_chain_flags(priv);
-			else if (priv->cfg->ops->lib->update_chain_flags)
-				IWL_DEBUG_POWER(priv,
+	ret = iwl_set_power(priv, cmd);
+	if (!ret) {
+		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+			clear_bit(STATUS_POWER_PMI, &priv->status);
+
+		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
+			priv->cfg->ops->lib->update_chain_flags(priv);
+		else if (priv->cfg->ops->lib->update_chain_flags)
+			IWL_DEBUG_POWER(priv,
 					"Cannot update the power, chain noise "
 					"Cannot update the power, chain noise "
 					"calibration running: %d\n",
 					"calibration running: %d\n",
 					priv->chain_noise_data.state);
 					priv->chain_noise_data.state);
-			memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
-		} else
-			IWL_ERR(priv, "set power fail, ret = %d", ret);
-	}
+
+		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
+	} else
+		IWL_ERR(priv, "set power fail, ret = %d", ret);
 
 
 	return ret;
 	return ret;
 }
 }
+EXPORT_SYMBOL(iwl_power_set_mode);
+
+int iwl_power_update_mode(struct iwl_priv *priv, bool force)
+{
+	struct iwl_powertable_cmd cmd;
+
+	iwl_power_build_cmd(priv, &cmd);
+	return iwl_power_set_mode(priv, &cmd, force);
+}
 EXPORT_SYMBOL(iwl_power_update_mode);
 EXPORT_SYMBOL(iwl_power_update_mode);
 
 
 /* initialize to default */
 /* initialize to default */

+ 3 - 0
drivers/net/wireless/iwlwifi/iwl-power.h

@@ -41,10 +41,13 @@ enum iwl_power_level {
 
 
 struct iwl_power_mgr {
 struct iwl_power_mgr {
 	struct iwl_powertable_cmd sleep_cmd;
 	struct iwl_powertable_cmd sleep_cmd;
+	struct iwl_powertable_cmd sleep_cmd_next;
 	int debug_sleep_level_override;
 	int debug_sleep_level_override;
 	bool pci_pm;
 	bool pci_pm;
 };
 };
 
 
+int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force);
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
 int iwl_power_update_mode(struct iwl_priv *priv, bool force);
 void iwl_power_initialize(struct iwl_priv *priv);
 void iwl_power_initialize(struct iwl_priv *priv);
 
 

+ 27 - 18
drivers/net/wireless/iwlwifi/iwl-rx.c

@@ -134,28 +134,37 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q
 	if (q->need_update == 0)
 	if (q->need_update == 0)
 		goto exit_unlock;
 		goto exit_unlock;
 
 
-	/* If power-saving is in use, make sure device is awake */
-	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
+		/* Device expects a multiple of 8 */
+		q->write_actual = (q->write & ~0x7);
+		iwl_write32(priv, rx_wrt_ptr_reg, q->write_actual);
+	} else {
+		/* If power-saving is in use, make sure device is awake */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
 
 
-		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,
-				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-			goto exit_unlock;
-		}
+			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,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				goto exit_unlock;
+			}
 
 
-		q->write_actual = (q->write & ~0x7);
-		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, rx_wrt_ptr_reg,
+					q->write_actual);
 
 
-	/* Else device is assumed to be awake */
-	} else {
-		/* Device expects a multiple of 8 */
-		q->write_actual = (q->write & ~0x7);
-		iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
+		/* Else device is assumed to be awake */
+		} else {
+			/* Device expects a multiple of 8 */
+			q->write_actual = (q->write & ~0x7);
+			iwl_write_direct32(priv, rx_wrt_ptr_reg,
+				q->write_actual);
+		}
 	}
 	}
-
 	q->need_update = 0;
 	q->need_update = 0;
 
 
  exit_unlock:
  exit_unlock:

+ 7 - 4
drivers/net/wireless/iwlwifi/iwl-scan.c

@@ -603,13 +603,16 @@ out_settings:
 	if (!iwl_is_ready_rf(priv))
 	if (!iwl_is_ready_rf(priv))
 		goto out;
 		goto out;
 
 
-	/* Since setting the TXPOWER may have been deferred while
-	 * performing the scan, fire one off */
-	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	/*
+	 * We do not commit power settings while scan is pending,
+	 * do it now if the settings changed.
+	 */
+	iwl_power_set_mode(priv, &priv->power_data.sleep_cmd_next, false);
+	iwl_set_tx_power(priv, priv->tx_power_next, false);
 
 
 	priv->cfg->ops->utils->post_scan(priv);
 	priv->cfg->ops->utils->post_scan(priv);
 
 
- out:
+out:
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 }
 }
 
 

+ 30 - 21
drivers/net/wireless/iwlwifi/iwl-tx.c

@@ -49,30 +49,39 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
 	if (txq->need_update == 0)
 	if (txq->need_update == 0)
 		return;
 		return;
 
 
-	/* if we're trying to save power */
-	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
-		/* wake up nic if it's powered down ...
-		 * uCode will wake up, and interrupt us again, so next
-		 * time we'll skip this part. */
-		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
-
-		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
-			IWL_DEBUG_INFO(priv, "Tx queue %d requesting wakeup, GP1 = 0x%x\n",
-				      txq_id, reg);
-			iwl_set_bit(priv, CSR_GP_CNTRL,
-				    CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-			return;
-		}
-
-		iwl_write_direct32(priv, HBUS_TARG_WRPTR,
-				     txq->q.write_ptr | (txq_id << 8));
-
-	/* else not in power-save mode, uCode will never sleep when we're
-	 * trying to tx (during RFKILL, we're not trying to tx). */
-	} else
+	if (priv->cfg->base_params->shadow_reg_enable) {
+		/* shadow register enabled */
 		iwl_write32(priv, HBUS_TARG_WRPTR,
 		iwl_write32(priv, HBUS_TARG_WRPTR,
 			    txq->q.write_ptr | (txq_id << 8));
 			    txq->q.write_ptr | (txq_id << 8));
+	} else {
+		/* if we're trying to save power */
+		if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+			/* wake up nic if it's powered down ...
+			 * uCode will wake up, and interrupt us again, so next
+			 * time we'll skip this part. */
+			reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+			if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+				IWL_DEBUG_INFO(priv,
+					"Tx queue %d requesting wakeup,"
+					" GP1 = 0x%x\n", txq_id, reg);
+				iwl_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+				return;
+			}
+
+			iwl_write_direct32(priv, HBUS_TARG_WRPTR,
+				     txq->q.write_ptr | (txq_id << 8));
 
 
+		/*
+		 * else not in power-save mode,
+		 * uCode will never sleep when we're
+		 * trying to tx (during RFKILL, we're not trying to tx).
+		 */
+		} else
+			iwl_write32(priv, HBUS_TARG_WRPTR,
+				    txq->q.write_ptr | (txq_id << 8));
+	}
 	txq->need_update = 0;
 	txq->need_update = 0;
 }
 }
 EXPORT_SYMBOL(iwl_txq_update_write_ptr);
 EXPORT_SYMBOL(iwl_txq_update_write_ptr);

+ 25 - 24
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -61,6 +61,7 @@
 #include "iwl-helpers.h"
 #include "iwl-helpers.h"
 #include "iwl-dev.h"
 #include "iwl-dev.h"
 #include "iwl-spectrum.h"
 #include "iwl-spectrum.h"
+#include "iwl-legacy.h"
 
 
 /*
 /*
  * module name, copyright, version, etc.
  * module name, copyright, version, etc.
@@ -3057,22 +3058,22 @@ static void iwl3945_bg_rx_replenish(struct work_struct *data)
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 }
 }
 
 
-void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
+void iwl3945_post_associate(struct iwl_priv *priv)
 {
 {
 	int rc = 0;
 	int rc = 0;
 	struct ieee80211_conf *conf = NULL;
 	struct ieee80211_conf *conf = NULL;
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 
-	if (!vif || !priv->is_open)
+	if (!ctx->vif || !priv->is_open)
 		return;
 		return;
 
 
-	if (vif->type == NL80211_IFTYPE_AP) {
+	if (ctx->vif->type == NL80211_IFTYPE_AP) {
 		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
 		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
 		return;
 		return;
 	}
 	}
 
 
 	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
 	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
+			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
 
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
 		return;
@@ -3091,18 +3092,18 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 
 
 	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 
 
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
 
 
 	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
 	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
 
 
-	if (vif->bss_conf.use_short_preamble)
+	if (ctx->vif->bss_conf.use_short_preamble)
 		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
 	else
 	else
 		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
 
 
 	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
 	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
+		if (ctx->vif->bss_conf.use_short_slot)
 			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
 		else
 		else
 			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
 			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
@@ -3110,7 +3111,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 
 
 	iwl3945_commit_rxon(priv, ctx);
 	iwl3945_commit_rxon(priv, ctx);
 
 
-	switch (vif->type) {
+	switch (ctx->vif->type) {
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_STATION:
 		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
 		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
 		break;
 		break;
@@ -3119,7 +3120,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif)
 		break;
 		break;
 	default:
 	default:
 		IWL_ERR(priv, "%s Should not be called in %d mode\n",
 		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			__func__, vif->type);
+			__func__, ctx->vif->type);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -3234,9 +3235,10 @@ static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	return NETDEV_TX_OK;
 	return NETDEV_TX_OK;
 }
 }
 
 
-void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif)
+void iwl3945_config_ap(struct iwl_priv *priv)
 {
 {
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
 	int rc = 0;
 	int rc = 0;
 
 
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -3407,9 +3409,9 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
 	ctx->staging.filter_flags |= filter_or;
 	ctx->staging.filter_flags |= filter_or;
 
 
 	/*
 	/*
-	 * Committing directly here breaks for some reason,
-	 * but we'll eventually commit the filter flags
-	 * change anyway.
+	 * Not committing directly because hardware can perform a scan,
+	 * but even if hw is ready, committing here breaks for some reason,
+	 * we'll eventually commit the filter flags change anyway.
 	 */
 	 */
 
 
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
@@ -3824,18 +3826,19 @@ static struct attribute_group iwl3945_attribute_group = {
 	.attrs = iwl3945_sysfs_entries,
 	.attrs = iwl3945_sysfs_entries,
 };
 };
 
 
-static struct ieee80211_ops iwl3945_hw_ops = {
+struct ieee80211_ops iwl3945_hw_ops = {
 	.tx = iwl3945_mac_tx,
 	.tx = iwl3945_mac_tx,
 	.start = iwl3945_mac_start,
 	.start = iwl3945_mac_start,
 	.stop = iwl3945_mac_stop,
 	.stop = iwl3945_mac_stop,
 	.add_interface = iwl_mac_add_interface,
 	.add_interface = iwl_mac_add_interface,
 	.remove_interface = iwl_mac_remove_interface,
 	.remove_interface = iwl_mac_remove_interface,
-	.config = iwl_mac_config,
+	.change_interface = iwl_mac_change_interface,
+	.config = iwl_legacy_mac_config,
 	.configure_filter = iwl3945_configure_filter,
 	.configure_filter = iwl3945_configure_filter,
 	.set_key = iwl3945_mac_set_key,
 	.set_key = iwl3945_mac_set_key,
 	.conf_tx = iwl_mac_conf_tx,
 	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_mac_reset_tsf,
-	.bss_info_changed = iwl_bss_info_changed,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
 	.hw_scan = iwl_mac_hw_scan,
 	.hw_scan = iwl_mac_hw_scan,
 	.sta_add = iwl3945_mac_sta_add,
 	.sta_add = iwl3945_mac_sta_add,
 	.sta_remove = iwl_mac_sta_remove,
 	.sta_remove = iwl_mac_sta_remove,
@@ -3866,6 +3869,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
 
 
 	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
 	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
+	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
 
 
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
 	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
 		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
 		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
@@ -3965,7 +3969,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 
 	/* mac80211 allocates memory for this device instance, including
 	/* mac80211 allocates memory for this device instance, including
 	 *   space for this driver's private structure */
 	 *   space for this driver's private structure */
-	hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
+	hw = iwl_alloc_all(cfg);
 	if (hw == NULL) {
 	if (hw == NULL) {
 		pr_err("Can not allocate network device\n");
 		pr_err("Can not allocate network device\n");
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -4117,7 +4121,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 
 
 	pci_enable_msi(priv->pci_dev);
 	pci_enable_msi(priv->pci_dev);
 
 
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
+	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
 			  IRQF_SHARED, DRV_NAME, priv);
 			  IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 	if (err) {
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
 		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -4275,10 +4279,7 @@ static struct pci_driver iwl3945_driver = {
 	.id_table = iwl3945_hw_card_ids,
 	.id_table = iwl3945_hw_card_ids,
 	.probe = iwl3945_pci_probe,
 	.probe = iwl3945_pci_probe,
 	.remove = __devexit_p(iwl3945_pci_remove),
 	.remove = __devexit_p(iwl3945_pci_remove),
-#ifdef CONFIG_PM
-	.suspend = iwl_pci_suspend,
-	.resume = iwl_pci_resume,
-#endif
+	.driver.pm = IWL_PM_OPS,
 };
 };
 
 
 static int __init iwl3945_init(void)
 static int __init iwl3945_init(void)

+ 4 - 1
drivers/net/wireless/mac80211_hwsim.c

@@ -309,6 +309,8 @@ struct mac80211_hwsim_data {
 	 */
 	 */
 	u64 group;
 	u64 group;
 	struct dentry *debugfs_group;
 	struct dentry *debugfs_group;
+
+	int power_level;
 };
 };
 
 
 
 
@@ -497,7 +499,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
 	rx_status.band = data->channel->band;
 	rx_status.band = data->channel->band;
 	rx_status.rate_idx = info->control.rates[0].idx;
 	rx_status.rate_idx = info->control.rates[0].idx;
 	/* TODO: simulate real signal strength (and optional packet loss) */
 	/* TODO: simulate real signal strength (and optional packet loss) */
-	rx_status.signal = -50;
+	rx_status.signal = data->power_level - 50;
 
 
 	if (data->ps != PS_DISABLED)
 	if (data->ps != PS_DISABLED)
 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
 		hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
@@ -698,6 +700,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
 	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
 
 	data->channel = conf->channel;
 	data->channel = conf->channel;
+	data->power_level = conf->power_level;
 	if (!data->started || !data->beacon_int)
 	if (!data->started || !data->beacon_int)
 		del_timer(&data->beacon_timer);
 		del_timer(&data->beacon_timer);
 	else
 	else

+ 6 - 1
drivers/net/wireless/mwl8k.c

@@ -1125,10 +1125,12 @@ struct mwl8k_tx_desc {
 	__le32 reserved;
 	__le32 reserved;
 	__le16 rate_info;
 	__le16 rate_info;
 	__u8 peer_id;
 	__u8 peer_id;
-	__u8 tx_frag_cnt;
+	__u8 xmitcontrol;
 } __packed;
 } __packed;
 
 
 #define MWL8K_TX_DESCS		128
 #define MWL8K_TX_DESCS		128
+#define MWL8K_XMITCONTROL_NON_AMPDU	0x04
+
 
 
 static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 static int mwl8k_txq_init(struct ieee80211_hw *hw, int index)
 {
 {
@@ -1448,6 +1450,9 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 		tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
 		tx->peer_id = MWL8K_STA(tx_info->control.sta)->peer_id;
 	else
 	else
 		tx->peer_id = 0;
 		tx->peer_id = 0;
+
+	if (priv->ap_fw)
+		tx->xmitcontrol = MWL8K_XMITCONTROL_NON_AMPDU;
 	wmb();
 	wmb();
 	tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
 	tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus);
 
 

+ 6 - 8
drivers/net/wireless/rt2x00/rt2400pci.c

@@ -885,8 +885,7 @@ static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
 
 	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
 	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
+			   (state == STATE_RADIO_RX_OFF));
 	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 }
 }
 
 
@@ -989,9 +988,7 @@ static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2400pci_disable_radio(rt2x00dev);
 		rt2400pci_disable_radio(rt2x00dev);
 		break;
 		break;
 	case STATE_RADIO_RX_ON:
 	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
 	case STATE_RADIO_RX_OFF:
 	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
 		rt2400pci_toggle_rx(rt2x00dev, state);
 		rt2400pci_toggle_rx(rt2x00dev, state);
 		break;
 		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON:
@@ -1612,6 +1609,7 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
 	.get_tsf		= rt2400pci_get_tsf,
 	.get_tsf		= rt2400pci_get_tsf,
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.tx_last_beacon		= rt2400pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 };
 
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
@@ -1640,28 +1638,28 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 };
 };
 
 
 static const struct data_queue_desc rt2400pci_queue_rx = {
 static const struct data_queue_desc rt2400pci_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 24,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2400pci_queue_tx = {
 static const struct data_queue_desc rt2400pci_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 24,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2400pci_queue_bcn = {
 static const struct data_queue_desc rt2400pci_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2400pci_queue_atim = {
 static const struct data_queue_desc rt2400pci_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),

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

@@ -809,8 +809,8 @@
 /*
 /*
  * DMA descriptor defines.
  * DMA descriptor defines.
  */
  */
-#define TXD_DESC_SIZE			( 8 * sizeof(__le32) )
-#define RXD_DESC_SIZE			( 8 * sizeof(__le32) )
+#define TXD_DESC_SIZE			(8 * sizeof(__le32))
+#define RXD_DESC_SIZE			(8 * sizeof(__le32))
 
 
 /*
 /*
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
@@ -948,6 +948,6 @@
 	((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
 	((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER)
 
 
 #define TXPOWER_TO_DEV(__txpower) \
 #define TXPOWER_TO_DEV(__txpower) \
-	MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER)
+	(MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER))
 
 
 #endif /* RT2400PCI_H */
 #endif /* RT2400PCI_H */

+ 9 - 11
drivers/net/wireless/rt2x00/rt2500pci.c

@@ -1040,8 +1040,7 @@ static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
 
 	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
 	rt2x00pci_register_read(rt2x00dev, RXCSR0, &reg);
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
 	rt2x00_set_field32(&reg, RXCSR0_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
+			   (state == STATE_RADIO_RX_OFF));
 	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 	rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 }
 }
 
 
@@ -1144,9 +1143,7 @@ static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500pci_disable_radio(rt2x00dev);
 		rt2500pci_disable_radio(rt2x00dev);
 		break;
 		break;
 	case STATE_RADIO_RX_ON:
 	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
 	case STATE_RADIO_RX_OFF:
 	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
 		rt2500pci_toggle_rx(rt2x00dev, state);
 		rt2500pci_toggle_rx(rt2x00dev, state);
 		break;
 		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON:
@@ -1193,9 +1190,9 @@ static void rt2500pci_write_tx_desc(struct queue_entry *entry,
 
 
 	rt2x00_desc_read(txd, 2, &word);
 	rt2x00_desc_read(txd, 2, &word);
 	rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
 	rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER);
-	rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs);
-	rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min);
-	rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max);
+	rt2x00_set_field32(&word, TXD_W2_AIFS, entry->queue->aifs);
+	rt2x00_set_field32(&word, TXD_W2_CWMIN, entry->queue->cw_min);
+	rt2x00_set_field32(&word, TXD_W2_CWMAX, entry->queue->cw_max);
 	rt2x00_desc_write(txd, 2, word);
 	rt2x00_desc_write(txd, 2, word);
 
 
 	rt2x00_desc_read(txd, 3, &word);
 	rt2x00_desc_read(txd, 3, &word);
@@ -1909,6 +1906,7 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
 	.get_tsf		= rt2500pci_get_tsf,
 	.get_tsf		= rt2500pci_get_tsf,
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.tx_last_beacon		= rt2500pci_tx_last_beacon,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 };
 
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
@@ -1937,28 +1935,28 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 };
 };
 
 
 static const struct data_queue_desc rt2500pci_queue_rx = {
 static const struct data_queue_desc rt2500pci_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2500pci_queue_tx = {
 static const struct data_queue_desc rt2500pci_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2500pci_queue_bcn = {
 static const struct data_queue_desc rt2500pci_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2500pci_queue_atim = {
 static const struct data_queue_desc rt2500pci_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),

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

@@ -1088,8 +1088,8 @@
 /*
 /*
  * DMA descriptor defines.
  * DMA descriptor defines.
  */
  */
-#define TXD_DESC_SIZE			( 11 * sizeof(__le32) )
-#define RXD_DESC_SIZE			( 11 * sizeof(__le32) )
+#define TXD_DESC_SIZE			(11 * sizeof(__le32))
+#define RXD_DESC_SIZE			(11 * sizeof(__le32))
 
 
 /*
 /*
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.
  * TX descriptor format for TX, PRIO, ATIM and Beacon Ring.

+ 10 - 12
drivers/net/wireless/rt2x00/rt2500usb.c

@@ -39,7 +39,7 @@
 /*
 /*
  * Allow hardware encryption to be disabled.
  * Allow hardware encryption to be disabled.
  */
  */
-static int modparam_nohwcrypt = 0;
+static int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
 
@@ -938,8 +938,7 @@ static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
 
 	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
 	rt2500usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
 	rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX,
 	rt2x00_set_field16(&reg, TXRX_CSR2_DISABLE_RX,
-			   (state == STATE_RADIO_RX_OFF) ||
-			   (state == STATE_RADIO_RX_OFF_LINK));
+			   (state == STATE_RADIO_RX_OFF));
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg);
 }
 }
 
 
@@ -1019,9 +1018,7 @@ static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2500usb_disable_radio(rt2x00dev);
 		rt2500usb_disable_radio(rt2x00dev);
 		break;
 		break;
 	case STATE_RADIO_RX_ON:
 	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
 	case STATE_RADIO_RX_OFF:
 	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
 		rt2500usb_toggle_rx(rt2x00dev, state);
 		rt2500usb_toggle_rx(rt2x00dev, state);
 		break;
 		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON:
@@ -1081,9 +1078,9 @@ static void rt2500usb_write_tx_desc(struct queue_entry *entry,
 
 
 	rt2x00_desc_read(txd, 1, &word);
 	rt2x00_desc_read(txd, 1, &word);
 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
 	rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
-	rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
-	rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
-	rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
+	rt2x00_set_field32(&word, TXD_W1_AIFS, entry->queue->aifs);
+	rt2x00_set_field32(&word, TXD_W1_CWMIN, entry->queue->cw_min);
+	rt2x00_set_field32(&word, TXD_W1_CWMAX, entry->queue->cw_max);
 	rt2x00_desc_write(txd, 1, word);
 	rt2x00_desc_write(txd, 1, word);
 
 
 	rt2x00_desc_read(txd, 2, &word);
 	rt2x00_desc_read(txd, 2, &word);
@@ -1801,6 +1798,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.bss_info_changed	= rt2x00mac_bss_info_changed,
 	.conf_tx		= rt2x00mac_conf_tx,
 	.conf_tx		= rt2x00mac_conf_tx,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.flush			= rt2x00mac_flush,
 };
 };
 
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1829,28 +1827,28 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 };
 };
 
 
 static const struct data_queue_desc rt2500usb_queue_rx = {
 static const struct data_queue_desc rt2500usb_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 };
 
 
 static const struct data_queue_desc rt2500usb_queue_tx = {
 static const struct data_queue_desc rt2500usb_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 32,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 };
 
 
 static const struct data_queue_desc rt2500usb_queue_bcn = {
 static const struct data_queue_desc rt2500usb_queue_bcn = {
-	.entry_num		= BEACON_ENTRIES,
+	.entry_num		= 1,
 	.data_size		= MGMT_FRAME_SIZE,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb_bcn),
 	.priv_size		= sizeof(struct queue_entry_priv_usb_bcn),
 };
 };
 
 
 static const struct data_queue_desc rt2500usb_queue_atim = {
 static const struct data_queue_desc rt2500usb_queue_atim = {
-	.entry_num		= ATIM_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= DATA_FRAME_SIZE,
 	.data_size		= DATA_FRAME_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),

+ 48 - 13
drivers/net/wireless/rt2x00/rt2800.h

@@ -412,10 +412,22 @@
 #define BCN_OFFSET1_BCN7		FIELD32(0xff000000)
 #define BCN_OFFSET1_BCN7		FIELD32(0xff000000)
 
 
 /*
 /*
- * PBF registers
- * Most are for debug. Driver doesn't touch PBF register.
+ * TXRXQ_PCNT: PBF register
+ * PCNT_TX0Q: Page count for TX hardware queue 0
+ * PCNT_TX1Q: Page count for TX hardware queue 1
+ * PCNT_TX2Q: Page count for TX hardware queue 2
+ * PCNT_RX0Q: Page count for RX hardware queue
  */
  */
 #define TXRXQ_PCNT			0x0438
 #define TXRXQ_PCNT			0x0438
+#define TXRXQ_PCNT_TX0Q			FIELD32(0x000000ff)
+#define TXRXQ_PCNT_TX1Q			FIELD32(0x0000ff00)
+#define TXRXQ_PCNT_TX2Q			FIELD32(0x00ff0000)
+#define TXRXQ_PCNT_RX0Q			FIELD32(0xff000000)
+
+/*
+ * PBF register
+ * Debug. Driver doesn't touch PBF register.
+ */
 #define PBF_DBG				0x043c
 #define PBF_DBG				0x043c
 
 
 /*
 /*
@@ -960,8 +972,31 @@
 
 
 /*
 /*
  * TXOP_CTRL_CFG:
  * TXOP_CTRL_CFG:
+ * TIMEOUT_TRUN_EN: Enable/Disable TXOP timeout truncation
+ * AC_TRUN_EN: Enable/Disable truncation for AC change
+ * TXRATEGRP_TRUN_EN: Enable/Disable truncation for TX rate group change
+ * USER_MODE_TRUN_EN: Enable/Disable truncation for user TXOP mode
+ * MIMO_PS_TRUN_EN: Enable/Disable truncation for MIMO PS RTS/CTS
+ * RESERVED_TRUN_EN: Reserved
+ * LSIG_TXOP_EN: Enable/Disable L-SIG TXOP protection
+ * EXT_CCA_EN: Enable/Disable extension channel CCA reference (Defer 40Mhz
+ *	       transmissions if extension CCA is clear).
+ * EXT_CCA_DLY: Extension CCA signal delay time (unit: us)
+ * EXT_CWMIN: CwMin for extension channel backoff
+ *	      0: Disabled
+ *
  */
  */
 #define TXOP_CTRL_CFG			0x1340
 #define TXOP_CTRL_CFG			0x1340
+#define TXOP_CTRL_CFG_TIMEOUT_TRUN_EN	FIELD32(0x00000001)
+#define TXOP_CTRL_CFG_AC_TRUN_EN	FIELD32(0x00000002)
+#define TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN	FIELD32(0x00000004)
+#define TXOP_CTRL_CFG_USER_MODE_TRUN_EN	FIELD32(0x00000008)
+#define TXOP_CTRL_CFG_MIMO_PS_TRUN_EN	FIELD32(0x00000010)
+#define TXOP_CTRL_CFG_RESERVED_TRUN_EN	FIELD32(0x00000020)
+#define TXOP_CTRL_CFG_LSIG_TXOP_EN	FIELD32(0x00000040)
+#define TXOP_CTRL_CFG_EXT_CCA_EN	FIELD32(0x00000080)
+#define TXOP_CTRL_CFG_EXT_CCA_DLY	FIELD32(0x0000ff00)
+#define TXOP_CTRL_CFG_EXT_CWMIN		FIELD32(0x000f0000)
 
 
 /*
 /*
  * TX_RTS_CFG:
  * TX_RTS_CFG:
@@ -1485,17 +1520,17 @@
 #define SHARED_KEY_MODE_BASE		0x7000
 #define SHARED_KEY_MODE_BASE		0x7000
 
 
 #define MAC_WCID_ENTRY(__idx) \
 #define MAC_WCID_ENTRY(__idx) \
-	( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) )
+	(MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)))
 #define PAIRWISE_KEY_ENTRY(__idx) \
 #define PAIRWISE_KEY_ENTRY(__idx) \
-	( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+	(PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
 #define MAC_IVEIV_ENTRY(__idx) \
 #define MAC_IVEIV_ENTRY(__idx) \
-	( MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)) )
+	(MAC_IVEIV_TABLE_BASE + ((__idx) * sizeof(struct mac_iveiv_entry)))
 #define MAC_WCID_ATTR_ENTRY(__idx) \
 #define MAC_WCID_ATTR_ENTRY(__idx) \
-	( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) )
+	(MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)))
 #define SHARED_KEY_ENTRY(__idx) \
 #define SHARED_KEY_ENTRY(__idx) \
-	( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) )
+	(SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)))
 #define SHARED_KEY_MODE_ENTRY(__idx) \
 #define SHARED_KEY_MODE_ENTRY(__idx) \
-	( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) )
+	(SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)))
 
 
 struct mac_wcid_entry {
 struct mac_wcid_entry {
 	u8 mac[6];
 	u8 mac[6];
@@ -1635,9 +1670,9 @@ struct mac_iveiv_entry {
 #define HW_BEACON_BASE7			0x5bc0
 #define HW_BEACON_BASE7			0x5bc0
 
 
 #define HW_BEACON_OFFSET(__index) \
 #define HW_BEACON_OFFSET(__index) \
-	( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \
-	  (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \
-	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) )
+	(((__index) < 4) ? (HW_BEACON_BASE0 + (__index * 0x0200)) : \
+	  (((__index) < 6) ? (HW_BEACON_BASE4 + ((__index - 4) * 0x0200)) : \
+	  (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))))
 
 
 /*
 /*
  * BBP registers.
  * BBP registers.
@@ -1987,8 +2022,8 @@ struct mac_iveiv_entry {
 /*
 /*
  * DMA descriptor defines.
  * DMA descriptor defines.
  */
  */
-#define TXWI_DESC_SIZE			( 4 * sizeof(__le32) )
-#define RXWI_DESC_SIZE			( 4 * sizeof(__le32) )
+#define TXWI_DESC_SIZE			(4 * sizeof(__le32))
+#define RXWI_DESC_SIZE			(4 * sizeof(__le32))
 
 
 /*
 /*
  * TX WI structure
  * TX WI structure

+ 37 - 6
drivers/net/wireless/rt2x00/rt2800lib.c

@@ -277,13 +277,17 @@ int rt2800_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev)
 	unsigned int i;
 	unsigned int i;
 	u32 reg;
 	u32 reg;
 
 
+	/*
+	 * Some devices are really slow to respond here. Wait a whole second
+	 * before timing out.
+	 */
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 	for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
 		rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 		rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, &reg);
 		if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
 		if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) &&
 		    !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
 		    !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY))
 			return 0;
 			return 0;
 
 
-		msleep(1);
+		msleep(10);
 	}
 	}
 
 
 	ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
 	ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n");
@@ -483,7 +487,7 @@ void rt2800_write_tx_data(struct queue_entry *entry,
 			   txdesc->key_idx : 0xff);
 			   txdesc->key_idx : 0xff);
 	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
 	rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
 			   txdesc->length);
 			   txdesc->length);
-	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, txdesc->qid);
+	rt2x00_set_field32(&word, TXWI_W1_PACKETID_QUEUE, entry->queue->qid);
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID_ENTRY, (entry->entry_idx % 3) + 1);
 	rt2x00_desc_write(txwi, 1, word);
 	rt2x00_desc_write(txwi, 1, word);
 
 
@@ -727,7 +731,7 @@ void rt2800_txdone(struct rt2x00_dev *rt2x00dev)
 	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
 	 * that the TX_STA_FIFO stack has a size of 16. We stick to our
 	 * tx ring size for now.
 	 * tx ring size for now.
 	 */
 	 */
-	for (i = 0; i < TX_ENTRIES; i++) {
+	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
 		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
 		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &reg);
 		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
 		if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID))
 			break;
 			break;
@@ -824,7 +828,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 }
 }
 EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 
 
-static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
+static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
 				       unsigned int beacon_base)
 				       unsigned int beacon_base)
 {
 {
 	int i;
 	int i;
@@ -1144,6 +1148,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 			struct rt2x00intf_conf *conf, const unsigned int flags)
 			struct rt2x00intf_conf *conf, const unsigned int flags)
 {
 {
 	u32 reg;
 	u32 reg;
+	bool update_bssid = false;
 
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
 		/*
@@ -1173,6 +1178,16 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 	}
 	}
 
 
 	if (flags & CONFIG_UPDATE_MAC) {
 	if (flags & CONFIG_UPDATE_MAC) {
+		if (flags & CONFIG_UPDATE_TYPE &&
+		    conf->sync == TSF_SYNC_AP_NONE) {
+			/*
+			 * The BSSID register has to be set to our own mac
+			 * address in AP mode.
+			 */
+			memcpy(conf->bssid, conf->mac, sizeof(conf->mac));
+			update_bssid = true;
+		}
+
 		if (!is_zero_ether_addr((const u8 *)conf->mac)) {
 		if (!is_zero_ether_addr((const u8 *)conf->mac)) {
 			reg = le32_to_cpu(conf->mac[1]);
 			reg = le32_to_cpu(conf->mac[1]);
 			rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
 			rt2x00_set_field32(&reg, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff);
@@ -1183,7 +1198,7 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 					      conf->mac, sizeof(conf->mac));
 					      conf->mac, sizeof(conf->mac));
 	}
 	}
 
 
-	if (flags & CONFIG_UPDATE_BSSID) {
+	if ((flags & CONFIG_UPDATE_BSSID) || update_bssid) {
 		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
 		if (!is_zero_ether_addr((const u8 *)conf->bssid)) {
 			reg = le32_to_cpu(conf->bssid[1]);
 			reg = le32_to_cpu(conf->bssid[1]);
 			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
 			rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
@@ -2097,7 +2112,23 @@ static int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 		rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 		rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 	}
 	}
 
 
-	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f);
+	/*
+	 * The legacy driver also sets TXOP_CTRL_CFG_RESERVED_TRUN_EN to 1
+	 * although it is reserved.
+	 */
+	rt2800_register_read(rt2x00dev, TXOP_CTRL_CFG, &reg);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TIMEOUT_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_AC_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_TXRATEGRP_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_USER_MODE_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_MIMO_PS_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_RESERVED_TRUN_EN, 1);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_LSIG_TXOP_EN, 0);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_EN, 0);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CCA_DLY, 88);
+	rt2x00_set_field32(&reg, TXOP_CTRL_CFG_EXT_CWMIN, 0);
+	rt2800_register_write(rt2x00dev, TXOP_CTRL_CFG, reg);
+
 	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
 	rt2800_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002);
 
 
 	rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);
 	rt2800_register_read(rt2x00dev, TX_RTS_CFG, &reg);

+ 7 - 9
drivers/net/wireless/rt2x00/rt2800pci.c

@@ -328,8 +328,7 @@ static void rt2800pci_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
 
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
-			   (state == STATE_RADIO_RX_ON) ||
-			   (state == STATE_RADIO_RX_ON_LINK));
+			   (state == STATE_RADIO_RX_ON));
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 }
 }
 
 
@@ -442,7 +441,7 @@ static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 	 * if the device is booting and wasn't asleep it will return
 	 * if the device is booting and wasn't asleep it will return
 	 * failure when attempting to wakeup.
 	 * failure when attempting to wakeup.
 	 */
 	 */
-	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
 
 
 	if (state == STATE_AWAKE) {
 	if (state == STATE_AWAKE) {
 		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
 		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
@@ -477,9 +476,7 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
 		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 		break;
 	case STATE_RADIO_RX_ON:
 	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
 	case STATE_RADIO_RX_OFF:
 	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
 		rt2800pci_toggle_rx(rt2x00dev, state);
 		rt2800pci_toggle_rx(rt2x00dev, state);
 		break;
 		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON:
@@ -777,7 +774,7 @@ static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
 	 * Since we have only one producer and one consumer we don't
 	 * Since we have only one producer and one consumer we don't
 	 * need to lock the kfifo.
 	 * need to lock the kfifo.
 	 */
 	 */
-	for (i = 0; i < TX_ENTRIES; i++) {
+	for (i = 0; i < rt2x00dev->ops->tx->entry_num; i++) {
 		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
 		rt2800_register_read(rt2x00dev, TX_STA_FIFO, &status);
 
 
 		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
 		if (!rt2x00_get_field32(status, TX_STA_FIFO_VALID))
@@ -943,6 +940,7 @@ static const struct ieee80211_ops rt2800pci_mac80211_ops = {
 	.get_tsf		= rt2800_get_tsf,
 	.get_tsf		= rt2800_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.ampdu_action		= rt2800_ampdu_action,
 	.ampdu_action		= rt2800_ampdu_action,
+	.flush			= rt2x00mac_flush,
 };
 };
 
 
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
 static const struct rt2800_ops rt2800pci_rt2800_ops = {
@@ -991,21 +989,21 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 };
 };
 
 
 static const struct data_queue_desc rt2800pci_queue_rx = {
 static const struct data_queue_desc rt2800pci_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 128,
 	.data_size		= AGGREGATION_SIZE,
 	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.desc_size		= RXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2800pci_queue_tx = {
 static const struct data_queue_desc rt2800pci_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 64,
 	.data_size		= AGGREGATION_SIZE,
 	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.desc_size		= TXD_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 };
 };
 
 
 static const struct data_queue_desc rt2800pci_queue_bcn = {
 static const struct data_queue_desc rt2800pci_queue_bcn = {
-	.entry_num		= 8 * BEACON_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= 0, /* No DMA required for beacons */
 	.data_size		= 0, /* No DMA required for beacons */
 	.desc_size		= TXWI_DESC_SIZE,
 	.desc_size		= TXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_pci),
 	.priv_size		= sizeof(struct queue_entry_priv_pci),

+ 6 - 6
drivers/net/wireless/rt2x00/rt2800pci.h

@@ -38,10 +38,10 @@
  * Queue register offset macros
  * Queue register offset macros
  */
  */
 #define TX_QUEUE_REG_OFFSET		0x10
 #define TX_QUEUE_REG_OFFSET		0x10
-#define TX_BASE_PTR(__x)		TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET)
-#define TX_MAX_CNT(__x)			TX_MAX_CNT0 + ((__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_BASE_PTR(__x)		(TX_BASE_PTR0 + ((__x) * TX_QUEUE_REG_OFFSET))
+#define TX_MAX_CNT(__x)			(TX_MAX_CNT0 + ((__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))
 
 
 /*
 /*
  * 8051 firmware image.
  * 8051 firmware image.
@@ -52,8 +52,8 @@
 /*
 /*
  * DMA descriptor defines.
  * DMA descriptor defines.
  */
  */
-#define TXD_DESC_SIZE			( 4 * sizeof(__le32) )
-#define RXD_DESC_SIZE			( 4 * sizeof(__le32) )
+#define TXD_DESC_SIZE			(4 * sizeof(__le32))
+#define RXD_DESC_SIZE			(4 * sizeof(__le32))
 
 
 /*
 /*
  * TX descriptor format for TX, PRIO and Beacon Ring.
  * TX descriptor format for TX, PRIO and Beacon Ring.

+ 54 - 12
drivers/net/wireless/rt2x00/rt2800usb.c

@@ -45,7 +45,7 @@
 /*
 /*
  * Allow hardware encryption to be disabled.
  * Allow hardware encryption to be disabled.
  */
  */
-static int modparam_nohwcrypt = 0;
+static int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
 
 
@@ -114,8 +114,7 @@ static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
 
 
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX,
-			   (state == STATE_RADIO_RX_ON) ||
-			   (state == STATE_RADIO_RX_ON_LINK));
+			   (state == STATE_RADIO_RX_ON));
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 }
 }
 
 
@@ -165,7 +164,8 @@ static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev)
 	 * this limit so reduce the number to prevent errors.
 	 * this limit so reduce the number to prevent errors.
 	 */
 	 */
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_AGG_LIMIT,
-			   ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3);
+			   ((rt2x00dev->ops->rx->entry_num * DATA_FRAME_SIZE)
+			    / 1024) - 3);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_RX_BULK_EN, 1);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
 	rt2x00_set_field32(&reg, USB_DMA_CFG_TX_BULK_EN, 1);
 	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
 	rt2800_register_write(rt2x00dev, USB_DMA_CFG, reg);
@@ -183,9 +183,9 @@ static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 			       enum dev_state state)
 {
 {
 	if (state == STATE_AWAKE)
 	if (state == STATE_AWAKE)
-		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 2);
 	else
 	else
-		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2);
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -215,9 +215,7 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
 		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 		break;
 	case STATE_RADIO_RX_ON:
 	case STATE_RADIO_RX_ON:
-	case STATE_RADIO_RX_ON_LINK:
 	case STATE_RADIO_RX_OFF:
 	case STATE_RADIO_RX_OFF:
-	case STATE_RADIO_RX_OFF_LINK:
 		rt2800usb_toggle_rx(rt2x00dev, state);
 		rt2800usb_toggle_rx(rt2x00dev, state);
 		break;
 		break;
 	case STATE_RADIO_IRQ_ON:
 	case STATE_RADIO_IRQ_ON:
@@ -244,6 +242,49 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 	return retval;
 	return retval;
 }
 }
 
 
+/*
+ * Watchdog handlers
+ */
+static void rt2800usb_watchdog(struct rt2x00_dev *rt2x00dev)
+{
+	unsigned int i;
+	u32 reg;
+
+	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q)) {
+		WARNING(rt2x00dev, "TX HW queue 0 timed out,"
+			" invoke forced kick");
+
+		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40012);
+
+		for (i = 0; i < 10; i++) {
+			udelay(10);
+			if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX0Q))
+				break;
+		}
+
+		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+	}
+
+	rt2800_register_read(rt2x00dev, TXRXQ_PCNT, &reg);
+	if (rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q)) {
+		WARNING(rt2x00dev, "TX HW queue 1 timed out,"
+			" invoke forced kick");
+
+		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf4000a);
+
+		for (i = 0; i < 10; i++) {
+			udelay(10);
+			if (!rt2x00_get_field32(reg, TXRXQ_PCNT_TX1Q))
+				break;
+		}
+
+		rt2800_register_write(rt2x00dev, PBF_CFG, 0xf40006);
+	}
+
+	rt2x00usb_watchdog(rt2x00dev);
+}
+
 /*
 /*
  * TX descriptor initialization
  * TX descriptor initialization
  */
  */
@@ -507,6 +548,7 @@ static const struct ieee80211_ops rt2800usb_mac80211_ops = {
 	.get_tsf		= rt2800_get_tsf,
 	.get_tsf		= rt2800_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
 	.ampdu_action		= rt2800_ampdu_action,
 	.ampdu_action		= rt2800_ampdu_action,
+	.flush			= rt2x00mac_flush,
 };
 };
 
 
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
 static const struct rt2800_ops rt2800usb_rt2800_ops = {
@@ -535,7 +577,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.link_stats		= rt2800_link_stats,
 	.link_stats		= rt2800_link_stats,
 	.reset_tuner		= rt2800_reset_tuner,
 	.reset_tuner		= rt2800_reset_tuner,
 	.link_tuner		= rt2800_link_tuner,
 	.link_tuner		= rt2800_link_tuner,
-	.watchdog		= rt2x00usb_watchdog,
+	.watchdog		= rt2800usb_watchdog,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
 	.write_beacon		= rt2800_write_beacon,
@@ -553,21 +595,21 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 };
 };
 
 
 static const struct data_queue_desc rt2800usb_queue_rx = {
 static const struct data_queue_desc rt2800usb_queue_rx = {
-	.entry_num		= RX_ENTRIES,
+	.entry_num		= 128,
 	.data_size		= AGGREGATION_SIZE,
 	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
 	.desc_size		= RXINFO_DESC_SIZE + RXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 };
 
 
 static const struct data_queue_desc rt2800usb_queue_tx = {
 static const struct data_queue_desc rt2800usb_queue_tx = {
-	.entry_num		= TX_ENTRIES,
+	.entry_num		= 64,
 	.data_size		= AGGREGATION_SIZE,
 	.data_size		= AGGREGATION_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 };
 };
 
 
 static const struct data_queue_desc rt2800usb_queue_bcn = {
 static const struct data_queue_desc rt2800usb_queue_bcn = {
-	.entry_num		= 8 * BEACON_ENTRIES,
+	.entry_num		= 8,
 	.data_size		= MGMT_FRAME_SIZE,
 	.data_size		= MGMT_FRAME_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.desc_size		= TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
 	.priv_size		= sizeof(struct queue_entry_priv_usb),
 	.priv_size		= sizeof(struct queue_entry_priv_usb),

+ 2 - 2
drivers/net/wireless/rt2x00/rt2800usb.h

@@ -40,8 +40,8 @@
 /*
 /*
  * DMA descriptor defines.
  * DMA descriptor defines.
  */
  */
-#define TXINFO_DESC_SIZE		( 1 * sizeof(__le32) )
-#define RXINFO_DESC_SIZE		( 1 * sizeof(__le32) )
+#define TXINFO_DESC_SIZE		(1 * sizeof(__le32))
+#define RXINFO_DESC_SIZE		(1 * sizeof(__le32))
 
 
 /*
 /*
  * TX Info structure
  * TX Info structure

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

@@ -1133,6 +1133,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
 		      const struct ieee80211_tx_queue_params *params);
 		      const struct ieee80211_tx_queue_params *params);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
 void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw);
+void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop);
 
 
 /*
 /*
  * Driver allocation handlers.
  * Driver allocation handlers.

+ 5 - 3
drivers/net/wireless/rt2x00/rt2x00config.c

@@ -133,7 +133,7 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 	 */
 	 */
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
 	if (!(ant->flags & ANTENNA_RX_DIVERSITY))
 		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
 		config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx);
-	else if(config.rx == ANTENNA_SW_DIVERSITY)
+	else if (config.rx == ANTENNA_SW_DIVERSITY)
 		config.rx = active->rx;
 		config.rx = active->rx;
 
 
 	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
 	if (!(ant->flags & ANTENNA_TX_DIVERSITY))
@@ -146,7 +146,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 	 * else the changes will be ignored by the device.
 	 * else the changes will be ignored by the device.
 	 */
 	 */
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK);
+		rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+						      STATE_RADIO_RX_OFF);
 
 
 	/*
 	/*
 	 * Write new antenna setup to device and reset the link tuner.
 	 * Write new antenna setup to device and reset the link tuner.
@@ -160,7 +161,8 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
 	memcpy(active, &config, sizeof(config));
 	memcpy(active, &config, sizeof(config));
 
 
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 	if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
-		rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
+		rt2x00dev->ops->lib->set_device_state(rt2x00dev,
+						      STATE_RADIO_RX_ON);
 }
 }
 
 
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
 void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,

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

@@ -162,11 +162,11 @@ void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
 	struct timeval timestamp;
 	struct timeval timestamp;
 	u32 data_len;
 	u32 data_len;
 
 
-	do_gettimeofday(&timestamp);
-
-	if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags))
+	if (likely(!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)))
 		return;
 		return;
 
 
+	do_gettimeofday(&timestamp);
+
 	if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
 	if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) {
 		DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
 		DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n");
 		return;
 		return;
@@ -342,7 +342,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
 	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 	    sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdma done\tdone\n");
 
 
 	queue_for_each(intf->rt2x00dev, queue) {
 	queue_for_each(intf->rt2x00dev, queue) {
-		spin_lock_irqsave(&queue->lock, irqflags);
+		spin_lock_irqsave(&queue->index_lock, irqflags);
 
 
 		temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
 		temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid,
 				queue->count, queue->limit, queue->length,
 				queue->count, queue->limit, queue->length,
@@ -350,7 +350,7 @@ static ssize_t rt2x00debug_read_queue_stats(struct file *file,
 				queue->index[Q_INDEX_DMA_DONE],
 				queue->index[Q_INDEX_DMA_DONE],
 				queue->index[Q_INDEX_DONE]);
 				queue->index[Q_INDEX_DONE]);
 
 
-		spin_unlock_irqrestore(&queue->lock, irqflags);
+		spin_unlock_irqrestore(&queue->index_lock, irqflags);
 	}
 	}
 
 
 	size = strlen(data);
 	size = strlen(data);

+ 15 - 22
drivers/net/wireless/rt2x00/rt2x00dev.c

@@ -68,7 +68,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
 	/*
 	/*
 	 * Enable RX.
 	 * Enable RX.
 	 */
 	 */
-	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_ON);
+	rt2x00link_start_tuner(rt2x00dev);
 
 
 	/*
 	/*
 	 * Start watchdog monitoring.
 	 * Start watchdog monitoring.
@@ -102,7 +103,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
 	/*
 	/*
 	 * Disable RX.
 	 * Disable RX.
 	 */
 	 */
-	rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
+	rt2x00link_stop_tuner(rt2x00dev);
+	rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_RX_OFF);
 
 
 	/*
 	/*
 	 * Disable radio.
 	 * Disable radio.
@@ -113,23 +115,6 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
 	rt2x00leds_led_radio(rt2x00dev, false);
 	rt2x00leds_led_radio(rt2x00dev, false);
 }
 }
 
 
-void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
-{
-	/*
-	 * When we are disabling the RX, we should also stop the link tuner.
-	 */
-	if (state == STATE_RADIO_RX_OFF)
-		rt2x00link_stop_tuner(rt2x00dev);
-
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev, state);
-
-	/*
-	 * When we are enabling the RX, we should also start the link tuner.
-	 */
-	if (state == STATE_RADIO_RX_ON)
-		rt2x00link_start_tuner(rt2x00dev);
-}
-
 static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 					  struct ieee80211_vif *vif)
 					  struct ieee80211_vif *vif)
 {
 {
@@ -483,6 +468,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 	unsigned int header_length;
 	unsigned int header_length;
 	int rate_idx;
 	int rate_idx;
 
 
+	if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) ||
+	    !test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+		goto submit_entry;
+
 	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
 	if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags))
 		goto submit_entry;
 		goto submit_entry;
 
 
@@ -567,9 +556,13 @@ void rt2x00lib_rxdone(struct queue_entry *entry)
 	entry->skb = skb;
 	entry->skb = skb;
 
 
 submit_entry:
 submit_entry:
-	rt2x00dev->ops->lib->clear_entry(entry);
-	rt2x00queue_index_inc(entry->queue, Q_INDEX);
+	entry->flags = 0;
 	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
 	rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
+	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
+	    test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
+		rt2x00dev->ops->lib->clear_entry(entry);
+		rt2x00queue_index_inc(entry->queue, Q_INDEX);
+	}
 }
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
 EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
 
 
@@ -678,7 +671,7 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry,
 {
 {
 	entry->flags = 0;
 	entry->flags = 0;
 	entry->bitrate = rate->bitrate;
 	entry->bitrate = rate->bitrate;
-	entry->hw_value =index;
+	entry->hw_value = index;
 	entry->hw_value_short = index;
 	entry->hw_value_short = index;
 
 
 	if (rate->flags & DEV_RATE_SHORT_PREAMBLE)
 	if (rate->flags & DEV_RATE_SHORT_PREAMBLE)

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

@@ -57,7 +57,7 @@ static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value)
 }
 }
 
 
 #define RATE_MCS(__mode, __mcs) \
 #define RATE_MCS(__mode, __mcs) \
-	( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) )
+	((((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff))
 
 
 static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
 static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
 {
 {
@@ -69,7 +69,6 @@ static inline int rt2x00_get_rate_mcs(const u16 mcs_value)
  */
  */
 int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
 int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
 void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev);
-void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state);
 
 
 /*
 /*
  * Initialization handlers.
  * Initialization handlers.

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