Browse Source

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

Conflicts:
	drivers/net/wireless/libertas_tf/cmd.c
	drivers/net/wireless/libertas_tf/main.c
John W. Linville 15 years ago
parent
commit
83163244f8
100 changed files with 4253 additions and 1085 deletions
  1. 1 0
      MAINTAINERS
  2. 6 0
      drivers/net/wireless/Kconfig
  3. 1 0
      drivers/net/wireless/at76c50x-usb.c
  4. 1 3
      drivers/net/wireless/ath/ar9170/main.c
  5. 2 4
      drivers/net/wireless/ath/ath5k/base.c
  6. 0 9
      drivers/net/wireless/ath/ath9k/ani.c
  7. 0 1
      drivers/net/wireless/ath/ath9k/ani.h
  8. 1 1
      drivers/net/wireless/ath/ath9k/ar5008_initvals.h
  9. 2 3
      drivers/net/wireless/ath/ath9k/ar5008_phy.c
  10. 5 0
      drivers/net/wireless/ath/ath9k/ar9002_hw.c
  11. 4 4
      drivers/net/wireless/ath/ath9k/ar9002_initvals.h
  12. 6 10
      drivers/net/wireless/ath/ath9k/ar9002_phy.c
  13. 2 1
      drivers/net/wireless/ath/ath9k/ar9003_calib.c
  14. 6 2
      drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
  15. 1 1
      drivers/net/wireless/ath/ath9k/ar9003_eeprom.h
  16. 128 137
      drivers/net/wireless/ath/ath9k/ar9003_initvals.h
  17. 3 0
      drivers/net/wireless/ath/ath9k/ar9003_mac.c
  18. 4 12
      drivers/net/wireless/ath/ath9k/ar9003_phy.c
  19. 0 1
      drivers/net/wireless/ath/ath9k/common.c
  20. 2 1
      drivers/net/wireless/ath/ath9k/eeprom.h
  21. 2 0
      drivers/net/wireless/ath/ath9k/eeprom_def.c
  22. 84 65
      drivers/net/wireless/ath/ath9k/hif_usb.c
  23. 0 1
      drivers/net/wireless/ath/ath9k/hif_usb.h
  24. 2 0
      drivers/net/wireless/ath/ath9k/htc.h
  25. 8 0
      drivers/net/wireless/ath/ath9k/htc_drv_init.c
  26. 59 25
      drivers/net/wireless/ath/ath9k/htc_drv_main.c
  27. 34 25
      drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
  28. 3 2
      drivers/net/wireless/ath/ath9k/htc_hst.c
  29. 20 7
      drivers/net/wireless/ath/ath9k/hw.c
  30. 5 3
      drivers/net/wireless/ath/ath9k/hw.h
  31. 6 4
      drivers/net/wireless/ath/ath9k/mac.c
  32. 20 0
      drivers/net/wireless/ath/ath9k/main.c
  33. 7 4
      drivers/net/wireless/ath/ath9k/wmi.c
  34. 2 2
      drivers/net/wireless/ath/ath9k/wmi.h
  35. 2 0
      drivers/net/wireless/ath/ath9k/xmit.c
  36. 19 2
      drivers/net/wireless/b43/main.c
  37. 0 1
      drivers/net/wireless/b43/xmit.c
  38. 19 2
      drivers/net/wireless/b43legacy/main.c
  39. 0 1
      drivers/net/wireless/b43legacy/xmit.c
  40. 1 0
      drivers/net/wireless/iwlwifi/Makefile
  41. 0 1
      drivers/net/wireless/iwlwifi/iwl-1000.c
  42. 500 0
      drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
  43. 60 0
      drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
  44. 71 1
      drivers/net/wireless/iwlwifi/iwl-3945.c
  45. 2 0
      drivers/net/wireless/iwlwifi/iwl-3945.h
  46. 52 21
      drivers/net/wireless/iwlwifi/iwl-5000.c
  47. 51 22
      drivers/net/wireless/iwlwifi/iwl-6000.c
  48. 18 5
      drivers/net/wireless/iwlwifi/iwl-agn-lib.c
  49. 11 9
      drivers/net/wireless/iwlwifi/iwl-agn-rs.c
  50. 13 3
      drivers/net/wireless/iwlwifi/iwl-agn-tx.c
  51. 0 14
      drivers/net/wireless/iwlwifi/iwl-agn.c
  52. 3 1
      drivers/net/wireless/iwlwifi/iwl-commands.h
  53. 6 4
      drivers/net/wireless/iwlwifi/iwl-core.c
  54. 3 1
      drivers/net/wireless/iwlwifi/iwl-core.h
  55. 6 12
      drivers/net/wireless/iwlwifi/iwl-debugfs.c
  56. 5 0
      drivers/net/wireless/iwlwifi/iwl-dev.h
  57. 2 1
      drivers/net/wireless/iwlwifi/iwl-scan.c
  58. 3 3
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  59. 1 1
      drivers/net/wireless/iwmc3200wifi/bus.h
  60. 2 5
      drivers/net/wireless/iwmc3200wifi/debug.h
  61. 10 100
      drivers/net/wireless/iwmc3200wifi/debugfs.c
  62. 2 15
      drivers/net/wireless/iwmc3200wifi/sdio.c
  63. 3 1
      drivers/net/wireless/libertas/if_sdio.c
  64. 169 34
      drivers/net/wireless/libertas_tf/cmd.c
  65. 104 0
      drivers/net/wireless/libertas_tf/deb_defs.h
  66. 210 41
      drivers/net/wireless/libertas_tf/if_usb.c
  67. 2 0
      drivers/net/wireless/libertas_tf/libertas_tf.h
  68. 85 6
      drivers/net/wireless/libertas_tf/main.c
  69. 4 2
      drivers/net/wireless/mac80211_hwsim.c
  70. 2 4
      drivers/net/wireless/mwl8k.c
  71. 7 0
      drivers/net/wireless/orinoco/Kconfig
  72. 1 0
      drivers/net/wireless/orinoco/Makefile
  73. 4 4
      drivers/net/wireless/orinoco/airport.c
  74. 1 1
      drivers/net/wireless/orinoco/cfg.c
  75. 5 5
      drivers/net/wireless/orinoco/fw.c
  76. 263 23
      drivers/net/wireless/orinoco/hermes.c
  77. 40 22
      drivers/net/wireless/orinoco/hermes.h
  78. 9 234
      drivers/net/wireless/orinoco/hermes_dld.c
  79. 32 31
      drivers/net/wireless/orinoco/hw.c
  80. 76 61
      drivers/net/wireless/orinoco/main.c
  81. 26 4
      drivers/net/wireless/orinoco/orinoco.h
  82. 3 3
      drivers/net/wireless/orinoco/orinoco_cs.c
  83. 1 1
      drivers/net/wireless/orinoco/orinoco_nortel.c
  84. 1 1
      drivers/net/wireless/orinoco/orinoco_pci.c
  85. 1 1
      drivers/net/wireless/orinoco/orinoco_plx.c
  86. 1 1
      drivers/net/wireless/orinoco/orinoco_tmd.c
  87. 1800 0
      drivers/net/wireless/orinoco/orinoco_usb.c
  88. 4 3
      drivers/net/wireless/orinoco/spectrum_cs.c
  89. 3 3
      drivers/net/wireless/orinoco/wext.c
  90. 1 2
      drivers/net/wireless/p54/main.c
  91. 8 8
      drivers/net/wireless/p54/p54pci.c
  92. 0 1
      drivers/net/wireless/p54/txrx.c
  93. 2 2
      drivers/net/wireless/rt2x00/Kconfig
  94. 2 2
      drivers/net/wireless/rt2x00/rt2400pci.c
  95. 1 1
      drivers/net/wireless/rt2x00/rt2500pci.c
  96. 1 1
      drivers/net/wireless/rt2x00/rt2500usb.c
  97. 8 3
      drivers/net/wireless/rt2x00/rt2800.h
  98. 76 15
      drivers/net/wireless/rt2x00/rt2800lib.c
  99. 1 5
      drivers/net/wireless/rt2x00/rt2800pci.c
  100. 7 6
      drivers/net/wireless/rt2x00/rt2800usb.c

+ 1 - 0
MAINTAINERS

@@ -3956,6 +3956,7 @@ F:	net/rfkill/
 F:	net/wireless/
 F:	net/wireless/
 F:	include/net/ieee80211*
 F:	include/net/ieee80211*
 F:	include/linux/wireless.h
 F:	include/linux/wireless.h
+F:	include/linux/iw_handler.h
 F:	drivers/net/wireless/
 F:	drivers/net/wireless/
 
 
 NETWORKING DRIVERS
 NETWORKING DRIVERS

+ 6 - 0
drivers/net/wireless/Kconfig

@@ -38,6 +38,12 @@ config LIBERTAS_THINFIRM
 	---help---
 	---help---
 	  A library for Marvell Libertas 8xxx devices using thinfirm.
 	  A library for Marvell Libertas 8xxx devices using thinfirm.
 
 
+config LIBERTAS_THINFIRM_DEBUG
+	bool "Enable full debugging output in the Libertas thin firmware module."
+	depends on LIBERTAS_THINFIRM
+	---help---
+	  Debugging support.
+
 config LIBERTAS_THINFIRM_USB
 config LIBERTAS_THINFIRM_USB
 	tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
 	tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware"
 	depends on LIBERTAS_THINFIRM && USB
 	depends on LIBERTAS_THINFIRM && USB

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

@@ -1889,6 +1889,7 @@ static void at76_dwork_hw_scan(struct work_struct *work)
 }
 }
 
 
 static int at76_hw_scan(struct ieee80211_hw *hw,
 static int at76_hw_scan(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
 			struct cfg80211_scan_request *req)
 			struct cfg80211_scan_request *req)
 {
 {
 	struct at76_priv *priv = hw->priv;
 	struct at76_priv *priv = hw->priv;

+ 1 - 3
drivers/net/wireless/ath/ar9170/main.c

@@ -927,7 +927,6 @@ static void ar9170_rx_phy_status(struct ar9170 *ar,
 
 
 	/* TODO: we could do something with phy_errors */
 	/* TODO: we could do something with phy_errors */
 	status->signal = ar->noise[0] + phy->rssi_combined;
 	status->signal = ar->noise[0] + phy->rssi_combined;
-	status->noise = ar->noise[0];
 }
 }
 
 
 static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
 static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
@@ -2548,8 +2547,7 @@ void *ar9170_alloc(size_t priv_size)
 					 BIT(NL80211_IFTYPE_ADHOC);
 					 BIT(NL80211_IFTYPE_ADHOC);
 	ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
 	ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
 			 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 			 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-			 IEEE80211_HW_SIGNAL_DBM |
-			 IEEE80211_HW_NOISE_DBM;
+			 IEEE80211_HW_SIGNAL_DBM;
 
 
 	if (modparam_ht) {
 	if (modparam_ht) {
 		ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
 		ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;

+ 2 - 4
drivers/net/wireless/ath/ath5k/base.c

@@ -548,8 +548,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	SET_IEEE80211_DEV(hw, &pdev->dev);
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
-		    IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM;
+		    IEEE80211_HW_SIGNAL_DBM;
 
 
 	hw->wiphy->interface_modes =
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_AP) |
@@ -2030,8 +2029,7 @@ accept:
 		rxs->freq = sc->curchan->center_freq;
 		rxs->freq = sc->curchan->center_freq;
 		rxs->band = sc->curband->band;
 		rxs->band = sc->curband->band;
 
 
-		rxs->noise = sc->ah->ah_noise_floor;
-		rxs->signal = rxs->noise + rs.rs_rssi;
+		rxs->signal = sc->ah->ah_noise_floor + rs.rs_rssi;
 
 
 		rxs->antenna = rs.rs_antenna;
 		rxs->antenna = rs.rs_antenna;
 
 

+ 0 - 9
drivers/net/wireless/ath/ath9k/ani.c

@@ -657,12 +657,3 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
 	if (ah->config.enable_ani)
 	if (ah->config.enable_ani)
 		ah->proc_phyerr |= HAL_PROCESS_ANI;
 		ah->proc_phyerr |= HAL_PROCESS_ANI;
 }
 }
-
-void ath9k_hw_ani_disable(struct ath_hw *ah)
-{
-	ath_print(ath9k_hw_common(ah), ATH_DBG_ANI, "Disabling ANI\n");
-
-	ath9k_hw_disable_mib_counters(ah);
-	REG_WRITE(ah, AR_PHY_ERR_1, 0);
-	REG_WRITE(ah, AR_PHY_ERR_2, 0);
-}

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

@@ -118,6 +118,5 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt,
 void ath9k_hw_procmibevent(struct ath_hw *ah);
 void ath9k_hw_procmibevent(struct ath_hw *ah);
 void ath9k_hw_ani_setup(struct ath_hw *ah);
 void ath9k_hw_ani_setup(struct ath_hw *ah);
 void ath9k_hw_ani_init(struct ath_hw *ah);
 void ath9k_hw_ani_init(struct ath_hw *ah);
-void ath9k_hw_ani_disable(struct ath_hw *ah);
 
 
 #endif /* ANI_H */
 #endif /* ANI_H */

+ 1 - 1
drivers/net/wireless/ath/ath9k/ar5008_initvals.h

@@ -249,7 +249,7 @@ static const u32 ar5416Common[][2] = {
     { 0x00008258, 0x00000000 },
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8000010 },
+    { 0x00008264, 0x88000010 },
     { 0x00008270, 0x00000000 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
     { 0x00008278, 0x003e4180 },

+ 2 - 3
drivers/net/wireless/ath/ath9k/ar5008_phy.c

@@ -850,7 +850,7 @@ static int ar5008_hw_process_ini(struct ath_hw *ah,
 
 
 	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
 	REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites);
 
 
-	if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
+	if (IS_CHAN_A_FAST_CLOCK(ah, chan)) {
 		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
 		REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex,
 				regWrites);
 				regWrites);
 	}
 	}
@@ -892,8 +892,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan)
 		rfMode |= (IS_CHAN_5GHZ(chan)) ?
 		rfMode |= (IS_CHAN_5GHZ(chan)) ?
 			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
 			AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
 
 
-	if ((AR_SREV_9280_20(ah) || AR_SREV_9300_20_OR_LATER(ah))
-	    && IS_CHAN_A_5MHZ_SPACED(chan))
+	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
 		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
 		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
 
 
 	REG_WRITE(ah, AR_PHY_MODE, rfMode);
 	REG_WRITE(ah, AR_PHY_MODE, rfMode);

+ 5 - 0
drivers/net/wireless/ath/ath9k/ar9002_hw.c

@@ -408,6 +408,8 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 
 
 		} else {
 		} else {
+			ENABLE_REGWRITE_BUFFER(ah);
+
 			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
 			REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
 			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
 			REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
 
 
@@ -428,6 +430,9 @@ static void ar9002_hw_configpcipowersave(struct ath_hw *ah,
 
 
 			/* Load the new settings */
 			/* Load the new settings */
 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 			REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+
+			REGWRITE_BUFFER_FLUSH(ah);
+			DISABLE_REGWRITE_BUFFER(ah);
 		}
 		}
 
 
 		udelay(1000);
 		udelay(1000);

+ 4 - 4
drivers/net/wireless/ath/ath9k/ar9002_initvals.h

@@ -793,7 +793,7 @@ static const u32 ar9280Common_9280_2[][2] = {
     { 0x00008258, 0x00000000 },
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
     { 0x00008278, 0x003e4180 },
@@ -1963,7 +1963,7 @@ static const u32 ar9285Common_9285[][2] = {
     { 0x00008258, 0x00000000 },
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
     { 0x00008278, 0x003e4180 },
@@ -3185,7 +3185,7 @@ static const u32 ar9287Common_9287_1_0[][2] = {
     { 0x00008258, 0x00000000 },
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
     { 0x00008278, 0x003e4180 },
@@ -4973,7 +4973,7 @@ static const u32 ar9271Common_9271[][2] = {
     { 0x00008258, 0x00000000 },
     { 0x00008258, 0x00000000 },
     { 0x0000825c, 0x400000ff },
     { 0x0000825c, 0x400000ff },
     { 0x00008260, 0x00080922 },
     { 0x00008260, 0x00080922 },
-    { 0x00008264, 0xa8a00010 },
+    { 0x00008264, 0x88a00010 },
     { 0x00008270, 0x00000000 },
     { 0x00008270, 0x00000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008274, 0x40000000 },
     { 0x00008278, 0x003e4180 },
     { 0x00008278, 0x003e4180 },

+ 6 - 10
drivers/net/wireless/ath/ath9k/ar9002_phy.c

@@ -455,16 +455,12 @@ static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
 		pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
 		pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
 
 
 	if (chan && IS_CHAN_5GHZ(chan)) {
 	if (chan && IS_CHAN_5GHZ(chan)) {
-		pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-
-
-		if (AR_SREV_9280_20(ah)) {
-			if (((chan->channel % 20) == 0)
-			    || ((chan->channel % 10) == 0))
-				pll = 0x2850;
-			else
-				pll = 0x142c;
-		}
+		if (IS_CHAN_A_FAST_CLOCK(ah, chan))
+			pll = 0x142c;
+		else if (AR_SREV_9280_20(ah))
+			pll = 0x2850;
+		else
+			pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
 	} else {
 	} else {
 		pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
 		pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
 	}
 	}

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

@@ -755,7 +755,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
 	}
 	}
 
 
 	/* Do Tx IQ Calibration */
 	/* Do Tx IQ Calibration */
-	ar9003_hw_tx_iq_cal(ah);
+	if (ah->config.tx_iq_calibration)
+		ar9003_hw_tx_iq_cal(ah);
 
 
 	/* Revert chainmasks to their original values before NF cal */
 	/* Revert chainmasks to their original values before NF cal */
 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
 	ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);

+ 6 - 2
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c

@@ -659,6 +659,9 @@ static void ar9300_swap_eeprom(struct ar9300_eeprom *eep)
 	word = swab16(eep->baseEepHeader.regDmn[1]);
 	word = swab16(eep->baseEepHeader.regDmn[1]);
 	eep->baseEepHeader.regDmn[1] = word;
 	eep->baseEepHeader.regDmn[1] = word;
 
 
+	dword = swab32(eep->baseEepHeader.swreg);
+	eep->baseEepHeader.swreg = dword;
+
 	dword = swab32(eep->modalHeader2G.antCtrlCommon);
 	dword = swab32(eep->modalHeader2G.antCtrlCommon);
 	eep->modalHeader2G.antCtrlCommon = dword;
 	eep->modalHeader2G.antCtrlCommon = dword;
 
 
@@ -1200,7 +1203,7 @@ static u8 ar9003_hw_eeprom_get_tgt_pwr(struct ath_hw *ah,
 	u8 *pFreqBin;
 	u8 *pFreqBin;
 
 
 	if (is2GHz) {
 	if (is2GHz) {
-		numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+		numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
 		pEepromTargetPwr = eep->calTargetPower2G;
 		pEepromTargetPwr = eep->calTargetPower2G;
 		pFreqBin = eep->calTarget_freqbin_2G;
 		pFreqBin = eep->calTarget_freqbin_2G;
 	} else {
 	} else {
@@ -1236,7 +1239,7 @@ static u8 ar9003_hw_eeprom_get_ht20_tgt_pwr(struct ath_hw *ah,
 	u8 *pFreqBin;
 	u8 *pFreqBin;
 
 
 	if (is2GHz) {
 	if (is2GHz) {
-		numPiers = AR9300_NUM_5G_20_TARGET_POWERS;
+		numPiers = AR9300_NUM_2G_20_TARGET_POWERS;
 		pEepromTargetPwr = eep->calTargetPower2GHT20;
 		pEepromTargetPwr = eep->calTargetPower2GHT20;
 		pFreqBin = eep->calTarget_freqbin_2GHT20;
 		pFreqBin = eep->calTarget_freqbin_2GHT20;
 	} else {
 	} else {
@@ -1817,6 +1820,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
 					u8 twiceMaxRegulatoryPower,
 					u8 twiceMaxRegulatoryPower,
 					u8 powerLimit)
 					u8 powerLimit)
 {
 {
+	ah->txpower_limit = powerLimit;
 	ar9003_hw_set_target_power_eeprom(ah, chan->channel);
 	ar9003_hw_set_target_power_eeprom(ah, chan->channel);
 	ar9003_hw_calibration_apply(ah, chan->channel);
 	ar9003_hw_calibration_apply(ah, chan->channel);
 }
 }

+ 1 - 1
drivers/net/wireless/ath/ath9k/ar9003_eeprom.h

@@ -265,7 +265,7 @@ struct cal_ctl_edge_pwr {
 } __packed;
 } __packed;
 
 
 struct cal_ctl_data_2g {
 struct cal_ctl_data_2g {
-	struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_5G];
+	struct cal_ctl_edge_pwr ctlEdges[AR9300_NUM_BAND_EDGES_2G];
 } __packed;
 } __packed;
 
 
 struct cal_ctl_data_5g {
 struct cal_ctl_data_5g {

+ 128 - 137
drivers/net/wireless/ath/ath9k/ar9003_initvals.h

@@ -31,7 +31,7 @@ static const u32 ar9300_2p0_radio_postamble[][5] = {
 
 
 static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
 static const u32 ar9300Modes_lowest_ob_db_tx_gain_table_2p0[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
 	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
 	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
 	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
@@ -545,7 +545,7 @@ static const u32 ar9300_2p0_soc_postamble[][5] = {
 };
 };
 
 
 static const u32 ar9200_merlin_2p0_radio_core[][2] = {
 static const u32 ar9200_merlin_2p0_radio_core[][2] = {
-	/* Addr      common    */
+	/* Addr      allmodes  */
 	{0x00007800, 0x00040000},
 	{0x00007800, 0x00040000},
 	{0x00007804, 0xdb005012},
 	{0x00007804, 0xdb005012},
 	{0x00007808, 0x04924914},
 	{0x00007808, 0x04924914},
@@ -835,71 +835,71 @@ static const u32 ar9300_2p0_baseband_core[][2] = {
 
 
 static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
 static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
+	{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
 	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
-	{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400},
-	{0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402},
-	{0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404},
-	{0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603},
-	{0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02},
-	{0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04},
-	{0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20},
-	{0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20},
-	{0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22},
-	{0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24},
-	{0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640},
-	{0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660},
-	{0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861},
-	{0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81},
-	{0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83},
-	{0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84},
-	{0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3},
-	{0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5},
-	{0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9},
-	{0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb},
-	{0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
+	{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+	{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+	{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+	{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+	{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+	{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+	{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+	{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+	{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+	{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20},
+	{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22},
+	{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24},
+	{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640},
+	{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660},
+	{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861},
+	{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81},
+	{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83},
+	{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84},
+	{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3},
+	{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9},
+	{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb},
+	{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec},
+	{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec},
+	{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
 	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
 	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
 	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
 	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
-	{0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400},
-	{0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402},
-	{0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603},
-	{0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02},
-	{0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04},
-	{0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20},
-	{0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20},
-	{0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22},
-	{0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24},
-	{0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640},
-	{0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660},
-	{0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861},
-	{0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81},
-	{0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83},
-	{0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84},
-	{0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3},
-	{0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5},
-	{0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9},
-	{0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb},
-	{0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
+	{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004},
+	{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200},
+	{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202},
+	{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400},
+	{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402},
+	{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404},
+	{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603},
+	{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02},
+	{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04},
+	{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20},
+	{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20},
+	{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22},
+	{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24},
+	{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640},
+	{0x0000a5c0, 0x4c8a3065, 0x44883e46, 0x44883e46, 0x38801660},
+	{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861},
+	{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81},
+	{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83},
+	{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84},
+	{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3},
+	{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5},
+	{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9},
+	{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb},
+	{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec},
+	{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec},
+	{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
 	{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
 	{0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6},
 	{0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61},
 	{0x00016048, 0xad241a61, 0xad241a61, 0xad241a61, 0xad241a61},
 	{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
 	{0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c},
@@ -913,71 +913,71 @@ static const u32 ar9300Modes_high_power_tx_gain_table_2p0[][5] = {
 
 
 static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
 static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p0[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050da, 0x000050da},
+	{0x0000a410, 0x000050db, 0x000050db, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00020220, 0x00020220, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
 	{0x0000a504, 0x06020223, 0x06020223, 0x04000002, 0x04000002},
-	{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
-	{0x0000a50c, 0x10022223, 0x10022223, 0x0b000200, 0x0b000200},
-	{0x0000a510, 0x17022620, 0x17022620, 0x0f000202, 0x0f000202},
-	{0x0000a514, 0x1b022622, 0x1b022622, 0x11000400, 0x11000400},
-	{0x0000a518, 0x1f022822, 0x1f022822, 0x15000402, 0x15000402},
-	{0x0000a51c, 0x24022842, 0x24022842, 0x19000404, 0x19000404},
-	{0x0000a520, 0x28042840, 0x28042840, 0x1b000603, 0x1b000603},
-	{0x0000a524, 0x2c042842, 0x2c042842, 0x1f000a02, 0x1f000a02},
-	{0x0000a528, 0x30042844, 0x30042844, 0x23000a04, 0x23000a04},
-	{0x0000a52c, 0x34042846, 0x34042846, 0x26000a20, 0x26000a20},
-	{0x0000a530, 0x39042869, 0x39042869, 0x2a000e20, 0x2a000e20},
-	{0x0000a534, 0x3d062869, 0x3d062869, 0x2e000e22, 0x2e000e22},
-	{0x0000a538, 0x44062c69, 0x44062c69, 0x31000e24, 0x31000e24},
-	{0x0000a53c, 0x48063069, 0x48063069, 0x34001640, 0x34001640},
-	{0x0000a540, 0x4c0a3065, 0x4c0a3065, 0x38001660, 0x38001660},
-	{0x0000a544, 0x500a3069, 0x500a3069, 0x3b001861, 0x3b001861},
-	{0x0000a548, 0x530a3469, 0x530a3469, 0x3e001a81, 0x3e001a81},
-	{0x0000a54c, 0x590a7464, 0x590a7464, 0x42001a83, 0x42001a83},
-	{0x0000a550, 0x5e0a7865, 0x5e0a7865, 0x44001c84, 0x44001c84},
-	{0x0000a554, 0x630a7e66, 0x630a7e66, 0x48001ce3, 0x48001ce3},
-	{0x0000a558, 0x680a7e89, 0x680a7e89, 0x4c001ce5, 0x4c001ce5},
-	{0x0000a55c, 0x6e0a7e8c, 0x6e0a7e8c, 0x50001ce9, 0x50001ce9},
-	{0x0000a560, 0x730e7e8c, 0x730e7e8c, 0x54001ceb, 0x54001ceb},
-	{0x0000a564, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a568, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a56c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a570, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a574, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a578, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
-	{0x0000a57c, 0x730e7e8c, 0x730e7e8c, 0x56001eec, 0x56001eec},
+	{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x0f022223, 0x0f022223, 0x0b000200, 0x0b000200},
+	{0x0000a510, 0x14022620, 0x14022620, 0x0f000202, 0x0f000202},
+	{0x0000a514, 0x18022622, 0x18022622, 0x11000400, 0x11000400},
+	{0x0000a518, 0x1b022822, 0x1b022822, 0x15000402, 0x15000402},
+	{0x0000a51c, 0x20022842, 0x20022842, 0x19000404, 0x19000404},
+	{0x0000a520, 0x22022c41, 0x22022c41, 0x1b000603, 0x1b000603},
+	{0x0000a524, 0x28023042, 0x28023042, 0x1f000a02, 0x1f000a02},
+	{0x0000a528, 0x2c023044, 0x2c023044, 0x23000a04, 0x23000a04},
+	{0x0000a52c, 0x2f023644, 0x2f023644, 0x26000a20, 0x26000a20},
+	{0x0000a530, 0x34043643, 0x34043643, 0x2a000e20, 0x2a000e20},
+	{0x0000a534, 0x38043a44, 0x38043a44, 0x2e000e22, 0x2e000e22},
+	{0x0000a538, 0x3b043e45, 0x3b043e45, 0x31000e24, 0x31000e24},
+	{0x0000a53c, 0x40063e46, 0x40063e46, 0x34001640, 0x34001640},
+	{0x0000a540, 0x44083e46, 0x44083e46, 0x38001660, 0x38001660},
+	{0x0000a544, 0x46083e66, 0x46083e66, 0x3b001861, 0x3b001861},
+	{0x0000a548, 0x4b0a3e69, 0x4b0a3e69, 0x3e001a81, 0x3e001a81},
+	{0x0000a54c, 0x4f0a5e66, 0x4f0a5e66, 0x42001a83, 0x42001a83},
+	{0x0000a550, 0x540a7e66, 0x540a7e66, 0x44001c84, 0x44001c84},
+	{0x0000a554, 0x570a7e89, 0x570a7e89, 0x48001ce3, 0x48001ce3},
+	{0x0000a558, 0x5c0e7e8a, 0x5c0e7e8a, 0x4c001ce5, 0x4c001ce5},
+	{0x0000a55c, 0x60127e8b, 0x60127e8b, 0x50001ce9, 0x50001ce9},
+	{0x0000a560, 0x65127ecc, 0x65127ecc, 0x54001ceb, 0x54001ceb},
+	{0x0000a564, 0x6b169ecd, 0x6b169ecd, 0x56001eec, 0x56001eec},
+	{0x0000a568, 0x70169f0e, 0x70169f0e, 0x56001eec, 0x56001eec},
+	{0x0000a56c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a570, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a574, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a578, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
+	{0x0000a57c, 0x75169f4f, 0x75169f4f, 0x56001eec, 0x56001eec},
 	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
 	{0x0000a580, 0x00820220, 0x00820220, 0x00800000, 0x00800000},
 	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
 	{0x0000a584, 0x06820223, 0x06820223, 0x04800002, 0x04800002},
-	{0x0000a588, 0x0b822220, 0x0b822220, 0x08800004, 0x08800004},
-	{0x0000a58c, 0x10822223, 0x10822223, 0x0b800200, 0x0b800200},
-	{0x0000a590, 0x17822620, 0x17822620, 0x0f800202, 0x0f800202},
-	{0x0000a594, 0x1b822622, 0x1b822622, 0x11800400, 0x11800400},
-	{0x0000a598, 0x1f822822, 0x1f822822, 0x15800402, 0x15800402},
-	{0x0000a59c, 0x24822842, 0x24822842, 0x19800404, 0x19800404},
-	{0x0000a5a0, 0x28842840, 0x28842840, 0x1b800603, 0x1b800603},
-	{0x0000a5a4, 0x2c842842, 0x2c842842, 0x1f800a02, 0x1f800a02},
-	{0x0000a5a8, 0x30842844, 0x30842844, 0x23800a04, 0x23800a04},
-	{0x0000a5ac, 0x34842846, 0x34842846, 0x26800a20, 0x26800a20},
-	{0x0000a5b0, 0x39842869, 0x39842869, 0x2a800e20, 0x2a800e20},
-	{0x0000a5b4, 0x3d862869, 0x3d862869, 0x2e800e22, 0x2e800e22},
-	{0x0000a5b8, 0x44862c69, 0x44862c69, 0x31800e24, 0x31800e24},
-	{0x0000a5bc, 0x48863069, 0x48863069, 0x34801640, 0x34801640},
-	{0x0000a5c0, 0x4c8a3065, 0x4c8a3065, 0x38801660, 0x38801660},
-	{0x0000a5c4, 0x508a3069, 0x508a3069, 0x3b801861, 0x3b801861},
-	{0x0000a5c8, 0x538a3469, 0x538a3469, 0x3e801a81, 0x3e801a81},
-	{0x0000a5cc, 0x598a7464, 0x598a7464, 0x42801a83, 0x42801a83},
-	{0x0000a5d0, 0x5e8a7865, 0x5e8a7865, 0x44801c84, 0x44801c84},
-	{0x0000a5d4, 0x638a7e66, 0x638a7e66, 0x48801ce3, 0x48801ce3},
-	{0x0000a5d8, 0x688a7e89, 0x688a7e89, 0x4c801ce5, 0x4c801ce5},
-	{0x0000a5dc, 0x6e8a7e8c, 0x6e8a7e8c, 0x50801ce9, 0x50801ce9},
-	{0x0000a5e0, 0x738e7e8c, 0x738e7e8c, 0x54801ceb, 0x54801ceb},
-	{0x0000a5e4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5e8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5ec, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f0, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f4, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5f8, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
-	{0x0000a5fc, 0x738e7e8c, 0x738e7e8c, 0x56801eec, 0x56801eec},
+	{0x0000a588, 0x0a822220, 0x0a822220, 0x08800004, 0x08800004},
+	{0x0000a58c, 0x0f822223, 0x0f822223, 0x0b800200, 0x0b800200},
+	{0x0000a590, 0x14822620, 0x14822620, 0x0f800202, 0x0f800202},
+	{0x0000a594, 0x18822622, 0x18822622, 0x11800400, 0x11800400},
+	{0x0000a598, 0x1b822822, 0x1b822822, 0x15800402, 0x15800402},
+	{0x0000a59c, 0x20822842, 0x20822842, 0x19800404, 0x19800404},
+	{0x0000a5a0, 0x22822c41, 0x22822c41, 0x1b800603, 0x1b800603},
+	{0x0000a5a4, 0x28823042, 0x28823042, 0x1f800a02, 0x1f800a02},
+	{0x0000a5a8, 0x2c823044, 0x2c823044, 0x23800a04, 0x23800a04},
+	{0x0000a5ac, 0x2f823644, 0x2f823644, 0x26800a20, 0x26800a20},
+	{0x0000a5b0, 0x34843643, 0x34843643, 0x2a800e20, 0x2a800e20},
+	{0x0000a5b4, 0x38843a44, 0x38843a44, 0x2e800e22, 0x2e800e22},
+	{0x0000a5b8, 0x3b843e45, 0x3b843e45, 0x31800e24, 0x31800e24},
+	{0x0000a5bc, 0x40863e46, 0x40863e46, 0x34801640, 0x34801640},
+	{0x0000a5c0, 0x44883e46, 0x44883e46, 0x38801660, 0x38801660},
+	{0x0000a5c4, 0x46883e66, 0x46883e66, 0x3b801861, 0x3b801861},
+	{0x0000a5c8, 0x4b8a3e69, 0x4b8a3e69, 0x3e801a81, 0x3e801a81},
+	{0x0000a5cc, 0x4f8a5e66, 0x4f8a5e66, 0x42801a83, 0x42801a83},
+	{0x0000a5d0, 0x548a7e66, 0x548a7e66, 0x44801c84, 0x44801c84},
+	{0x0000a5d4, 0x578a7e89, 0x578a7e89, 0x48801ce3, 0x48801ce3},
+	{0x0000a5d8, 0x5c8e7e8a, 0x5c8e7e8a, 0x4c801ce5, 0x4c801ce5},
+	{0x0000a5dc, 0x60927e8b, 0x60927e8b, 0x50801ce9, 0x50801ce9},
+	{0x0000a5e0, 0x65927ecc, 0x65927ecc, 0x54801ceb, 0x54801ceb},
+	{0x0000a5e4, 0x6b969ecd, 0x6b969ecd, 0x56801eec, 0x56801eec},
+	{0x0000a5e8, 0x70969f0e, 0x70969f0e, 0x56801eec, 0x56801eec},
+	{0x0000a5ec, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f0, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f4, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5f8, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
+	{0x0000a5fc, 0x75969f4f, 0x75969f4f, 0x56801eec, 0x56801eec},
 	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
 	{0x00016044, 0x056db2e4, 0x056db2e4, 0x056db2e4, 0x056db2e4},
 	{0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61},
 	{0x00016048, 0x8c001a61, 0x8c001a61, 0x8c001a61, 0x8c001a61},
 	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
 	{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
@@ -1251,7 +1251,7 @@ static const u32 ar9300Common_rx_gain_table_2p0[][2] = {
 
 
 static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
 static const u32 ar9300Modes_low_ob_db_tx_gain_table_2p0[][5] = {
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
 	/* Addr      5G_HT20     5G_HT40     2G_HT40     2G_HT20   */
-	{0x0000a410, 0x000050da, 0x000050da, 0x000050da, 0x000050da},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
 	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
 	{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
 	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
 	{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
@@ -1760,31 +1760,22 @@ static const u32 ar9300_2p0_soc_preamble[][2] = {
 	{0x00007038, 0x000004c2},
 	{0x00007038, 0x000004c2},
 };
 };
 
 
-/*
- * PCIE-PHY programming array, to be used prior to entering
- * full sleep (holding RTC in reset, PLL is ON in L1 mode)
- */
 static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = {
 static const u32 ar9300PciePhy_pll_on_clkreq_disable_L1_2p0[][2] = {
+	/* Addr      allmodes  */
 	{0x00004040, 0x08212e5e},
 	{0x00004040, 0x08212e5e},
 	{0x00004040, 0x0008003b},
 	{0x00004040, 0x0008003b},
 	{0x00004044, 0x00000000},
 	{0x00004044, 0x00000000},
 };
 };
 
 
-/*
- * PCIE-PHY programming array, to be used when not in
- * full sleep (holding RTC in reset)
- */
 static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = {
 static const u32 ar9300PciePhy_clkreq_enable_L1_2p0[][2] = {
+	/* Addr      allmodes  */
 	{0x00004040, 0x08253e5e},
 	{0x00004040, 0x08253e5e},
 	{0x00004040, 0x0008003b},
 	{0x00004040, 0x0008003b},
 	{0x00004044, 0x00000000},
 	{0x00004044, 0x00000000},
 };
 };
 
 
-/*
- * PCIE-PHY programming array, to be used prior to entering
- * full sleep (holding RTC in reset)
- */
 static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
 static const u32 ar9300PciePhy_clkreq_disable_L1_2p0[][2] = {
+	/* Addr      allmodes  */
 	{0x00004040, 0x08213e5e},
 	{0x00004040, 0x08213e5e},
 	{0x00004040, 0x0008003b},
 	{0x00004040, 0x0008003b},
 	{0x00004044, 0x00000000},
 	{0x00004044, 0x00000000},

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

@@ -311,6 +311,9 @@ static void ar9003_hw_set11n_txdesc(struct ath_hw *ah, void *ds,
 {
 {
 	struct ar9003_txc *ads = (struct ar9003_txc *) ds;
 	struct ar9003_txc *ads = (struct ar9003_txc *) ds;
 
 
+	if (txpower > ah->txpower_limit)
+		txpower = ah->txpower_limit;
+
 	txpower += ah->txpower_indexoffset;
 	txpower += ah->txpower_indexoffset;
 	if (txpower > 63)
 	if (txpower > 63)
 		txpower = 63;
 		txpower = 63;

+ 4 - 12
drivers/net/wireless/ath/ath9k/ar9003_phy.c

@@ -375,16 +375,7 @@ static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
 	else if (chan && IS_CHAN_QUARTER_RATE(chan))
 	else if (chan && IS_CHAN_QUARTER_RATE(chan))
 		pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
 		pll |= SM(0x2, AR_RTC_9300_PLL_CLKSEL);
 
 
-	if (chan && IS_CHAN_5GHZ(chan)) {
-		pll |= SM(0x28, AR_RTC_9300_PLL_DIV);
-
-		/*
-		 * When doing fast clock, set PLL to 0x142c
-		 */
-		if (IS_CHAN_A_5MHZ_SPACED(chan))
-			pll = 0x142c;
-	} else
-		pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
+	pll |= SM(0x2c, AR_RTC_9300_PLL_DIV);
 
 
 	return pll;
 	return pll;
 }
 }
@@ -592,7 +583,7 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
 	 * For 5GHz channels requiring Fast Clock, apply
 	 * For 5GHz channels requiring Fast Clock, apply
 	 * different modal values.
 	 * different modal values.
 	 */
 	 */
-	if (IS_CHAN_A_5MHZ_SPACED(chan))
+	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
 		REG_WRITE_ARRAY(&ah->iniModesAdditional,
 		REG_WRITE_ARRAY(&ah->iniModesAdditional,
 				modesIndex, regWrites);
 				modesIndex, regWrites);
 
 
@@ -622,7 +613,7 @@ static void ar9003_hw_set_rfmode(struct ath_hw *ah,
 	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
 	rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
 		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
 		? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
 
 
-	if (IS_CHAN_A_5MHZ_SPACED(chan))
+	if (IS_CHAN_A_FAST_CLOCK(ah, chan))
 		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
 		rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
 
 
 	REG_WRITE(ah, AR_PHY_MODE, rfMode);
 	REG_WRITE(ah, AR_PHY_MODE, rfMode);
@@ -1102,6 +1093,7 @@ static void ar9003_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
 		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
 		ath_print(common, ATH_DBG_ANY, "Timeout while waiting for nf "
 			  "to load: AR_PHY_AGC_CONTROL=0x%x\n",
 			  "to load: AR_PHY_AGC_CONTROL=0x%x\n",
 			  REG_READ(ah, AR_PHY_AGC_CONTROL));
 			  REG_READ(ah, AR_PHY_AGC_CONTROL));
+		return;
 	}
 	}
 
 
 	/*
 	/*

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

@@ -212,7 +212,6 @@ int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
 	rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
 	rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
 	rx_status->band = hw->conf.channel->band;
 	rx_status->band = hw->conf.channel->band;
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->freq = hw->conf.channel->center_freq;
-	rx_status->noise = common->ani.noise_floor;
 	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
 	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
 	rx_status->antenna = rx_stats->rs_antenna;
 	rx_status->antenna = rx_stats->rs_antenna;
 	rx_status->flag |= RX_FLAG_TSFT;
 	rx_status->flag |= RX_FLAG_TSFT;

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

@@ -300,7 +300,8 @@ struct base_eep_header {
 	u32 binBuildNumber;
 	u32 binBuildNumber;
 	u8 deviceType;
 	u8 deviceType;
 	u8 pwdclkind;
 	u8 pwdclkind;
-	u8 futureBase_1[2];
+	u8 fastClk5g;
+	u8 divChain;
 	u8 rxGainType;
 	u8 rxGainType;
 	u8 dacHiPwrMode_5G;
 	u8 dacHiPwrMode_5G;
 	u8 openLoopPwrCntl;
 	u8 openLoopPwrCntl;

+ 2 - 0
drivers/net/wireless/ath/ath9k/eeprom_def.c

@@ -274,6 +274,8 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
 		return pBase->txMask;
 		return pBase->txMask;
 	case EEP_RX_MASK:
 	case EEP_RX_MASK:
 		return pBase->rxMask;
 		return pBase->rxMask;
+	case EEP_FSTCLK_5G:
+		return pBase->fastClk5g;
 	case EEP_RXGAIN_TYPE:
 	case EEP_RXGAIN_TYPE:
 		return pBase->rxGainType;
 		return pBase->rxGainType;
 	case EEP_TXGAIN_TYPE:
 	case EEP_TXGAIN_TYPE:

+ 84 - 65
drivers/net/wireless/ath/ath9k/hif_usb.c

@@ -93,14 +93,24 @@ static int hif_usb_send_regout(struct hif_device_usb *hif_dev,
 	return ret;
 	return ret;
 }
 }
 
 
+static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
+					 struct sk_buff_head *list)
+{
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(list)) != NULL) {
+		dev_kfree_skb_any(skb);
+		TX_STAT_INC(skb_dropped);
+	}
+}
+
 static void hif_usb_tx_cb(struct urb *urb)
 static void hif_usb_tx_cb(struct urb *urb)
 {
 {
 	struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
 	struct tx_buf *tx_buf = (struct tx_buf *) urb->context;
 	struct hif_device_usb *hif_dev = tx_buf->hif_dev;
 	struct hif_device_usb *hif_dev = tx_buf->hif_dev;
 	struct sk_buff *skb;
 	struct sk_buff *skb;
-	bool drop, flush;
 
 
-	if (!hif_dev)
+	if (!hif_dev || !tx_buf)
 		return;
 		return;
 
 
 	switch (urb->status) {
 	switch (urb->status) {
@@ -108,57 +118,47 @@ static void hif_usb_tx_cb(struct urb *urb)
 		break;
 		break;
 	case -ENOENT:
 	case -ENOENT:
 	case -ECONNRESET:
 	case -ECONNRESET:
-		break;
 	case -ENODEV:
 	case -ENODEV:
 	case -ESHUTDOWN:
 	case -ESHUTDOWN:
+		/*
+		 * The URB has been killed, free the SKBs
+		 * and return.
+		 */
+		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
 		return;
 		return;
 	default:
 	default:
 		break;
 		break;
 	}
 	}
 
 
-	if (tx_buf) {
-		spin_lock(&hif_dev->tx.tx_lock);
-		drop = !!(hif_dev->tx.flags & HIF_USB_TX_STOP);
-		flush = !!(hif_dev->tx.flags & HIF_USB_TX_FLUSH);
-		spin_unlock(&hif_dev->tx.tx_lock);
-
-		while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
-			if (!drop && !flush) {
-				ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
-							  skb, 1);
-				TX_STAT_INC(skb_completed);
-			} else {
-				dev_kfree_skb_any(skb);
-				TX_STAT_INC(skb_dropped);
-			}
-		}
-
-		if (flush)
-			return;
-
-		tx_buf->len = tx_buf->offset = 0;
-		__skb_queue_head_init(&tx_buf->skb_queue);
-
-		spin_lock(&hif_dev->tx.tx_lock);
-		list_del(&tx_buf->list);
-		list_add_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
-		hif_dev->tx.tx_buf_cnt++;
-		if (!drop)
-			__hif_usb_tx(hif_dev); /* Check for pending SKBs */
-		TX_STAT_INC(buf_completed);
+	/* Check if TX has been stopped */
+	spin_lock(&hif_dev->tx.tx_lock);
+	if (hif_dev->tx.flags & HIF_USB_TX_STOP) {
 		spin_unlock(&hif_dev->tx.tx_lock);
 		spin_unlock(&hif_dev->tx.tx_lock);
-	}
-}
-
-static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev,
-					 struct sk_buff_head *list)
-{
-	struct sk_buff *skb;
-
-	while ((skb = __skb_dequeue(list)) != NULL) {
-		dev_kfree_skb_any(skb);
-		TX_STAT_INC(skb_dropped);
-	}
+		ath9k_skb_queue_purge(hif_dev, &tx_buf->skb_queue);
+		goto add_free;
+	}
+	spin_unlock(&hif_dev->tx.tx_lock);
+
+	/* Complete the queued SKBs. */
+	while ((skb = __skb_dequeue(&tx_buf->skb_queue)) != NULL) {
+		ath9k_htc_txcompletion_cb(hif_dev->htc_handle,
+					  skb, 1);
+		TX_STAT_INC(skb_completed);
+	}
+
+add_free:
+	/* Re-initialize the SKB queue */
+	tx_buf->len = tx_buf->offset = 0;
+	__skb_queue_head_init(&tx_buf->skb_queue);
+
+	/* Add this TX buffer to the free list */
+	spin_lock(&hif_dev->tx.tx_lock);
+	list_move_tail(&tx_buf->list, &hif_dev->tx.tx_buf);
+	hif_dev->tx.tx_buf_cnt++;
+	if (!(hif_dev->tx.flags & HIF_USB_TX_STOP))
+		__hif_usb_tx(hif_dev); /* Check for pending SKBs */
+	TX_STAT_INC(buf_completed);
+	spin_unlock(&hif_dev->tx.tx_lock);
 }
 }
 
 
 /* TX lock has to be taken */
 /* TX lock has to be taken */
@@ -178,8 +178,7 @@ static int __hif_usb_tx(struct hif_device_usb *hif_dev)
 		return 0;
 		return 0;
 
 
 	tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
 	tx_buf = list_first_entry(&hif_dev->tx.tx_buf, struct tx_buf, list);
-	list_del(&tx_buf->list);
-	list_add_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
+	list_move_tail(&tx_buf->list, &hif_dev->tx.tx_pending);
 	hif_dev->tx.tx_buf_cnt--;
 	hif_dev->tx.tx_buf_cnt--;
 
 
 	tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
 	tx_skb_cnt = min_t(u16, hif_dev->tx.tx_skb_cnt, MAX_TX_AGGR_NUM);
@@ -511,9 +510,18 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
 	if (likely(urb->actual_length != 0)) {
 	if (likely(urb->actual_length != 0)) {
 		skb_put(skb, urb->actual_length);
 		skb_put(skb, urb->actual_length);
 
 
+		/* Process the command first */
+		ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
+				 skb->len, USB_REG_IN_PIPE);
+
+
 		nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
 		nskb = alloc_skb(MAX_REG_IN_BUF_SIZE, GFP_ATOMIC);
-		if (!nskb)
-			goto resubmit;
+		if (!nskb) {
+			dev_err(&hif_dev->udev->dev,
+				"ath9k_htc: REG_IN memory allocation failure\n");
+			urb->context = NULL;
+			return;
+		}
 
 
 		usb_fill_int_urb(urb, hif_dev->udev,
 		usb_fill_int_urb(urb, hif_dev->udev,
 				 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
 				 usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE),
@@ -523,12 +531,9 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		ret = usb_submit_urb(urb, GFP_ATOMIC);
 		if (ret) {
 		if (ret) {
 			kfree_skb(nskb);
 			kfree_skb(nskb);
-			goto free;
+			urb->context = NULL;
 		}
 		}
 
 
-		ath9k_htc_rx_msg(hif_dev->htc_handle, skb,
-				 skb->len, USB_REG_IN_PIPE);
-
 		return;
 		return;
 	}
 	}
 
 
@@ -548,20 +553,17 @@ free:
 
 
 static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
 static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
 {
 {
-	unsigned long flags;
 	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
 	struct tx_buf *tx_buf = NULL, *tx_buf_tmp = NULL;
 
 
-	list_for_each_entry_safe(tx_buf, tx_buf_tmp, &hif_dev->tx.tx_buf, list) {
+	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
+				 &hif_dev->tx.tx_buf, list) {
+		usb_kill_urb(tx_buf->urb);
 		list_del(&tx_buf->list);
 		list_del(&tx_buf->list);
 		usb_free_urb(tx_buf->urb);
 		usb_free_urb(tx_buf->urb);
 		kfree(tx_buf->buf);
 		kfree(tx_buf->buf);
 		kfree(tx_buf);
 		kfree(tx_buf);
 	}
 	}
 
 
-	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
-	hif_dev->tx.flags |= HIF_USB_TX_FLUSH;
-	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
-
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 	list_for_each_entry_safe(tx_buf, tx_buf_tmp,
 				 &hif_dev->tx.tx_pending, list) {
 				 &hif_dev->tx.tx_pending, list) {
 		usb_kill_urb(tx_buf->urb);
 		usb_kill_urb(tx_buf->urb);
@@ -570,10 +572,6 @@ static void ath9k_hif_usb_dealloc_tx_urbs(struct hif_device_usb *hif_dev)
 		kfree(tx_buf->buf);
 		kfree(tx_buf->buf);
 		kfree(tx_buf);
 		kfree(tx_buf);
 	}
 	}
-
-	spin_lock_irqsave(&hif_dev->tx.tx_lock, flags);
-	hif_dev->tx.flags &= ~HIF_USB_TX_FLUSH;
-	spin_unlock_irqrestore(&hif_dev->tx.tx_lock, flags);
 }
 }
 
 
 static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
 static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev)
@@ -897,6 +895,26 @@ err_alloc:
 	return ret;
 	return ret;
 }
 }
 
 
+static void ath9k_hif_usb_reboot(struct usb_device *udev)
+{
+	u32 reboot_cmd = 0xffffffff;
+	void *buf;
+	int ret;
+
+	buf = kmalloc(4, GFP_KERNEL);
+	if (!buf)
+		return;
+
+	memcpy(buf, &reboot_cmd, 4);
+
+	ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, USB_REG_OUT_PIPE),
+			   buf, 4, NULL, HZ);
+	if (ret)
+		dev_err(&udev->dev, "ath9k_htc: USB reboot failed\n");
+
+	kfree(buf);
+}
+
 static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 {
 {
 	struct usb_device *udev = interface_to_usbdev(interface);
 	struct usb_device *udev = interface_to_usbdev(interface);
@@ -904,14 +922,15 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
 		(struct hif_device_usb *) usb_get_intfdata(interface);
 		(struct hif_device_usb *) usb_get_intfdata(interface);
 
 
 	if (hif_dev) {
 	if (hif_dev) {
-		ath9k_htc_hw_deinit(hif_dev->htc_handle, true);
+		ath9k_htc_hw_deinit(hif_dev->htc_handle,
+		    (udev->state == USB_STATE_NOTATTACHED) ? true : false);
 		ath9k_htc_hw_free(hif_dev->htc_handle);
 		ath9k_htc_hw_free(hif_dev->htc_handle);
 		ath9k_hif_usb_dev_deinit(hif_dev);
 		ath9k_hif_usb_dev_deinit(hif_dev);
 		usb_set_intfdata(interface, NULL);
 		usb_set_intfdata(interface, NULL);
 	}
 	}
 
 
 	if (hif_dev->flags & HIF_USB_START)
 	if (hif_dev->flags & HIF_USB_START)
-		usb_reset_device(udev);
+		ath9k_hif_usb_reboot(udev);
 
 
 	kfree(hif_dev);
 	kfree(hif_dev);
 	dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");
 	dev_info(&udev->dev, "ath9k_htc: USB layer deinitialized\n");

+ 0 - 1
drivers/net/wireless/ath/ath9k/hif_usb.h

@@ -61,7 +61,6 @@ struct tx_buf {
 };
 };
 
 
 #define HIF_USB_TX_STOP  BIT(0)
 #define HIF_USB_TX_STOP  BIT(0)
-#define HIF_USB_TX_FLUSH BIT(1)
 
 
 struct hif_usb_tx {
 struct hif_usb_tx {
 	u8 flags;
 	u8 flags;

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

@@ -329,6 +329,7 @@ struct htc_beacon_config {
 #define OP_ASSOCIATED     BIT(8)
 #define OP_ASSOCIATED     BIT(8)
 #define OP_ENABLE_BEACON  BIT(9)
 #define OP_ENABLE_BEACON  BIT(9)
 #define OP_LED_DEINIT     BIT(10)
 #define OP_LED_DEINIT     BIT(10)
+#define OP_UNPLUGGED      BIT(11)
 
 
 struct ath9k_htc_priv {
 struct ath9k_htc_priv {
 	struct device *dev;
 	struct device *dev;
@@ -378,6 +379,7 @@ struct ath9k_htc_priv {
 	struct mutex htc_pm_lock;
 	struct mutex htc_pm_lock;
 	unsigned long ps_usecount;
 	unsigned long ps_usecount;
 	bool ps_enabled;
 	bool ps_enabled;
+	bool ps_idle;
 
 
 	struct ath_led radio_led;
 	struct ath_led radio_led;
 	struct ath_led assoc_led;
 	struct ath_led assoc_led;

+ 8 - 0
drivers/net/wireless/ath/ath9k/htc_drv_init.c

@@ -744,6 +744,9 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev,
 	if (ret)
 	if (ret)
 		goto err_init;
 		goto err_init;
 
 
+	/* The device may have been unplugged earlier. */
+	priv->op_flags &= ~OP_UNPLUGGED;
+
 	ret = ath9k_init_device(priv, devid);
 	ret = ath9k_init_device(priv, devid);
 	if (ret)
 	if (ret)
 		goto err_init;
 		goto err_init;
@@ -760,6 +763,11 @@ err_free:
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug)
 {
 {
 	if (htc_handle->drv_priv) {
 	if (htc_handle->drv_priv) {
+
+		/* Check if the device has been yanked out. */
+		if (hotunplug)
+			htc_handle->drv_priv->op_flags |= OP_UNPLUGGED;
+
 		ath9k_deinit_device(htc_handle->drv_priv);
 		ath9k_deinit_device(htc_handle->drv_priv);
 		ath9k_deinit_wmi(htc_handle->drv_priv);
 		ath9k_deinit_wmi(htc_handle->drv_priv);
 		ieee80211_free_hw(htc_handle->drv_priv->hw);
 		ieee80211_free_hw(htc_handle->drv_priv->hw);

+ 59 - 25
drivers/net/wireless/ath/ath9k/htc_drv_main.c

@@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
 	if (--priv->ps_usecount != 0)
 	if (--priv->ps_usecount != 0)
 		goto unlock;
 		goto unlock;
 
 
-	if (priv->ps_enabled)
+	if (priv->ps_idle)
+		ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
+	else if (priv->ps_enabled)
 		ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
 		ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
+
 unlock:
 unlock:
 	mutex_unlock(&priv->htc_pm_lock);
 	mutex_unlock(&priv->htc_pm_lock);
 }
 }
@@ -153,7 +156,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
 		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", channel->center_freq, ret);
 			  "reset status %d\n", channel->center_freq, ret);
-		ath9k_htc_ps_restore(priv);
 		goto err;
 		goto err;
 	}
 	}
 
 
@@ -1097,7 +1099,7 @@ fail_tx:
 	return 0;
 	return 0;
 }
 }
 
 
-static int ath9k_htc_start(struct ieee80211_hw *hw)
+static int ath9k_htc_radio_enable(struct ieee80211_hw *hw)
 {
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
 	struct ath_hw *ah = priv->ah;
@@ -1113,8 +1115,6 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 		  "Starting driver with initial channel: %d MHz\n",
 		  "Starting driver with initial channel: %d MHz\n",
 		  curchan->center_freq);
 		  curchan->center_freq);
 
 
-	mutex_lock(&priv->mutex);
-
 	/* setup initial channel */
 	/* setup initial channel */
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
 
@@ -1127,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 		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", ret, curchan->center_freq);
 			  "(freq %u MHz)\n", ret, curchan->center_freq);
-		goto mutex_unlock;
+		return ret;
 	}
 	}
 
 
 	ath_update_txpow(priv);
 	ath_update_txpow(priv);
@@ -1135,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 	mode = ath9k_htc_get_curmode(priv, init_channel);
 	mode = ath9k_htc_get_curmode(priv, init_channel);
 	htc_mode = cpu_to_be16(mode);
 	htc_mode = cpu_to_be16(mode);
 	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
 	WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
-	if (ret)
-		goto mutex_unlock;
-
 	WMI_CMD(WMI_ATH_INIT_CMDID);
 	WMI_CMD(WMI_ATH_INIT_CMDID);
-	if (ret)
-		goto mutex_unlock;
-
 	WMI_CMD(WMI_START_RECV_CMDID);
 	WMI_CMD(WMI_START_RECV_CMDID);
-	if (ret)
-		goto mutex_unlock;
 
 
 	ath9k_host_rx_init(priv);
 	ath9k_host_rx_init(priv);
 
 
@@ -1157,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
 
 
 	ieee80211_wake_queues(hw);
 	ieee80211_wake_queues(hw);
 
 
-mutex_unlock:
+	return ret;
+}
+
+static int ath9k_htc_start(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+	int ret = 0;
+
+	mutex_lock(&priv->mutex);
+	ret = ath9k_htc_radio_enable(hw);
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
+
 	return ret;
 	return ret;
 }
 }
 
 
-static void ath9k_htc_stop(struct ieee80211_hw *hw)
+static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
 {
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
 	struct ath_hw *ah = priv->ah;
@@ -1170,14 +1172,18 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	int ret = 0;
 	int ret = 0;
 	u8 cmd_rsp;
 	u8 cmd_rsp;
 
 
-	mutex_lock(&priv->mutex);
-
 	if (priv->op_flags & OP_INVALID) {
 	if (priv->op_flags & OP_INVALID) {
 		ath_print(common, ATH_DBG_ANY, "Device not present\n");
 		ath_print(common, ATH_DBG_ANY, "Device not present\n");
-		mutex_unlock(&priv->mutex);
 		return;
 		return;
 	}
 	}
 
 
+	/* Cancel all the running timers/work .. */
+	cancel_work_sync(&priv->ps_work);
+	cancel_delayed_work_sync(&priv->ath9k_ani_work);
+	cancel_delayed_work_sync(&priv->ath9k_aggr_work);
+	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_led_stop_brightness(priv);
+
 	ath9k_htc_ps_wakeup(priv);
 	ath9k_htc_ps_wakeup(priv);
 	htc_stop(priv->htc);
 	htc_stop(priv->htc);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
@@ -1189,11 +1195,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	ath9k_htc_ps_restore(priv);
 	ath9k_htc_ps_restore(priv);
 	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
 	ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
 
 
-	cancel_work_sync(&priv->ps_work);
-	cancel_delayed_work_sync(&priv->ath9k_ani_work);
-	cancel_delayed_work_sync(&priv->ath9k_aggr_work);
-	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
-	ath9k_led_stop_brightness(priv);
 	skb_queue_purge(&priv->tx_queue);
 	skb_queue_purge(&priv->tx_queue);
 
 
 	/* Remove monitor interface here */
 	/* Remove monitor interface here */
@@ -1207,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
 	}
 	}
 
 
 	priv->op_flags |= OP_INVALID;
 	priv->op_flags |= OP_INVALID;
-	mutex_unlock(&priv->mutex);
 
 
 	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
 	ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
 }
 }
 
 
+static void ath9k_htc_stop(struct ieee80211_hw *hw)
+{
+	struct ath9k_htc_priv *priv = hw->priv;
+
+	mutex_lock(&priv->mutex);
+	ath9k_htc_radio_disable(hw);
+	mutex_unlock(&priv->mutex);
+}
+
+
 static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 				   struct ieee80211_vif *vif)
 {
 {
@@ -1325,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 
 
 	mutex_lock(&priv->mutex);
 	mutex_lock(&priv->mutex);
 
 
+	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+		bool enable_radio = false;
+		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+
+		if (!idle && priv->ps_idle)
+			enable_radio = true;
+
+		priv->ps_idle = idle;
+
+		if (enable_radio) {
+			ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
+			ath9k_htc_radio_enable(hw);
+			ath_print(common, ATH_DBG_CONFIG,
+				  "not-idle: enabling radio\n");
+		}
+	}
+
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
 		struct ieee80211_channel *curchan = hw->conf.channel;
 		struct ieee80211_channel *curchan = hw->conf.channel;
 		int pos = curchan->hw_value;
 		int pos = curchan->hw_value;
@@ -1368,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
 		}
 		}
 	}
 	}
 
 
+	if (priv->ps_idle) {
+		ath_print(common, ATH_DBG_CONFIG,
+			  "idle: disabling radio\n");
+		ath9k_htc_radio_disable(hw);
+	}
+
+
 	mutex_unlock(&priv->mutex);
 	mutex_unlock(&priv->mutex);
 
 
 	return 0;
 	return 0;

+ 34 - 25
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c

@@ -244,16 +244,25 @@ void ath9k_htc_txep(void *drv_priv, struct sk_buff *skb,
 		    enum htc_endpoint_id ep_id, bool txok)
 		    enum htc_endpoint_id ep_id, bool txok)
 {
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) drv_priv;
+	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct ieee80211_tx_info *tx_info;
 	struct ieee80211_tx_info *tx_info;
 
 
 	if (!skb)
 	if (!skb)
 		return;
 		return;
 
 
-	if (ep_id == priv->mgmt_ep)
+	if (ep_id == priv->mgmt_ep) {
 		skb_pull(skb, sizeof(struct tx_mgmt_hdr));
 		skb_pull(skb, sizeof(struct tx_mgmt_hdr));
-	else
-		/* TODO: Check for cab/uapsd/data */
+	} else if ((ep_id == priv->data_bk_ep) ||
+		   (ep_id == priv->data_be_ep) ||
+		   (ep_id == priv->data_vi_ep) ||
+		   (ep_id == priv->data_vo_ep)) {
 		skb_pull(skb, sizeof(struct tx_frame_hdr));
 		skb_pull(skb, sizeof(struct tx_frame_hdr));
+	} else {
+		ath_print(common, ATH_DBG_FATAL,
+			  "Unsupported TX EPID: %d\n", ep_id);
+		dev_kfree_skb_any(skb);
+		return;
+	}
 
 
 	tx_info = IEEE80211_SKB_CB(skb);
 	tx_info = IEEE80211_SKB_CB(skb);
 
 
@@ -439,10 +448,32 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
 	struct ieee80211_hw *hw = priv->hw;
 	struct ieee80211_hw *hw = priv->hw;
 	struct sk_buff *skb = rxbuf->skb;
 	struct sk_buff *skb = rxbuf->skb;
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath_htc_rx_status *rxstatus;
 	int hdrlen, padpos, padsize;
 	int hdrlen, padpos, padsize;
 	int last_rssi = ATH_RSSI_DUMMY_MARKER;
 	int last_rssi = ATH_RSSI_DUMMY_MARKER;
 	__le16 fc;
 	__le16 fc;
 
 
+	if (skb->len <= HTC_RX_FRAME_HEADER_SIZE) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "Corrupted RX frame, dropping\n");
+		goto rx_next;
+	}
+
+	rxstatus = (struct ath_htc_rx_status *)skb->data;
+
+	if (be16_to_cpu(rxstatus->rs_datalen) -
+	    (skb->len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
+		ath_print(common, ATH_DBG_FATAL,
+			  "Corrupted RX data len, dropping "
+			  "(dlen: %d, skblen: %d)\n",
+			  rxstatus->rs_datalen, skb->len);
+		goto rx_next;
+	}
+
+	/* Get the RX status information */
+	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
+	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
+
 	hdr = (struct ieee80211_hdr *)skb->data;
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
 	fc = hdr->frame_control;
 	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
 	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
@@ -607,8 +638,6 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 	struct ath_hw *ah = priv->ah;
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
 	struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
-	struct ath_htc_rx_status *rxstatus;
-	u32 len = 0;
 
 
 	spin_lock(&priv->rx.rxbuflock);
 	spin_lock(&priv->rx.rxbuflock);
 	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
 	list_for_each_entry(tmp_buf, &priv->rx.rxbuf, list) {
@@ -625,27 +654,7 @@ void ath9k_htc_rxep(void *drv_priv, struct sk_buff *skb,
 		goto err;
 		goto err;
 	}
 	}
 
 
-	len = skb->len;
-	if (len <= HTC_RX_FRAME_HEADER_SIZE) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Corrupted RX frame, dropping\n");
-		goto err;
-	}
-
-	rxstatus = (struct ath_htc_rx_status *)skb->data;
-
-	if (be16_to_cpu(rxstatus->rs_datalen) -
-	    (len - HTC_RX_FRAME_HEADER_SIZE) != 0) {
-		ath_print(common, ATH_DBG_FATAL,
-			  "Corrupted RX data len, dropping "
-			  "(epid: %d, dlen: %d, skblen: %d)\n",
-			  ep_id, rxstatus->rs_datalen, len);
-		goto err;
-	}
-
 	spin_lock(&priv->rx.rxbuflock);
 	spin_lock(&priv->rx.rxbuflock);
-	memcpy(&rxbuf->rxstatus, rxstatus, HTC_RX_FRAME_HEADER_SIZE);
-	skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
 	rxbuf->skb = skb;
 	rxbuf->skb = skb;
 	rxbuf->in_process = true;
 	rxbuf->in_process = true;
 	spin_unlock(&priv->rx.rxbuflock);
 	spin_unlock(&priv->rx.rxbuflock);

+ 3 - 2
drivers/net/wireless/ath/ath9k/htc_hst.c

@@ -341,8 +341,9 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
 		skb_pull(skb, sizeof(struct htc_frame_hdr));
 		skb_pull(skb, sizeof(struct htc_frame_hdr));
 
 
 		if (endpoint->ep_callbacks.tx) {
 		if (endpoint->ep_callbacks.tx) {
-			endpoint->ep_callbacks.tx(htc_handle->drv_priv, skb,
-						  htc_hdr->endpoint_id, txok);
+			endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
+						  skb, htc_hdr->endpoint_id,
+						  txok);
 		}
 		}
 	}
 	}
 
 

+ 20 - 7
drivers/net/wireless/ath/ath9k/hw.c

@@ -26,6 +26,7 @@
 #define ATH9K_CLOCK_RATE_CCK		22
 #define ATH9K_CLOCK_RATE_CCK		22
 #define ATH9K_CLOCK_RATE_5GHZ_OFDM	40
 #define ATH9K_CLOCK_RATE_5GHZ_OFDM	40
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM	44
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM	44
+#define ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM 44
 
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
 
 
@@ -91,7 +92,11 @@ static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs)
 		return usecs *ATH9K_CLOCK_RATE_CCK;
 		return usecs *ATH9K_CLOCK_RATE_CCK;
 	if (conf->channel->band == IEEE80211_BAND_2GHZ)
 	if (conf->channel->band == IEEE80211_BAND_2GHZ)
 		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
 		return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM;
-	return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM;
+
+	if (ah->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK)
+		return usecs * ATH9K_CLOCK_FAST_RATE_5GHZ_OFDM;
+	else
+		return usecs * ATH9K_CLOCK_RATE_5GHZ_OFDM;
 }
 }
 
 
 static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
 static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs)
@@ -386,6 +391,12 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
 
 
 	ah->config.rx_intr_mitigation = true;
 	ah->config.rx_intr_mitigation = true;
 
 
+	/*
+	 * Tx IQ Calibration (ah->config.tx_iq_calibration) is only
+	 * used by AR9003, but it is showing reliability issues.
+	 * It will take a while to fix so this is currently disabled.
+	 */
+
 	/*
 	/*
 	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
 	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
 	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
 	 * _and_ if on non-uniprocessor systems (Multiprocessor/HT).
@@ -819,9 +830,6 @@ void ath9k_hw_deinit(struct ath_hw *ah)
 	if (common->state < ATH_HW_INITIALIZED)
 	if (common->state < ATH_HW_INITIALIZED)
 		goto free_hw;
 		goto free_hw;
 
 
-	if (!AR_SREV_9100(ah))
-		ath9k_hw_ani_disable(ah);
-
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 	ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
 
 
 free_hw:
 free_hw:
@@ -1221,8 +1229,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	    (chan->channel != ah->curchan->channel) &&
 	    (chan->channel != ah->curchan->channel) &&
 	    ((chan->channelFlags & CHANNEL_ALL) ==
 	    ((chan->channelFlags & CHANNEL_ALL) ==
 	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
 	     (ah->curchan->channelFlags & CHANNEL_ALL)) &&
-	     !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) ||
-	     IS_CHAN_A_5MHZ_SPACED(ah->curchan))) {
+	    !AR_SREV_9280(ah)) {
 
 
 		if (ath9k_hw_channel_change(ah, chan)) {
 		if (ath9k_hw_channel_change(ah, chan)) {
 			ath9k_hw_loadnf(ah, ah->curchan);
 			ath9k_hw_loadnf(ah, ah->curchan);
@@ -2186,7 +2193,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 	}
 	}
 
 
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
 	if (AR_SREV_9300_20_OR_LATER(ah)) {
-		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC;
+		pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_LDPC |
+				 ATH9K_HW_CAP_FASTCLOCK;
 		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
 		pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
 		pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
 		pCap->rx_lp_qdepth = ATH9K_HW_RX_LP_QDEPTH;
 		pCap->rx_status_len = sizeof(struct ar9003_rxs);
 		pCap->rx_status_len = sizeof(struct ar9003_rxs);
@@ -2194,6 +2202,11 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 		pCap->txs_len = sizeof(struct ar9003_txs);
 		pCap->txs_len = sizeof(struct ar9003_txs);
 	} else {
 	} else {
 		pCap->tx_desc_len = sizeof(struct ath_desc);
 		pCap->tx_desc_len = sizeof(struct ath_desc);
+		if (AR_SREV_9280_20(ah) &&
+		    ((ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) <=
+		      AR5416_EEP_MINOR_VER_16) ||
+		     ah->eep_ops->get_eeprom(ah, EEP_FSTCLK_5G)))
+			pCap->hw_caps |= ATH9K_HW_CAP_FASTCLOCK;
 	}
 	}
 
 
 	if (AR_SREV_9300_20_OR_LATER(ah))
 	if (AR_SREV_9300_20_OR_LATER(ah))

+ 5 - 3
drivers/net/wireless/ath/ath9k/hw.h

@@ -198,6 +198,7 @@ enum ath9k_hw_caps {
 	ATH9K_HW_CAP_EDMA			= BIT(17),
 	ATH9K_HW_CAP_EDMA			= BIT(17),
 	ATH9K_HW_CAP_RAC_SUPPORTED		= BIT(18),
 	ATH9K_HW_CAP_RAC_SUPPORTED		= BIT(18),
 	ATH9K_HW_CAP_LDPC			= BIT(19),
 	ATH9K_HW_CAP_LDPC			= BIT(19),
+	ATH9K_HW_CAP_FASTCLOCK			= BIT(20),
 };
 };
 
 
 enum ath9k_capability_type {
 enum ath9k_capability_type {
@@ -261,6 +262,7 @@ struct ath9k_ops_config {
 #define AR_BASE_FREQ_5GHZ   	4900
 #define AR_BASE_FREQ_5GHZ   	4900
 #define AR_SPUR_FEEQ_BOUND_HT40 19
 #define AR_SPUR_FEEQ_BOUND_HT40 19
 #define AR_SPUR_FEEQ_BOUND_HT20 10
 #define AR_SPUR_FEEQ_BOUND_HT20 10
+	bool tx_iq_calibration; /* Only available for >= AR9003 */
 	int spurmode;
 	int spurmode;
 	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
 	u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
 	u8 max_txtrig_level;
 	u8 max_txtrig_level;
@@ -367,10 +369,9 @@ struct ath9k_channel {
 #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
 #define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
 #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
 #define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0)
 #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
 #define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
-#define IS_CHAN_A_5MHZ_SPACED(_c)			\
+#define IS_CHAN_A_FAST_CLOCK(_ah, _c)			\
 	((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&	\
 	((((_c)->channelFlags & CHANNEL_5GHZ) != 0) &&	\
-	 (((_c)->channel % 20) != 0) &&			\
-	 (((_c)->channel % 10) != 0))
+	 ((_ah)->caps.hw_caps & ATH9K_HW_CAP_FASTCLOCK))
 
 
 /* These macros check chanmode and not channelFlags */
 /* These macros check chanmode and not channelFlags */
 #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
 #define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
@@ -718,6 +719,7 @@ struct ath_hw {
 	u32 *addac5416_21;
 	u32 *addac5416_21;
 	u32 *bank6Temp;
 	u32 *bank6Temp;
 
 
+	u8 txpower_limit;
 	int16_t txpower_indexoffset;
 	int16_t txpower_indexoffset;
 	int coverage_class;
 	int coverage_class;
 	u32 beacon_interval;
 	u32 beacon_interval;

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

@@ -878,10 +878,12 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah,
 	if (ints & ATH9K_INT_TX) {
 	if (ints & ATH9K_INT_TX) {
 		if (ah->config.tx_intr_mitigation)
 		if (ah->config.tx_intr_mitigation)
 			mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
 			mask |= AR_IMR_TXMINTR | AR_IMR_TXINTM;
-		if (ah->txok_interrupt_mask)
-			mask |= AR_IMR_TXOK;
-		if (ah->txdesc_interrupt_mask)
-			mask |= AR_IMR_TXDESC;
+		else {
+			if (ah->txok_interrupt_mask)
+				mask |= AR_IMR_TXOK;
+			if (ah->txdesc_interrupt_mask)
+				mask |= AR_IMR_TXDESC;
+		}
 		if (ah->txerr_interrupt_mask)
 		if (ah->txerr_interrupt_mask)
 			mask |= AR_IMR_TXERR;
 			mask |= AR_IMR_TXERR;
 		if (ah->txeol_interrupt_mask)
 		if (ah->txeol_interrupt_mask)

+ 20 - 0
drivers/net/wireless/ath/ath9k/main.c

@@ -2044,6 +2044,25 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
 	return ret;
 	return ret;
 }
 }
 
 
+static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
+			     struct survey_info *survey)
+{
+	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = aphy->sc;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ieee80211_conf *conf = &hw->conf;
+
+	 if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = common->ani.noise_floor;
+
+	return 0;
+}
+
 static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
 {
 {
 	struct ath_wiphy *aphy = hw->priv;
 	struct ath_wiphy *aphy = hw->priv;
@@ -2115,6 +2134,7 @@ struct ieee80211_ops ath9k_ops = {
 	.set_tsf 	    = ath9k_set_tsf,
 	.set_tsf 	    = ath9k_set_tsf,
 	.reset_tsf 	    = ath9k_reset_tsf,
 	.reset_tsf 	    = ath9k_reset_tsf,
 	.ampdu_action       = ath9k_ampdu_action,
 	.ampdu_action       = ath9k_ampdu_action,
+	.get_survey	    = ath9k_get_survey,
 	.sw_scan_start      = ath9k_sw_scan_start,
 	.sw_scan_start      = ath9k_sw_scan_start,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
 	.sw_scan_complete   = ath9k_sw_scan_complete,
 	.rfkill_poll        = ath9k_rfkill_poll_state,
 	.rfkill_poll        = ath9k_rfkill_poll_state,

+ 7 - 4
drivers/net/wireless/ath/ath9k/wmi.c

@@ -276,6 +276,9 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
 	int time_left, ret = 0;
 	int time_left, ret = 0;
 	unsigned long flags;
 	unsigned long flags;
 
 
+	if (wmi->drv_priv->op_flags & OP_UNPLUGGED)
+		return 0;
+
 	if (!wmi)
 	if (!wmi)
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -302,14 +305,14 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
 	wmi->cmd_rsp_buf = rsp_buf;
 	wmi->cmd_rsp_buf = rsp_buf;
 	wmi->cmd_rsp_len = rsp_len;
 	wmi->cmd_rsp_len = rsp_len;
 
 
-	ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
-	if (ret)
-		goto out;
-
 	spin_lock_irqsave(&wmi->wmi_lock, flags);
 	spin_lock_irqsave(&wmi->wmi_lock, flags);
 	wmi->last_cmd_id = cmd_id;
 	wmi->last_cmd_id = cmd_id;
 	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 	spin_unlock_irqrestore(&wmi->wmi_lock, flags);
 
 
+	ret = ath9k_wmi_cmd_issue(wmi, skb, cmd_id, cmd_len);
+	if (ret)
+		goto out;
+
 	time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
 	time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
 	if (!time_left) {
 	if (!time_left) {
 		ath_print(common, ATH_DBG_WMI,
 		ath_print(common, ATH_DBG_WMI,

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

@@ -126,14 +126,14 @@ void ath9k_wmi_tasklet(unsigned long data);
 	do {								\
 	do {								\
 		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0,	\
 		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd, NULL, 0,	\
 				    (u8 *) &cmd_rsp,			\
 				    (u8 *) &cmd_rsp,			\
-				    sizeof(cmd_rsp), HZ);		\
+				    sizeof(cmd_rsp), HZ*2);		\
 	} while (0)
 	} while (0)
 
 
 #define WMI_CMD_BUF(_wmi_cmd, _buf)					\
 #define WMI_CMD_BUF(_wmi_cmd, _buf)					\
 	do {								\
 	do {								\
 		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd,		\
 		ret = ath9k_wmi_cmd(priv->wmi, _wmi_cmd,		\
 				    (u8 *) _buf, sizeof(*_buf),		\
 				    (u8 *) _buf, sizeof(*_buf),		\
-				    &cmd_rsp, sizeof(cmd_rsp), HZ);	\
+				    &cmd_rsp, sizeof(cmd_rsp), HZ*2);	\
 	} while (0)
 	} while (0)
 
 
 #endif /* WMI_H */
 #endif /* WMI_H */

+ 2 - 0
drivers/net/wireless/ath/ath9k/xmit.c

@@ -2290,6 +2290,8 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 			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);
+
 		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)) {
 			INIT_LIST_HEAD(&bf_head);
 			INIT_LIST_HEAD(&bf_head);

+ 19 - 2
drivers/net/wireless/b43/main.c

@@ -4571,6 +4571,23 @@ static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
 	mutex_unlock(&wl->mutex);
 	mutex_unlock(&wl->mutex);
 }
 }
 
 
+static int b43_op_get_survey(struct ieee80211_hw *hw, int idx,
+			     struct survey_info *survey)
+{
+	struct b43_wl *wl = hw_to_b43_wl(hw);
+	struct b43_wldev *dev = wl->current_dev;
+	struct ieee80211_conf *conf = &hw->conf;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = dev->stats.link_noise;
+
+	return 0;
+}
+
 static const struct ieee80211_ops b43_hw_ops = {
 static const struct ieee80211_ops b43_hw_ops = {
 	.tx			= b43_op_tx,
 	.tx			= b43_op_tx,
 	.conf_tx		= b43_op_conf_tx,
 	.conf_tx		= b43_op_conf_tx,
@@ -4590,6 +4607,7 @@ static const struct ieee80211_ops b43_hw_ops = {
 	.sta_notify		= b43_op_sta_notify,
 	.sta_notify		= b43_op_sta_notify,
 	.sw_scan_start		= b43_op_sw_scan_start_notifier,
 	.sw_scan_start		= b43_op_sw_scan_start_notifier,
 	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
 	.sw_scan_complete	= b43_op_sw_scan_complete_notifier,
+	.get_survey		= b43_op_get_survey,
 	.rfkill_poll		= b43_rfkill_poll,
 	.rfkill_poll		= b43_rfkill_poll,
 };
 };
 
 
@@ -4905,8 +4923,7 @@ static int b43_wireless_init(struct ssb_device *dev)
 
 
 	/* fill hw info */
 	/* fill hw info */
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM;
+		    IEEE80211_HW_SIGNAL_DBM;
 
 
 	hw->wiphy->interface_modes =
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_AP) |

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

@@ -610,7 +610,6 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 	}
 	}
 
 
 	/* Link quality statistics */
 	/* Link quality statistics */
-	status.noise = dev->stats.link_noise;
 	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
 	if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) {
 //		s8 rssi = max(rxhdr->power0, rxhdr->power1);
 //		s8 rssi = max(rxhdr->power0, rxhdr->power1);
 		//TODO: Find out what the rssi value is (dBm or percentage?)
 		//TODO: Find out what the rssi value is (dBm or percentage?)

+ 19 - 2
drivers/net/wireless/b43legacy/main.c

@@ -3482,6 +3482,23 @@ static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
 	return 0;
 	return 0;
 }
 }
 
 
+static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
+				   struct survey_info *survey)
+{
+	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+	struct b43legacy_wldev *dev = wl->current_dev;
+	struct ieee80211_conf *conf = &hw->conf;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = dev->stats.link_noise;
+
+	return 0;
+}
+
 static const struct ieee80211_ops b43legacy_hw_ops = {
 static const struct ieee80211_ops b43legacy_hw_ops = {
 	.tx			= b43legacy_op_tx,
 	.tx			= b43legacy_op_tx,
 	.conf_tx		= b43legacy_op_conf_tx,
 	.conf_tx		= b43legacy_op_conf_tx,
@@ -3494,6 +3511,7 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
 	.start			= b43legacy_op_start,
 	.start			= b43legacy_op_start,
 	.stop			= b43legacy_op_stop,
 	.stop			= b43legacy_op_stop,
 	.set_tim		= b43legacy_op_beacon_set_tim,
 	.set_tim		= b43legacy_op_beacon_set_tim,
+	.get_survey		= b43legacy_op_get_survey,
 	.rfkill_poll		= b43legacy_rfkill_poll,
 	.rfkill_poll		= b43legacy_rfkill_poll,
 };
 };
 
 
@@ -3769,8 +3787,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
 
 
 	/* fill hw info */
 	/* fill hw info */
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM;
+		    IEEE80211_HW_SIGNAL_DBM;
 	hw->wiphy->interface_modes =
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_AP) |
 		BIT(NL80211_IFTYPE_STATION) |
 		BIT(NL80211_IFTYPE_STATION) |

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

@@ -548,7 +548,6 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
 				      (phystat0 & B43legacy_RX_PHYST0_OFDM),
 				      (phystat0 & B43legacy_RX_PHYST0_OFDM),
 				      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
 				      (phystat0 & B43legacy_RX_PHYST0_GAINCTL),
 				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
 				      (phystat3 & B43legacy_RX_PHYST3_TRSTATE));
-	status.noise = dev->stats.link_noise;
 	/* change to support A PHY */
 	/* change to support A PHY */
 	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
 	if (phystat0 & B43legacy_RX_PHYST0_OFDM)
 		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);
 		status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false);

+ 1 - 0
drivers/net/wireless/iwlwifi/Makefile

@@ -22,5 +22,6 @@ iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
 # 3945
 # 3945
 obj-$(CONFIG_IWL3945)	+= iwl3945.o
 obj-$(CONFIG_IWL3945)	+= iwl3945.o
 iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
 iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
+iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o
 
 
 ccflags-y += -D__CHECK_ENDIAN__
 ccflags-y += -D__CHECK_ENDIAN__

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

@@ -282,7 +282,6 @@ struct iwl_cfg iwl1000_bg_cfg = {
 	.use_bsm = false,
 	.use_bsm = false,
 	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
 	.max_ll_items = OTP_MAX_LL_ITEMS_1000,
 	.shadow_ram_support = false,
 	.shadow_ram_support = false,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.support_ct_kill_exit = true,
 	.support_ct_kill_exit = true,

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

@@ -0,0 +1,500 @@
+/******************************************************************************
+ *
+ * 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 "iwl-3945-debugfs.h"
+
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
+		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
+	ssize_t ret;
+	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
+	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+	struct iwl39_statistics_rx_non_phy *general, *accum_general;
+	struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->_3945.statistics.rx.ofdm;
+	cck = &priv->_3945.statistics.rx.cck;
+	general = &priv->_3945.statistics.rx.general;
+	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_3945.accum_statistics.rx.cck;
+	accum_general = &priv->_3945.accum_statistics.rx.general;
+	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_3945.delta_statistics.rx.cck;
+	delta_general = &priv->_3945.delta_statistics.rx.general;
+	max_ofdm = &priv->_3945.max_delta.rx.ofdm;
+	max_cck = &priv->_3945.max_delta.rx.cck;
+	max_general = &priv->_3945.max_delta.rx.general;
+
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - OFDM:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
+			 accum_ofdm->ina_cnt,
+			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
+			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
+			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+			 le32_to_cpu(ofdm->overrun_err),
+			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
+			 max_ofdm->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(ofdm->early_overrun_err),
+			 accum_ofdm->early_overrun_err,
+			 delta_ofdm->early_overrun_err,
+			 max_ofdm->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
+			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
+			 max_ofdm->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+			 le32_to_cpu(ofdm->false_alarm_cnt),
+			 accum_ofdm->false_alarm_cnt,
+			 delta_ofdm->false_alarm_cnt,
+			 max_ofdm->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt),
+			 accum_ofdm->fina_sync_err_cnt,
+			 delta_ofdm->fina_sync_err_cnt,
+			 max_ofdm->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(ofdm->sfd_timeout),
+			 accum_ofdm->sfd_timeout,
+			 delta_ofdm->sfd_timeout,
+			 max_ofdm->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(ofdm->fina_timeout),
+			 accum_ofdm->fina_timeout,
+			 delta_ofdm->fina_timeout,
+			 max_ofdm->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(ofdm->unresponded_rts),
+			 accum_ofdm->unresponded_rts,
+			 delta_ofdm->unresponded_rts,
+			 max_ofdm->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+			 accum_ofdm->rxe_frame_limit_overrun,
+			 delta_ofdm->rxe_frame_limit_overrun,
+			 max_ofdm->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(ofdm->sent_ack_cnt),
+			 accum_ofdm->sent_ack_cnt,
+			 delta_ofdm->sent_ack_cnt,
+			 max_ofdm->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(ofdm->sent_cts_cnt),
+			 accum_ofdm->sent_cts_cnt,
+			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - CCK:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:",
+			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+			 delta_cck->ina_cnt, max_cck->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+			 delta_cck->fina_cnt, max_cck->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "plcp_err:",
+			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+			 delta_cck->plcp_err, max_cck->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_err:",
+			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+			 delta_cck->crc32_err, max_cck->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "overrun_err:",
+			 le32_to_cpu(cck->overrun_err),
+			 accum_cck->overrun_err,
+			 delta_cck->overrun_err, max_cck->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(cck->early_overrun_err),
+			 accum_cck->early_overrun_err,
+			 delta_cck->early_overrun_err,
+			 max_cck->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:",
+			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+			 delta_cck->crc32_good,
+			 max_cck->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "false_alarm_cnt:",
+			 le32_to_cpu(cck->false_alarm_cnt),
+			 accum_cck->false_alarm_cnt,
+			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(cck->fina_sync_err_cnt),
+			 accum_cck->fina_sync_err_cnt,
+			 delta_cck->fina_sync_err_cnt,
+			 max_cck->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(cck->sfd_timeout),
+			 accum_cck->sfd_timeout,
+			 delta_cck->sfd_timeout, max_cck->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(cck->fina_timeout),
+			 accum_cck->fina_timeout,
+			 delta_cck->fina_timeout, max_cck->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(cck->unresponded_rts),
+			 accum_cck->unresponded_rts,
+			 delta_cck->unresponded_rts,
+			 max_cck->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(cck->rxe_frame_limit_overrun),
+			 accum_cck->rxe_frame_limit_overrun,
+			 delta_cck->rxe_frame_limit_overrun,
+			 max_cck->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(cck->sent_ack_cnt),
+			 accum_cck->sent_ack_cnt,
+			 delta_cck->sent_ack_cnt,
+			 max_cck->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(cck->sent_cts_cnt),
+			 accum_cck->sent_cts_cnt,
+			 delta_cck->sent_cts_cnt,
+			 max_cck->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - GENERAL:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_cts:",
+			 le32_to_cpu(general->bogus_cts),
+			 accum_general->bogus_cts,
+			 delta_general->bogus_cts, max_general->bogus_cts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_ack:",
+			 le32_to_cpu(general->bogus_ack),
+			 accum_general->bogus_ack,
+			 delta_general->bogus_ack, max_general->bogus_ack);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_bssid_frames:",
+			 le32_to_cpu(general->non_bssid_frames),
+			 accum_general->non_bssid_frames,
+			 delta_general->non_bssid_frames,
+			 max_general->non_bssid_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "filtered_frames:",
+			 le32_to_cpu(general->filtered_frames),
+			 accum_general->filtered_frames,
+			 delta_general->filtered_frames,
+			 max_general->filtered_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_channel_beacons:",
+			 le32_to_cpu(general->non_channel_beacons),
+			 accum_general->non_channel_beacons,
+			 delta_general->non_channel_beacons,
+			 max_general->non_channel_beacons);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
+	ssize_t ret;
+	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	tx = &priv->_3945.statistics.tx;
+	accum_tx = &priv->_3945.accum_statistics.tx;
+	delta_tx = &priv->_3945.delta_statistics.tx;
+	max_tx = &priv->_3945.max_delta.tx;
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Tx:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "preamble:",
+			 le32_to_cpu(tx->preamble_cnt),
+			 accum_tx->preamble_cnt,
+			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rx_detected_cnt:",
+			 le32_to_cpu(tx->rx_detected_cnt),
+			 accum_tx->rx_detected_cnt,
+			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_defer_cnt:",
+			 le32_to_cpu(tx->bt_prio_defer_cnt),
+			 accum_tx->bt_prio_defer_cnt,
+			 delta_tx->bt_prio_defer_cnt,
+			 max_tx->bt_prio_defer_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_kill_cnt:",
+			 le32_to_cpu(tx->bt_prio_kill_cnt),
+			 accum_tx->bt_prio_kill_cnt,
+			 delta_tx->bt_prio_kill_cnt,
+			 max_tx->bt_prio_kill_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "few_bytes_cnt:",
+			 le32_to_cpu(tx->few_bytes_cnt),
+			 accum_tx->few_bytes_cnt,
+			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "cts_timeout:",
+			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+			 delta_tx->cts_timeout, max_tx->cts_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ack_timeout:",
+			 le32_to_cpu(tx->ack_timeout),
+			 accum_tx->ack_timeout,
+			 delta_tx->ack_timeout, max_tx->ack_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "expected_ack_cnt:",
+			 le32_to_cpu(tx->expected_ack_cnt),
+			 accum_tx->expected_ack_cnt,
+			 delta_tx->expected_ack_cnt,
+			 max_tx->expected_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "actual_ack_cnt:",
+			 le32_to_cpu(tx->actual_ack_cnt),
+			 accum_tx->actual_ack_cnt,
+			 delta_tx->actual_ack_cnt,
+			 max_tx->actual_ack_cnt);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
+	ssize_t ret;
+	struct iwl39_statistics_general *general, *accum_general;
+	struct iwl39_statistics_general *delta_general, *max_general;
+	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
+
+	if (!iwl_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	general = &priv->_3945.statistics.general;
+	dbg = &priv->_3945.statistics.general.dbg;
+	div = &priv->_3945.statistics.general.div;
+	accum_general = &priv->_3945.accum_statistics.general;
+	delta_general = &priv->_3945.delta_statistics.general;
+	max_general = &priv->_3945.max_delta.general;
+	accum_dbg = &priv->_3945.accum_statistics.general.dbg;
+	delta_dbg = &priv->_3945.delta_statistics.general.dbg;
+	max_dbg = &priv->_3945.max_delta.general.dbg;
+	accum_div = &priv->_3945.accum_statistics.general.div;
+	delta_div = &priv->_3945.delta_statistics.general.div;
+	max_div = &priv->_3945.max_delta.general.div;
+	pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_General:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_check:",
+			 le32_to_cpu(dbg->burst_check),
+			 accum_dbg->burst_check,
+			 delta_dbg->burst_check, max_dbg->burst_check);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_count:",
+			 le32_to_cpu(dbg->burst_count),
+			 accum_dbg->burst_count,
+			 delta_dbg->burst_count, max_dbg->burst_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sleep_time:",
+			 le32_to_cpu(general->sleep_time),
+			 accum_general->sleep_time,
+			 delta_general->sleep_time, max_general->sleep_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_out:",
+			 le32_to_cpu(general->slots_out),
+			 accum_general->slots_out,
+			 delta_general->slots_out, max_general->slots_out);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_idle:",
+			 le32_to_cpu(general->slots_idle),
+			 accum_general->slots_idle,
+			 delta_general->slots_idle, max_general->slots_idle);
+	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_a:",
+			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+			 delta_div->tx_on_a, max_div->tx_on_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_b:",
+			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+			 delta_div->tx_on_b, max_div->tx_on_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "exec_time:",
+			 le32_to_cpu(div->exec_time), accum_div->exec_time,
+			 delta_div->exec_time, max_div->exec_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "probe_time:",
+			 le32_to_cpu(div->probe_time), accum_div->probe_time,
+			 delta_div->probe_time, max_div->probe_time);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}

+ 60 - 0
drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h

@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * 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 "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf, size_t count,
+					 loff_t *ppos);
+#else
+static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	return 0;
+}
+#endif

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

@@ -50,6 +50,7 @@
 #include "iwl-helpers.h"
 #include "iwl-helpers.h"
 #include "iwl-led.h"
 #include "iwl-led.h"
 #include "iwl-3945-led.h"
 #include "iwl-3945-led.h"
+#include "iwl-3945-debugfs.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,   \
@@ -293,7 +294,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
  * iwl3945_rx_reply_tx - Handle Tx response
  * iwl3945_rx_reply_tx - Handle Tx response
  */
  */
 static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
 static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb)
+				struct iwl_rx_mem_buffer *rxb)
 {
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
@@ -351,18 +352,81 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
  *  RX handler implementations
  *  RX handler implementations
  *
  *
  *****************************************************************************/
  *****************************************************************************/
+#ifdef CONFIG_IWLWIFI_DEBUG
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
+					    __le32 *stats)
+{
+	int i;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+
+	prev_stats = (__le32 *)&priv->_3945.statistics;
+	accum_stats = (u32 *)&priv->_3945.accum_statistics;
+	delta = (u32 *)&priv->_3945.delta_statistics;
+	max_delta = (u32 *)&priv->_3945.max_delta;
+
+	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	priv->_3945.accum_statistics.general.temperature =
+		priv->_3945.statistics.general.temperature;
+	priv->_3945.accum_statistics.general.ttl_timestamp =
+		priv->_3945.statistics.general.ttl_timestamp;
+}
+#endif
 
 
 void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 		struct iwl_rx_mem_buffer *rxb)
 		struct iwl_rx_mem_buffer *rxb)
 {
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
 		     (int)sizeof(struct iwl3945_notif_statistics),
 		     (int)sizeof(struct iwl3945_notif_statistics),
 		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
 		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+#ifdef CONFIG_IWLWIFI_DEBUG
+	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
+#endif
 
 
 	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
 	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
 }
 }
 
 
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	__le32 *flag = (__le32 *)&pkt->u.raw;
+
+	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_DEBUG
+		memset(&priv->_3945.accum_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.delta_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.max_delta, 0,
+			sizeof(struct iwl3945_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl3945_hw_rx_statistics(priv, rxb);
+}
+
+
 /******************************************************************************
 /******************************************************************************
  *
  *
  * Misc. internal state and helper functions
  * Misc. internal state and helper functions
@@ -2736,6 +2800,12 @@ static struct iwl_lib_ops iwl3945_lib = {
 	.isr = iwl_isr_legacy,
 	.isr = iwl_isr_legacy,
 	.config_ap = iwl3945_config_ap,
 	.config_ap = iwl3945_config_ap,
 	.add_bcast_station = iwl3945_add_bcast_station,
 	.add_bcast_station = iwl3945_add_bcast_station,
+
+	.debugfs_ops = {
+		.rx_stats_read = iwl3945_ucode_rx_stats_read,
+		.tx_stats_read = iwl3945_ucode_tx_stats_read,
+		.general_stats_read = iwl3945_ucode_general_stats_read,
+	},
 };
 };
 
 
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
 static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {

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

@@ -264,6 +264,8 @@ extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
 extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
 extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
 extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
 				 struct iwl_rx_mem_buffer *rxb);
 				 struct iwl_rx_mem_buffer *rxb);
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      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);
 extern void iwl3945_post_associate(struct iwl_priv *priv);

+ 52 - 21
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -200,26 +200,57 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
 
 
 	/* Set initial sensitivity parameters */
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
 	/* Set initial calibration set */
-	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
-	case CSR_HW_REV_TYPE_5150:
-		priv->hw_params.sens = &iwl5150_sensitivity;
-		priv->hw_params.calib_init_cfg =
-			BIT(IWL_CALIB_DC)		|
-			BIT(IWL_CALIB_LO)		|
-			BIT(IWL_CALIB_TX_IQ) 		|
-			BIT(IWL_CALIB_BASE_BAND);
-
-		break;
-	default:
-		priv->hw_params.sens = &iwl5000_sensitivity;
-		priv->hw_params.calib_init_cfg =
-			BIT(IWL_CALIB_XTAL)		|
-			BIT(IWL_CALIB_LO)		|
-			BIT(IWL_CALIB_TX_IQ) 		|
-			BIT(IWL_CALIB_TX_IQ_PERD)	|
-			BIT(IWL_CALIB_BASE_BAND);
-		break;
-	}
+	priv->hw_params.sens = &iwl5000_sensitivity;
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_XTAL)		|
+		BIT(IWL_CALIB_LO)		|
+		BIT(IWL_CALIB_TX_IQ)		|
+		BIT(IWL_CALIB_TX_IQ_PERD)	|
+		BIT(IWL_CALIB_BASE_BAND);
+
+	return 0;
+}
+
+static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
+		priv->cfg->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+			priv->cfg->num_of_queues *
+			sizeof(struct iwlagn_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWL5000_STATION_COUNT;
+	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
+
+	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
+
+	priv->hw_params.max_bsm_size = 0;
+	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
+					BIT(IEEE80211_BAND_5GHZ);
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
+		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+
+	/* Set initial sensitivity parameters */
+	/* Set initial calibration set */
+	priv->hw_params.sens = &iwl5150_sensitivity;
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_DC)		|
+		BIT(IWL_CALIB_LO)		|
+		BIT(IWL_CALIB_TX_IQ)		|
+		BIT(IWL_CALIB_BASE_BAND);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -332,7 +363,7 @@ static struct iwl_lib_ops iwl5000_lib = {
 };
 };
 
 
 static struct iwl_lib_ops iwl5150_lib = {
 static struct iwl_lib_ops iwl5150_lib = {
-	.set_hw_params = iwl5000_hw_set_hw_params,
+	.set_hw_params = iwl5150_hw_set_hw_params,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
 	.txq_set_sched = iwlagn_txq_set_sched,
 	.txq_set_sched = iwlagn_txq_set_sched,

+ 51 - 22
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -176,24 +176,56 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 	/* Set initial sensitivity parameters */
 	/* Set initial sensitivity parameters */
 	/* Set initial calibration set */
 	/* Set initial calibration set */
 	priv->hw_params.sens = &iwl6000_sensitivity;
 	priv->hw_params.sens = &iwl6000_sensitivity;
-	switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
-	case CSR_HW_REV_TYPE_6x50:
-		priv->hw_params.calib_init_cfg =
-			BIT(IWL_CALIB_XTAL)		|
-			BIT(IWL_CALIB_DC)		|
-			BIT(IWL_CALIB_LO)		|
-			BIT(IWL_CALIB_TX_IQ) 		|
-			BIT(IWL_CALIB_BASE_BAND);
-
-		break;
-	default:
-		priv->hw_params.calib_init_cfg =
-			BIT(IWL_CALIB_XTAL)		|
-			BIT(IWL_CALIB_LO)		|
-			BIT(IWL_CALIB_TX_IQ) 		|
-			BIT(IWL_CALIB_BASE_BAND);
-		break;
-	}
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_XTAL)		|
+		BIT(IWL_CALIB_LO)		|
+		BIT(IWL_CALIB_TX_IQ)		|
+		BIT(IWL_CALIB_BASE_BAND);
+
+	return 0;
+}
+
+static int iwl6050_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
+		priv->cfg->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+			priv->cfg->num_of_queues *
+			sizeof(struct iwlagn_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWL5000_STATION_COUNT;
+	priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
+
+	priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
+
+	priv->hw_params.max_bsm_size = 0;
+	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
+					BIT(IEEE80211_BAND_5GHZ);
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
+		priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
+
+	/* Set initial sensitivity parameters */
+	/* Set initial calibration set */
+	priv->hw_params.sens = &iwl6000_sensitivity;
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_XTAL)		|
+		BIT(IWL_CALIB_DC)		|
+		BIT(IWL_CALIB_LO)		|
+		BIT(IWL_CALIB_TX_IQ)		|
+		BIT(IWL_CALIB_BASE_BAND);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -304,7 +336,7 @@ static const struct iwl_ops iwl6000_ops = {
 };
 };
 
 
 static struct iwl_lib_ops iwl6050_lib = {
 static struct iwl_lib_ops iwl6050_lib = {
-	.set_hw_params = iwl6000_hw_set_hw_params,
+	.set_hw_params = iwl6050_hw_set_hw_params,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
 	.txq_set_sched = iwlagn_txq_set_sched,
 	.txq_set_sched = iwlagn_txq_set_sched,
@@ -468,7 +500,6 @@ struct iwl_cfg iwl6000i_2abg_cfg = {
 	.pa_type = IWL_PA_INTERNAL,
 	.pa_type = IWL_PA_INTERNAL,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
 	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.supports_idle = true,
 	.supports_idle = true,
@@ -501,7 +532,6 @@ struct iwl_cfg iwl6000i_2bg_cfg = {
 	.pa_type = IWL_PA_INTERNAL,
 	.pa_type = IWL_PA_INTERNAL,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x00,
 	.shadow_ram_support = true,
 	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.supports_idle = true,
 	.supports_idle = true,
@@ -568,7 +598,6 @@ struct iwl_cfg iwl6050_2abg_cfg = {
 	.pa_type = IWL_PA_SYSTEM,
 	.pa_type = IWL_PA_SYSTEM,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
 	.max_ll_items = OTP_MAX_LL_ITEMS_6x50,
 	.shadow_ram_support = true,
 	.shadow_ram_support = true,
-	.ht_greenfield_support = true,
 	.led_compensation = 51,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
 	.supports_idle = true,
 	.supports_idle = true,

+ 18 - 5
drivers/net/wireless/iwlwifi/iwl-agn-lib.c

@@ -1395,16 +1395,29 @@ void iwlagn_request_scan(struct iwl_priv *priv)
 			rate = IWL_RATE_1M_PLCP;
 			rate = IWL_RATE_1M_PLCP;
 			rate_flags = RATE_MCS_CCK_MSK;
 			rate_flags = RATE_MCS_CCK_MSK;
 		}
 		}
-		scan->good_CRC_th = 0;
+		scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED;
 		break;
 		break;
 	case IEEE80211_BAND_5GHZ:
 	case IEEE80211_BAND_5GHZ:
 		rate = IWL_RATE_6M_PLCP;
 		rate = IWL_RATE_6M_PLCP;
 		/*
 		/*
-		 * If active scaning is requested but a certain channel
-		 * is marked passive, we can do active scanning if we
-		 * detect transmissions.
+		 * If active scanning is requested but a certain channel is
+		 * marked passive, we can do active scanning if we detect
+		 * transmissions.
+		 *
+		 * There is an issue with some firmware versions that triggers
+		 * a sysassert on a "good CRC threshold" of zero (== disabled),
+		 * on a radar channel even though this means that we should NOT
+		 * send probes.
+		 *
+		 * The "good CRC threshold" is the number of frames that we
+		 * need to receive during our dwell time on a channel before
+		 * sending out probes -- setting this to a huge value will
+		 * mean we never reach it, but at the same time work around
+		 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+		 * here instead of IWL_GOOD_CRC_TH_DISABLED.
 		 */
 		 */
-		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+						IWL_GOOD_CRC_TH_NEVER;
 		break;
 		break;
 	default:
 	default:
 		IWL_WARN(priv, "Invalid scan band count\n");
 		IWL_WARN(priv, "Invalid scan band count\n");

+ 11 - 9
drivers/net/wireless/iwlwifi/iwl-agn-rs.c

@@ -868,14 +868,14 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
 		rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
 		rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
 				&rs_index);
 				&rs_index);
 		rs_collect_tx_data(curr_tbl, rs_index,
 		rs_collect_tx_data(curr_tbl, rs_index,
-				   info->status.ampdu_ack_len,
-				   info->status.ampdu_ack_map);
+				   info->status.ampdu_len,
+				   info->status.ampdu_ack_len);
 
 
 		/* Update success/fail counts if not searching for new mode */
 		/* Update success/fail counts if not searching for new mode */
 		if (lq_sta->stay_in_tbl) {
 		if (lq_sta->stay_in_tbl) {
-			lq_sta->total_success += info->status.ampdu_ack_map;
-			lq_sta->total_failed += (info->status.ampdu_ack_len -
-					info->status.ampdu_ack_map);
+			lq_sta->total_success += info->status.ampdu_ack_len;
+			lq_sta->total_failed += (info->status.ampdu_len -
+					info->status.ampdu_ack_len);
 		}
 		}
 	} else {
 	} else {
 	/*
 	/*
@@ -2078,10 +2078,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
 	}
 	}
 	/* Else we have enough samples; calculate estimate of
 	/* Else we have enough samples; calculate estimate of
 	 * actual average throughput */
 	 * actual average throughput */
-
-	/* Sanity-check TPT calculations */
-	BUG_ON(window->average_tpt != ((window->success_ratio *
-			tbl->expected_tpt[index] + 64) / 128));
+	if (window->average_tpt != ((window->success_ratio *
+			tbl->expected_tpt[index] + 64) / 128)) {
+		IWL_ERR(priv, "expected_tpt should have been calculated by now\n");
+		window->average_tpt = ((window->success_ratio *
+					tbl->expected_tpt[index] + 64) / 128);
+	}
 
 
 	/* If we are searching for better modulation mode, check success. */
 	/* If we are searching for better modulation mode, check success. */
 	if (lq_sta->search_better_tbl &&
 	if (lq_sta->search_better_tbl &&

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

@@ -83,6 +83,15 @@ static inline int get_fifo_from_ac(u8 ac)
 	return ac_to_fifo[ac];
 	return ac_to_fifo[ac];
 }
 }
 
 
+static inline int get_ac_from_tid(u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return tid_to_ac[tid];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
 static inline int get_fifo_from_tid(u16 tid)
 static inline int get_fifo_from_tid(u16 tid)
 {
 {
 	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
 	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
@@ -991,7 +1000,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
 	tid_data = &priv->stations[sta_id].tid[tid];
 	tid_data = &priv->stations[sta_id].tid[tid];
 	*ssn = SEQ_TO_SN(tid_data->seq_number);
 	*ssn = SEQ_TO_SN(tid_data->seq_number);
 	tid_data->agg.txq_id = txq_id;
 	tid_data->agg.txq_id = txq_id;
-	priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id);
+	priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(get_ac_from_tid(tid), txq_id);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
 
 	ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
 	ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo,
@@ -1224,8 +1233,9 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
 	memset(&info->status, 0, sizeof(info->status));
 	memset(&info->status, 0, sizeof(info->status));
 	info->flags |= IEEE80211_TX_STAT_ACK;
 	info->flags |= IEEE80211_TX_STAT_ACK;
 	info->flags |= IEEE80211_TX_STAT_AMPDU;
 	info->flags |= IEEE80211_TX_STAT_AMPDU;
-	info->status.ampdu_ack_map = successes;
-	info->status.ampdu_ack_len = agg->frame_count;
+	info->status.ampdu_ack_len = successes;
+	info->status.ampdu_ack_map = bitmap;
+	info->status.ampdu_len = agg->frame_count;
 	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
 	iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
 
 
 	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);
 	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap);

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

@@ -2654,7 +2654,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv)
 
 
 	/* Tell mac80211 our characteristics */
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_AMPDU_AGGREGATION |
 		    IEEE80211_HW_SPECTRUM_MGMT;
 		    IEEE80211_HW_SPECTRUM_MGMT;
 
 
@@ -3002,18 +3001,6 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 	return 0;
 	return 0;
 }
 }
 
 
-static int iwl_mac_get_stats(struct ieee80211_hw *hw,
-			     struct ieee80211_low_level_stats *stats)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	priv = hw->priv;
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return 0;
-}
-
 static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
 static void iwl_mac_sta_notify(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       struct ieee80211_vif *vif,
 			       enum sta_notify_cmd cmd,
 			       enum sta_notify_cmd cmd,
@@ -3391,7 +3378,6 @@ static struct ieee80211_ops iwl_hw_ops = {
 	.configure_filter = iwl_configure_filter,
 	.configure_filter = iwl_configure_filter,
 	.set_key = iwl_mac_set_key,
 	.set_key = iwl_mac_set_key,
 	.update_tkip_key = iwl_mac_update_tkip_key,
 	.update_tkip_key = iwl_mac_update_tkip_key,
-	.get_stats = iwl_mac_get_stats,
 	.conf_tx = iwl_mac_conf_tx,
 	.conf_tx = iwl_mac_conf_tx,
 	.reset_tsf = iwl_mac_reset_tsf,
 	.reset_tsf = iwl_mac_reset_tsf,
 	.bss_info_changed = iwl_bss_info_changed,
 	.bss_info_changed = iwl_bss_info_changed,

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

@@ -2663,7 +2663,9 @@ struct iwl_ssid_ie {
 #define PROBE_OPTION_MAX_3945		4
 #define PROBE_OPTION_MAX_3945		4
 #define PROBE_OPTION_MAX		20
 #define PROBE_OPTION_MAX		20
 #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF)
 #define TX_CMD_LIFE_TIME_INFINITE	cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH			cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_DISABLED	0
+#define IWL_GOOD_CRC_TH_DEFAULT		cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_NEVER		cpu_to_le16(0xffff)
 #define IWL_MAX_SCAN_SIZE 1024
 #define IWL_MAX_SCAN_SIZE 1024
 #define IWL_MAX_CMD_SIZE 4096
 #define IWL_MAX_CMD_SIZE 4096
 #define IWL_MAX_PROBE_REQUEST		200
 #define IWL_MAX_PROBE_REQUEST		200

+ 6 - 4
drivers/net/wireless/iwlwifi/iwl-core.c

@@ -2117,10 +2117,6 @@ EXPORT_SYMBOL(iwl_mac_remove_interface);
 
 
 /**
 /**
  * iwl_mac_config - mac80211 config callback
  * iwl_mac_config - mac80211 config callback
- *
- * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
- * be set inappropriately and the driver currently sets the hardware up to
- * use it whenever needed.
  */
  */
 int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 {
 {
@@ -2935,6 +2931,12 @@ int iwl_pci_resume(struct pci_dev *pdev)
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	int ret;
 	int ret;
 
 
+	/*
+	 * We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
 	pci_set_power_state(pdev, PCI_D0);
 	pci_set_power_state(pdev, PCI_D0);
 	ret = pci_enable_device(pdev);
 	ret = pci_enable_device(pdev);
 	if (ret)
 	if (ret)

+ 3 - 1
drivers/net/wireless/iwlwifi/iwl-core.h

@@ -512,7 +512,9 @@ static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags)
 void iwl_init_scan_params(struct iwl_priv *priv);
 void iwl_init_scan_params(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
 int iwl_scan_cancel(struct iwl_priv *priv);
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
 int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
-int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req);
+int iwl_mac_hw_scan(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req);
 void iwl_internal_short_hw_scan(struct iwl_priv *priv);
 void iwl_internal_short_hw_scan(struct iwl_priv *priv);
 int iwl_force_reset(struct iwl_priv *priv, int mode);
 int iwl_force_reset(struct iwl_priv *priv, int mode);
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
 u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,

+ 6 - 12
drivers/net/wireless/iwlwifi/iwl-debugfs.c

@@ -1059,10 +1059,8 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file,
 					size_t count, loff_t *ppos)
 					size_t count, loff_t *ppos)
 {
 {
 	struct iwl_priv *priv = file->private_data;
 	struct iwl_priv *priv = file->private_data;
-	if (priv->cfg->ops->lib->debugfs_ops.rx_stats_read)
-		return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
-						user_buf, count, ppos);
-	return 0;
+	return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
+			user_buf, count, ppos);
 }
 }
 
 
 static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
 static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
@@ -1070,10 +1068,8 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file,
 					size_t count, loff_t *ppos)
 					size_t count, loff_t *ppos)
 {
 {
 	struct iwl_priv *priv = file->private_data;
 	struct iwl_priv *priv = file->private_data;
-	if (priv->cfg->ops->lib->debugfs_ops.tx_stats_read)
-		return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
-						user_buf, count, ppos);
-	return 0;
+	return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
+			user_buf, count, ppos);
 }
 }
 
 
 static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
 static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
@@ -1081,10 +1077,8 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file,
 					size_t count, loff_t *ppos)
 					size_t count, loff_t *ppos)
 {
 {
 	struct iwl_priv *priv = file->private_data;
 	struct iwl_priv *priv = file->private_data;
-	if (priv->cfg->ops->lib->debugfs_ops.general_stats_read)
-		return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
-						user_buf, count, ppos);
-	return 0;
+	return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
+			user_buf, count, ppos);
 }
 }
 
 
 static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,
 static ssize_t iwl_dbgfs_sensitivity_read(struct file *file,

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

@@ -1202,6 +1202,11 @@ struct iwl_priv {
 			struct delayed_work rfkill_poll;
 			struct delayed_work rfkill_poll;
 
 
 			struct iwl3945_notif_statistics statistics;
 			struct iwl3945_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_DEBUG
+			struct iwl3945_notif_statistics accum_statistics;
+			struct iwl3945_notif_statistics delta_statistics;
+			struct iwl3945_notif_statistics max_delta;
+#endif
 
 
 			u32 sta_supp_rates;
 			u32 sta_supp_rates;
 			int last_rx_rssi;	/* From Rx packet statistics */
 			int last_rx_rssi;	/* From Rx packet statistics */

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

@@ -313,7 +313,8 @@ static int iwl_scan_initiate(struct iwl_priv *priv)
 }
 }
 
 
 int iwl_mac_hw_scan(struct ieee80211_hw *hw,
 int iwl_mac_hw_scan(struct ieee80211_hw *hw,
-		     struct cfg80211_scan_request *req)
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req)
 {
 {
 	struct iwl_priv *priv = hw->priv;
 	struct iwl_priv *priv = hw->priv;
 	int ret;
 	int ret;

+ 3 - 3
drivers/net/wireless/iwlwifi/iwl3945-base.c

@@ -957,7 +957,7 @@ static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
 	 * statistics request from the host as well as for the periodic
 	 * statistics request from the host as well as for the periodic
 	 * statistics notifications (after received beacons) from the uCode.
 	 * statistics notifications (after received beacons) from the uCode.
 	 */
 	 */
-	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics;
+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
 	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
 	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
 
 
 	iwl_setup_rx_scan_handlers(priv);
 	iwl_setup_rx_scan_handlers(priv);
@@ -2939,7 +2939,8 @@ void iwl3945_request_scan(struct iwl_priv *priv)
 		 * is marked passive, we can do active scanning if we
 		 * is marked passive, we can do active scanning if we
 		 * detect transmissions.
 		 * detect transmissions.
 		 */
 		 */
-		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
+		scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+						IWL_GOOD_CRC_TH_DISABLED;
 		band = IEEE80211_BAND_5GHZ;
 		band = IEEE80211_BAND_5GHZ;
 		break;
 		break;
 	default:
 	default:
@@ -3873,7 +3874,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
 
 
 	/* Tell mac80211 our characteristics */
 	/* Tell mac80211 our characteristics */
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
 	hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_NOISE_DBM |
 		    IEEE80211_HW_SPECTRUM_MGMT;
 		    IEEE80211_HW_SPECTRUM_MGMT;
 
 
 	if (!priv->cfg->broken_powersave)
 	if (!priv->cfg->broken_powersave)

+ 1 - 1
drivers/net/wireless/iwmc3200wifi/bus.h

@@ -31,7 +31,7 @@ struct iwm_if_ops {
 	int (*disable)(struct iwm_priv *iwm);
 	int (*disable)(struct iwm_priv *iwm);
 	int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
 	int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
 
 
-	int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
+	void (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
 	void (*debugfs_exit)(struct iwm_priv *iwm);
 	void (*debugfs_exit)(struct iwm_priv *iwm);
 
 
 	const char *umac_name;
 	const char *umac_name;

+ 2 - 5
drivers/net/wireless/iwmc3200wifi/debug.h

@@ -113,13 +113,10 @@ struct iwm_debugfs {
 };
 };
 
 
 #ifdef CONFIG_IWM_DEBUG
 #ifdef CONFIG_IWM_DEBUG
-int iwm_debugfs_init(struct iwm_priv *iwm);
+void iwm_debugfs_init(struct iwm_priv *iwm);
 void iwm_debugfs_exit(struct iwm_priv *iwm);
 void iwm_debugfs_exit(struct iwm_priv *iwm);
 #else
 #else
-static inline int iwm_debugfs_init(struct iwm_priv *iwm)
-{
-	return 0;
-}
+static inline void iwm_debugfs_init(struct iwm_priv *iwm) {}
 static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
 static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
 #endif
 #endif
 
 

+ 10 - 100
drivers/net/wireless/iwmc3200wifi/debugfs.c

@@ -48,12 +48,11 @@ static struct {
 
 
 #define add_dbg_module(dbg, name, id, initlevel) 	\
 #define add_dbg_module(dbg, name, id, initlevel) 	\
 do {							\
 do {							\
-	struct dentry *d;				\
 	dbg.dbg_module[id] = (initlevel);		\
 	dbg.dbg_module[id] = (initlevel);		\
-	d = debugfs_create_x8(name, 0600, dbg.dbgdir,	\
-			     &(dbg.dbg_module[id]));	\
-	if (!IS_ERR(d))					\
-		dbg.dbg_module_dentries[id] = d;        \
+	dbg.dbg_module_dentries[id] =			\
+		debugfs_create_x8(name, 0600,		\
+				dbg.dbgdir,		\
+				&(dbg.dbg_module[id]));	\
 } while (0)
 } while (0)
 
 
 static int iwm_debugfs_u32_read(void *data, u64 *val)
 static int iwm_debugfs_u32_read(void *data, u64 *val)
@@ -423,89 +422,29 @@ static const struct file_operations iwm_debugfs_fw_err_fops = {
 	.read =		iwm_debugfs_fw_err_read,
 	.read =		iwm_debugfs_fw_err_read,
 };
 };
 
 
-int iwm_debugfs_init(struct iwm_priv *iwm)
+void iwm_debugfs_init(struct iwm_priv *iwm)
 {
 {
-	int i, result;
-	char devdir[16];
+	int i;
 
 
 	iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
 	iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
-	result = PTR_ERR(iwm->dbg.rootdir);
-	if (!result || IS_ERR(iwm->dbg.rootdir)) {
-		if (result == -ENODEV) {
-			IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not "
-				"enabled in kernel config\n");
-			result = 0;	/* No debugfs support */
-		}
-		IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result);
-		goto error;
-	}
-
-	snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm)));
-
-	iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir);
-	result = PTR_ERR(iwm->dbg.devdir);
-	if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create devdir: %d\n", result);
-		goto error;
-	}
-
+	iwm->dbg.devdir = debugfs_create_dir(wiphy_name(iwm_to_wiphy(iwm)),
+					     iwm->dbg.rootdir);
 	iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
 	iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
-	result = PTR_ERR(iwm->dbg.dbgdir);
-	if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
 	iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
-	result = PTR_ERR(iwm->dbg.rxdir);
-	if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
 	iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
-	result = PTR_ERR(iwm->dbg.txdir);
-	if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
 	iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
-	result = PTR_ERR(iwm->dbg.busdir);
-	if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result);
-		goto error;
-	}
-
-	if (iwm->bus_ops->debugfs_init) {
-		result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
-		if (result < 0) {
-			IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result);
-			goto error;
-		}
-	}
-
+	if (iwm->bus_ops->debugfs_init)
+		iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
 
 
 	iwm->dbg.dbg_level = IWM_DL_NONE;
 	iwm->dbg.dbg_level = IWM_DL_NONE;
 	iwm->dbg.dbg_level_dentry =
 	iwm->dbg.dbg_level_dentry =
 		debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
 		debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
 				    &fops_iwm_dbg_level);
 				    &fops_iwm_dbg_level);
-	result = PTR_ERR(iwm->dbg.dbg_level_dentry);
-	if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result);
-		goto error;
-	}
-
 
 
 	iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
 	iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
 	iwm->dbg.dbg_modules_dentry =
 	iwm->dbg.dbg_modules_dentry =
 		debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
 		debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
 				    &fops_iwm_dbg_modules);
 				    &fops_iwm_dbg_modules);
-	result = PTR_ERR(iwm->dbg.dbg_modules_dentry);
-	if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result);
-		goto error;
-	}
 
 
 	for (i = 0; i < __IWM_DM_NR; i++)
 	for (i = 0; i < __IWM_DM_NR; i++)
 		add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
 		add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
@@ -514,44 +453,15 @@ int iwm_debugfs_init(struct iwm_priv *iwm)
 	iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
 	iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
 						  iwm->dbg.txdir, iwm,
 						  iwm->dbg.txdir, iwm,
 						  &iwm_debugfs_txq_fops);
 						  &iwm_debugfs_txq_fops);
-	result = PTR_ERR(iwm->dbg.txq_dentry);
-	if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
 	iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
 						   iwm->dbg.txdir, iwm,
 						   iwm->dbg.txdir, iwm,
 						   &iwm_debugfs_tx_credit_fops);
 						   &iwm_debugfs_tx_credit_fops);
-	result = PTR_ERR(iwm->dbg.tx_credit_dentry);
-	if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
 	iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
 						  iwm->dbg.rxdir, iwm,
 						  iwm->dbg.rxdir, iwm,
 						  &iwm_debugfs_rx_ticket_fops);
 						  &iwm_debugfs_rx_ticket_fops);
-	result = PTR_ERR(iwm->dbg.rx_ticket_dentry);
-	if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result);
-		goto error;
-	}
-
 	iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
 	iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200,
 						     iwm->dbg.dbgdir, iwm,
 						     iwm->dbg.dbgdir, iwm,
 						     &iwm_debugfs_fw_err_fops);
 						     &iwm_debugfs_fw_err_fops);
-	result = PTR_ERR(iwm->dbg.fw_err_dentry);
-	if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result);
-		goto error;
-	}
-
-
-	return 0;
-
- error:
-	return result;
 }
 }
 
 
 void iwm_debugfs_exit(struct iwm_priv *iwm)
 void iwm_debugfs_exit(struct iwm_priv *iwm)

+ 2 - 15
drivers/net/wireless/iwmc3200wifi/sdio.c

@@ -366,21 +366,13 @@ static const struct file_operations iwm_debugfs_sdio_fops = {
 	.read =		iwm_debugfs_sdio_read,
 	.read =		iwm_debugfs_sdio_read,
 };
 };
 
 
-static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
+static void if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
 {
 {
-	int result;
 	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
 	struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
 
 
 	hw->cccr_dentry = debugfs_create_file("cccr", 0200,
 	hw->cccr_dentry = debugfs_create_file("cccr", 0200,
 					      parent_dir, iwm,
 					      parent_dir, iwm,
 					      &iwm_debugfs_sdio_fops);
 					      &iwm_debugfs_sdio_fops);
-	result = PTR_ERR(hw->cccr_dentry);
-	if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) {
-		IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result);
-		return result;
-	}
-
-	return 0;
 }
 }
 
 
 static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
 static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
@@ -440,11 +432,7 @@ static int iwm_sdio_probe(struct sdio_func *func,
 	hw = iwm_private(iwm);
 	hw = iwm_private(iwm);
 	hw->iwm = iwm;
 	hw->iwm = iwm;
 
 
-	ret = iwm_debugfs_init(iwm);
-	if (ret < 0) {
-		IWM_ERR(iwm, "Debugfs registration failed\n");
-		goto if_free;
-	}
+	iwm_debugfs_init(iwm);
 
 
 	sdio_set_drvdata(func, hw);
 	sdio_set_drvdata(func, hw);
 
 
@@ -473,7 +461,6 @@ static int iwm_sdio_probe(struct sdio_func *func,
 	destroy_workqueue(hw->isr_wq);
 	destroy_workqueue(hw->isr_wq);
  debugfs_exit:
  debugfs_exit:
 	iwm_debugfs_exit(iwm);
 	iwm_debugfs_exit(iwm);
- if_free:
 	iwm_if_free(iwm);
 	iwm_if_free(iwm);
 	return ret;
 	return ret;
 }
 }

+ 3 - 1
drivers/net/wireless/libertas/if_sdio.c

@@ -324,7 +324,9 @@ static int if_sdio_wait_status(struct if_sdio_card *card, const u8 condition)
 	timeout = jiffies + HZ;
 	timeout = jiffies + HZ;
 	while (1) {
 	while (1) {
 		status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
 		status = sdio_readb(card->func, IF_SDIO_STATUS, &ret);
-		if (ret || (status & condition))
+		if (ret)
+			return ret;
+		if ((status & condition) == condition)
 			break;
 			break;
 		if (time_after(jiffies, timeout))
 		if (time_after(jiffies, timeout))
 			return -ETIMEDOUT;
 			return -ETIMEDOUT;

+ 169 - 34
drivers/net/wireless/libertas_tf/cmd.c

@@ -7,6 +7,8 @@
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  your option) any later version.
  *  your option) any later version.
  */
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
 #include "libertas_tf.h"
 #include "libertas_tf.h"
@@ -82,6 +84,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
 	int ret = -1;
 	int ret = -1;
 	u32 i;
 	u32 i;
 
 
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	memset(&cmd, 0, sizeof(cmd));
 	memset(&cmd, 0, sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
 	memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN);
@@ -104,6 +108,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
 		priv->fwrelease >>  8 & 0xff,
 		priv->fwrelease >>  8 & 0xff,
 		priv->fwrelease       & 0xff,
 		priv->fwrelease       & 0xff,
 		priv->fwcapinfo);
 		priv->fwcapinfo);
+	lbtf_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n",
+		    cmd.hwifversion, cmd.version);
 
 
 	/* Clamp region code to 8-bit since FW spec indicates that it should
 	/* Clamp region code to 8-bit since FW spec indicates that it should
 	 * only ever be 8-bit, even though the field size is 16-bit.  Some
 	 * only ever be 8-bit, even though the field size is 16-bit.  Some
@@ -118,8 +124,10 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
 	}
 	}
 
 
 	/* if it's unidentified region code, use the default (USA) */
 	/* if it's unidentified region code, use the default (USA) */
-	if (i >= MRVDRV_MAX_REGION_CODE)
+	if (i >= MRVDRV_MAX_REGION_CODE) {
 		priv->regioncode = 0x10;
 		priv->regioncode = 0x10;
+		pr_info("unidentified region code; using the default (USA)\n");
+	}
 
 
 	if (priv->current_addr[0] == 0xff)
 	if (priv->current_addr[0] == 0xff)
 		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
 		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
@@ -128,6 +136,7 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
 
 
 	lbtf_geo_init(priv);
 	lbtf_geo_init(priv);
 out:
 out:
+	lbtf_deb_leave(LBTF_DEB_CMD);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -141,13 +150,18 @@ out:
  */
  */
 int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
 int lbtf_set_channel(struct lbtf_private *priv, u8 channel)
 {
 {
+	int ret = 0;
 	struct cmd_ds_802_11_rf_channel cmd;
 	struct cmd_ds_802_11_rf_channel cmd;
 
 
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
 	cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET);
 	cmd.channel = cpu_to_le16(channel);
 	cmd.channel = cpu_to_le16(channel);
 
 
-	return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+	ret = lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd);
+	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
+	return ret;
 }
 }
 
 
 int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
 int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
@@ -155,20 +169,28 @@ int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon)
 	struct cmd_ds_802_11_beacon_set cmd;
 	struct cmd_ds_802_11_beacon_set cmd;
 	int size;
 	int size;
 
 
-	if (beacon->len > MRVL_MAX_BCN_SIZE)
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
+	if (beacon->len > MRVL_MAX_BCN_SIZE) {
+		lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", -1);
 		return -1;
 		return -1;
+	}
 	size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
 	size =  sizeof(cmd) - sizeof(cmd.beacon) + beacon->len;
 	cmd.hdr.size = cpu_to_le16(size);
 	cmd.hdr.size = cpu_to_le16(size);
 	cmd.len = cpu_to_le16(beacon->len);
 	cmd.len = cpu_to_le16(beacon->len);
 	memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
 	memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len);
 
 
 	lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
 	lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size);
+
+	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", 0);
 	return 0;
 	return 0;
 }
 }
 
 
 int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
 int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
-		     int beacon_int) {
+		     int beacon_int)
+{
 	struct cmd_ds_802_11_beacon_control cmd;
 	struct cmd_ds_802_11_beacon_control cmd;
+	lbtf_deb_enter(LBTF_DEB_CMD);
 
 
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -176,6 +198,8 @@ int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable,
 	cmd.beacon_period = cpu_to_le16(beacon_int);
 	cmd.beacon_period = cpu_to_le16(beacon_int);
 
 
 	lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
 	lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd));
+
+	lbtf_deb_leave(LBTF_DEB_CMD);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -183,17 +207,28 @@ static void lbtf_queue_cmd(struct lbtf_private *priv,
 			  struct cmd_ctrl_node *cmdnode)
 			  struct cmd_ctrl_node *cmdnode)
 {
 {
 	unsigned long flags;
 	unsigned long flags;
+	lbtf_deb_enter(LBTF_DEB_HOST);
 
 
-	if (!cmdnode)
-		return;
+	if (!cmdnode) {
+		lbtf_deb_host("QUEUE_CMD: cmdnode is NULL\n");
+		goto qcmd_done;
+	}
 
 
-	if (!cmdnode->cmdbuf->size)
-		return;
+	if (!cmdnode->cmdbuf->size) {
+		lbtf_deb_host("DNLD_CMD: cmd size is zero\n");
+		goto qcmd_done;
+	}
 
 
 	cmdnode->result = 0;
 	cmdnode->result = 0;
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	list_add_tail(&cmdnode->list, &priv->cmdpendingq);
 	list_add_tail(&cmdnode->list, &priv->cmdpendingq);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+	lbtf_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
+		     le16_to_cpu(cmdnode->cmdbuf->command));
+
+qcmd_done:
+	lbtf_deb_leave(LBTF_DEB_HOST);
 }
 }
 
 
 static void lbtf_submit_command(struct lbtf_private *priv,
 static void lbtf_submit_command(struct lbtf_private *priv,
@@ -206,22 +241,33 @@ static void lbtf_submit_command(struct lbtf_private *priv,
 	int timeo = 5 * HZ;
 	int timeo = 5 * HZ;
 	int ret;
 	int ret;
 
 
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	cmd = cmdnode->cmdbuf;
 	cmd = cmdnode->cmdbuf;
 
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	priv->cur_cmd = cmdnode;
 	priv->cur_cmd = cmdnode;
 	cmdsize = le16_to_cpu(cmd->size);
 	cmdsize = le16_to_cpu(cmd->size);
 	command = le16_to_cpu(cmd->command);
 	command = le16_to_cpu(cmd->command);
+
+	lbtf_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
+		     command, le16_to_cpu(cmd->seqnum), cmdsize);
+	lbtf_deb_hex(LBTF_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
+
 	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
 	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 
-	if (ret)
+	if (ret) {
+		pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret);
 		/* Let the timer kick in and retry, and potentially reset
 		/* Let the timer kick in and retry, and potentially reset
 		   the whole thing if the condition persists */
 		   the whole thing if the condition persists */
 		timeo = HZ;
 		timeo = HZ;
+	}
 
 
 	/* Setup the timer after transmit command */
 	/* Setup the timer after transmit command */
 	mod_timer(&priv->command_timer, jiffies + timeo);
 	mod_timer(&priv->command_timer, jiffies + timeo);
+
+	lbtf_deb_leave(LBTF_DEB_HOST);
 }
 }
 
 
 /**
 /**
@@ -231,8 +277,10 @@ static void lbtf_submit_command(struct lbtf_private *priv,
 static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
 static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
 					 struct cmd_ctrl_node *cmdnode)
 					 struct cmd_ctrl_node *cmdnode)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	if (!cmdnode)
 	if (!cmdnode)
-		return;
+		goto cl_ins_out;
 
 
 	cmdnode->callback = NULL;
 	cmdnode->callback = NULL;
 	cmdnode->callback_arg = 0;
 	cmdnode->callback_arg = 0;
@@ -240,6 +288,9 @@ static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
 	memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
 	memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE);
 
 
 	list_add_tail(&cmdnode->list, &priv->cmdfreeq);
 	list_add_tail(&cmdnode->list, &priv->cmdfreeq);
+
+cl_ins_out:
+	lbtf_deb_leave(LBTF_DEB_HOST);
 }
 }
 
 
 static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
 static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv,
@@ -268,29 +319,41 @@ int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv)
 {
 {
 	struct cmd_ds_mac_multicast_addr cmd;
 	struct cmd_ds_mac_multicast_addr cmd;
 
 
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 
 
 	cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
 	cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr);
+
+	lbtf_deb_cmd("MULTICAST_ADR: setting %d addresses\n", cmd.nr_of_adrs);
+
 	memcpy(cmd.maclist, priv->multicastlist,
 	memcpy(cmd.maclist, priv->multicastlist,
 	       priv->nr_of_multicastmacaddr * ETH_ALEN);
 	       priv->nr_of_multicastmacaddr * ETH_ALEN);
 
 
 	lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
 	lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd));
+
+	lbtf_deb_leave(LBTF_DEB_CMD);
 	return 0;
 	return 0;
 }
 }
 
 
 void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
 void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode)
 {
 {
 	struct cmd_ds_set_mode cmd;
 	struct cmd_ds_set_mode cmd;
+	lbtf_deb_enter(LBTF_DEB_WEXT);
 
 
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.mode = cpu_to_le16(mode);
 	cmd.mode = cpu_to_le16(mode);
+	lbtf_deb_wext("Switching to mode: 0x%x\n", mode);
 	lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
 	lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd));
+
+	lbtf_deb_leave(LBTF_DEB_WEXT);
 }
 }
 
 
 void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
 void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
 {
 {
 	struct cmd_ds_set_bssid cmd;
 	struct cmd_ds_set_bssid cmd;
+	lbtf_deb_enter(LBTF_DEB_CMD);
 
 
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.activate = activate ? 1 : 0;
 	cmd.activate = activate ? 1 : 0;
@@ -298,11 +361,13 @@ void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid)
 		memcpy(cmd.bssid, bssid, ETH_ALEN);
 		memcpy(cmd.bssid, bssid, ETH_ALEN);
 
 
 	lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
 	lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd));
+	lbtf_deb_leave(LBTF_DEB_CMD);
 }
 }
 
 
 int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
 int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
 {
 {
 	struct cmd_ds_802_11_mac_address cmd;
 	struct cmd_ds_802_11_mac_address cmd;
+	lbtf_deb_enter(LBTF_DEB_CMD);
 
 
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
@@ -310,6 +375,7 @@ int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr)
 	memcpy(cmd.macadd, mac_addr, ETH_ALEN);
 	memcpy(cmd.macadd, mac_addr, ETH_ALEN);
 
 
 	lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
 	lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd));
+	lbtf_deb_leave(LBTF_DEB_CMD);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -318,6 +384,8 @@ int lbtf_set_radio_control(struct lbtf_private *priv)
 	int ret = 0;
 	int ret = 0;
 	struct cmd_ds_802_11_radio_control cmd;
 	struct cmd_ds_802_11_radio_control cmd;
 
 
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 	cmd.action = cpu_to_le16(CMD_ACT_SET);
 
 
@@ -341,19 +409,28 @@ int lbtf_set_radio_control(struct lbtf_private *priv)
 	else
 	else
 		cmd.control &= cpu_to_le16(~TURN_ON_RF);
 		cmd.control &= cpu_to_le16(~TURN_ON_RF);
 
 
+	lbtf_deb_cmd("RADIO_SET: radio %d, preamble %d\n", priv->radioon,
+		    priv->preamble);
+
 	ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
 	ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd);
+
+	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
 	return ret;
 	return ret;
 }
 }
 
 
 void lbtf_set_mac_control(struct lbtf_private *priv)
 void lbtf_set_mac_control(struct lbtf_private *priv)
 {
 {
 	struct cmd_ds_mac_control cmd;
 	struct cmd_ds_mac_control cmd;
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
 	cmd.action = cpu_to_le16(priv->mac_control);
 	cmd.action = cpu_to_le16(priv->mac_control);
 	cmd.reserved = 0;
 	cmd.reserved = 0;
 
 
 	lbtf_cmd_async(priv, CMD_MAC_CONTROL,
 	lbtf_cmd_async(priv, CMD_MAC_CONTROL,
 		&cmd.hdr, sizeof(cmd));
 		&cmd.hdr, sizeof(cmd));
+
+	lbtf_deb_leave(LBTF_DEB_CMD);
 }
 }
 
 
 /**
 /**
@@ -365,29 +442,43 @@ void lbtf_set_mac_control(struct lbtf_private *priv)
  */
  */
 int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
 int lbtf_allocate_cmd_buffer(struct lbtf_private *priv)
 {
 {
+	int ret = 0;
 	u32 bufsize;
 	u32 bufsize;
 	u32 i;
 	u32 i;
 	struct cmd_ctrl_node *cmdarray;
 	struct cmd_ctrl_node *cmdarray;
 
 
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	/* Allocate and initialize the command array */
 	/* Allocate and initialize the command array */
 	bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
 	bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS;
 	cmdarray = kzalloc(bufsize, GFP_KERNEL);
 	cmdarray = kzalloc(bufsize, GFP_KERNEL);
-	if (!cmdarray)
-		return -1;
+	if (!cmdarray) {
+		lbtf_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n");
+		ret = -1;
+		goto done;
+	}
 	priv->cmd_array = cmdarray;
 	priv->cmd_array = cmdarray;
 
 
 	/* Allocate and initialize each command buffer in the command array */
 	/* Allocate and initialize each command buffer in the command array */
 	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 		cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
 		cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL);
-		if (!cmdarray[i].cmdbuf)
-			return -1;
+		if (!cmdarray[i].cmdbuf) {
+			lbtf_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n");
+			ret = -1;
+			goto done;
+		}
 	}
 	}
 
 
 	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 	for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) {
 		init_waitqueue_head(&cmdarray[i].cmdwait_q);
 		init_waitqueue_head(&cmdarray[i].cmdwait_q);
 		lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
 		lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]);
 	}
 	}
-	return 0;
+
+	ret = 0;
+
+done:
+	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
+	return ret;
 }
 }
 
 
 /**
 /**
@@ -402,9 +493,13 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)
 	struct cmd_ctrl_node *cmdarray;
 	struct cmd_ctrl_node *cmdarray;
 	unsigned int i;
 	unsigned int i;
 
 
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	/* need to check if cmd array is allocated or not */
 	/* need to check if cmd array is allocated or not */
-	if (priv->cmd_array == NULL)
-		return 0;
+	if (priv->cmd_array == NULL) {
+		lbtf_deb_host("FREE_CMD_BUF: cmd_array is NULL\n");
+		goto done;
+	}
 
 
 	cmdarray = priv->cmd_array;
 	cmdarray = priv->cmd_array;
 
 
@@ -418,6 +513,8 @@ int lbtf_free_cmd_buffer(struct lbtf_private *priv)
 	kfree(priv->cmd_array);
 	kfree(priv->cmd_array);
 	priv->cmd_array = NULL;
 	priv->cmd_array = NULL;
 
 
+done:
+	lbtf_deb_leave(LBTF_DEB_HOST);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -433,6 +530,8 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
 	struct cmd_ctrl_node *tempnode;
 	struct cmd_ctrl_node *tempnode;
 	unsigned long flags;
 	unsigned long flags;
 
 
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	if (!priv)
 	if (!priv)
 		return NULL;
 		return NULL;
 
 
@@ -442,11 +541,14 @@ static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv)
 		tempnode = list_first_entry(&priv->cmdfreeq,
 		tempnode = list_first_entry(&priv->cmdfreeq,
 					    struct cmd_ctrl_node, list);
 					    struct cmd_ctrl_node, list);
 		list_del(&tempnode->list);
 		list_del(&tempnode->list);
-	} else
+	} else {
+		lbtf_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n");
 		tempnode = NULL;
 		tempnode = NULL;
+	}
 
 
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 
+	lbtf_deb_leave(LBTF_DEB_HOST);
 	return tempnode;
 	return tempnode;
 }
 }
 
 
@@ -462,16 +564,20 @@ int lbtf_execute_next_command(struct lbtf_private *priv)
 	struct cmd_ctrl_node *cmdnode = NULL;
 	struct cmd_ctrl_node *cmdnode = NULL;
 	struct cmd_header *cmd;
 	struct cmd_header *cmd;
 	unsigned long flags;
 	unsigned long flags;
+	int ret = 0;
 
 
-	/* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the
+	/* Debug group is lbtf_deb_THREAD and not lbtf_deb_HOST, because the
 	 * only caller to us is lbtf_thread() and we get even when a
 	 * only caller to us is lbtf_thread() and we get even when a
 	 * data packet is received */
 	 * data packet is received */
+	lbtf_deb_enter(LBTF_DEB_THREAD);
 
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 
 
 	if (priv->cur_cmd) {
 	if (priv->cur_cmd) {
+		pr_alert("EXEC_NEXT_CMD: already processing command!\n");
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
-		return -1;
+		ret = -1;
+		goto done;
 	}
 	}
 
 
 	if (!list_empty(&priv->cmdpendingq)) {
 	if (!list_empty(&priv->cmdpendingq)) {
@@ -483,11 +589,17 @@ int lbtf_execute_next_command(struct lbtf_private *priv)
 		cmd = cmdnode->cmdbuf;
 		cmd = cmdnode->cmdbuf;
 
 
 		list_del(&cmdnode->list);
 		list_del(&cmdnode->list);
+		lbtf_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
+			    le16_to_cpu(cmd->command));
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		lbtf_submit_command(priv, cmdnode);
 		lbtf_submit_command(priv, cmdnode);
 	} else
 	} else
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
-	return 0;
+
+	ret = 0;
+done:
+	lbtf_deb_leave(LBTF_DEB_THREAD);
+	return ret;
 }
 }
 
 
 static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
 static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
@@ -498,14 +610,22 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
 {
 {
 	struct cmd_ctrl_node *cmdnode;
 	struct cmd_ctrl_node *cmdnode;
 
 
-	if (priv->surpriseremoved)
-		return ERR_PTR(-ENOENT);
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
+	if (priv->surpriseremoved) {
+		lbtf_deb_host("PREP_CMD: card removed\n");
+		cmdnode = ERR_PTR(-ENOENT);
+		goto done;
+	}
 
 
 	cmdnode = lbtf_get_cmd_ctrl_node(priv);
 	cmdnode = lbtf_get_cmd_ctrl_node(priv);
 	if (cmdnode == NULL) {
 	if (cmdnode == NULL) {
+		lbtf_deb_host("PREP_CMD: cmdnode is NULL\n");
+
 		/* Wake up main thread to execute next command */
 		/* Wake up main thread to execute next command */
 		queue_work(lbtf_wq, &priv->cmd_work);
 		queue_work(lbtf_wq, &priv->cmd_work);
-		return ERR_PTR(-ENOBUFS);
+		cmdnode = ERR_PTR(-ENOBUFS);
+		goto done;
 	}
 	}
 
 
 	cmdnode->callback = callback;
 	cmdnode->callback = callback;
@@ -520,17 +640,24 @@ static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv,
 	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
 	cmdnode->cmdbuf->size    = cpu_to_le16(in_cmd_size);
 	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
 	cmdnode->cmdbuf->seqnum  = cpu_to_le16(priv->seqnum);
 	cmdnode->cmdbuf->result  = 0;
 	cmdnode->cmdbuf->result  = 0;
+
+	lbtf_deb_host("PREP_CMD: command 0x%04x\n", command);
+
 	cmdnode->cmdwaitqwoken = 0;
 	cmdnode->cmdwaitqwoken = 0;
 	lbtf_queue_cmd(priv, cmdnode);
 	lbtf_queue_cmd(priv, cmdnode);
 	queue_work(lbtf_wq, &priv->cmd_work);
 	queue_work(lbtf_wq, &priv->cmd_work);
 
 
+ done:
+	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %p", cmdnode);
 	return cmdnode;
 	return cmdnode;
 }
 }
 
 
 void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
 void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command,
 	struct cmd_header *in_cmd, int in_cmd_size)
 	struct cmd_header *in_cmd, int in_cmd_size)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_CMD);
 	__lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
 	__lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0);
+	lbtf_deb_leave(LBTF_DEB_CMD);
 }
 }
 
 
 int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
 int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
@@ -543,30 +670,35 @@ int __lbtf_cmd(struct lbtf_private *priv, uint16_t command,
 	unsigned long flags;
 	unsigned long flags;
 	int ret = 0;
 	int ret = 0;
 
 
+	lbtf_deb_enter(LBTF_DEB_HOST);
+
 	cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
 	cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size,
 				  callback, callback_arg);
 				  callback, callback_arg);
-	if (IS_ERR(cmdnode))
-		return PTR_ERR(cmdnode);
+	if (IS_ERR(cmdnode)) {
+		ret = PTR_ERR(cmdnode);
+		goto done;
+	}
 
 
 	might_sleep();
 	might_sleep();
 	ret = wait_event_interruptible(cmdnode->cmdwait_q,
 	ret = wait_event_interruptible(cmdnode->cmdwait_q,
 				       cmdnode->cmdwaitqwoken);
 				       cmdnode->cmdwaitqwoken);
-       if (ret)	{
-		printk(KERN_DEBUG
-		       "libertastf: command 0x%04x interrupted by signal",
-		       command);
-		return ret;
+	if (ret) {
+		pr_info("PREP_CMD: command 0x%04x interrupted by signal: %d\n",
+			    command, ret);
+		goto done;
 	}
 	}
 
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	ret = cmdnode->result;
 	ret = cmdnode->result;
 	if (ret)
 	if (ret)
-		printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n",
+		pr_info("PREP_CMD: command 0x%04x failed: %d\n",
 			    command, ret);
 			    command, ret);
 
 
 	__lbtf_cleanup_and_insert_cmd(priv, cmdnode);
 	__lbtf_cleanup_and_insert_cmd(priv, cmdnode);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 
+done:
+	lbtf_deb_leave_args(LBTF_DEB_HOST, "ret %d", ret);
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(__lbtf_cmd);
 EXPORT_SYMBOL_GPL(__lbtf_cmd);
@@ -587,6 +719,8 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
 	unsigned long flags;
 	unsigned long flags;
 	uint16_t result;
 	uint16_t result;
 
 
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	mutex_lock(&priv->lock);
 	mutex_lock(&priv->lock);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 
 
@@ -602,7 +736,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
 	result = le16_to_cpu(resp->result);
 	result = le16_to_cpu(resp->result);
 
 
 	if (net_ratelimit())
 	if (net_ratelimit())
-		printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n",
+		pr_info("libertastf: cmd response 0x%04x, seq %d, size %d\n",
 			respcmd, le16_to_cpu(resp->seqnum),
 			respcmd, le16_to_cpu(resp->seqnum),
 			le16_to_cpu(resp->size));
 			le16_to_cpu(resp->size));
 
 
@@ -639,7 +773,7 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
 		switch (respcmd) {
 		switch (respcmd) {
 		case CMD_RET(CMD_GET_HW_SPEC):
 		case CMD_RET(CMD_GET_HW_SPEC):
 		case CMD_RET(CMD_802_11_RESET):
 		case CMD_RET(CMD_802_11_RESET):
-			printk(KERN_DEBUG "libertastf: reset failed\n");
+			pr_info("libertastf: reset failed\n");
 			break;
 			break;
 
 
 		}
 		}
@@ -666,5 +800,6 @@ int lbtf_process_rx_command(struct lbtf_private *priv)
 
 
 done:
 done:
 	mutex_unlock(&priv->lock);
 	mutex_unlock(&priv->lock);
+	lbtf_deb_leave_args(LBTF_DEB_CMD, "ret %d", ret);
 	return ret;
 	return ret;
 }
 }

+ 104 - 0
drivers/net/wireless/libertas_tf/deb_defs.h

@@ -0,0 +1,104 @@
+/**
+  * This header file contains global constant/enum definitions,
+  * global variable declaration.
+  */
+#ifndef _LBS_DEB_DEFS_H_
+#define _LBS_DEB_EFS_H_
+
+#ifndef DRV_NAME
+#define DRV_NAME "libertas_tf"
+#endif
+
+#include <linux/spinlock.h>
+
+#ifdef CONFIG_LIBERTAS_THINFIRM_DEBUG
+#define DEBUG
+#define PROC_DEBUG
+#endif
+
+#define LBTF_DEB_ENTER	0x00000001
+#define LBTF_DEB_LEAVE	0x00000002
+#define LBTF_DEB_MAIN	0x00000004
+#define LBTF_DEB_NET	0x00000008
+#define LBTF_DEB_MESH	0x00000010
+#define LBTF_DEB_WEXT	0x00000020
+#define LBTF_DEB_IOCTL	0x00000040
+#define LBTF_DEB_SCAN	0x00000080
+#define LBTF_DEB_ASSOC	0x00000100
+#define LBTF_DEB_JOIN	0x00000200
+#define LBTF_DEB_11D	0x00000400
+#define LBTF_DEB_DEBUGFS	0x00000800
+#define LBTF_DEB_ETHTOOL	0x00001000
+#define LBTF_DEB_HOST	0x00002000
+#define LBTF_DEB_CMD	0x00004000
+#define LBTF_DEB_RX	0x00008000
+#define LBTF_DEB_TX	0x00010000
+#define LBTF_DEB_USB	0x00020000
+#define LBTF_DEB_CS	0x00040000
+#define LBTF_DEB_FW	0x00080000
+#define LBTF_DEB_THREAD	0x00100000
+#define LBTF_DEB_HEX	0x00200000
+#define LBTF_DEB_SDIO	0x00400000
+#define LBTF_DEB_MACOPS	0x00800000
+
+extern unsigned int lbtf_debug;
+
+
+#ifdef DEBUG
+#define LBTF_DEB_LL(grp, grpnam, fmt, args...) \
+do { if ((lbtf_debug & (grp)) == (grp)) \
+  printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \
+         in_interrupt() ? " (INT)" : "", ## args); } while (0)
+#else
+#define LBTF_DEB_LL(grp, grpnam, fmt, args...) do {} while (0)
+#endif
+
+#define lbtf_deb_enter(grp) \
+  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s()\n", __func__);
+#define lbtf_deb_enter_args(grp, fmt, args...) \
+  LBTF_DEB_LL(grp | LBTF_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args);
+#define lbtf_deb_leave(grp) \
+  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s()\n", __func__);
+#define lbtf_deb_leave_args(grp, fmt, args...) \
+  LBTF_DEB_LL(grp | LBTF_DEB_LEAVE, " leave", "%s(), " fmt "\n", \
+  __func__, ##args);
+#define lbtf_deb_main(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MAIN, " main", fmt, ##args)
+#define lbtf_deb_net(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_NET, " net", fmt, ##args)
+#define lbtf_deb_mesh(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MESH, " mesh", fmt, ##args)
+#define lbtf_deb_wext(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_WEXT, " wext", fmt, ##args)
+#define lbtf_deb_ioctl(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_IOCTL, " ioctl", fmt, ##args)
+#define lbtf_deb_scan(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SCAN, " scan", fmt, ##args)
+#define lbtf_deb_assoc(fmt, args...)     LBTF_DEB_LL(LBTF_DEB_ASSOC, " assoc", fmt, ##args)
+#define lbtf_deb_join(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_JOIN, " join", fmt, ##args)
+#define lbtf_deb_11d(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_11D, " 11d", fmt, ##args)
+#define lbtf_deb_debugfs(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_DEBUGFS, " debugfs", fmt, ##args)
+#define lbtf_deb_ethtool(fmt, args...)   LBTF_DEB_LL(LBTF_DEB_ETHTOOL, " ethtool", fmt, ##args)
+#define lbtf_deb_host(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_HOST, " host", fmt, ##args)
+#define lbtf_deb_cmd(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_CMD, " cmd", fmt, ##args)
+#define lbtf_deb_rx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_RX, " rx", fmt, ##args)
+#define lbtf_deb_tx(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_TX, " tx", fmt, ##args)
+#define lbtf_deb_fw(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_FW, " fw", fmt, ##args)
+#define lbtf_deb_usb(fmt, args...)       LBTF_DEB_LL(LBTF_DEB_USB, " usb", fmt, ##args)
+#define lbtf_deb_usbd(dev, fmt, args...) LBTF_DEB_LL(LBTF_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
+#define lbtf_deb_cs(fmt, args...)        LBTF_DEB_LL(LBTF_DEB_CS, " cs", fmt, ##args)
+#define lbtf_deb_thread(fmt, args...)    LBTF_DEB_LL(LBTF_DEB_THREAD, " thread", fmt, ##args)
+#define lbtf_deb_sdio(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_SDIO, " thread", fmt, ##args)
+#define lbtf_deb_macops(fmt, args...)      LBTF_DEB_LL(LBTF_DEB_MACOPS, " thread", fmt, ##args)
+
+#ifdef DEBUG
+static inline void lbtf_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
+{
+	char newprompt[32];
+
+	if (len &&
+	    (lbtf_debug & LBTF_DEB_HEX) &&
+	    (lbtf_debug & grp))	{
+		snprintf(newprompt, sizeof(newprompt), DRV_NAME " %s: ", prompt);
+		print_hex_dump_bytes(prompt, DUMP_PREFIX_NONE, buf, len);
+	}
+}
+#else
+#define lbtf_deb_hex(grp, prompt, buf, len)	do {} while (0)
+#endif
+
+#endif

+ 210 - 41
drivers/net/wireless/libertas_tf/if_usb.c

@@ -7,6 +7,13 @@
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  your option) any later version.
  *  your option) any later version.
  */
  */
+#define DRV_NAME "lbtf_usb"
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "libertas_tf.h"
+#include "if_usb.h"
+
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/firmware.h>
@@ -14,10 +21,8 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
 #include <linux/usb.h>
 
 
-#define DRV_NAME "lbtf_usb"
-
-#include "libertas_tf.h"
-#include "if_usb.h"
+#define INSANEDEBUG	0
+#define lbtf_deb_usb2(...) do { if (INSANEDEBUG) lbtf_deb_usbd(__VA_ARGS__); } while (0)
 
 
 #define MESSAGE_HEADER_LEN	4
 #define MESSAGE_HEADER_LEN	4
 
 
@@ -53,9 +58,14 @@ static int if_usb_reset_device(struct if_usb_card *cardp);
  */
  */
 static void if_usb_write_bulk_callback(struct urb *urb)
 static void if_usb_write_bulk_callback(struct urb *urb)
 {
 {
-	if (urb->status != 0)
-		printk(KERN_INFO "libertastf: URB in failure status: %d\n",
-		       urb->status);
+	if (urb->status != 0) {
+		/* print the failure status number for debug */
+		pr_info("URB in failure status: %d\n", urb->status);
+	} else {
+		lbtf_deb_usb2(&urb->dev->dev, "URB status is successful\n");
+		lbtf_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n",
+			     urb->actual_length);
+	}
 }
 }
 
 
 /**
 /**
@@ -65,6 +75,8 @@ static void if_usb_write_bulk_callback(struct urb *urb)
  */
  */
 static void if_usb_free(struct if_usb_card *cardp)
 static void if_usb_free(struct if_usb_card *cardp)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_USB);
+
 	/* Unlink tx & rx urb */
 	/* Unlink tx & rx urb */
 	usb_kill_urb(cardp->tx_urb);
 	usb_kill_urb(cardp->tx_urb);
 	usb_kill_urb(cardp->rx_urb);
 	usb_kill_urb(cardp->rx_urb);
@@ -81,6 +93,8 @@ static void if_usb_free(struct if_usb_card *cardp)
 
 
 	kfree(cardp->ep_out_buf);
 	kfree(cardp->ep_out_buf);
 	cardp->ep_out_buf = NULL;
 	cardp->ep_out_buf = NULL;
+
+	lbtf_deb_leave(LBTF_DEB_USB);
 }
 }
 
 
 static void if_usb_setup_firmware(struct lbtf_private *priv)
 static void if_usb_setup_firmware(struct lbtf_private *priv)
@@ -88,23 +102,33 @@ static void if_usb_setup_firmware(struct lbtf_private *priv)
 	struct if_usb_card *cardp = priv->card;
 	struct if_usb_card *cardp = priv->card;
 	struct cmd_ds_set_boot2_ver b2_cmd;
 	struct cmd_ds_set_boot2_ver b2_cmd;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
+
 	if_usb_submit_rx_urb(cardp);
 	if_usb_submit_rx_urb(cardp);
 	b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
 	b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd));
 	b2_cmd.action = 0;
 	b2_cmd.action = 0;
 	b2_cmd.version = cardp->boot2_version;
 	b2_cmd.version = cardp->boot2_version;
 
 
 	if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
 	if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd))
-		printk(KERN_INFO "libertastf: setting boot2 version failed\n");
+		lbtf_deb_usb("Setting boot2 version failed\n");
+
+	lbtf_deb_leave(LBTF_DEB_USB);
 }
 }
 
 
 static void if_usb_fw_timeo(unsigned long priv)
 static void if_usb_fw_timeo(unsigned long priv)
 {
 {
 	struct if_usb_card *cardp = (void *)priv;
 	struct if_usb_card *cardp = (void *)priv;
 
 
-	if (!cardp->fwdnldover)
+	lbtf_deb_enter(LBTF_DEB_USB);
+	if (!cardp->fwdnldover) {
 		/* Download timed out */
 		/* Download timed out */
 		cardp->priv->surpriseremoved = 1;
 		cardp->priv->surpriseremoved = 1;
+		pr_err("Download timed out\n");
+	} else {
+		lbtf_deb_usb("Download complete, no event. Assuming success\n");
+	}
 	wake_up(&cardp->fw_wq);
 	wake_up(&cardp->fw_wq);
+	lbtf_deb_leave(LBTF_DEB_USB);
 }
 }
 
 
 /**
 /**
@@ -125,11 +149,14 @@ static int if_usb_probe(struct usb_interface *intf,
 	struct if_usb_card *cardp;
 	struct if_usb_card *cardp;
 	int i;
 	int i;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
 	udev = interface_to_usbdev(intf);
 	udev = interface_to_usbdev(intf);
 
 
 	cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
 	cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL);
-	if (!cardp)
+	if (!cardp) {
+		pr_err("Out of memory allocating private data.\n");
 		goto error;
 		goto error;
+	}
 
 
 	setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
 	setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp);
 	init_waitqueue_head(&cardp->fw_wq);
 	init_waitqueue_head(&cardp->fw_wq);
@@ -137,38 +164,62 @@ static int if_usb_probe(struct usb_interface *intf,
 	cardp->udev = udev;
 	cardp->udev = udev;
 	iface_desc = intf->cur_altsetting;
 	iface_desc = intf->cur_altsetting;
 
 
+	lbtf_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X"
+		     " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
+		     le16_to_cpu(udev->descriptor.bcdUSB),
+		     udev->descriptor.bDeviceClass,
+		     udev->descriptor.bDeviceSubClass,
+		     udev->descriptor.bDeviceProtocol);
+
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 		endpoint = &iface_desc->endpoint[i].desc;
 		endpoint = &iface_desc->endpoint[i].desc;
 		if (usb_endpoint_is_bulk_in(endpoint)) {
 		if (usb_endpoint_is_bulk_in(endpoint)) {
 			cardp->ep_in_size =
 			cardp->ep_in_size =
 				le16_to_cpu(endpoint->wMaxPacketSize);
 				le16_to_cpu(endpoint->wMaxPacketSize);
 			cardp->ep_in = usb_endpoint_num(endpoint);
 			cardp->ep_in = usb_endpoint_num(endpoint);
+
+			lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in);
+			lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size);
 		} else if (usb_endpoint_is_bulk_out(endpoint)) {
 		} else if (usb_endpoint_is_bulk_out(endpoint)) {
 			cardp->ep_out_size =
 			cardp->ep_out_size =
 				le16_to_cpu(endpoint->wMaxPacketSize);
 				le16_to_cpu(endpoint->wMaxPacketSize);
 			cardp->ep_out = usb_endpoint_num(endpoint);
 			cardp->ep_out = usb_endpoint_num(endpoint);
+
+			lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out);
+			lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n",
+			              cardp->ep_out_size);
 		}
 		}
 	}
 	}
-	if (!cardp->ep_out_size || !cardp->ep_in_size)
+	if (!cardp->ep_out_size || !cardp->ep_in_size) {
+		lbtf_deb_usbd(&udev->dev, "Endpoints not found\n");
 		/* Endpoints not found */
 		/* Endpoints not found */
 		goto dealloc;
 		goto dealloc;
+	}
 
 
 	cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!cardp->rx_urb)
+	if (!cardp->rx_urb) {
+		lbtf_deb_usbd(&udev->dev, "Rx URB allocation failed\n");
 		goto dealloc;
 		goto dealloc;
+	}
 
 
 	cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
 	cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!cardp->tx_urb)
+	if (!cardp->tx_urb) {
+		lbtf_deb_usbd(&udev->dev, "Tx URB allocation failed\n");
 		goto dealloc;
 		goto dealloc;
+	}
 
 
 	cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
 	cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL);
-	if (!cardp->cmd_urb)
+	if (!cardp->cmd_urb) {
+		lbtf_deb_usbd(&udev->dev, "Cmd URB allocation failed\n");
 		goto dealloc;
 		goto dealloc;
+	}
 
 
 	cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
 	cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
 				    GFP_KERNEL);
 				    GFP_KERNEL);
-	if (!cardp->ep_out_buf)
+	if (!cardp->ep_out_buf) {
+		lbtf_deb_usbd(&udev->dev, "Could not allocate buffer\n");
 		goto dealloc;
 		goto dealloc;
+	}
 
 
 	priv = lbtf_add_card(cardp, &udev->dev);
 	priv = lbtf_add_card(cardp, &udev->dev);
 	if (!priv)
 	if (!priv)
@@ -189,6 +240,7 @@ static int if_usb_probe(struct usb_interface *intf,
 dealloc:
 dealloc:
 	if_usb_free(cardp);
 	if_usb_free(cardp);
 error:
 error:
+lbtf_deb_leave(LBTF_DEB_MAIN);
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
 
 
@@ -202,6 +254,8 @@ static void if_usb_disconnect(struct usb_interface *intf)
 	struct if_usb_card *cardp = usb_get_intfdata(intf);
 	struct if_usb_card *cardp = usb_get_intfdata(intf);
 	struct lbtf_private *priv = (struct lbtf_private *) cardp->priv;
 	struct lbtf_private *priv = (struct lbtf_private *) cardp->priv;
 
 
+	lbtf_deb_enter(LBTF_DEB_MAIN);
+
 	if_usb_reset_device(cardp);
 	if_usb_reset_device(cardp);
 
 
 	if (priv)
 	if (priv)
@@ -212,6 +266,8 @@ static void if_usb_disconnect(struct usb_interface *intf)
 
 
 	usb_set_intfdata(intf, NULL);
 	usb_set_intfdata(intf, NULL);
 	usb_put_dev(interface_to_usbdev(intf));
 	usb_put_dev(interface_to_usbdev(intf));
+
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 }
 
 
 /**
 /**
@@ -226,6 +282,8 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
 	struct fwdata *fwdata = cardp->ep_out_buf;
 	struct fwdata *fwdata = cardp->ep_out_buf;
 	u8 *firmware = (u8 *) cardp->fw->data;
 	u8 *firmware = (u8 *) cardp->fw->data;
 
 
+	lbtf_deb_enter(LBTF_DEB_FW);
+
 	/* If we got a CRC failure on the last block, back
 	/* If we got a CRC failure on the last block, back
 	   up and retry it */
 	   up and retry it */
 	if (!cardp->CRC_OK) {
 	if (!cardp->CRC_OK) {
@@ -233,6 +291,9 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
 		cardp->fwseqnum--;
 		cardp->fwseqnum--;
 	}
 	}
 
 
+	lbtf_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n",
+		     cardp->totalbytes);
+
 	/* struct fwdata (which we sent to the card) has an
 	/* struct fwdata (which we sent to the card) has an
 	   extra __le32 field in between the header and the data,
 	   extra __le32 field in between the header and the data,
 	   which is not in the struct fwheader in the actual
 	   which is not in the struct fwheader in the actual
@@ -246,18 +307,33 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
 	memcpy(fwdata->data, &firmware[cardp->totalbytes],
 	memcpy(fwdata->data, &firmware[cardp->totalbytes],
 	       le32_to_cpu(fwdata->hdr.datalength));
 	       le32_to_cpu(fwdata->hdr.datalength));
 
 
+	lbtf_deb_usb2(&cardp->udev->dev, "Data length = %d\n",
+		     le32_to_cpu(fwdata->hdr.datalength));
+
 	fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
 	fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum);
 	cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
 	cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength);
 
 
 	usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
 	usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) +
 		     le32_to_cpu(fwdata->hdr.datalength), 0);
 		     le32_to_cpu(fwdata->hdr.datalength), 0);
 
 
-	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK))
+	if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) {
+		lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n");
+		lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n",
+			     cardp->fwseqnum, cardp->totalbytes);
+	} else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) {
+		lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n");
+		lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n");
+
 		/* Host has finished FW downloading
 		/* Host has finished FW downloading
 		 * Donwloading FW JUMP BLOCK
 		 * Donwloading FW JUMP BLOCK
 		 */
 		 */
 		cardp->fwfinalblk = 1;
 		cardp->fwfinalblk = 1;
+	}
 
 
+	lbtf_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n",
+		     cardp->totalbytes);
+
+	lbtf_deb_leave(LBTF_DEB_FW);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -266,6 +342,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
 	struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
 	struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4;
 	int ret;
 	int ret;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
+
 	*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 	*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 
 
 	cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
 	cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET);
@@ -280,6 +358,8 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
 	ret = usb_reset_device(cardp->udev);
 	ret = usb_reset_device(cardp->udev);
 	msleep(100);
 	msleep(100);
 
 
+	lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
+
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(if_usb_reset_device);
 EXPORT_SYMBOL_GPL(if_usb_reset_device);
@@ -297,11 +377,15 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device);
 static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
 static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
 			uint16_t nb, u8 data)
 			uint16_t nb, u8 data)
 {
 {
+	int ret = -1;
 	struct urb *urb;
 	struct urb *urb;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
 	/* check if device is removed */
 	/* check if device is removed */
-	if (cardp->priv->surpriseremoved)
-		return -1;
+	if (cardp->priv->surpriseremoved) {
+		lbtf_deb_usbd(&cardp->udev->dev, "Device removed\n");
+		goto tx_ret;
+	}
 
 
 	if (data)
 	if (data)
 		urb = cardp->tx_urb;
 		urb = cardp->tx_urb;
@@ -315,19 +399,34 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload,
 
 
 	urb->transfer_flags |= URB_ZERO_PACKET;
 	urb->transfer_flags |= URB_ZERO_PACKET;
 
 
-	if (usb_submit_urb(urb, GFP_ATOMIC))
-		return -1;
-	return 0;
+	if (usb_submit_urb(urb, GFP_ATOMIC)) {
+		lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret);
+		goto tx_ret;
+	}
+
+	lbtf_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n");
+
+	ret = 0;
+
+tx_ret:
+	lbtf_deb_leave(LBTF_DEB_USB);
+	return ret;
 }
 }
 
 
 static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
 static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
 				  void (*callbackfn)(struct urb *urb))
 				  void (*callbackfn)(struct urb *urb))
 {
 {
 	struct sk_buff *skb;
 	struct sk_buff *skb;
+	int ret = -1;
+
+	lbtf_deb_enter(LBTF_DEB_USB);
 
 
 	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
 	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
-	if (!skb)
+	if (!skb) {
+		pr_err("No free skb\n");
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return -1;
 		return -1;
+	}
 
 
 	cardp->rx_skb = skb;
 	cardp->rx_skb = skb;
 
 
@@ -339,12 +438,19 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
 
 
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
 	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
 
 
-	if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) {
+	lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb);
+	ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC);
+	if (ret) {
+		lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret);
 		kfree_skb(skb);
 		kfree_skb(skb);
 		cardp->rx_skb = NULL;
 		cardp->rx_skb = NULL;
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return -1;
 		return -1;
-	} else
+	} else {
+		lbtf_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n");
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return 0;
 		return 0;
+	}
 }
 }
 
 
 static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
 static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp)
@@ -364,8 +470,12 @@ static void if_usb_receive_fwload(struct urb *urb)
 	struct fwsyncheader *syncfwheader;
 	struct fwsyncheader *syncfwheader;
 	struct bootcmdresp bcmdresp;
 	struct bootcmdresp bcmdresp;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
 	if (urb->status) {
 	if (urb->status) {
+		lbtf_deb_usbd(&cardp->udev->dev,
+			     "URB status is failed during fw load\n");
 		kfree_skb(skb);
 		kfree_skb(skb);
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 		return;
 	}
 	}
 
 
@@ -373,12 +483,17 @@ static void if_usb_receive_fwload(struct urb *urb)
 		__le32 *tmp = (__le32 *)(skb->data);
 		__le32 *tmp = (__le32 *)(skb->data);
 
 
 		if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
 		if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) &&
-		    tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY))
+		    tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) {
 			/* Firmware ready event received */
 			/* Firmware ready event received */
+			pr_info("Firmware ready event received\n");
 			wake_up(&cardp->fw_wq);
 			wake_up(&cardp->fw_wq);
-		else
+		} else {
+			lbtf_deb_usb("Waiting for confirmation; got %x %x\n",
+				    le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1]));
 			if_usb_submit_rx_urb_fwload(cardp);
 			if_usb_submit_rx_urb_fwload(cardp);
+		}
 		kfree_skb(skb);
 		kfree_skb(skb);
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 		return;
 	}
 	}
 	if (cardp->bootcmdresp <= 0) {
 	if (cardp->bootcmdresp <= 0) {
@@ -389,34 +504,60 @@ static void if_usb_receive_fwload(struct urb *urb)
 			if_usb_submit_rx_urb_fwload(cardp);
 			if_usb_submit_rx_urb_fwload(cardp);
 			cardp->bootcmdresp = 1;
 			cardp->bootcmdresp = 1;
 			/* Received valid boot command response */
 			/* Received valid boot command response */
+			lbtf_deb_usbd(&cardp->udev->dev,
+				     "Received valid boot command response\n");
+			lbtf_deb_leave(LBTF_DEB_USB);
 			return;
 			return;
 		}
 		}
 		if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
 		if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) {
 			if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
 			if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) ||
 			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
 			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) ||
-			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION))
+			    bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) {
+				if (!cardp->bootcmdresp)
+					pr_info("Firmware already seems alive; resetting\n");
 				cardp->bootcmdresp = -1;
 				cardp->bootcmdresp = -1;
-		} else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB &&
-			   bcmdresp.result == BOOT_CMD_RESP_OK)
+			} else {
+				pr_info("boot cmd response wrong magic number (0x%x)\n",
+					    le32_to_cpu(bcmdresp.magic));
+			}
+		} else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) {
+			pr_info("boot cmd response cmd_tag error (%d)\n",
+				    bcmdresp.cmd);
+		} else if (bcmdresp.result != BOOT_CMD_RESP_OK) {
+			pr_info("boot cmd response result error (%d)\n",
+				    bcmdresp.result);
+		} else {
 			cardp->bootcmdresp = 1;
 			cardp->bootcmdresp = 1;
+			lbtf_deb_usbd(&cardp->udev->dev,
+				     "Received valid boot command response\n");
+		}
 
 
 		kfree_skb(skb);
 		kfree_skb(skb);
 		if_usb_submit_rx_urb_fwload(cardp);
 		if_usb_submit_rx_urb_fwload(cardp);
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 		return;
 	}
 	}
 
 
 	syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
 	syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC);
 	if (!syncfwheader) {
 	if (!syncfwheader) {
+		lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
 		kfree_skb(skb);
 		kfree_skb(skb);
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 		return;
 	}
 	}
 
 
 	memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader));
 	memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader));
 
 
-	if (!syncfwheader->cmd)
+	if (!syncfwheader->cmd) {
+		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
+		lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
+			     le32_to_cpu(syncfwheader->seqnum));
 		cardp->CRC_OK = 1;
 		cardp->CRC_OK = 1;
-	else
+	} else {
+		lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n");
 		cardp->CRC_OK = 0;
 		cardp->CRC_OK = 0;
+	}
+
 	kfree_skb(skb);
 	kfree_skb(skb);
 
 
 	/* reschedule timer for 200ms hence */
 	/* reschedule timer for 200ms hence */
@@ -434,6 +575,7 @@ static void if_usb_receive_fwload(struct urb *urb)
 
 
 	kfree(syncfwheader);
 	kfree(syncfwheader);
 
 
+	lbtf_deb_leave(LBTF_DEB_USB);
 	return;
 	return;
 }
 }
 
 
@@ -445,6 +587,7 @@ static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb,
 {
 {
 	if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
 	if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN
 	    || recvlength < MRVDRV_MIN_PKT_LEN) {
 	    || recvlength < MRVDRV_MIN_PKT_LEN) {
+		lbtf_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n");
 		kfree_skb(skb);
 		kfree_skb(skb);
 		return;
 		return;
 	}
 	}
@@ -460,6 +603,8 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
 				      struct lbtf_private *priv)
 				      struct lbtf_private *priv)
 {
 {
 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
 	if (recvlength > LBS_CMD_BUFFER_SIZE) {
+		lbtf_deb_usbd(&cardp->udev->dev,
+			     "The receive buffer is too large\n");
 		kfree_skb(skb);
 		kfree_skb(skb);
 		return;
 		return;
 	}
 	}
@@ -489,16 +634,24 @@ static void if_usb_receive(struct urb *urb)
 	uint32_t recvtype = 0;
 	uint32_t recvtype = 0;
 	__le32 *pkt = (__le32 *) skb->data;
 	__le32 *pkt = (__le32 *) skb->data;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
+
 	if (recvlength) {
 	if (recvlength) {
 		if (urb->status) {
 		if (urb->status) {
+			lbtf_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n",
+				     urb->status);
 			kfree_skb(skb);
 			kfree_skb(skb);
 			goto setup_for_next;
 			goto setup_for_next;
 		}
 		}
 
 
 		recvbuff = skb->data;
 		recvbuff = skb->data;
 		recvtype = le32_to_cpu(pkt[0]);
 		recvtype = le32_to_cpu(pkt[0]);
+		lbtf_deb_usbd(&cardp->udev->dev,
+			    "Recv length = 0x%x, Recv type = 0x%X\n",
+			    recvlength, recvtype);
 	} else if (urb->status) {
 	} else if (urb->status) {
 		kfree_skb(skb);
 		kfree_skb(skb);
+		lbtf_deb_leave(LBTF_DEB_USB);
 		return;
 		return;
 	}
 	}
 
 
@@ -515,6 +668,7 @@ static void if_usb_receive(struct urb *urb)
 	{
 	{
 		/* Event cause handling */
 		/* Event cause handling */
 		u32 event_cause = le32_to_cpu(pkt[1]);
 		u32 event_cause = le32_to_cpu(pkt[1]);
+		lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause);
 
 
 		/* Icky undocumented magic special case */
 		/* Icky undocumented magic special case */
 		if (event_cause & 0xffff0000) {
 		if (event_cause & 0xffff0000) {
@@ -529,21 +683,22 @@ static void if_usb_receive(struct urb *urb)
 		} else if (event_cause == LBTF_EVENT_BCN_SENT)
 		} else if (event_cause == LBTF_EVENT_BCN_SENT)
 			lbtf_bcn_sent(priv);
 			lbtf_bcn_sent(priv);
 		else
 		else
-			printk(KERN_DEBUG
+			lbtf_deb_usbd(&cardp->udev->dev,
 			       "Unsupported notification %d received\n",
 			       "Unsupported notification %d received\n",
 			       event_cause);
 			       event_cause);
 		kfree_skb(skb);
 		kfree_skb(skb);
 		break;
 		break;
 	}
 	}
 	default:
 	default:
-		printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n",
-			     recvtype);
+		lbtf_deb_usbd(&cardp->udev->dev,
+		         "libertastf: unknown command type 0x%X\n", recvtype);
 		kfree_skb(skb);
 		kfree_skb(skb);
 		break;
 		break;
 	}
 	}
 
 
 setup_for_next:
 setup_for_next:
 	if_usb_submit_rx_urb(cardp);
 	if_usb_submit_rx_urb(cardp);
+	lbtf_deb_leave(LBTF_DEB_USB);
 }
 }
 
 
 /**
 /**
@@ -562,6 +717,9 @@ static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type,
 	struct if_usb_card *cardp = priv->card;
 	struct if_usb_card *cardp = priv->card;
 	u8 data = 0;
 	u8 data = 0;
 
 
+	lbtf_deb_usbd(&cardp->udev->dev, "*** type = %u\n", type);
+	lbtf_deb_usbd(&cardp->udev->dev, "size after = %d\n", nb);
+
 	if (type == MVMS_CMD) {
 	if (type == MVMS_CMD) {
 		*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 		*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 	} else {
 	} else {
@@ -639,8 +797,10 @@ static int check_fwfile_format(const u8 *data, u32 totlen)
 	} while (!exit);
 	} while (!exit);
 
 
 	if (ret)
 	if (ret)
-		printk(KERN_INFO
-		       "libertastf: firmware file format check failed\n");
+		pr_err("firmware file format check FAIL\n");
+	else
+		lbtf_deb_fw("firmware file format check PASS\n");
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -651,10 +811,12 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
 	static int reset_count = 10;
 	static int reset_count = 10;
 	int ret = 0;
 	int ret = 0;
 
 
+	lbtf_deb_enter(LBTF_DEB_USB);
+
 	ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
 	ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev);
 	if (ret < 0) {
 	if (ret < 0) {
-		printk(KERN_INFO "libertastf: firmware %s not found\n",
-		       lbtf_fw_name);
+		pr_err("request_firmware() failed with %#x\n", ret);
+		pr_err("firmware %s not found\n", lbtf_fw_name);
 		goto done;
 		goto done;
 	}
 	}
 
 
@@ -663,6 +825,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp)
 
 
 restart:
 restart:
 	if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
 	if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
+		lbtf_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
 		ret = -1;
 		ret = -1;
 		goto release_fw;
 		goto release_fw;
 	}
 	}
@@ -709,14 +872,13 @@ restart:
 	usb_kill_urb(cardp->rx_urb);
 	usb_kill_urb(cardp->rx_urb);
 
 
 	if (!cardp->fwdnldover) {
 	if (!cardp->fwdnldover) {
-		printk(KERN_INFO "libertastf: failed to load fw,"
-				 " resetting device!\n");
+		pr_info("failed to load fw, resetting device!\n");
 		if (--reset_count >= 0) {
 		if (--reset_count >= 0) {
 			if_usb_reset_device(cardp);
 			if_usb_reset_device(cardp);
 			goto restart;
 			goto restart;
 		}
 		}
 
 
-		printk(KERN_INFO "libertastf: fw download failure\n");
+		pr_info("FW download failure, time = %d ms\n", i * 100);
 		ret = -1;
 		ret = -1;
 		goto release_fw;
 		goto release_fw;
 	}
 	}
@@ -730,6 +892,7 @@ restart:
 	if_usb_setup_firmware(cardp->priv);
 	if_usb_setup_firmware(cardp->priv);
 
 
  done:
  done:
+	lbtf_deb_leave_args(LBTF_DEB_USB, "ret %d", ret);
 	return ret;
 	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(if_usb_prog_firmware);
 EXPORT_SYMBOL_GPL(if_usb_prog_firmware);
@@ -751,13 +914,19 @@ static int __init if_usb_init_module(void)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
+	lbtf_deb_enter(LBTF_DEB_MAIN);
+
 	ret = usb_register(&if_usb_driver);
 	ret = usb_register(&if_usb_driver);
+
+	lbtf_deb_leave_args(LBTF_DEB_MAIN, "ret %d", ret);
 	return ret;
 	return ret;
 }
 }
 
 
 static void __exit if_usb_exit_module(void)
 static void __exit if_usb_exit_module(void)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_MAIN);
 	usb_deregister(&if_usb_driver);
 	usb_deregister(&if_usb_driver);
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 }
 
 
 module_init(if_usb_init_module);
 module_init(if_usb_init_module);

+ 2 - 0
drivers/net/wireless/libertas_tf/libertas_tf.h

@@ -13,6 +13,8 @@
 #include <linux/kthread.h>
 #include <linux/kthread.h>
 #include <net/mac80211.h>
 #include <net/mac80211.h>
 
 
+#include "deb_defs.h"
+
 #ifndef DRV_NAME
 #ifndef DRV_NAME
 #define DRV_NAME "libertas_tf"
 #define DRV_NAME "libertas_tf"
 #endif
 #endif

+ 85 - 6
drivers/net/wireless/libertas_tf/main.c

@@ -7,10 +7,12 @@
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  the Free Software Foundation; either version 2 of the License, or (at
  *  your option) any later version.
  *  your option) any later version.
  */
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
+#include <linux/etherdevice.h>
 #include "libertas_tf.h"
 #include "libertas_tf.h"
-#include "linux/etherdevice.h"
 
 
 #define DRIVER_RELEASE_VERSION "004.p0"
 #define DRIVER_RELEASE_VERSION "004.p0"
 /* thinfirm version: 5.132.X.pX */
 /* thinfirm version: 5.132.X.pX */
@@ -18,7 +20,17 @@
 #define LBTF_FW_VER_MAX		0x0584ffff
 #define LBTF_FW_VER_MAX		0x0584ffff
 #define QOS_CONTROL_LEN		2
 #define QOS_CONTROL_LEN		2
 
 
-static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION;
+/* Module parameters */
+unsigned int lbtf_debug;
+EXPORT_SYMBOL_GPL(lbtf_debug);
+module_param_named(libertas_tf_debug, lbtf_debug, int, 0644);
+
+static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION
+#ifdef DEBUG
+	"-dbg"
+#endif
+	"";
+
 struct workqueue_struct *lbtf_wq;
 struct workqueue_struct *lbtf_wq;
 
 
 static const struct ieee80211_channel lbtf_channels[] = {
 static const struct ieee80211_channel lbtf_channels[] = {
@@ -81,6 +93,9 @@ static void lbtf_cmd_work(struct work_struct *work)
 {
 {
 	struct lbtf_private *priv = container_of(work, struct lbtf_private,
 	struct lbtf_private *priv = container_of(work, struct lbtf_private,
 					 cmd_work);
 					 cmd_work);
+
+	lbtf_deb_enter(LBTF_DEB_CMD);
+
 	spin_lock_irq(&priv->driver_lock);
 	spin_lock_irq(&priv->driver_lock);
 	/* command response? */
 	/* command response? */
 	if (priv->cmd_response_rxed) {
 	if (priv->cmd_response_rxed) {
@@ -108,11 +123,16 @@ static void lbtf_cmd_work(struct work_struct *work)
 	priv->cmd_timed_out = 0;
 	priv->cmd_timed_out = 0;
 	spin_unlock_irq(&priv->driver_lock);
 	spin_unlock_irq(&priv->driver_lock);
 
 
-	if (!priv->fw_ready)
+	if (!priv->fw_ready) {
+		lbtf_deb_leave_args(LBTF_DEB_CMD, "fw not ready");
 		return;
 		return;
+	}
+
 	/* Execute the next command */
 	/* Execute the next command */
 	if (!priv->cur_cmd)
 	if (!priv->cur_cmd)
 		lbtf_execute_next_command(priv);
 		lbtf_execute_next_command(priv);
+
+	lbtf_deb_leave(LBTF_DEB_CMD);
 }
 }
 
 
 /**
 /**
@@ -126,6 +146,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)
 {
 {
 	int ret = -1;
 	int ret = -1;
 
 
+	lbtf_deb_enter(LBTF_DEB_FW);
 	/*
 	/*
 	 * Read priv address from HW
 	 * Read priv address from HW
 	 */
 	 */
@@ -141,6 +162,7 @@ static int lbtf_setup_firmware(struct lbtf_private *priv)
 
 
 	ret = 0;
 	ret = 0;
 done:
 done:
+	lbtf_deb_leave_args(LBTF_DEB_FW, "ret: %d", ret);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -152,6 +174,7 @@ static void command_timer_fn(unsigned long data)
 {
 {
 	struct lbtf_private *priv = (struct lbtf_private *)data;
 	struct lbtf_private *priv = (struct lbtf_private *)data;
 	unsigned long flags;
 	unsigned long flags;
+	lbtf_deb_enter(LBTF_DEB_CMD);
 
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 
 
@@ -168,10 +191,12 @@ static void command_timer_fn(unsigned long data)
 	queue_work(lbtf_wq, &priv->cmd_work);
 	queue_work(lbtf_wq, &priv->cmd_work);
 out:
 out:
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
+	lbtf_deb_leave(LBTF_DEB_CMD);
 }
 }
 
 
 static int lbtf_init_adapter(struct lbtf_private *priv)
 static int lbtf_init_adapter(struct lbtf_private *priv)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_MAIN);
 	memset(priv->current_addr, 0xff, ETH_ALEN);
 	memset(priv->current_addr, 0xff, ETH_ALEN);
 	mutex_init(&priv->lock);
 	mutex_init(&priv->lock);
 
 
@@ -188,13 +213,16 @@ static int lbtf_init_adapter(struct lbtf_private *priv)
 	if (lbtf_allocate_cmd_buffer(priv))
 	if (lbtf_allocate_cmd_buffer(priv))
 		return -1;
 		return -1;
 
 
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 	return 0;
 	return 0;
 }
 }
 
 
 static void lbtf_free_adapter(struct lbtf_private *priv)
 static void lbtf_free_adapter(struct lbtf_private *priv)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_MAIN);
 	lbtf_free_cmd_buffer(priv);
 	lbtf_free_cmd_buffer(priv);
 	del_timer(&priv->command_timer);
 	del_timer(&priv->command_timer);
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 }
 
 
 static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
@@ -221,14 +249,18 @@ static void lbtf_tx_work(struct work_struct *work)
 	struct sk_buff *skb = NULL;
 	struct sk_buff *skb = NULL;
 	int err;
 	int err;
 
 
+	lbtf_deb_enter(LBTF_DEB_MACOPS | LBTF_DEB_TX);
+
 	if ((priv->vif->type == NL80211_IFTYPE_AP) &&
 	if ((priv->vif->type == NL80211_IFTYPE_AP) &&
 	    (!skb_queue_empty(&priv->bc_ps_buf)))
 	    (!skb_queue_empty(&priv->bc_ps_buf)))
 		skb = skb_dequeue(&priv->bc_ps_buf);
 		skb = skb_dequeue(&priv->bc_ps_buf);
 	else if (priv->skb_to_tx) {
 	else if (priv->skb_to_tx) {
 		skb = priv->skb_to_tx;
 		skb = priv->skb_to_tx;
 		priv->skb_to_tx = NULL;
 		priv->skb_to_tx = NULL;
-	} else
+	} else {
+		lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
 		return;
 		return;
+	}
 
 
 	len = skb->len;
 	len = skb->len;
 	info  = IEEE80211_SKB_CB(skb);
 	info  = IEEE80211_SKB_CB(skb);
@@ -236,6 +268,7 @@ static void lbtf_tx_work(struct work_struct *work)
 
 
 	if (priv->surpriseremoved) {
 	if (priv->surpriseremoved) {
 		dev_kfree_skb_any(skb);
 		dev_kfree_skb_any(skb);
+		lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
 		return;
 		return;
 	}
 	}
 
 
@@ -249,6 +282,7 @@ static void lbtf_tx_work(struct work_struct *work)
 		ETH_ALEN);
 		ETH_ALEN);
 	txpd->tx_packet_length = cpu_to_le16(len);
 	txpd->tx_packet_length = cpu_to_le16(len);
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
+	lbtf_deb_hex(LBTF_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100));
 	BUG_ON(priv->tx_skb);
 	BUG_ON(priv->tx_skb);
 	spin_lock_irq(&priv->driver_lock);
 	spin_lock_irq(&priv->driver_lock);
 	priv->tx_skb = skb;
 	priv->tx_skb = skb;
@@ -257,7 +291,9 @@ static void lbtf_tx_work(struct work_struct *work)
 	if (err) {
 	if (err) {
 		dev_kfree_skb_any(skb);
 		dev_kfree_skb_any(skb);
 		priv->tx_skb = NULL;
 		priv->tx_skb = NULL;
+		pr_err("TX error: %d", err);
 	}
 	}
+	lbtf_deb_leave(LBTF_DEB_MACOPS | LBTF_DEB_TX);
 }
 }
 
 
 static int lbtf_op_start(struct ieee80211_hw *hw)
 static int lbtf_op_start(struct ieee80211_hw *hw)
@@ -266,6 +302,8 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
 	void *card = priv->card;
 	void *card = priv->card;
 	int ret = -1;
 	int ret = -1;
 
 
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
+
 	if (!priv->fw_ready)
 	if (!priv->fw_ready)
 		/* Upload firmware */
 		/* Upload firmware */
 		if (priv->hw_prog_firmware(card))
 		if (priv->hw_prog_firmware(card))
@@ -286,10 +324,12 @@ static int lbtf_op_start(struct ieee80211_hw *hw)
 	}
 	}
 
 
 	printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
 	printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n");
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 	return 0;
 	return 0;
 
 
 err_prog_firmware:
 err_prog_firmware:
 	priv->hw_reset_device(card);
 	priv->hw_reset_device(card);
+	lbtf_deb_leave_args(LBTF_DEB_MACOPS, "error programing fw; ret=%d", ret);
 	return ret;
 	return ret;
 }
 }
 
 
@@ -300,6 +340,9 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
 	struct sk_buff *skb;
 	struct sk_buff *skb;
 
 
 	struct cmd_ctrl_node *cmdnode;
 	struct cmd_ctrl_node *cmdnode;
+
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
+
 	/* Flush pending command nodes */
 	/* Flush pending command nodes */
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
 	list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
@@ -316,6 +359,7 @@ static void lbtf_op_stop(struct ieee80211_hw *hw)
 	priv->radioon = RADIO_OFF;
 	priv->radioon = RADIO_OFF;
 	lbtf_set_radio_control(priv);
 	lbtf_set_radio_control(priv);
 
 
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 	return;
 	return;
 }
 }
 
 
@@ -323,6 +367,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif)
 			struct ieee80211_vif *vif)
 {
 {
 	struct lbtf_private *priv = hw->priv;
 	struct lbtf_private *priv = hw->priv;
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
 	if (priv->vif != NULL)
 	if (priv->vif != NULL)
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 
 
@@ -340,6 +385,7 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw,
 		return -EOPNOTSUPP;
 		return -EOPNOTSUPP;
 	}
 	}
 	lbtf_set_mac_address(priv, (u8 *) vif->addr);
 	lbtf_set_mac_address(priv, (u8 *) vif->addr);
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -347,6 +393,7 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
 			struct ieee80211_vif *vif)
 			struct ieee80211_vif *vif)
 {
 {
 	struct lbtf_private *priv = hw->priv;
 	struct lbtf_private *priv = hw->priv;
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
 
 
 	if (priv->vif->type == NL80211_IFTYPE_AP ||
 	if (priv->vif->type == NL80211_IFTYPE_AP ||
 	    priv->vif->type == NL80211_IFTYPE_MESH_POINT)
 	    priv->vif->type == NL80211_IFTYPE_MESH_POINT)
@@ -354,17 +401,20 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
 	lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
 	lbtf_set_mode(priv, LBTF_PASSIVE_MODE);
 	lbtf_set_bssid(priv, 0, NULL);
 	lbtf_set_bssid(priv, 0, NULL);
 	priv->vif = NULL;
 	priv->vif = NULL;
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 }
 }
 
 
 static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
 static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
 {
 {
 	struct lbtf_private *priv = hw->priv;
 	struct lbtf_private *priv = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	struct ieee80211_conf *conf = &hw->conf;
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
 
 
 	if (conf->channel->center_freq != priv->cur_freq) {
 	if (conf->channel->center_freq != priv->cur_freq) {
 		priv->cur_freq = conf->channel->center_freq;
 		priv->cur_freq = conf->channel->center_freq;
 		lbtf_set_channel(priv, conf->channel->hw_value);
 		lbtf_set_channel(priv, conf->channel->hw_value);
 	}
 	}
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -395,11 +445,16 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
 {
 {
 	struct lbtf_private *priv = hw->priv;
 	struct lbtf_private *priv = hw->priv;
 	int old_mac_control = priv->mac_control;
 	int old_mac_control = priv->mac_control;
+
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
+
 	changed_flags &= SUPPORTED_FIF_FLAGS;
 	changed_flags &= SUPPORTED_FIF_FLAGS;
 	*new_flags &= SUPPORTED_FIF_FLAGS;
 	*new_flags &= SUPPORTED_FIF_FLAGS;
 
 
-	if (!changed_flags)
+	if (!changed_flags) {
+		lbtf_deb_leave(LBTF_DEB_MACOPS);
 		return;
 		return;
+	}
 
 
 	if (*new_flags & (FIF_PROMISC_IN_BSS))
 	if (*new_flags & (FIF_PROMISC_IN_BSS))
 		priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE;
 		priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE;
@@ -425,6 +480,8 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw,
 
 
 	if (priv->mac_control != old_mac_control)
 	if (priv->mac_control != old_mac_control)
 		lbtf_set_mac_control(priv);
 		lbtf_set_mac_control(priv);
+
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 }
 }
 
 
 static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
 static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
@@ -434,6 +491,7 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
 {
 {
 	struct lbtf_private *priv = hw->priv;
 	struct lbtf_private *priv = hw->priv;
 	struct sk_buff *beacon;
 	struct sk_buff *beacon;
+	lbtf_deb_enter(LBTF_DEB_MACOPS);
 
 
 	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
 	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) {
 		switch (priv->vif->type) {
 		switch (priv->vif->type) {
@@ -464,6 +522,8 @@ static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw,
 			priv->preamble = CMD_TYPE_LONG_PREAMBLE;
 			priv->preamble = CMD_TYPE_LONG_PREAMBLE;
 		lbtf_set_radio_control(priv);
 		lbtf_set_radio_control(priv);
 	}
 	}
+
+	lbtf_deb_leave(LBTF_DEB_MACOPS);
 }
 }
 
 
 static const struct ieee80211_ops lbtf_ops = {
 static const struct ieee80211_ops lbtf_ops = {
@@ -486,6 +546,8 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 	unsigned int flags;
 	unsigned int flags;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_hdr *hdr;
 
 
+	lbtf_deb_enter(LBTF_DEB_RX);
+
 	prxpd = (struct rxpd *) skb->data;
 	prxpd = (struct rxpd *) skb->data;
 
 
 	stats.flag = 0;
 	stats.flag = 0;
@@ -494,7 +556,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 	stats.freq = priv->cur_freq;
 	stats.freq = priv->cur_freq;
 	stats.band = IEEE80211_BAND_2GHZ;
 	stats.band = IEEE80211_BAND_2GHZ;
 	stats.signal = prxpd->snr;
 	stats.signal = prxpd->snr;
-	stats.noise = prxpd->nf;
 	/* Marvell rate index has a hole at value 4 */
 	/* Marvell rate index has a hole at value 4 */
 	if (prxpd->rx_rate > 4)
 	if (prxpd->rx_rate > 4)
 		--prxpd->rx_rate;
 		--prxpd->rx_rate;
@@ -516,7 +577,15 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb)
 	}
 	}
 
 
 	memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
 	memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats));
+
+	lbtf_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n",
+	       skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd));
+	lbtf_deb_hex(LBTF_DEB_RX, "RX Data", skb->data,
+	             min_t(unsigned int, skb->len, 100));
+
 	ieee80211_rx_irqsafe(priv->hw, skb);
 	ieee80211_rx_irqsafe(priv->hw, skb);
+
+	lbtf_deb_leave(LBTF_DEB_RX);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(lbtf_rx);
 EXPORT_SYMBOL_GPL(lbtf_rx);
@@ -533,6 +602,8 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev)
 	struct ieee80211_hw *hw;
 	struct ieee80211_hw *hw;
 	struct lbtf_private *priv = NULL;
 	struct lbtf_private *priv = NULL;
 
 
+	lbtf_deb_enter(LBTF_DEB_MAIN);
+
 	hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
 	hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops);
 	if (!hw)
 	if (!hw)
 		goto done;
 		goto done;
@@ -575,6 +646,7 @@ err_init_adapter:
 	priv = NULL;
 	priv = NULL;
 
 
 done:
 done:
+	lbtf_deb_leave_args(LBTF_DEB_MAIN, "priv %p", priv);
 	return priv;
 	return priv;
 }
 }
 EXPORT_SYMBOL_GPL(lbtf_add_card);
 EXPORT_SYMBOL_GPL(lbtf_add_card);
@@ -584,6 +656,8 @@ int lbtf_remove_card(struct lbtf_private *priv)
 {
 {
 	struct ieee80211_hw *hw = priv->hw;
 	struct ieee80211_hw *hw = priv->hw;
 
 
+	lbtf_deb_enter(LBTF_DEB_MAIN);
+
 	priv->surpriseremoved = 1;
 	priv->surpriseremoved = 1;
 	del_timer(&priv->command_timer);
 	del_timer(&priv->command_timer);
 	lbtf_free_adapter(priv);
 	lbtf_free_adapter(priv);
@@ -591,6 +665,7 @@ int lbtf_remove_card(struct lbtf_private *priv)
 	ieee80211_unregister_hw(hw);
 	ieee80211_unregister_hw(hw);
 	ieee80211_free_hw(hw);
 	ieee80211_free_hw(hw);
 
 
+    lbtf_deb_leave(LBTF_DEB_MAIN);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(lbtf_remove_card);
 EXPORT_SYMBOL_GPL(lbtf_remove_card);
@@ -649,17 +724,21 @@ EXPORT_SYMBOL_GPL(lbtf_bcn_sent);
 
 
 static int __init lbtf_init_module(void)
 static int __init lbtf_init_module(void)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_MAIN);
 	lbtf_wq = create_workqueue("libertastf");
 	lbtf_wq = create_workqueue("libertastf");
 	if (lbtf_wq == NULL) {
 	if (lbtf_wq == NULL) {
 		printk(KERN_ERR "libertastf: couldn't create workqueue\n");
 		printk(KERN_ERR "libertastf: couldn't create workqueue\n");
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 	return 0;
 	return 0;
 }
 }
 
 
 static void __exit lbtf_exit_module(void)
 static void __exit lbtf_exit_module(void)
 {
 {
+	lbtf_deb_enter(LBTF_DEB_MAIN);
 	destroy_workqueue(lbtf_wq);
 	destroy_workqueue(lbtf_wq);
+	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 }
 
 
 module_init(lbtf_init_module);
 module_init(lbtf_init_module);

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

@@ -974,6 +974,7 @@ static void hw_scan_done(struct work_struct *work)
 }
 }
 
 
 static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
 static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
 				  struct cfg80211_scan_request *req)
 				  struct cfg80211_scan_request *req)
 {
 {
 	struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
 	struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL);
@@ -1020,7 +1021,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
 	mutex_lock(&hwsim->mutex);
 	mutex_lock(&hwsim->mutex);
 
 
 	printk(KERN_DEBUG "hwsim sw_scan_complete\n");
 	printk(KERN_DEBUG "hwsim sw_scan_complete\n");
-	hwsim->scanning = true;
+	hwsim->scanning = false;
 
 
 	mutex_unlock(&hwsim->mutex);
 	mutex_unlock(&hwsim->mutex);
 }
 }
@@ -1299,7 +1300,8 @@ static int __init init_mac80211_hwsim(void)
 		hw->flags = IEEE80211_HW_MFP_CAPABLE |
 		hw->flags = IEEE80211_HW_MFP_CAPABLE |
 			    IEEE80211_HW_SIGNAL_DBM |
 			    IEEE80211_HW_SIGNAL_DBM |
 			    IEEE80211_HW_SUPPORTS_STATIC_SMPS |
 			    IEEE80211_HW_SUPPORTS_STATIC_SMPS |
-			    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS;
+			    IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
+			    IEEE80211_HW_AMPDU_AGGREGATION;
 
 
 		/* ask mac80211 to reserve space for magic */
 		/* ask mac80211 to reserve space for magic */
 		hw->vif_data_size = sizeof(struct hwsim_vif_priv);
 		hw->vif_data_size = sizeof(struct hwsim_vif_priv);

+ 2 - 4
drivers/net/wireless/mwl8k.c

@@ -750,7 +750,6 @@ mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status,
 	memset(status, 0, sizeof(*status));
 	memset(status, 0, sizeof(*status));
 
 
 	status->signal = -rxd->rssi;
 	status->signal = -rxd->rssi;
-	status->noise = -rxd->noise_floor;
 
 
 	if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
 	if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) {
 		status->flag |= RX_FLAG_HT;
 		status->flag |= RX_FLAG_HT;
@@ -852,7 +851,6 @@ mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status,
 	memset(status, 0, sizeof(*status));
 	memset(status, 0, sizeof(*status));
 
 
 	status->signal = -rxd->rssi;
 	status->signal = -rxd->rssi;
-	status->noise = -rxd->noise_level;
 	status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
 	status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info);
 	status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
 	status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info);
 
 
@@ -3984,8 +3982,8 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev,
 
 
 	hw->queues = MWL8K_TX_QUEUES;
 	hw->queues = MWL8K_TX_QUEUES;
 
 
-	/* Set rssi and noise values to dBm */
-	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM;
+	/* Set rssi values to dBm */
+	hw->flags |= IEEE80211_HW_SIGNAL_DBM;
 	hw->vif_data_size = sizeof(struct mwl8k_vif);
 	hw->vif_data_size = sizeof(struct mwl8k_vif);
 	hw->sta_data_size = sizeof(struct mwl8k_sta);
 	hw->sta_data_size = sizeof(struct mwl8k_sta);
 
 

+ 7 - 0
drivers/net/wireless/orinoco/Kconfig

@@ -132,3 +132,10 @@ config PCMCIA_SPECTRUM
 	  This driver requires firmware download on startup.  Utilities
 	  This driver requires firmware download on startup.  Utilities
 	  for downloading Symbol firmware are available at
 	  for downloading Symbol firmware are available at
 	  <http://sourceforge.net/projects/orinoco/>
 	  <http://sourceforge.net/projects/orinoco/>
+
+config ORINOCO_USB
+	tristate "Agere Orinoco USB support"
+	depends on USB && HERMES
+	select FW_LOADER
+	---help---
+	  This driver is for USB versions of the Agere Orinoco card.

+ 1 - 0
drivers/net/wireless/orinoco/Makefile

@@ -11,6 +11,7 @@ obj-$(CONFIG_PCI_HERMES)	+= orinoco_pci.o
 obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o
 obj-$(CONFIG_TMD_HERMES)	+= orinoco_tmd.o
 obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o
 obj-$(CONFIG_NORTEL_HERMES)	+= orinoco_nortel.o
 obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o
 obj-$(CONFIG_PCMCIA_SPECTRUM)	+= spectrum_cs.o
+obj-$(CONFIG_ORINOCO_USB)	+= orinoco_usb.o
 
 
 # Orinoco should be endian clean.
 # Orinoco should be endian clean.
 ccflags-y += -D__CHECK_ENDIAN__
 ccflags-y += -D__CHECK_ENDIAN__

+ 4 - 4
drivers/net/wireless/orinoco/airport.c

@@ -77,9 +77,9 @@ airport_resume(struct macio_dev *mdev)
 
 
 	enable_irq(card->irq);
 	enable_irq(card->irq);
 
 
-	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, &flags);
 	err = orinoco_up(priv);
 	err = orinoco_up(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
 
 
 	return err;
 	return err;
 }
 }
@@ -195,7 +195,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
 	ssleep(1);
 	ssleep(1);
 
 
 	/* Reset it before we get the interrupt */
 	/* Reset it before we get the interrupt */
-	hermes_init(hw);
+	hw->ops->init(hw);
 
 
 	if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
 	if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) {
 		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
 		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq);
@@ -210,7 +210,7 @@ airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
 	}
 	}
 
 
 	/* Register an interface with the stack */
 	/* Register an interface with the stack */
-	if (orinoco_if_add(priv, phys_addr, card->irq) != 0) {
+	if (orinoco_if_add(priv, phys_addr, card->irq, NULL) != 0) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto failed;
 		goto failed;
 	}
 	}

+ 1 - 1
drivers/net/wireless/orinoco/cfg.c

@@ -189,7 +189,7 @@ static int orinoco_set_channel(struct wiphy *wiphy,
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 		/* Fast channel change - no commit if successful */
 		/* Fast channel change - no commit if successful */
 		hermes_t *hw = &priv->hw;
 		hermes_t *hw = &priv->hw;
-		err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_SET_CHANNEL,
 					    HERMES_TEST_SET_CHANNEL,
 					channel, NULL);
 					channel, NULL);
 	}
 	}

+ 5 - 5
drivers/net/wireless/orinoco/fw.c

@@ -122,7 +122,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
 	dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
 	dev_dbg(dev, "Attempting to download firmware %s\n", firmware);
 
 
 	/* Read current plug data */
 	/* Read current plug data */
-	err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
+	err = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
 	dev_dbg(dev, "Read PDA returned %d\n", err);
 	dev_dbg(dev, "Read PDA returned %d\n", err);
 	if (err)
 	if (err)
 		goto free;
 		goto free;
@@ -149,7 +149,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
 	}
 	}
 
 
 	/* Enable aux port to allow programming */
 	/* Enable aux port to allow programming */
-	err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
+	err = hw->ops->program_init(hw, le32_to_cpu(hdr->entry_point));
 	dev_dbg(dev, "Program init returned %d\n", err);
 	dev_dbg(dev, "Program init returned %d\n", err);
 	if (err != 0)
 	if (err != 0)
 		goto abort;
 		goto abort;
@@ -177,7 +177,7 @@ orinoco_dl_firmware(struct orinoco_private *priv,
 		goto abort;
 		goto abort;
 
 
 	/* Tell card we've finished */
 	/* Tell card we've finished */
-	err = hermesi_program_end(hw);
+	err = hw->ops->program_end(hw);
 	dev_dbg(dev, "Program end returned %d\n", err);
 	dev_dbg(dev, "Program end returned %d\n", err);
 	if (err != 0)
 	if (err != 0)
 		goto abort;
 		goto abort;
@@ -224,7 +224,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
 		if (!pda)
 		if (!pda)
 			return -ENOMEM;
 			return -ENOMEM;
 
 
-		ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
+		ret = hw->ops->read_pda(hw, pda, fw->pda_addr, fw->pda_size);
 		if (ret)
 		if (ret)
 			goto free;
 			goto free;
 	}
 	}
@@ -260,7 +260,7 @@ symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
 	}
 	}
 
 
 	/* Reset hermes chip and make sure it responds */
 	/* Reset hermes chip and make sure it responds */
-	ret = hermes_init(hw);
+	ret = hw->ops->init(hw);
 
 
 	/* hermes_reset() should return 0 with the secondary firmware */
 	/* hermes_reset() should return 0 with the secondary firmware */
 	if (secondary && ret != 0)
 	if (secondary && ret != 0)

+ 263 - 23
drivers/net/wireless/orinoco/hermes.c

@@ -51,6 +51,26 @@
 #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
 #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
 #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
 #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
 
 
+/*
+ * AUX port access.  To unlock the AUX port write the access keys to the
+ * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
+ * register.  Then read it and make sure it's HERMES_AUX_ENABLED.
+ */
+#define HERMES_AUX_ENABLE	0x8000	/* Enable auxiliary port access */
+#define HERMES_AUX_DISABLE	0x4000	/* Disable to auxiliary port access */
+#define HERMES_AUX_ENABLED	0xC000	/* Auxiliary port is open */
+#define HERMES_AUX_DISABLED	0x0000	/* Auxiliary port is closed */
+
+#define HERMES_AUX_PW0	0xFE01
+#define HERMES_AUX_PW1	0xDC23
+#define HERMES_AUX_PW2	0xBA45
+
+/* HERMES_CMD_DOWNLD */
+#define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
+#define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD)
+
 /*
 /*
  * Debugging helpers
  * Debugging helpers
  */
  */
@@ -70,6 +90,7 @@
 
 
 #endif /* ! HERMES_DEBUG */
 #endif /* ! HERMES_DEBUG */
 
 
+static const struct hermes_ops hermes_ops_local;
 
 
 /*
 /*
  * Internal functions
  * Internal functions
@@ -111,9 +132,9 @@ static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
  */
  */
 
 
 /* For doing cmds that wipe the magic constant in SWSUPPORT0 */
 /* For doing cmds that wipe the magic constant in SWSUPPORT0 */
-int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
-		       u16 parm0, u16 parm1, u16 parm2,
-		       struct hermes_response *resp)
+static int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
+			      u16 parm0, u16 parm1, u16 parm2,
+			      struct hermes_response *resp)
 {
 {
 	int err = 0;
 	int err = 0;
 	int k;
 	int k;
@@ -163,17 +184,18 @@ int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
 out:
 out:
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_doicmd_wait);
 
 
 void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
 void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
 {
 {
 	hw->iobase = address;
 	hw->iobase = address;
 	hw->reg_spacing = reg_spacing;
 	hw->reg_spacing = reg_spacing;
 	hw->inten = 0x0;
 	hw->inten = 0x0;
+	hw->eeprom_pda = false;
+	hw->ops = &hermes_ops_local;
 }
 }
 EXPORT_SYMBOL(hermes_struct_init);
 EXPORT_SYMBOL(hermes_struct_init);
 
 
-int hermes_init(hermes_t *hw)
+static int hermes_init(hermes_t *hw)
 {
 {
 	u16 reg;
 	u16 reg;
 	int err = 0;
 	int err = 0;
@@ -217,7 +239,6 @@ int hermes_init(hermes_t *hw)
 
 
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_init);
 
 
 /* Issue a command to the chip, and (busy!) wait for it to
 /* Issue a command to the chip, and (busy!) wait for it to
  * complete.
  * complete.
@@ -228,8 +249,8 @@ EXPORT_SYMBOL(hermes_init);
  *     > 0 on error returned by the firmware
  *     > 0 on error returned by the firmware
  *
  *
  * Callable from any context, but locking is your problem. */
  * Callable from any context, but locking is your problem. */
-int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
-		      struct hermes_response *resp)
+static int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+			     struct hermes_response *resp)
 {
 {
 	int err;
 	int err;
 	int k;
 	int k;
@@ -291,9 +312,8 @@ int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
  out:
  out:
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_docmd_wait);
 
 
-int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
+static int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
 {
 {
 	int err = 0;
 	int err = 0;
 	int k;
 	int k;
@@ -333,7 +353,6 @@ int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
 
 
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL(hermes_allocate);
 
 
 /* Set up a BAP to read a particular chunk of data from card's internal buffer.
 /* Set up a BAP to read a particular chunk of data from card's internal buffer.
  *
  *
@@ -403,8 +422,8 @@ static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
  *       0 on success
  *       0 on success
  *     > 0 on error from firmware
  *     > 0 on error from firmware
  */
  */
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
-		     u16 id, u16 offset)
+static int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
+			    u16 id, u16 offset)
 {
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int err = 0;
 	int err = 0;
@@ -422,7 +441,6 @@ int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
  out:
  out:
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_bap_pread);
 
 
 /* Write a block of data to the chip's buffer, via the
 /* Write a block of data to the chip's buffer, via the
  * BAP. Synchronization/serialization is the caller's problem.
  * BAP. Synchronization/serialization is the caller's problem.
@@ -432,8 +450,8 @@ EXPORT_SYMBOL(hermes_bap_pread);
  *       0 on success
  *       0 on success
  *     > 0 on error from firmware
  *     > 0 on error from firmware
  */
  */
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
-		      u16 id, u16 offset)
+static int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
+			     u16 id, u16 offset)
 {
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int err = 0;
 	int err = 0;
@@ -451,7 +469,6 @@ int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
  out:
  out:
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_bap_pwrite);
 
 
 /* Read a Length-Type-Value record from the card.
 /* Read a Length-Type-Value record from the card.
  *
  *
@@ -461,8 +478,8 @@ EXPORT_SYMBOL(hermes_bap_pwrite);
  * practice.
  * practice.
  *
  *
  * Callable from user or bh context.  */
  * Callable from user or bh context.  */
-int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
-		    u16 *length, void *buf)
+static int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
+			   u16 *length, void *buf)
 {
 {
 	int err = 0;
 	int err = 0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
@@ -505,10 +522,9 @@ int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
 
 
 	return 0;
 	return 0;
 }
 }
-EXPORT_SYMBOL(hermes_read_ltv);
 
 
-int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
-		     u16 length, const void *value)
+static int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
+			    u16 length, const void *value)
 {
 {
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 	int err = 0;
 	int err = 0;
@@ -533,4 +549,228 @@ int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
 
 
 	return err;
 	return err;
 }
 }
-EXPORT_SYMBOL(hermes_write_ltv);
+
+/*** Hermes AUX control ***/
+
+static inline void
+hermes_aux_setaddr(hermes_t *hw, u32 addr)
+{
+	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
+	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
+}
+
+static inline int
+hermes_aux_control(hermes_t *hw, int enabled)
+{
+	int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
+	int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
+	int i;
+
+	/* Already open? */
+	if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
+		return 0;
+
+	hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
+	hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
+	hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
+	hermes_write_reg(hw, HERMES_CONTROL, action);
+
+	for (i = 0; i < 20; i++) {
+		udelay(10);
+		if (hermes_read_reg(hw, HERMES_CONTROL) ==
+		    desired_state)
+			return 0;
+	}
+
+	return -EBUSY;
+}
+
+/*** Hermes programming ***/
+
+/* About to start programming data (Hermes I)
+ * offset is the entry point
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+static int hermesi_program_init(hermes_t *hw, u32 offset)
+{
+	int err;
+
+	/* Disable interrupts?*/
+	/*hw->inten = 0x0;*/
+	/*hermes_write_regn(hw, INTEN, 0);*/
+	/*hermes_set_irqmask(hw, 0);*/
+
+	/* Acknowledge any outstanding command */
+	hermes_write_regn(hw, EVACK, 0xFFFF);
+
+	/* Using init_cmd_wait rather than cmd_wait */
+	err = hw->ops->init_cmd_wait(hw,
+				     0x0100 | HERMES_CMD_INIT,
+				     0, 0, 0, NULL);
+	if (err)
+		return err;
+
+	err = hw->ops->init_cmd_wait(hw,
+				     0x0000 | HERMES_CMD_INIT,
+				     0, 0, 0, NULL);
+	if (err)
+		return err;
+
+	err = hermes_aux_control(hw, 1);
+	pr_debug("AUX enable returned %d\n", err);
+
+	if (err)
+		return err;
+
+	pr_debug("Enabling volatile, EP 0x%08x\n", offset);
+	err = hw->ops->init_cmd_wait(hw,
+				     HERMES_PROGRAM_ENABLE_VOLATILE,
+				     offset & 0xFFFFu,
+				     offset >> 16,
+				     0,
+				     NULL);
+	pr_debug("PROGRAM_ENABLE returned %d\n", err);
+
+	return err;
+}
+
+/* Done programming data (Hermes I)
+ *
+ * Spectrum_cs' Symbol fw does not require this
+ * wl_lkm Agere fw does
+ * Don't know about intersil
+ */
+static int hermesi_program_end(hermes_t *hw)
+{
+	struct hermes_response resp;
+	int rc = 0;
+	int err;
+
+	rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
+
+	pr_debug("PROGRAM_DISABLE returned %d, "
+		 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
+		 rc, resp.resp0, resp.resp1, resp.resp2);
+
+	if ((rc == 0) &&
+	    ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
+		rc = -EIO;
+
+	err = hermes_aux_control(hw, 0);
+	pr_debug("AUX disable returned %d\n", err);
+
+	/* Acknowledge any outstanding command */
+	hermes_write_regn(hw, EVACK, 0xFFFF);
+
+	/* Reinitialise, ignoring return */
+	(void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
+				      0, 0, 0, NULL);
+
+	return rc ? rc : err;
+}
+
+static int hermes_program_bytes(struct hermes *hw, const char *data,
+				u32 addr, u32 len)
+{
+	/* wl lkm splits the programming into chunks of 2000 bytes.
+	 * This restriction appears to come from USB. The PCMCIA
+	 * adapters can program the whole lot in one go */
+	hermes_aux_setaddr(hw, addr);
+	hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
+	return 0;
+}
+
+/* Read PDA from the adapter */
+static int hermes_read_pda(hermes_t *hw, __le16 *pda, u32 pda_addr, u16 pda_len)
+{
+	int ret;
+	u16 pda_size;
+	u16 data_len = pda_len;
+	__le16 *data = pda;
+
+	if (hw->eeprom_pda) {
+		/* PDA of spectrum symbol is in eeprom */
+
+		/* Issue command to read EEPROM */
+		ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
+		if (ret)
+			return ret;
+	} else {
+		/* wl_lkm does not include PDA size in the PDA area.
+		 * We will pad the information into pda, so other routines
+		 * don't have to be modified */
+		pda[0] = cpu_to_le16(pda_len - 2);
+			/* Includes CFG_PROD_DATA but not itself */
+		pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
+		data_len = pda_len - 4;
+		data = pda + 2;
+	}
+
+	/* Open auxiliary port */
+	ret = hermes_aux_control(hw, 1);
+	pr_debug("AUX enable returned %d\n", ret);
+	if (ret)
+		return ret;
+
+	/* Read PDA */
+	hermes_aux_setaddr(hw, pda_addr);
+	hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
+
+	/* Close aux port */
+	ret = hermes_aux_control(hw, 0);
+	pr_debug("AUX disable returned %d\n", ret);
+
+	/* Check PDA length */
+	pda_size = le16_to_cpu(pda[0]);
+	pr_debug("Actual PDA length %d, Max allowed %d\n",
+		 pda_size, pda_len);
+	if (pda_size > pda_len)
+		return -EINVAL;
+
+	return 0;
+}
+
+static void hermes_lock_irqsave(spinlock_t *lock,
+				unsigned long *flags) __acquires(lock)
+{
+	spin_lock_irqsave(lock, *flags);
+}
+
+static void hermes_unlock_irqrestore(spinlock_t *lock,
+				     unsigned long *flags) __releases(lock)
+{
+	spin_unlock_irqrestore(lock, *flags);
+}
+
+static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
+{
+	spin_lock_irq(lock);
+}
+
+static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
+{
+	spin_unlock_irq(lock);
+}
+
+/* Hermes operations for local buses */
+static const struct hermes_ops hermes_ops_local = {
+	.init = hermes_init,
+	.cmd_wait = hermes_docmd_wait,
+	.init_cmd_wait = hermes_doicmd_wait,
+	.allocate = hermes_allocate,
+	.read_ltv = hermes_read_ltv,
+	.write_ltv = hermes_write_ltv,
+	.bap_pread = hermes_bap_pread,
+	.bap_pwrite = hermes_bap_pwrite,
+	.read_pda = hermes_read_pda,
+	.program_init = hermesi_program_init,
+	.program_end = hermesi_program_end,
+	.program = hermes_program_bytes,
+	.lock_irqsave = hermes_lock_irqsave,
+	.unlock_irqrestore = hermes_unlock_irqrestore,
+	.lock_irq = hermes_lock_irq,
+	.unlock_irq = hermes_unlock_irq,
+};

+ 40 - 22
drivers/net/wireless/orinoco/hermes.h

@@ -374,6 +374,37 @@ struct hermes_multicast {
 /* Timeouts */
 /* Timeouts */
 #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
 #define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
 
 
+struct hermes;
+
+/* Functions to access hardware */
+struct hermes_ops {
+	int (*init)(struct hermes *hw);
+	int (*cmd_wait)(struct hermes *hw, u16 cmd, u16 parm0,
+			struct hermes_response *resp);
+	int (*init_cmd_wait)(struct hermes *hw, u16 cmd,
+			     u16 parm0, u16 parm1, u16 parm2,
+			     struct hermes_response *resp);
+	int (*allocate)(struct hermes *hw, u16 size, u16 *fid);
+	int (*read_ltv)(struct hermes *hw, int bap, u16 rid, unsigned buflen,
+			u16 *length, void *buf);
+	int (*write_ltv)(struct hermes *hw, int bap, u16 rid,
+			 u16 length, const void *value);
+	int (*bap_pread)(struct hermes *hw, int bap, void *buf, int len,
+			 u16 id, u16 offset);
+	int (*bap_pwrite)(struct hermes *hw, int bap, const void *buf,
+			  int len, u16 id, u16 offset);
+	int (*read_pda)(struct hermes *hw, __le16 *pda,
+			u32 pda_addr, u16 pda_len);
+	int (*program_init)(struct hermes *hw, u32 entry_point);
+	int (*program_end)(struct hermes *hw);
+	int (*program)(struct hermes *hw, const char *buf,
+		       u32 addr, u32 len);
+	void (*lock_irqsave)(spinlock_t *lock, unsigned long *flags);
+	void (*unlock_irqrestore)(spinlock_t *lock, unsigned long *flags);
+	void (*lock_irq)(spinlock_t *lock);
+	void (*unlock_irq)(spinlock_t *lock);
+};
+
 /* Basic control structure */
 /* Basic control structure */
 typedef struct hermes {
 typedef struct hermes {
 	void __iomem *iobase;
 	void __iomem *iobase;
@@ -381,6 +412,9 @@ typedef struct hermes {
 #define HERMES_16BIT_REGSPACING	0
 #define HERMES_16BIT_REGSPACING	0
 #define HERMES_32BIT_REGSPACING	1
 #define HERMES_32BIT_REGSPACING	1
 	u16 inten; /* Which interrupts should be enabled? */
 	u16 inten; /* Which interrupts should be enabled? */
+	bool eeprom_pda;
+	const struct hermes_ops *ops;
+	void *priv;
 } hermes_t;
 } hermes_t;
 
 
 /* Register access convenience macros */
 /* Register access convenience macros */
@@ -394,22 +428,6 @@ typedef struct hermes {
 
 
 /* Function prototypes */
 /* Function prototypes */
 void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
 void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
-int hermes_init(hermes_t *hw);
-int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
-		      struct hermes_response *resp);
-int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
-		       u16 parm0, u16 parm1, u16 parm2,
-		       struct hermes_response *resp);
-int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
-
-int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
-		       u16 id, u16 offset);
-int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
-			u16 id, u16 offset);
-int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
-		    u16 *length, void *buf);
-int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
-		      u16 length, const void *value);
 
 
 /* Inline functions */
 /* Inline functions */
 
 
@@ -426,13 +444,13 @@ static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
 
 
 static inline int hermes_enable_port(hermes_t *hw, int port)
 static inline int hermes_enable_port(hermes_t *hw, int port)
 {
 {
-	return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
+	return hw->ops->cmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
 				 0, NULL);
 				 0, NULL);
 }
 }
 
 
 static inline int hermes_disable_port(hermes_t *hw, int port)
 static inline int hermes_disable_port(hermes_t *hw, int port)
 {
 {
-	return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
+	return hw->ops->cmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
 				 0, NULL);
 				 0, NULL);
 }
 }
 
 
@@ -440,7 +458,7 @@ static inline int hermes_disable_port(hermes_t *hw, int port)
  * information frame in __orinoco_ev_info() */
  * information frame in __orinoco_ev_info() */
 static inline int hermes_inquire(hermes_t *hw, u16 rid)
 static inline int hermes_inquire(hermes_t *hw, u16 rid)
 {
 {
-	return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
+	return hw->ops->cmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
 }
 }
 
 
 #define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
 #define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1)
@@ -475,10 +493,10 @@ static inline void hermes_clear_words(struct hermes *hw, int off,
 }
 }
 
 
 #define HERMES_READ_RECORD(hw, bap, rid, buf) \
 #define HERMES_READ_RECORD(hw, bap, rid, buf) \
-	(hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
+	(hw->ops->read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf)))
 #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
 #define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
-	(hermes_write_ltv((hw), (bap), (rid), \
-			  HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
+	(hw->ops->write_ltv((hw), (bap), (rid), \
+			    HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf)))
 
 
 static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
 {
 {

+ 9 - 234
drivers/net/wireless/orinoco/hermes_dld.c

@@ -46,37 +46,11 @@
 
 
 #define PFX "hermes_dld: "
 #define PFX "hermes_dld: "
 
 
-/*
- * AUX port access.  To unlock the AUX port write the access keys to the
- * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
- * register.  Then read it and make sure it's HERMES_AUX_ENABLED.
- */
-#define HERMES_AUX_ENABLE	0x8000	/* Enable auxiliary port access */
-#define HERMES_AUX_DISABLE	0x4000	/* Disable to auxiliary port access */
-#define HERMES_AUX_ENABLED	0xC000	/* Auxiliary port is open */
-#define HERMES_AUX_DISABLED	0x0000	/* Auxiliary port is closed */
-
-#define HERMES_AUX_PW0	0xFE01
-#define HERMES_AUX_PW1	0xDC23
-#define HERMES_AUX_PW2	0xBA45
-
-/* HERMES_CMD_DOWNLD */
-#define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD)
-#define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD)
-#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
-#define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD)
-
 /* End markers used in dblocks */
 /* End markers used in dblocks */
 #define PDI_END		0x00000000	/* End of PDA */
 #define PDI_END		0x00000000	/* End of PDA */
 #define BLOCK_END	0xFFFFFFFF	/* Last image block */
 #define BLOCK_END	0xFFFFFFFF	/* Last image block */
 #define TEXT_END	0x1A		/* End of text header */
 #define TEXT_END	0x1A		/* End of text header */
 
 
-/* Limit the amout we try to download in a single shot.
- * Size is in bytes.
- */
-#define MAX_DL_SIZE 1024
-#define LIMIT_PROGRAM_SIZE 0
-
 /*
 /*
  * The following structures have little-endian fields denoted by
  * The following structures have little-endian fields denoted by
  * the leading underscore.  Don't access them directly - use inline
  * the leading underscore.  Don't access them directly - use inline
@@ -165,41 +139,6 @@ pdi_len(const struct pdi *pdi)
 	return 2 * (le16_to_cpu(pdi->len) - 1);
 	return 2 * (le16_to_cpu(pdi->len) - 1);
 }
 }
 
 
-/*** Hermes AUX control ***/
-
-static inline void
-hermes_aux_setaddr(hermes_t *hw, u32 addr)
-{
-	hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
-	hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
-}
-
-static inline int
-hermes_aux_control(hermes_t *hw, int enabled)
-{
-	int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
-	int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
-	int i;
-
-	/* Already open? */
-	if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
-		return 0;
-
-	hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
-	hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
-	hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
-	hermes_write_reg(hw, HERMES_CONTROL, action);
-
-	for (i = 0; i < 20; i++) {
-		udelay(10);
-		if (hermes_read_reg(hw, HERMES_CONTROL) ==
-		    desired_state)
-			return 0;
-	}
-
-	return -EBUSY;
-}
-
 /*** Plug Data Functions ***/
 /*** Plug Data Functions ***/
 
 
 /*
 /*
@@ -271,62 +210,7 @@ hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/* do the actual plugging */
 	/* do the actual plugging */
-	hermes_aux_setaddr(hw, pdr_addr(pdr));
-	hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
-
-	return 0;
-}
-
-/* Read PDA from the adapter */
-int hermes_read_pda(hermes_t *hw,
-		    __le16 *pda,
-		    u32 pda_addr,
-		    u16 pda_len,
-		    int use_eeprom) /* can we get this into hw? */
-{
-	int ret;
-	u16 pda_size;
-	u16 data_len = pda_len;
-	__le16 *data = pda;
-
-	if (use_eeprom) {
-		/* PDA of spectrum symbol is in eeprom */
-
-		/* Issue command to read EEPROM */
-		ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
-		if (ret)
-			return ret;
-	} else {
-		/* wl_lkm does not include PDA size in the PDA area.
-		 * We will pad the information into pda, so other routines
-		 * don't have to be modified */
-		pda[0] = cpu_to_le16(pda_len - 2);
-			/* Includes CFG_PROD_DATA but not itself */
-		pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
-		data_len = pda_len - 4;
-		data = pda + 2;
-	}
-
-	/* Open auxiliary port */
-	ret = hermes_aux_control(hw, 1);
-	pr_debug(PFX "AUX enable returned %d\n", ret);
-	if (ret)
-		return ret;
-
-	/* read PDA from EEPROM */
-	hermes_aux_setaddr(hw, pda_addr);
-	hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
-
-	/* Close aux port */
-	ret = hermes_aux_control(hw, 0);
-	pr_debug(PFX "AUX disable returned %d\n", ret);
-
-	/* Check PDA length */
-	pda_size = le16_to_cpu(pda[0]);
-	pr_debug(PFX "Actual PDA length %d, Max allowed %d\n",
-		 pda_size, pda_len);
-	if (pda_size > pda_len)
-		return -EINVAL;
+	hw->ops->program(hw, pdi->data, pdr_addr(pdr), pdi_len(pdi));
 
 
 	return 0;
 	return 0;
 }
 }
@@ -389,101 +273,13 @@ hermes_blocks_length(const char *first_block, const void *end)
 
 
 /*** Hermes programming ***/
 /*** Hermes programming ***/
 
 
-/* About to start programming data (Hermes I)
- * offset is the entry point
- *
- * Spectrum_cs' Symbol fw does not require this
- * wl_lkm Agere fw does
- * Don't know about intersil
- */
-int hermesi_program_init(hermes_t *hw, u32 offset)
-{
-	int err;
-
-	/* Disable interrupts?*/
-	/*hw->inten = 0x0;*/
-	/*hermes_write_regn(hw, INTEN, 0);*/
-	/*hermes_set_irqmask(hw, 0);*/
-
-	/* Acknowledge any outstanding command */
-	hermes_write_regn(hw, EVACK, 0xFFFF);
-
-	/* Using doicmd_wait rather than docmd_wait */
-	err = hermes_doicmd_wait(hw,
-				 0x0100 | HERMES_CMD_INIT,
-				 0, 0, 0, NULL);
-	if (err)
-		return err;
-
-	err = hermes_doicmd_wait(hw,
-				 0x0000 | HERMES_CMD_INIT,
-				 0, 0, 0, NULL);
-	if (err)
-		return err;
-
-	err = hermes_aux_control(hw, 1);
-	pr_debug(PFX "AUX enable returned %d\n", err);
-
-	if (err)
-		return err;
-
-	pr_debug(PFX "Enabling volatile, EP 0x%08x\n", offset);
-	err = hermes_doicmd_wait(hw,
-				 HERMES_PROGRAM_ENABLE_VOLATILE,
-				 offset & 0xFFFFu,
-				 offset >> 16,
-				 0,
-				 NULL);
-	pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err);
-
-	return err;
-}
-
-/* Done programming data (Hermes I)
- *
- * Spectrum_cs' Symbol fw does not require this
- * wl_lkm Agere fw does
- * Don't know about intersil
- */
-int hermesi_program_end(hermes_t *hw)
-{
-	struct hermes_response resp;
-	int rc = 0;
-	int err;
-
-	rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
-
-	pr_debug(PFX "PROGRAM_DISABLE returned %d, "
-		 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
-		 rc, resp.resp0, resp.resp1, resp.resp2);
-
-	if ((rc == 0) &&
-	    ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
-		rc = -EIO;
-
-	err = hermes_aux_control(hw, 0);
-	pr_debug(PFX "AUX disable returned %d\n", err);
-
-	/* Acknowledge any outstanding command */
-	hermes_write_regn(hw, EVACK, 0xFFFF);
-
-	/* Reinitialise, ignoring return */
-	(void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
-				  0, 0, 0, NULL);
-
-	return rc ? rc : err;
-}
-
 /* Program the data blocks */
 /* Program the data blocks */
 int hermes_program(hermes_t *hw, const char *first_block, const void *end)
 int hermes_program(hermes_t *hw, const char *first_block, const void *end)
 {
 {
 	const struct dblock *blk;
 	const struct dblock *blk;
 	u32 blkaddr;
 	u32 blkaddr;
 	u32 blklen;
 	u32 blklen;
-#if LIMIT_PROGRAM_SIZE
-	u32 addr;
-	u32 len;
-#endif
+	int err = 0;
 
 
 	blk = (const struct dblock *) first_block;
 	blk = (const struct dblock *) first_block;
 
 
@@ -498,30 +294,10 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
 		pr_debug(PFX "Programming block of length %d "
 		pr_debug(PFX "Programming block of length %d "
 			 "to address 0x%08x\n", blklen, blkaddr);
 			 "to address 0x%08x\n", blklen, blkaddr);
 
 
-#if !LIMIT_PROGRAM_SIZE
-		/* wl_lkm driver splits this into writes of 2000 bytes */
-		hermes_aux_setaddr(hw, blkaddr);
-		hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
-				   blklen);
-#else
-		len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
-		addr = blkaddr;
-
-		while (addr < (blkaddr + blklen)) {
-			pr_debug(PFX "Programming subblock of length %d "
-				 "to address 0x%08x. Data @ %p\n",
-				 len, addr, &blk->data[addr - blkaddr]);
-
-			hermes_aux_setaddr(hw, addr);
-			hermes_write_bytes(hw, HERMES_AUXDATA,
-					   &blk->data[addr - blkaddr],
-					   len);
-
-			addr += len;
-			len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
-				(blkaddr + blklen - addr) : MAX_DL_SIZE;
-		}
-#endif
+		err = hw->ops->program(hw, blk->data, blkaddr, blklen);
+		if (err)
+			break;
+
 		blk = (const struct dblock *) &blk->data[blklen];
 		blk = (const struct dblock *) &blk->data[blklen];
 
 
 		if ((void *) blk > (end - sizeof(*blk)))
 		if ((void *) blk > (end - sizeof(*blk)))
@@ -530,7 +306,7 @@ int hermes_program(hermes_t *hw, const char *first_block, const void *end)
 		blkaddr = dblock_addr(blk);
 		blkaddr = dblock_addr(blk);
 		blklen = dblock_len(blk);
 		blklen = dblock_len(blk);
 	}
 	}
-	return 0;
+	return err;
 }
 }
 
 
 /*** Default plugging data for Hermes I ***/
 /*** Default plugging data for Hermes I ***/
@@ -690,9 +466,8 @@ int hermes_apply_pda_with_defaults(hermes_t *hw,
 			if ((pdi_len(pdi) == pdr_len(pdr)) &&
 			if ((pdi_len(pdi) == pdr_len(pdr)) &&
 			    ((void *) pdi->data + pdi_len(pdi) < pda_end)) {
 			    ((void *) pdi->data + pdi_len(pdi) < pda_end)) {
 				/* do the actual plugging */
 				/* do the actual plugging */
-				hermes_aux_setaddr(hw, pdr_addr(pdr));
-				hermes_write_bytes(hw, HERMES_AUXDATA,
-						   pdi->data, pdi_len(pdi));
+				hw->ops->program(hw, pdi->data, pdr_addr(pdr),
+						 pdi_len(pdi));
 			}
 			}
 		}
 		}
 
 

+ 32 - 31
drivers/net/wireless/orinoco/hw.c

@@ -177,9 +177,9 @@ int determine_fw_capabilities(struct orinoco_private *priv,
 		/* 3Com MAC : 00:50:DA:* */
 		/* 3Com MAC : 00:50:DA:* */
 		memset(tmp, 0, sizeof(tmp));
 		memset(tmp, 0, sizeof(tmp));
 		/* Get the Symbol firmware version */
 		/* Get the Symbol firmware version */
-		err = hermes_read_ltv(hw, USER_BAP,
-				      HERMES_RID_SECONDARYVERSION_SYMBOL,
-				      SYMBOL_MAX_VER_LEN, NULL, &tmp);
+		err = hw->ops->read_ltv(hw, USER_BAP,
+					HERMES_RID_SECONDARYVERSION_SYMBOL,
+					SYMBOL_MAX_VER_LEN, NULL, &tmp);
 		if (err) {
 		if (err) {
 			dev_warn(dev, "Error %d reading Symbol firmware info. "
 			dev_warn(dev, "Error %d reading Symbol firmware info. "
 				 "Wildly guessing capabilities...\n", err);
 				 "Wildly guessing capabilities...\n", err);
@@ -286,8 +286,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
 	u16 reclen;
 	u16 reclen;
 
 
 	/* Get the MAC address */
 	/* Get the MAC address */
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
-			      ETH_ALEN, NULL, dev_addr);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+				ETH_ALEN, NULL, dev_addr);
 	if (err) {
 	if (err) {
 		dev_warn(dev, "Failed to read MAC address!\n");
 		dev_warn(dev, "Failed to read MAC address!\n");
 		goto out;
 		goto out;
@@ -296,8 +296,8 @@ int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
 	dev_dbg(dev, "MAC address %pM\n", dev_addr);
 	dev_dbg(dev, "MAC address %pM\n", dev_addr);
 
 
 	/* Get the station name */
 	/* Get the station name */
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
-			      sizeof(nickbuf), &reclen, &nickbuf);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+				sizeof(nickbuf), &reclen, &nickbuf);
 	if (err) {
 	if (err) {
 		dev_err(dev, "failed to read station name\n");
 		dev_err(dev, "failed to read station name\n");
 		goto out;
 		goto out;
@@ -413,11 +413,11 @@ int orinoco_hw_allocate_fid(struct orinoco_private *priv)
 	struct hermes *hw = &priv->hw;
 	struct hermes *hw = &priv->hw;
 	int err;
 	int err;
 
 
-	err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+	err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 		/* Try workaround for old Symbol firmware bug */
 		/* Try workaround for old Symbol firmware bug */
 		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
 		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
-		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
+		err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 
 
 		dev_warn(dev, "Firmware ALLOC bug detected "
 		dev_warn(dev, "Firmware ALLOC bug detected "
 			 "(old Symbol firmware?). Work around %s\n",
 			 "(old Symbol firmware?). Work around %s\n",
@@ -463,8 +463,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	struct hermes_idstring idbuf;
 	struct hermes_idstring idbuf;
 
 
 	/* Set the MAC address */
 	/* Set the MAC address */
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
-			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
+	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
+				 HERMES_BYTES_TO_RECLEN(ETH_ALEN),
+				 dev->dev_addr);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting MAC address\n",
 		printk(KERN_ERR "%s: Error %d setting MAC address\n",
 		       dev->name, err);
 		       dev->name, err);
@@ -527,7 +528,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
 	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
 	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
 	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
+	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
 			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			&idbuf);
 			&idbuf);
 	if (err) {
 	if (err) {
@@ -535,7 +536,7 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 		       dev->name, err);
 		       dev->name, err);
 		return err;
 		return err;
 	}
 	}
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
+	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
 			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
 			&idbuf);
 			&idbuf);
 	if (err) {
 	if (err) {
@@ -547,9 +548,9 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	/* Set the station name */
 	/* Set the station name */
 	idbuf.len = cpu_to_le16(strlen(priv->nick));
 	idbuf.len = cpu_to_le16(strlen(priv->nick));
 	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
 	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
-	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
-			       &idbuf);
+	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
+				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+				 &idbuf);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting nickname\n",
 		printk(KERN_ERR "%s: Error %d setting nickname\n",
 		       dev->name, err);
 		       dev->name, err);
@@ -664,12 +665,12 @@ int orinoco_hw_program_rids(struct orinoco_private *priv)
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 		/* Enable monitor mode */
 		/* Enable monitor mode */
 		dev->type = ARPHRD_IEEE80211;
 		dev->type = ARPHRD_IEEE80211;
-		err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_MONITOR, 0, NULL);
 					    HERMES_TEST_MONITOR, 0, NULL);
 	} else {
 	} else {
 		/* Disable monitor mode */
 		/* Disable monitor mode */
 		dev->type = ARPHRD_ETHER;
 		dev->type = ARPHRD_ETHER;
-		err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_STOP, 0, NULL);
 					    HERMES_TEST_STOP, 0, NULL);
 	}
 	}
 	if (err)
 	if (err)
@@ -695,8 +696,8 @@ int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 	if ((key < 0) || (key >= 4))
 	if ((key < 0) || (key >= 4))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
-			      sizeof(tsc_arr), NULL, &tsc_arr);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
+				sizeof(tsc_arr), NULL, &tsc_arr);
 	if (!err)
 	if (!err)
 		memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
 		memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
 
 
@@ -875,7 +876,7 @@ int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 				memcpy(key, priv->keys[i].key,
 				memcpy(key, priv->keys[i].key,
 				       priv->keys[i].key_len);
 				       priv->keys[i].key_len);
 
 
-				err = hermes_write_ltv(hw, USER_BAP,
+				err = hw->ops->write_ltv(hw, USER_BAP,
 						HERMES_RID_CNFDEFAULTKEY0 + i,
 						HERMES_RID_CNFDEFAULTKEY0 + i,
 						HERMES_BYTES_TO_RECLEN(keylen),
 						HERMES_BYTES_TO_RECLEN(keylen),
 						key);
 						key);
@@ -1092,7 +1093,7 @@ int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
 			memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
 			memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
 		}
 		}
 
 
-		err = hermes_write_ltv(hw, USER_BAP,
+		err = hw->ops->write_ltv(hw, USER_BAP,
 				   HERMES_RID_CNFGROUPADDRESSES,
 				   HERMES_RID_CNFGROUPADDRESSES,
 				   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
 				   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
 				   &mclist);
 				   &mclist);
@@ -1134,15 +1135,15 @@ int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
 		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
 		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
 			HERMES_RID_CNFDESIREDSSID;
 			HERMES_RID_CNFDESIREDSSID;
 
 
-		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
-				      NULL, &essidbuf);
+		err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
+					NULL, &essidbuf);
 		if (err)
 		if (err)
 			goto fail_unlock;
 			goto fail_unlock;
 	} else {
 	} else {
 		*active = 0;
 		*active = 0;
 
 
-		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
-				      sizeof(essidbuf), NULL, &essidbuf);
+		err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
+					sizeof(essidbuf), NULL, &essidbuf);
 		if (err)
 		if (err)
 			goto fail_unlock;
 			goto fail_unlock;
 	}
 	}
@@ -1213,8 +1214,8 @@ int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
 	if (orinoco_lock(priv, &flags) != 0)
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
 		return -EBUSY;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
-			      sizeof(list), NULL, &list);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
+				sizeof(list), NULL, &list);
 	orinoco_unlock(priv, &flags);
 	orinoco_unlock(priv, &flags);
 
 
 	if (err)
 	if (err)
@@ -1281,7 +1282,7 @@ int orinoco_hw_trigger_scan(struct orinoco_private *priv,
 				idbuf.len = cpu_to_le16(len);
 				idbuf.len = cpu_to_le16(len);
 				memcpy(idbuf.val, ssid->ssid, len);
 				memcpy(idbuf.val, ssid->ssid, len);
 
 
-				err = hermes_write_ltv(hw, USER_BAP,
+				err = hw->ops->write_ltv(hw, USER_BAP,
 					       HERMES_RID_CNFSCANSSID_AGERE,
 					       HERMES_RID_CNFSCANSSID_AGERE,
 					       HERMES_BYTES_TO_RECLEN(len + 2),
 					       HERMES_BYTES_TO_RECLEN(len + 2),
 					       &idbuf);
 					       &idbuf);
@@ -1345,8 +1346,8 @@ int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
 	hermes_t *hw = &priv->hw;
 	hermes_t *hw = &priv->hw;
 	int err;
 	int err;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, addr);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+				ETH_ALEN, NULL, addr);
 
 
 	return err;
 	return err;
 }
 }

+ 76 - 61
drivers/net/wireless/orinoco/main.c

@@ -254,7 +254,7 @@ void set_port_type(struct orinoco_private *priv)
 /* Device methods                                                   */
 /* Device methods                                                   */
 /********************************************************************/
 /********************************************************************/
 
 
-static int orinoco_open(struct net_device *dev)
+int orinoco_open(struct net_device *dev)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	unsigned long flags;
 	unsigned long flags;
@@ -272,8 +272,9 @@ static int orinoco_open(struct net_device *dev)
 
 
 	return err;
 	return err;
 }
 }
+EXPORT_SYMBOL(orinoco_open);
 
 
-static int orinoco_stop(struct net_device *dev)
+int orinoco_stop(struct net_device *dev)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	int err = 0;
 	int err = 0;
@@ -281,25 +282,27 @@ static int orinoco_stop(struct net_device *dev)
 	/* We mustn't use orinoco_lock() here, because we need to be
 	/* We mustn't use orinoco_lock() here, because we need to be
 	   able to close the interface even if hw_unavailable is set
 	   able to close the interface even if hw_unavailable is set
 	   (e.g. as we're released after a PC Card removal) */
 	   (e.g. as we're released after a PC Card removal) */
-	spin_lock_irq(&priv->lock);
+	orinoco_lock_irq(priv);
 
 
 	priv->open = 0;
 	priv->open = 0;
 
 
 	err = __orinoco_down(priv);
 	err = __orinoco_down(priv);
 
 
-	spin_unlock_irq(&priv->lock);
+	orinoco_unlock_irq(priv);
 
 
 	return err;
 	return err;
 }
 }
+EXPORT_SYMBOL(orinoco_stop);
 
 
-static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
+struct net_device_stats *orinoco_get_stats(struct net_device *dev)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 
 
 	return &priv->stats;
 	return &priv->stats;
 }
 }
+EXPORT_SYMBOL(orinoco_get_stats);
 
 
-static void orinoco_set_multicast_list(struct net_device *dev)
+void orinoco_set_multicast_list(struct net_device *dev)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	unsigned long flags;
 	unsigned long flags;
@@ -313,8 +316,9 @@ static void orinoco_set_multicast_list(struct net_device *dev)
 	__orinoco_set_multicast_list(dev);
 	__orinoco_set_multicast_list(dev);
 	orinoco_unlock(priv, &flags);
 	orinoco_unlock(priv, &flags);
 }
 }
+EXPORT_SYMBOL(orinoco_set_multicast_list);
 
 
-static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
+int orinoco_change_mtu(struct net_device *dev, int new_mtu)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 
 
@@ -330,6 +334,7 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
 
 
 	return 0;
 	return 0;
 }
 }
+EXPORT_SYMBOL(orinoco_change_mtu);
 
 
 /********************************************************************/
 /********************************************************************/
 /* Tx path                                                          */
 /* Tx path                                                          */
@@ -400,8 +405,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 		memset(&desc, 0, sizeof(desc));
 		memset(&desc, 0, sizeof(desc));
 
 
 		*txcntl = cpu_to_le16(tx_control);
 		*txcntl = cpu_to_le16(tx_control);
-		err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
-					txfid, 0);
+		err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
+					  txfid, 0);
 		if (err) {
 		if (err) {
 			if (net_ratelimit())
 			if (net_ratelimit())
 				printk(KERN_ERR "%s: Error %d writing Tx "
 				printk(KERN_ERR "%s: Error %d writing Tx "
@@ -414,8 +419,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 		memset(&desc, 0, sizeof(desc));
 		memset(&desc, 0, sizeof(desc));
 
 
 		desc.tx_control = cpu_to_le16(tx_control);
 		desc.tx_control = cpu_to_le16(tx_control);
-		err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
-					txfid, 0);
+		err = hw->ops->bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
+					  txfid, 0);
 		if (err) {
 		if (err) {
 			if (net_ratelimit())
 			if (net_ratelimit())
 				printk(KERN_ERR "%s: Error %d writing Tx "
 				printk(KERN_ERR "%s: Error %d writing Tx "
@@ -458,8 +463,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 		memcpy(eh, &hdr, sizeof(hdr));
 		memcpy(eh, &hdr, sizeof(hdr));
 	}
 	}
 
 
-	err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
-				txfid, HERMES_802_3_OFFSET);
+	err = hw->ops->bap_pwrite(hw, USER_BAP, skb->data, skb->len,
+				  txfid, HERMES_802_3_OFFSET);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
 		printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
 		       dev->name, err);
 		       dev->name, err);
@@ -490,8 +495,8 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 			    skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
 			    skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
 
 
 		/* Write the MIC */
 		/* Write the MIC */
-		err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
-					txfid, HERMES_802_3_OFFSET + offset);
+		err = hw->ops->bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
+					  txfid, HERMES_802_3_OFFSET + offset);
 		if (err) {
 		if (err) {
 			printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
 			printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
 			       dev->name, err);
 			       dev->name, err);
@@ -502,7 +507,7 @@ static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Finally, we actually initiate the send */
 	/* Finally, we actually initiate the send */
 	netif_stop_queue(dev);
 	netif_stop_queue(dev);
 
 
-	err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
+	err = hw->ops->cmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
 				txfid, NULL);
 				txfid, NULL);
 	if (err) {
 	if (err) {
 		netif_start_queue(dev);
 		netif_start_queue(dev);
@@ -572,9 +577,9 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
 		return; /* Nothing's really happened */
 		return; /* Nothing's really happened */
 
 
 	/* Read part of the frame header - we need status and addr1 */
 	/* Read part of the frame header - we need status and addr1 */
-	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
-			       sizeof(struct hermes_txexc_data),
-			       fid, 0);
+	err = hw->ops->bap_pread(hw, IRQ_BAP, &hdr,
+				 sizeof(struct hermes_txexc_data),
+				 fid, 0);
 
 
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 	stats->tx_errors++;
 	stats->tx_errors++;
@@ -615,7 +620,7 @@ static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
 	netif_wake_queue(dev);
 	netif_wake_queue(dev);
 }
 }
 
 
-static void orinoco_tx_timeout(struct net_device *dev)
+void orinoco_tx_timeout(struct net_device *dev)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	struct net_device_stats *stats = &priv->stats;
@@ -630,6 +635,7 @@ static void orinoco_tx_timeout(struct net_device *dev)
 
 
 	schedule_work(&priv->reset_work);
 	schedule_work(&priv->reset_work);
 }
 }
+EXPORT_SYMBOL(orinoco_tx_timeout);
 
 
 /********************************************************************/
 /********************************************************************/
 /* Rx path (data frames)                                            */
 /* Rx path (data frames)                                            */
@@ -764,9 +770,9 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
 
 
 	/* If any, copy the data from the card to the skb */
 	/* If any, copy the data from the card to the skb */
 	if (datalen > 0) {
 	if (datalen > 0) {
-		err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
-				       ALIGN(datalen, 2), rxfid,
-				       HERMES_802_2_OFFSET);
+		err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
+					 ALIGN(datalen, 2), rxfid,
+					 HERMES_802_2_OFFSET);
 		if (err) {
 		if (err) {
 			printk(KERN_ERR "%s: error %d reading monitor frame\n",
 			printk(KERN_ERR "%s: error %d reading monitor frame\n",
 			       dev->name, err);
 			       dev->name, err);
@@ -792,7 +798,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
 	stats->rx_dropped++;
 	stats->rx_dropped++;
 }
 }
 
 
-static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct net_device_stats *stats = &priv->stats;
 	struct net_device_stats *stats = &priv->stats;
@@ -814,8 +820,8 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 
 
 	rxfid = hermes_read_regn(hw, RXFID);
 	rxfid = hermes_read_regn(hw, RXFID);
 
 
-	err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
-			       rxfid, 0);
+	err = hw->ops->bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
+				 rxfid, 0);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
 		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
 		       "Frame dropped.\n", dev->name, err);
 		       "Frame dropped.\n", dev->name, err);
@@ -882,9 +888,9 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
 	   nothing is removed.  2 is for aligning the IP header.  */
 	   nothing is removed.  2 is for aligning the IP header.  */
 	skb_reserve(skb, ETH_HLEN + 2);
 	skb_reserve(skb, ETH_HLEN + 2);
 
 
-	err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
-			       ALIGN(length, 2), rxfid,
-			       HERMES_802_2_OFFSET);
+	err = hw->ops->bap_pread(hw, IRQ_BAP, skb_put(skb, length),
+				 ALIGN(length, 2), rxfid,
+				 HERMES_802_2_OFFSET);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading frame. "
 		printk(KERN_ERR "%s: error %d reading frame. "
 		       "Frame dropped.\n", dev->name, err);
 		       "Frame dropped.\n", dev->name, err);
@@ -913,6 +919,7 @@ update_stats:
 out:
 out:
 	kfree(desc);
 	kfree(desc);
 }
 }
+EXPORT_SYMBOL(__orinoco_ev_rx);
 
 
 static void orinoco_rx(struct net_device *dev,
 static void orinoco_rx(struct net_device *dev,
 		       struct hermes_rx_descriptor *desc,
 		       struct hermes_rx_descriptor *desc,
@@ -1145,9 +1152,9 @@ static void orinoco_join_ap(struct work_struct *work)
 		goto out;
 		goto out;
 
 
 	/* Read scan results from the firmware */
 	/* Read scan results from the firmware */
-	err = hermes_read_ltv(hw, USER_BAP,
-			      HERMES_RID_SCANRESULTSTABLE,
-			      MAX_SCAN_LEN, &len, buf);
+	err = hw->ops->read_ltv(hw, USER_BAP,
+				HERMES_RID_SCANRESULTSTABLE,
+				MAX_SCAN_LEN, &len, buf);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: Cannot read scan results\n",
 		printk(KERN_ERR "%s: Cannot read scan results\n",
 		       dev->name);
 		       dev->name);
@@ -1194,8 +1201,8 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
 	union iwreq_data wrqu;
 	union iwreq_data wrqu;
 	int err;
 	int err;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
+				ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
 	if (err != 0)
 	if (err != 0)
 		return;
 		return;
 
 
@@ -1217,8 +1224,8 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
 	if (!priv->has_wpa)
 	if (!priv->has_wpa)
 		return;
 		return;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
-			      sizeof(buf), NULL, &buf);
+	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
+				sizeof(buf), NULL, &buf);
 	if (err != 0)
 	if (err != 0)
 		return;
 		return;
 
 
@@ -1247,8 +1254,9 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
 	if (!priv->has_wpa)
 	if (!priv->has_wpa)
 		return;
 		return;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
-			      sizeof(buf), NULL, &buf);
+	err = hw->ops->read_ltv(hw, USER_BAP,
+				HERMES_RID_CURRENT_ASSOC_RESP_INFO,
+				sizeof(buf), NULL, &buf);
 	if (err != 0)
 	if (err != 0)
 		return;
 		return;
 
 
@@ -1353,7 +1361,7 @@ static void orinoco_process_scan_results(struct work_struct *work)
 	spin_unlock_irqrestore(&priv->scan_lock, flags);
 	spin_unlock_irqrestore(&priv->scan_lock, flags);
 }
 }
 
 
-static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
+void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 {
 {
 	struct orinoco_private *priv = ndev_priv(dev);
 	struct orinoco_private *priv = ndev_priv(dev);
 	u16 infofid;
 	u16 infofid;
@@ -1371,8 +1379,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 	infofid = hermes_read_regn(hw, INFOFID);
 	infofid = hermes_read_regn(hw, INFOFID);
 
 
 	/* Read the info frame header - don't try too hard */
 	/* Read the info frame header - don't try too hard */
-	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
-			       infofid, 0);
+	err = hw->ops->bap_pread(hw, IRQ_BAP, &info, sizeof(info),
+				 infofid, 0);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading info frame. "
 		printk(KERN_ERR "%s: error %d reading info frame. "
 		       "Frame dropped.\n", dev->name, err);
 		       "Frame dropped.\n", dev->name, err);
@@ -1393,8 +1401,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 			len = sizeof(tallies);
 			len = sizeof(tallies);
 		}
 		}
 
 
-		err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
-				       infofid, sizeof(info));
+		err = hw->ops->bap_pread(hw, IRQ_BAP, &tallies, len,
+					 infofid, sizeof(info));
 		if (err)
 		if (err)
 			break;
 			break;
 
 
@@ -1429,8 +1437,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 			break;
 			break;
 		}
 		}
 
 
-		err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
-				       infofid, sizeof(info));
+		err = hw->ops->bap_pread(hw, IRQ_BAP, &linkstatus, len,
+					 infofid, sizeof(info));
 		if (err)
 		if (err)
 			break;
 			break;
 		newstatus = le16_to_cpu(linkstatus.linkstatus);
 		newstatus = le16_to_cpu(linkstatus.linkstatus);
@@ -1494,8 +1502,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 		}
 		}
 
 
 		/* Read scan data */
 		/* Read scan data */
-		err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
-				       infofid, sizeof(info));
+		err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) buf, len,
+					 infofid, sizeof(info));
 		if (err) {
 		if (err) {
 			kfree(buf);
 			kfree(buf);
 			qabort_scan(priv);
 			qabort_scan(priv);
@@ -1547,8 +1555,8 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 			break;
 			break;
 
 
 		/* Read scan data */
 		/* Read scan data */
-		err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
-				       infofid, sizeof(info));
+		err = hw->ops->bap_pread(hw, IRQ_BAP, (void *) bss, len,
+					 infofid, sizeof(info));
 		if (err)
 		if (err)
 			kfree(bss);
 			kfree(bss);
 		else
 		else
@@ -1571,6 +1579,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
 
 
 	return;
 	return;
 }
 }
+EXPORT_SYMBOL(__orinoco_ev_info);
 
 
 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
 {
 {
@@ -1647,7 +1656,7 @@ static int orinoco_reinit_firmware(struct orinoco_private *priv)
 	struct hermes *hw = &priv->hw;
 	struct hermes *hw = &priv->hw;
 	int err;
 	int err;
 
 
-	err = hermes_init(hw);
+	err = hw->ops->init(hw);
 	if (priv->do_fw_download && !err) {
 	if (priv->do_fw_download && !err) {
 		err = orinoco_download(priv);
 		err = orinoco_download(priv);
 		if (err)
 		if (err)
@@ -1735,7 +1744,7 @@ void orinoco_reset(struct work_struct *work)
 	}
 	}
 
 
 	/* This has to be called from user context */
 	/* This has to be called from user context */
-	spin_lock_irq(&priv->lock);
+	orinoco_lock_irq(priv);
 
 
 	priv->hw_unavailable--;
 	priv->hw_unavailable--;
 
 
@@ -1750,7 +1759,7 @@ void orinoco_reset(struct work_struct *work)
 			dev->trans_start = jiffies;
 			dev->trans_start = jiffies;
 	}
 	}
 
 
-	spin_unlock_irq(&priv->lock);
+	orinoco_unlock_irq(priv);
 
 
 	return;
 	return;
  disable:
  disable:
@@ -1984,7 +1993,7 @@ int orinoco_init(struct orinoco_private *priv)
 	priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
 	priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
 
 
 	/* Initialize the firmware */
 	/* Initialize the firmware */
-	err = hermes_init(hw);
+	err = hw->ops->init(hw);
 	if (err != 0) {
 	if (err != 0) {
 		dev_err(dev, "Failed to initialize firmware (err = %d)\n",
 		dev_err(dev, "Failed to initialize firmware (err = %d)\n",
 			err);
 			err);
@@ -2067,9 +2076,9 @@ int orinoco_init(struct orinoco_private *priv)
 
 
 	/* Make the hardware available, as long as it hasn't been
 	/* Make the hardware available, as long as it hasn't been
 	 * removed elsewhere (e.g. by PCMCIA hot unplug) */
 	 * removed elsewhere (e.g. by PCMCIA hot unplug) */
-	spin_lock_irq(&priv->lock);
+	orinoco_lock_irq(priv);
 	priv->hw_unavailable--;
 	priv->hw_unavailable--;
-	spin_unlock_irq(&priv->lock);
+	orinoco_unlock_irq(priv);
 
 
 	dev_dbg(dev, "Ready\n");
 	dev_dbg(dev, "Ready\n");
 
 
@@ -2192,7 +2201,8 @@ EXPORT_SYMBOL(alloc_orinocodev);
  */
  */
 int orinoco_if_add(struct orinoco_private *priv,
 int orinoco_if_add(struct orinoco_private *priv,
 		   unsigned long base_addr,
 		   unsigned long base_addr,
-		   unsigned int irq)
+		   unsigned int irq,
+		   const struct net_device_ops *ops)
 {
 {
 	struct wiphy *wiphy = priv_to_wiphy(priv);
 	struct wiphy *wiphy = priv_to_wiphy(priv);
 	struct wireless_dev *wdev;
 	struct wireless_dev *wdev;
@@ -2211,12 +2221,17 @@ int orinoco_if_add(struct orinoco_private *priv,
 
 
 	/* Setup / override net_device fields */
 	/* Setup / override net_device fields */
 	dev->ieee80211_ptr = wdev;
 	dev->ieee80211_ptr = wdev;
-	dev->netdev_ops = &orinoco_netdev_ops;
 	dev->watchdog_timeo = HZ; /* 1 second timeout */
 	dev->watchdog_timeo = HZ; /* 1 second timeout */
 	dev->wireless_handlers = &orinoco_handler_def;
 	dev->wireless_handlers = &orinoco_handler_def;
 #ifdef WIRELESS_SPY
 #ifdef WIRELESS_SPY
 	dev->wireless_data = &priv->wireless_data;
 	dev->wireless_data = &priv->wireless_data;
 #endif
 #endif
+	/* Default to standard ops if not set */
+	if (ops)
+		dev->netdev_ops = ops;
+	else
+		dev->netdev_ops = &orinoco_netdev_ops;
+
 	/* we use the default eth_mac_addr for setting the MAC addr */
 	/* we use the default eth_mac_addr for setting the MAC addr */
 
 
 	/* Reserve space in skb for the SNAP header */
 	/* Reserve space in skb for the SNAP header */
@@ -2305,7 +2320,7 @@ int orinoco_up(struct orinoco_private *priv)
 	unsigned long flags;
 	unsigned long flags;
 	int err;
 	int err;
 
 
-	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, &flags);
 
 
 	err = orinoco_reinit_firmware(priv);
 	err = orinoco_reinit_firmware(priv);
 	if (err) {
 	if (err) {
@@ -2325,7 +2340,7 @@ int orinoco_up(struct orinoco_private *priv)
 	}
 	}
 
 
 exit:
 exit:
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -2337,7 +2352,7 @@ void orinoco_down(struct orinoco_private *priv)
 	unsigned long flags;
 	unsigned long flags;
 	int err;
 	int err;
 
 
-	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, &flags);
 	err = __orinoco_down(priv);
 	err = __orinoco_down(priv);
 	if (err)
 	if (err)
 		printk(KERN_WARNING "%s: Error %d downing interface\n",
 		printk(KERN_WARNING "%s: Error %d downing interface\n",
@@ -2345,7 +2360,7 @@ void orinoco_down(struct orinoco_private *priv)
 
 
 	netif_device_detach(dev);
 	netif_device_detach(dev);
 	priv->hw_unavailable++;
 	priv->hw_unavailable++;
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
 }
 }
 EXPORT_SYMBOL(orinoco_down);
 EXPORT_SYMBOL(orinoco_down);
 
 

+ 26 - 4
drivers/net/wireless/orinoco/orinoco.h

@@ -190,12 +190,24 @@ extern void free_orinocodev(struct orinoco_private *priv);
 extern int orinoco_init(struct orinoco_private *priv);
 extern int orinoco_init(struct orinoco_private *priv);
 extern int orinoco_if_add(struct orinoco_private *priv,
 extern int orinoco_if_add(struct orinoco_private *priv,
 			  unsigned long base_addr,
 			  unsigned long base_addr,
-			  unsigned int irq);
+			  unsigned int irq,
+			  const struct net_device_ops *ops);
 extern void orinoco_if_del(struct orinoco_private *priv);
 extern void orinoco_if_del(struct orinoco_private *priv);
 extern int orinoco_up(struct orinoco_private *priv);
 extern int orinoco_up(struct orinoco_private *priv);
 extern void orinoco_down(struct orinoco_private *priv);
 extern void orinoco_down(struct orinoco_private *priv);
 extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
 extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
 
 
+extern void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);
+extern void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);
+
+/* Common ndo functions exported for reuse by orinoco_usb */
+int orinoco_open(struct net_device *dev);
+int orinoco_stop(struct net_device *dev);
+struct net_device_stats *orinoco_get_stats(struct net_device *dev);
+void orinoco_set_multicast_list(struct net_device *dev);
+int orinoco_change_mtu(struct net_device *dev, int new_mtu);
+void orinoco_tx_timeout(struct net_device *dev);
+
 /********************************************************************/
 /********************************************************************/
 /* Locking and synchronization functions                            */
 /* Locking and synchronization functions                            */
 /********************************************************************/
 /********************************************************************/
@@ -203,11 +215,11 @@ extern irqreturn_t orinoco_interrupt(int irq, void *dev_id);
 static inline int orinoco_lock(struct orinoco_private *priv,
 static inline int orinoco_lock(struct orinoco_private *priv,
 			       unsigned long *flags)
 			       unsigned long *flags)
 {
 {
-	spin_lock_irqsave(&priv->lock, *flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, flags);
 	if (priv->hw_unavailable) {
 	if (priv->hw_unavailable) {
 		DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
 		DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
 		       priv->ndev);
 		       priv->ndev);
-		spin_unlock_irqrestore(&priv->lock, *flags);
+		priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 	return 0;
 	return 0;
@@ -216,7 +228,17 @@ static inline int orinoco_lock(struct orinoco_private *priv,
 static inline void orinoco_unlock(struct orinoco_private *priv,
 static inline void orinoco_unlock(struct orinoco_private *priv,
 				  unsigned long *flags)
 				  unsigned long *flags)
 {
 {
-	spin_unlock_irqrestore(&priv->lock, *flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, flags);
+}
+
+static inline void orinoco_lock_irq(struct orinoco_private *priv)
+{
+	priv->hw.ops->lock_irq(&priv->lock);
+}
+
+static inline void orinoco_unlock_irq(struct orinoco_private *priv)
+{
+	priv->hw.ops->unlock_irq(&priv->lock);
 }
 }
 
 
 /*** Navigate from net_device to orinoco_private ***/
 /*** Navigate from net_device to orinoco_private ***/

+ 3 - 3
drivers/net/wireless/orinoco/orinoco_cs.c

@@ -296,7 +296,7 @@ orinoco_cs_config(struct pcmcia_device *link)
 
 
 	/* Register an interface with the stack */
 	/* Register an interface with the stack */
 	if (orinoco_if_add(priv, link->io.BasePort1,
 	if (orinoco_if_add(priv, link->io.BasePort1,
-			   link->irq.AssignedIRQ) != 0) {
+			   link->irq.AssignedIRQ, NULL) != 0) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto failed;
 		goto failed;
 	}
 	}
@@ -327,9 +327,9 @@ orinoco_cs_release(struct pcmcia_device *link)
 
 
 	/* We're committed to taking the device away now, so mark the
 	/* We're committed to taking the device away now, so mark the
 	 * hardware as unavailable */
 	 * hardware as unavailable */
-	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, &flags);
 	priv->hw_unavailable++;
 	priv->hw_unavailable++;
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
 
 
 	pcmcia_disable_device(link);
 	pcmcia_disable_device(link);
 	if (priv->hw.iobase)
 	if (priv->hw.iobase)

+ 1 - 1
drivers/net/wireless/orinoco/orinoco_nortel.c

@@ -220,7 +220,7 @@ static int orinoco_nortel_init_one(struct pci_dev *pdev,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	err = orinoco_if_add(priv, 0, 0);
+	err = orinoco_if_add(priv, 0, 0, NULL);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto fail;
 		goto fail;

+ 1 - 1
drivers/net/wireless/orinoco/orinoco_pci.c

@@ -170,7 +170,7 @@ static int orinoco_pci_init_one(struct pci_dev *pdev,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	err = orinoco_if_add(priv, 0, 0);
+	err = orinoco_if_add(priv, 0, 0, NULL);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto fail;
 		goto fail;

+ 1 - 1
drivers/net/wireless/orinoco/orinoco_plx.c

@@ -259,7 +259,7 @@ static int orinoco_plx_init_one(struct pci_dev *pdev,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	err = orinoco_if_add(priv, 0, 0);
+	err = orinoco_if_add(priv, 0, 0, NULL);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto fail;
 		goto fail;

+ 1 - 1
drivers/net/wireless/orinoco/orinoco_tmd.c

@@ -156,7 +156,7 @@ static int orinoco_tmd_init_one(struct pci_dev *pdev,
 		goto fail;
 		goto fail;
 	}
 	}
 
 
-	err = orinoco_if_add(priv, 0, 0);
+	err = orinoco_if_add(priv, 0, 0, NULL);
 	if (err) {
 	if (err) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto fail;
 		goto fail;

+ 1800 - 0
drivers/net/wireless/orinoco/orinoco_usb.c

@@ -0,0 +1,1800 @@
+/*
+ * USB Orinoco driver
+ *
+ * Copyright (c) 2003 Manuel Estrada Sainz
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License
+ * at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+ * the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * terms of the GNU General Public License version 2 (the "GPL"), in
+ * which case the provisions of the GPL are applicable instead of the
+ * above.  If you wish to allow the use of your version of this file
+ * only under the terms of the GPL and not to allow others to use your
+ * version of this file under the MPL, indicate your decision by
+ * deleting the provisions above and replace them with the notice and
+ * other provisions required by the GPL.  If you do not delete the
+ * provisions above, a recipient may use your version of this file
+ * under either the MPL or the GPL.
+ *
+ * Queueing code based on linux-wlan-ng 0.2.1-pre5
+ *
+ * Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ *
+ *	The license is the same as above.
+ *
+ * Initialy based on USB Skeleton driver - 0.7
+ *
+ * Copyright (c) 2001 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.
+ *
+ * NOTE: The original USB Skeleton driver is GPL, but all that code is
+ * gone so MPL/GPL applies.
+ */
+
+#define DRIVER_NAME "orinoco_usb"
+#define PFX DRIVER_NAME ": "
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/fcntl.h>
+#include <linux/spinlock.h>
+#include <linux/list.h>
+#include <linux/smp_lock.h>
+#include <linux/usb.h>
+#include <linux/timer.h>
+
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+
+#include "orinoco.h"
+
+#ifndef URB_ASYNC_UNLINK
+#define URB_ASYNC_UNLINK 0
+#endif
+
+/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
+static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
+#define ENCAPS_OVERHEAD		(sizeof(encaps_hdr) + 2)
+
+struct header_struct {
+	/* 802.3 */
+	u8 dest[ETH_ALEN];
+	u8 src[ETH_ALEN];
+	__be16 len;
+	/* 802.2 */
+	u8 dsap;
+	u8 ssap;
+	u8 ctrl;
+	/* SNAP */
+	u8 oui[3];
+	__be16 ethertype;
+} __attribute__ ((packed));
+
+struct ez_usb_fw {
+	u16 size;
+	const u8 *code;
+};
+
+static struct ez_usb_fw firmware = {
+	.size = 0,
+	.code = NULL,
+};
+
+#ifdef CONFIG_USB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+
+/* Debugging macros */
+#undef dbg
+#define dbg(format, arg...) \
+	do { if (debug) printk(KERN_DEBUG PFX "%s: " format "\n", \
+			       __func__ , ## arg); } while (0)
+#undef err
+#define err(format, arg...) \
+	do { printk(KERN_ERR PFX format "\n", ## arg); } while (0)
+
+/* Module paramaters */
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+MODULE_FIRMWARE("orinoco_ezusb_fw");
+
+/*
+ * Under some conditions, the card gets stuck and stops paying attention
+ * to the world (i.e. data communication stalls) until we do something to
+ * it.  Sending an INQ_TALLIES command seems to be enough and should be
+ * harmless otherwise.  This behaviour has been observed when using the
+ * driver on a systemimager client during installation.  In the past a
+ * timer was used to send INQ_TALLIES commands when there was no other
+ * activity, but it was troublesome and was removed.
+ */
+
+#define USB_COMPAQ_VENDOR_ID     0x049f /* Compaq Computer Corp. */
+#define USB_COMPAQ_WL215_ID      0x001f /* Compaq WL215 USB Adapter */
+#define USB_COMPAQ_W200_ID       0x0076 /* Compaq W200 USB Adapter */
+#define USB_HP_WL215_ID          0x0082 /* Compaq WL215 USB Adapter */
+
+#define USB_MELCO_VENDOR_ID      0x0411
+#define USB_BUFFALO_L11_ID       0x0006 /* BUFFALO WLI-USB-L11 */
+#define USB_BUFFALO_L11G_WR_ID   0x000B /* BUFFALO WLI-USB-L11G-WR */
+#define USB_BUFFALO_L11G_ID      0x000D /* BUFFALO WLI-USB-L11G */
+
+#define USB_LUCENT_VENDOR_ID     0x047E /* Lucent Technologies */
+#define USB_LUCENT_ORINOCO_ID    0x0300 /* Lucent/Agere Orinoco USB Client */
+
+#define USB_AVAYA8_VENDOR_ID     0x0D98
+#define USB_AVAYAE_VENDOR_ID     0x0D9E
+#define USB_AVAYA_WIRELESS_ID    0x0300 /* Avaya Wireless USB Card */
+
+#define USB_AGERE_VENDOR_ID      0x0D4E /* Agere Systems */
+#define USB_AGERE_MODEL0801_ID   0x1000 /* Wireless USB Card Model 0801 */
+#define USB_AGERE_MODEL0802_ID   0x1001 /* Wireless USB Card Model 0802 */
+#define USB_AGERE_REBRANDED_ID   0x047A /* WLAN USB Card */
+
+#define USB_ELSA_VENDOR_ID       0x05CC
+#define USB_ELSA_AIRLANCER_ID    0x3100 /* ELSA AirLancer USB-11 */
+
+#define USB_LEGEND_VENDOR_ID     0x0E7C
+#define USB_LEGEND_JOYNET_ID     0x0300 /* Joynet WLAN USB Card */
+
+#define USB_SAMSUNG_VENDOR_ID    0x04E8
+#define USB_SAMSUNG_SEW2001U1_ID 0x5002 /* Samsung SEW-2001u Card */
+#define USB_SAMSUNG_SEW2001U2_ID 0x5B11 /* Samsung SEW-2001u Card */
+#define USB_SAMSUNG_SEW2003U_ID  0x7011 /* Samsung SEW-2003U Card */
+
+#define USB_IGATE_VENDOR_ID      0x0681
+#define USB_IGATE_IGATE_11M_ID   0x0012 /* I-GATE 11M USB Card */
+
+#define USB_FUJITSU_VENDOR_ID    0x0BF8
+#define USB_FUJITSU_E1100_ID     0x1002 /* connect2AIR WLAN E-1100 USB */
+
+#define USB_2WIRE_VENDOR_ID      0x1630
+#define USB_2WIRE_WIRELESS_ID    0xff81 /* 2Wire Wireless USB adapter */
+
+
+#define EZUSB_REQUEST_FW_TRANS		0xA0
+#define EZUSB_REQUEST_TRIGER		0xAA
+#define EZUSB_REQUEST_TRIG_AC		0xAC
+#define EZUSB_CPUCS_REG			0x7F92
+
+#define EZUSB_RID_TX			0x0700
+#define EZUSB_RID_RX			0x0701
+#define EZUSB_RID_INIT1			0x0702
+#define EZUSB_RID_ACK			0x0710
+#define EZUSB_RID_READ_PDA		0x0800
+#define EZUSB_RID_PROG_INIT		0x0852
+#define EZUSB_RID_PROG_SET_ADDR		0x0853
+#define EZUSB_RID_PROG_BYTES		0x0854
+#define EZUSB_RID_PROG_END		0x0855
+#define EZUSB_RID_DOCMD			0x0860
+
+/* Recognize info frames */
+#define EZUSB_IS_INFO(id)		((id >= 0xF000) && (id <= 0xF2FF))
+
+#define EZUSB_MAGIC			0x0210
+
+#define EZUSB_FRAME_DATA		1
+#define EZUSB_FRAME_CONTROL		2
+
+#define DEF_TIMEOUT			(3*HZ)
+
+#define BULK_BUF_SIZE			2048
+
+#define MAX_DL_SIZE (BULK_BUF_SIZE - sizeof(struct ezusb_packet))
+
+#define FW_BUF_SIZE			64
+#define FW_VAR_OFFSET_PTR		0x359
+#define FW_VAR_VALUE			0
+#define FW_HOLE_START			0x100
+#define FW_HOLE_END			0x300
+
+struct ezusb_packet {
+	__le16 magic;		/* 0x0210 */
+	u8 req_reply_count;
+	u8 ans_reply_count;
+	__le16 frame_type;	/* 0x01 for data frames, 0x02 otherwise */
+	__le16 size;		/* transport size */
+	__le16 crc;		/* CRC up to here */
+	__le16 hermes_len;
+	__le16 hermes_rid;
+	u8 data[0];
+} __attribute__ ((packed));
+
+/* Table of devices that work or may work with this driver */
+static struct usb_device_id ezusb_table[] = {
+	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_WL215_ID)},
+	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_HP_WL215_ID)},
+	{USB_DEVICE(USB_COMPAQ_VENDOR_ID, USB_COMPAQ_W200_ID)},
+	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11_ID)},
+	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_WR_ID)},
+	{USB_DEVICE(USB_MELCO_VENDOR_ID, USB_BUFFALO_L11G_ID)},
+	{USB_DEVICE(USB_LUCENT_VENDOR_ID, USB_LUCENT_ORINOCO_ID)},
+	{USB_DEVICE(USB_AVAYA8_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
+	{USB_DEVICE(USB_AVAYAE_VENDOR_ID, USB_AVAYA_WIRELESS_ID)},
+	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0801_ID)},
+	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_MODEL0802_ID)},
+	{USB_DEVICE(USB_ELSA_VENDOR_ID, USB_ELSA_AIRLANCER_ID)},
+	{USB_DEVICE(USB_LEGEND_VENDOR_ID, USB_LEGEND_JOYNET_ID)},
+	{USB_DEVICE_VER(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U1_ID,
+			0, 0)},
+	{USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2001U2_ID)},
+	{USB_DEVICE(USB_SAMSUNG_VENDOR_ID, USB_SAMSUNG_SEW2003U_ID)},
+	{USB_DEVICE(USB_IGATE_VENDOR_ID, USB_IGATE_IGATE_11M_ID)},
+	{USB_DEVICE(USB_FUJITSU_VENDOR_ID, USB_FUJITSU_E1100_ID)},
+	{USB_DEVICE(USB_2WIRE_VENDOR_ID, USB_2WIRE_WIRELESS_ID)},
+	{USB_DEVICE(USB_AGERE_VENDOR_ID, USB_AGERE_REBRANDED_ID)},
+	{}			/* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, ezusb_table);
+
+/* Structure to hold all of our device specific stuff */
+struct ezusb_priv {
+	struct usb_device *udev;
+	struct net_device *dev;
+	struct mutex mtx;
+	spinlock_t req_lock;
+	struct list_head req_pending;
+	struct list_head req_active;
+	spinlock_t reply_count_lock;
+	u16 hermes_reg_fake[0x40];
+	u8 *bap_buf;
+	struct urb *read_urb;
+	int read_pipe;
+	int write_pipe;
+	u8 reply_count;
+};
+
+enum ezusb_state {
+	EZUSB_CTX_START,
+	EZUSB_CTX_QUEUED,
+	EZUSB_CTX_REQ_SUBMITTED,
+	EZUSB_CTX_REQ_COMPLETE,
+	EZUSB_CTX_RESP_RECEIVED,
+	EZUSB_CTX_REQ_TIMEOUT,
+	EZUSB_CTX_REQ_FAILED,
+	EZUSB_CTX_RESP_TIMEOUT,
+	EZUSB_CTX_REQSUBMIT_FAIL,
+	EZUSB_CTX_COMPLETE,
+};
+
+struct request_context {
+	struct list_head list;
+	atomic_t refcount;
+	struct completion done;	/* Signals that CTX is dead */
+	int killed;
+	struct urb *outurb;	/* OUT for req pkt */
+	struct ezusb_priv *upriv;
+	struct ezusb_packet *buf;
+	int buf_length;
+	struct timer_list timer;	/* Timeout handling */
+	enum ezusb_state state;	/* Current state */
+	/* the RID that we will wait for */
+	u16 out_rid;
+	u16 in_rid;
+};
+
+
+/* Forward declarations */
+static void ezusb_ctx_complete(struct request_context *ctx);
+static void ezusb_req_queue_run(struct ezusb_priv *upriv);
+static void ezusb_bulk_in_callback(struct urb *urb);
+
+static inline u8 ezusb_reply_inc(u8 count)
+{
+	if (count < 0x7F)
+		return count + 1;
+	else
+		return 1;
+}
+
+static void ezusb_request_context_put(struct request_context *ctx)
+{
+	if (!atomic_dec_and_test(&ctx->refcount))
+		return;
+
+	WARN_ON(!ctx->done.done);
+	BUG_ON(ctx->outurb->status == -EINPROGRESS);
+	BUG_ON(timer_pending(&ctx->timer));
+	usb_free_urb(ctx->outurb);
+	kfree(ctx->buf);
+	kfree(ctx);
+}
+
+static inline void ezusb_mod_timer(struct ezusb_priv *upriv,
+				   struct timer_list *timer,
+				   unsigned long expire)
+{
+	if (!upriv->udev)
+		return;
+	mod_timer(timer, expire);
+}
+
+static void ezusb_request_timerfn(u_long _ctx)
+{
+	struct request_context *ctx = (void *) _ctx;
+
+	ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
+	if (usb_unlink_urb(ctx->outurb) == -EINPROGRESS) {
+		ctx->state = EZUSB_CTX_REQ_TIMEOUT;
+	} else {
+		ctx->state = EZUSB_CTX_RESP_TIMEOUT;
+		dbg("couldn't unlink");
+		atomic_inc(&ctx->refcount);
+		ctx->killed = 1;
+		ezusb_ctx_complete(ctx);
+		ezusb_request_context_put(ctx);
+	}
+};
+
+static struct request_context *ezusb_alloc_ctx(struct ezusb_priv *upriv,
+					       u16 out_rid, u16 in_rid)
+{
+	struct request_context *ctx;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+	if (!ctx)
+		return NULL;
+
+	memset(ctx, 0, sizeof(*ctx));
+
+	ctx->buf = kmalloc(BULK_BUF_SIZE, GFP_ATOMIC);
+	if (!ctx->buf) {
+		kfree(ctx);
+		return NULL;
+	}
+	ctx->outurb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!ctx->outurb) {
+		kfree(ctx->buf);
+		kfree(ctx);
+		return NULL;
+	}
+
+	ctx->upriv = upriv;
+	ctx->state = EZUSB_CTX_START;
+	ctx->out_rid = out_rid;
+	ctx->in_rid = in_rid;
+
+	atomic_set(&ctx->refcount, 1);
+	init_completion(&ctx->done);
+
+	init_timer(&ctx->timer);
+	ctx->timer.function = ezusb_request_timerfn;
+	ctx->timer.data = (u_long) ctx;
+	return ctx;
+}
+
+
+/* Hopefully the real complete_all will soon be exported, in the mean
+ * while this should work. */
+static inline void ezusb_complete_all(struct completion *comp)
+{
+	complete(comp);
+	complete(comp);
+	complete(comp);
+	complete(comp);
+}
+
+static void ezusb_ctx_complete(struct request_context *ctx)
+{
+	struct ezusb_priv *upriv = ctx->upriv;
+	unsigned long flags;
+
+	spin_lock_irqsave(&upriv->req_lock, flags);
+
+	list_del_init(&ctx->list);
+	if (upriv->udev) {
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		ezusb_req_queue_run(upriv);
+		spin_lock_irqsave(&upriv->req_lock, flags);
+	}
+
+	switch (ctx->state) {
+	case EZUSB_CTX_COMPLETE:
+	case EZUSB_CTX_REQSUBMIT_FAIL:
+	case EZUSB_CTX_REQ_FAILED:
+	case EZUSB_CTX_REQ_TIMEOUT:
+	case EZUSB_CTX_RESP_TIMEOUT:
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+		if ((ctx->out_rid == EZUSB_RID_TX) && upriv->dev) {
+			struct net_device *dev = upriv->dev;
+			struct orinoco_private *priv = ndev_priv(dev);
+			struct net_device_stats *stats = &priv->stats;
+
+			if (ctx->state != EZUSB_CTX_COMPLETE)
+				stats->tx_errors++;
+			else
+				stats->tx_packets++;
+
+			netif_wake_queue(dev);
+		}
+		ezusb_complete_all(&ctx->done);
+		ezusb_request_context_put(ctx);
+		break;
+
+	default:
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		if (!upriv->udev) {
+			/* This is normal, as all request contexts get flushed
+			 * when the device is disconnected */
+			err("Called, CTX not terminating, but device gone");
+			ezusb_complete_all(&ctx->done);
+			ezusb_request_context_put(ctx);
+			break;
+		}
+
+		err("Called, CTX not in terminating state.");
+		/* Things are really bad if this happens. Just leak
+		 * the CTX because it may still be linked to the
+		 * queue or the OUT urb may still be active.
+		 * Just leaking at least prevents an Oops or Panic.
+		 */
+		break;
+	}
+}
+
+/**
+ * ezusb_req_queue_run:
+ * Description:
+ *	Note: Only one active CTX at any one time, because there's no
+ *	other (reliable) way to match the response URB to the correct
+ *	CTX.
+ **/
+static void ezusb_req_queue_run(struct ezusb_priv *upriv)
+{
+	unsigned long flags;
+	struct request_context *ctx;
+	int result;
+
+	spin_lock_irqsave(&upriv->req_lock, flags);
+
+	if (!list_empty(&upriv->req_active))
+		goto unlock;
+
+	if (list_empty(&upriv->req_pending))
+		goto unlock;
+
+	ctx =
+	    list_entry(upriv->req_pending.next, struct request_context,
+		       list);
+
+	if (!ctx->upriv->udev)
+		goto unlock;
+
+	/* We need to split this off to avoid a race condition */
+	list_move_tail(&ctx->list, &upriv->req_active);
+
+	if (ctx->state == EZUSB_CTX_QUEUED) {
+		atomic_inc(&ctx->refcount);
+		result = usb_submit_urb(ctx->outurb, GFP_ATOMIC);
+		if (result) {
+			ctx->state = EZUSB_CTX_REQSUBMIT_FAIL;
+
+			spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+			err("Fatal, failed to submit command urb."
+			    " error=%d\n", result);
+
+			ezusb_ctx_complete(ctx);
+			ezusb_request_context_put(ctx);
+			goto done;
+		}
+
+		ctx->state = EZUSB_CTX_REQ_SUBMITTED;
+		ezusb_mod_timer(ctx->upriv, &ctx->timer,
+				jiffies + DEF_TIMEOUT);
+	}
+
+ unlock:
+	spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+ done:
+	return;
+}
+
+static void ezusb_req_enqueue_run(struct ezusb_priv *upriv,
+				  struct request_context *ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&upriv->req_lock, flags);
+
+	if (!ctx->upriv->udev) {
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		goto done;
+	}
+	atomic_inc(&ctx->refcount);
+	list_add_tail(&ctx->list, &upriv->req_pending);
+	spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+	ctx->state = EZUSB_CTX_QUEUED;
+	ezusb_req_queue_run(upriv);
+
+ done:
+	return;
+}
+
+static void ezusb_request_out_callback(struct urb *urb)
+{
+	unsigned long flags;
+	enum ezusb_state state;
+	struct request_context *ctx = urb->context;
+	struct ezusb_priv *upriv = ctx->upriv;
+
+	spin_lock_irqsave(&upriv->req_lock, flags);
+
+	del_timer(&ctx->timer);
+
+	if (ctx->killed) {
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		pr_warning("interrupt called with dead ctx");
+		goto out;
+	}
+
+	state = ctx->state;
+
+	if (urb->status == 0) {
+		switch (state) {
+		case EZUSB_CTX_REQ_SUBMITTED:
+			if (ctx->in_rid) {
+				ctx->state = EZUSB_CTX_REQ_COMPLETE;
+				/* reply URB still pending */
+				ezusb_mod_timer(upriv, &ctx->timer,
+						jiffies + DEF_TIMEOUT);
+				spin_unlock_irqrestore(&upriv->req_lock,
+						       flags);
+				break;
+			}
+			/* fall through */
+		case EZUSB_CTX_RESP_RECEIVED:
+			/* IN already received before this OUT-ACK */
+			ctx->state = EZUSB_CTX_COMPLETE;
+			spin_unlock_irqrestore(&upriv->req_lock, flags);
+			ezusb_ctx_complete(ctx);
+			break;
+
+		default:
+			spin_unlock_irqrestore(&upriv->req_lock, flags);
+			err("Unexpected state(0x%x, %d) in OUT URB",
+			    state, urb->status);
+			break;
+		}
+	} else {
+		/* If someone cancels the OUT URB then its status
+		 * should be either -ECONNRESET or -ENOENT.
+		 */
+		switch (state) {
+		case EZUSB_CTX_REQ_SUBMITTED:
+		case EZUSB_CTX_RESP_RECEIVED:
+			ctx->state = EZUSB_CTX_REQ_FAILED;
+			/* fall through */
+
+		case EZUSB_CTX_REQ_FAILED:
+		case EZUSB_CTX_REQ_TIMEOUT:
+			spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+			ezusb_ctx_complete(ctx);
+			break;
+
+		default:
+			spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+			err("Unexpected state(0x%x, %d) in OUT URB",
+			    state, urb->status);
+			break;
+		}
+	}
+ out:
+	ezusb_request_context_put(ctx);
+}
+
+static void ezusb_request_in_callback(struct ezusb_priv *upriv,
+				      struct urb *urb)
+{
+	struct ezusb_packet *ans = urb->transfer_buffer;
+	struct request_context *ctx = NULL;
+	enum ezusb_state state;
+	unsigned long flags;
+
+	/* Find the CTX on the active queue that requested this URB */
+	spin_lock_irqsave(&upriv->req_lock, flags);
+	if (upriv->udev) {
+		struct list_head *item;
+
+		list_for_each(item, &upriv->req_active) {
+			struct request_context *c;
+			int reply_count;
+
+			c = list_entry(item, struct request_context, list);
+			reply_count =
+			    ezusb_reply_inc(c->buf->req_reply_count);
+			if ((ans->ans_reply_count == reply_count)
+			    && (le16_to_cpu(ans->hermes_rid) == c->in_rid)) {
+				ctx = c;
+				break;
+			}
+			dbg("Skipped (0x%x/0x%x) (%d/%d)",
+			    le16_to_cpu(ans->hermes_rid),
+			    c->in_rid, ans->ans_reply_count, reply_count);
+		}
+	}
+
+	if (ctx == NULL) {
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		err("%s: got unexpected RID: 0x%04X", __func__,
+		    le16_to_cpu(ans->hermes_rid));
+		ezusb_req_queue_run(upriv);
+		return;
+	}
+
+	/* The data we want is in the in buffer, exchange */
+	urb->transfer_buffer = ctx->buf;
+	ctx->buf = (void *) ans;
+	ctx->buf_length = urb->actual_length;
+
+	state = ctx->state;
+	switch (state) {
+	case EZUSB_CTX_REQ_SUBMITTED:
+		/* We have received our response URB before
+		 * our request has been acknowledged. Do NOT
+		 * destroy our CTX yet, because our OUT URB
+		 * is still alive ...
+		 */
+		ctx->state = EZUSB_CTX_RESP_RECEIVED;
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+		/* Let the machine continue running. */
+		break;
+
+	case EZUSB_CTX_REQ_COMPLETE:
+		/* This is the usual path: our request
+		 * has already been acknowledged, and
+		 * we have now received the reply.
+		 */
+		ctx->state = EZUSB_CTX_COMPLETE;
+
+		/* Stop the intimer */
+		del_timer(&ctx->timer);
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+		/* Call the completion handler */
+		ezusb_ctx_complete(ctx);
+		break;
+
+	default:
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+		pr_warning("Matched IN URB, unexpected context state(0x%x)",
+		     state);
+		/* Throw this CTX away and try submitting another */
+		del_timer(&ctx->timer);
+		ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
+		usb_unlink_urb(ctx->outurb);
+		ezusb_req_queue_run(upriv);
+		break;
+	}			/* switch */
+}
+
+
+static void ezusb_req_ctx_wait(struct ezusb_priv *upriv,
+			       struct request_context *ctx)
+{
+	switch (ctx->state) {
+	case EZUSB_CTX_QUEUED:
+	case EZUSB_CTX_REQ_SUBMITTED:
+	case EZUSB_CTX_REQ_COMPLETE:
+	case EZUSB_CTX_RESP_RECEIVED:
+		if (in_softirq()) {
+			/* If we get called from a timer, timeout timers don't
+			 * get the chance to run themselves. So we make sure
+			 * that we don't sleep for ever */
+			int msecs = DEF_TIMEOUT * (1000 / HZ);
+			while (!ctx->done.done && msecs--)
+				udelay(1000);
+		} else {
+			wait_event_interruptible(ctx->done.wait,
+						 ctx->done.done);
+		}
+		break;
+	default:
+		/* Done or failed - nothing to wait for */
+		break;
+	}
+}
+
+static inline u16 build_crc(struct ezusb_packet *data)
+{
+	u16 crc = 0;
+	u8 *bytes = (u8 *)data;
+	int i;
+
+	for (i = 0; i < 8; i++)
+		crc = (crc << 1) + bytes[i];
+
+	return crc;
+}
+
+/**
+ * ezusb_fill_req:
+ *
+ * if data == NULL and length > 0 the data is assumed to be already in
+ * the target buffer and only the header is filled.
+ *
+ */
+static int ezusb_fill_req(struct ezusb_packet *req, u16 length, u16 rid,
+			  const void *data, u16 frame_type, u8 reply_count)
+{
+	int total_size = sizeof(*req) + length;
+
+	BUG_ON(total_size > BULK_BUF_SIZE);
+
+	req->magic = cpu_to_le16(EZUSB_MAGIC);
+	req->req_reply_count = reply_count;
+	req->ans_reply_count = 0;
+	req->frame_type = cpu_to_le16(frame_type);
+	req->size = cpu_to_le16(length + 4);
+	req->crc = cpu_to_le16(build_crc(req));
+	req->hermes_len = cpu_to_le16(HERMES_BYTES_TO_RECLEN(length));
+	req->hermes_rid = cpu_to_le16(rid);
+	if (data)
+		memcpy(req->data, data, length);
+	return total_size;
+}
+
+static int ezusb_submit_in_urb(struct ezusb_priv *upriv)
+{
+	int retval = 0;
+	void *cur_buf = upriv->read_urb->transfer_buffer;
+
+	if (upriv->read_urb->status == -EINPROGRESS) {
+		dbg("urb busy, not resubmiting");
+		retval = -EBUSY;
+		goto exit;
+	}
+	usb_fill_bulk_urb(upriv->read_urb, upriv->udev, upriv->read_pipe,
+			  cur_buf, BULK_BUF_SIZE,
+			  ezusb_bulk_in_callback, upriv);
+	upriv->read_urb->transfer_flags = 0;
+	retval = usb_submit_urb(upriv->read_urb, GFP_ATOMIC);
+	if (retval)
+		err("%s submit failed %d", __func__, retval);
+
+ exit:
+	return retval;
+}
+
+static inline int ezusb_8051_cpucs(struct ezusb_priv *upriv, int reset)
+{
+	u8 res_val = reset;	/* avoid argument promotion */
+
+	if (!upriv->udev) {
+		err("%s: !upriv->udev", __func__);
+		return -EFAULT;
+	}
+	return usb_control_msg(upriv->udev,
+			       usb_sndctrlpipe(upriv->udev, 0),
+			       EZUSB_REQUEST_FW_TRANS,
+			       USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+			       USB_DIR_OUT, EZUSB_CPUCS_REG, 0, &res_val,
+			       sizeof(res_val), DEF_TIMEOUT);
+}
+
+static int ezusb_firmware_download(struct ezusb_priv *upriv,
+				   struct ez_usb_fw *fw)
+{
+	u8 fw_buffer[FW_BUF_SIZE];
+	int retval, addr;
+	int variant_offset;
+
+	/*
+	 * This byte is 1 and should be replaced with 0.  The offset is
+	 * 0x10AD in version 0.0.6.  The byte in question should follow
+	 * the end of the code pointed to by the jump in the beginning
+	 * of the firmware.  Also, it is read by code located at 0x358.
+	 */
+	variant_offset = be16_to_cpup((__be16 *) &fw->code[FW_VAR_OFFSET_PTR]);
+	if (variant_offset >= fw->size) {
+		printk(KERN_ERR PFX "Invalid firmware variant offset: "
+		       "0x%04x\n", variant_offset);
+		retval = -EINVAL;
+		goto fail;
+	}
+
+	retval = ezusb_8051_cpucs(upriv, 1);
+	if (retval < 0)
+		goto fail;
+	for (addr = 0; addr < fw->size; addr += FW_BUF_SIZE) {
+		/* 0x100-0x300 should be left alone, it contains card
+		 * specific data, like USB enumeration information */
+		if ((addr >= FW_HOLE_START) && (addr < FW_HOLE_END))
+			continue;
+
+		memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE);
+		if (variant_offset >= addr &&
+		    variant_offset < addr + FW_BUF_SIZE) {
+			dbg("Patching card_variant byte at 0x%04X",
+			    variant_offset);
+			fw_buffer[variant_offset - addr] = FW_VAR_VALUE;
+		}
+		retval = usb_control_msg(upriv->udev,
+					 usb_sndctrlpipe(upriv->udev, 0),
+					 EZUSB_REQUEST_FW_TRANS,
+					 USB_TYPE_VENDOR | USB_RECIP_DEVICE
+					 | USB_DIR_OUT,
+					 addr, 0x0,
+					 fw_buffer, FW_BUF_SIZE,
+					 DEF_TIMEOUT);
+
+		if (retval < 0)
+			goto fail;
+	}
+	retval = ezusb_8051_cpucs(upriv, 0);
+	if (retval < 0)
+		goto fail;
+
+	goto exit;
+ fail:
+	printk(KERN_ERR PFX "Firmware download failed, error %d\n",
+	       retval);
+ exit:
+	return retval;
+}
+
+static int ezusb_access_ltv(struct ezusb_priv *upriv,
+			    struct request_context *ctx,
+			    u16 length, const void *data, u16 frame_type,
+			    void *ans_buff, int ans_size, u16 *ans_length)
+{
+	int req_size;
+	int retval = 0;
+	enum ezusb_state state;
+
+	BUG_ON(in_irq());
+
+	if (!upriv->udev) {
+		dbg("Device disconnected");
+		return -ENODEV;
+	}
+
+	if (upriv->read_urb->status != -EINPROGRESS)
+		err("%s: in urb not pending", __func__);
+
+	/* protect upriv->reply_count, guarantee sequential numbers */
+	spin_lock_bh(&upriv->reply_count_lock);
+	req_size = ezusb_fill_req(ctx->buf, length, ctx->out_rid, data,
+				  frame_type, upriv->reply_count);
+	usb_fill_bulk_urb(ctx->outurb, upriv->udev, upriv->write_pipe,
+			  ctx->buf, req_size,
+			  ezusb_request_out_callback, ctx);
+
+	if (ctx->in_rid)
+		upriv->reply_count = ezusb_reply_inc(upriv->reply_count);
+
+	ezusb_req_enqueue_run(upriv, ctx);
+
+	spin_unlock_bh(&upriv->reply_count_lock);
+
+	if (ctx->in_rid)
+		ezusb_req_ctx_wait(upriv, ctx);
+
+	state = ctx->state;
+	switch (state) {
+	case EZUSB_CTX_COMPLETE:
+		retval = ctx->outurb->status;
+		break;
+
+	case EZUSB_CTX_QUEUED:
+	case EZUSB_CTX_REQ_SUBMITTED:
+		if (!ctx->in_rid)
+			break;
+	default:
+		err("%s: Unexpected context state %d", __func__,
+		    state);
+		/* fall though */
+	case EZUSB_CTX_REQ_TIMEOUT:
+	case EZUSB_CTX_REQ_FAILED:
+	case EZUSB_CTX_RESP_TIMEOUT:
+	case EZUSB_CTX_REQSUBMIT_FAIL:
+		printk(KERN_ERR PFX "Access failed, resetting (state %d,"
+		       " reply_count %d)\n", state, upriv->reply_count);
+		upriv->reply_count = 0;
+		if (state == EZUSB_CTX_REQ_TIMEOUT
+		    || state == EZUSB_CTX_RESP_TIMEOUT) {
+			printk(KERN_ERR PFX "ctx timed out\n");
+			retval = -ETIMEDOUT;
+		} else {
+			printk(KERN_ERR PFX "ctx failed\n");
+			retval = -EFAULT;
+		}
+		goto exit;
+		break;
+	}
+	if (ctx->in_rid) {
+		struct ezusb_packet *ans = ctx->buf;
+		int exp_len;
+
+		if (ans->hermes_len != 0)
+			exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
+		else
+			exp_len = 14;
+
+		if (exp_len != ctx->buf_length) {
+			err("%s: length mismatch for RID 0x%04x: "
+			    "expected %d, got %d", __func__,
+			    ctx->in_rid, exp_len, ctx->buf_length);
+			retval = -EIO;
+			goto exit;
+		}
+
+		if (ans_buff)
+			memcpy(ans_buff, ans->data,
+			       min_t(int, exp_len, ans_size));
+		if (ans_length)
+			*ans_length = le16_to_cpu(ans->hermes_len);
+	}
+ exit:
+	ezusb_request_context_put(ctx);
+	return retval;
+}
+
+static int ezusb_write_ltv(hermes_t *hw, int bap, u16 rid,
+			   u16 length, const void *data)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	u16 frame_type;
+	struct request_context *ctx;
+
+	if (length == 0)
+		return -EINVAL;
+
+	length = HERMES_RECLEN_TO_BYTES(length);
+
+	/* On memory mapped devices HERMES_RID_CNFGROUPADDRESSES can be
+	 * set to be empty, but the USB bridge doesn't like it */
+	if (length == 0)
+		return 0;
+
+	ctx = ezusb_alloc_ctx(upriv, rid, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	if (rid == EZUSB_RID_TX)
+		frame_type = EZUSB_FRAME_DATA;
+	else
+		frame_type = EZUSB_FRAME_CONTROL;
+
+	return ezusb_access_ltv(upriv, ctx, length, data, frame_type,
+				NULL, 0, NULL);
+}
+
+static int ezusb_read_ltv(hermes_t *hw, int bap, u16 rid,
+			  unsigned bufsize, u16 *length, void *buf)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+
+	if ((bufsize < 0) || (bufsize % 2))
+		return -EINVAL;
+
+	ctx = ezusb_alloc_ctx(upriv, rid, rid);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, 0, NULL, EZUSB_FRAME_CONTROL,
+				buf, bufsize, length);
+}
+
+static int ezusb_doicmd_wait(hermes_t *hw, u16 cmd, u16 parm0, u16 parm1,
+			     u16 parm2, struct hermes_response *resp)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+
+	__le16 data[4] = {
+		cpu_to_le16(cmd),
+		cpu_to_le16(parm0),
+		cpu_to_le16(parm1),
+		cpu_to_le16(parm2),
+	};
+	dbg("0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X",
+	    cmd, parm0, parm1, parm2);
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
+				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+}
+
+static int ezusb_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
+			    struct hermes_response *resp)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+
+	__le16 data[4] = {
+		cpu_to_le16(cmd),
+		cpu_to_le16(parm0),
+		0,
+		0,
+	};
+	dbg("0x%04X, parm0 0x%04X", cmd, parm0);
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
+				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+}
+
+static int ezusb_bap_pread(struct hermes *hw, int bap,
+			   void *buf, int len, u16 id, u16 offset)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct ezusb_packet *ans = (void *) upriv->read_urb->transfer_buffer;
+	int actual_length = upriv->read_urb->actual_length;
+
+	if (id == EZUSB_RID_RX) {
+		if ((sizeof(*ans) + offset + len) > actual_length) {
+			printk(KERN_ERR PFX "BAP read beyond buffer end "
+			       "in rx frame\n");
+			return -EINVAL;
+		}
+		memcpy(buf, ans->data + offset, len);
+		return 0;
+	}
+
+	if (EZUSB_IS_INFO(id)) {
+		/* Include 4 bytes for length/type */
+		if ((sizeof(*ans) + offset + len - 4) > actual_length) {
+			printk(KERN_ERR PFX "BAP read beyond buffer end "
+			       "in info frame\n");
+			return -EFAULT;
+		}
+		memcpy(buf, ans->data + offset - 4, len);
+	} else {
+		printk(KERN_ERR PFX "Unexpected fid 0x%04x\n", id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ezusb_read_pda(struct hermes *hw, __le16 *pda,
+			  u32 pda_addr, u16 pda_len)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+	__le16 data[] = {
+		cpu_to_le16(pda_addr & 0xffff),
+		cpu_to_le16(pda_len - 4)
+	};
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_READ_PDA, EZUSB_RID_READ_PDA);
+	if (!ctx)
+		return -ENOMEM;
+
+	/* wl_lkm does not include PDA size in the PDA area.
+	 * We will pad the information into pda, so other routines
+	 * don't have to be modified */
+	pda[0] = cpu_to_le16(pda_len - 2);
+	/* Includes CFG_PROD_DATA but not itself */
+	pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
+
+	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
+				EZUSB_FRAME_CONTROL, &pda[2], pda_len - 4,
+				NULL);
+}
+
+static int ezusb_program_init(struct hermes *hw, u32 entry_point)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+	__le32 data = cpu_to_le32(entry_point);
+
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_INIT, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
+				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+}
+
+static int ezusb_program_end(struct hermes *hw)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_END, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, 0, NULL,
+				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+}
+
+static int ezusb_program_bytes(struct hermes *hw, const char *buf,
+			       u32 addr, u32 len)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	struct request_context *ctx;
+	__le32 data = cpu_to_le32(addr);
+	int err;
+
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_SET_ADDR, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	err = ezusb_access_ltv(upriv, ctx, sizeof(data), &data,
+			       EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+	if (err)
+		return err;
+
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_PROG_BYTES, EZUSB_RID_ACK);
+	if (!ctx)
+		return -ENOMEM;
+
+	return ezusb_access_ltv(upriv, ctx, len, buf,
+				EZUSB_FRAME_CONTROL, NULL, 0, NULL);
+}
+
+static int ezusb_program(struct hermes *hw, const char *buf,
+			 u32 addr, u32 len)
+{
+	u32 ch_addr;
+	u32 ch_len;
+	int err = 0;
+
+	/* We can only send 2048 bytes out of the bulk xmit at a time,
+	 * so we have to split any programming into chunks of <2048
+	 * bytes. */
+
+	ch_len = (len < MAX_DL_SIZE) ? len : MAX_DL_SIZE;
+	ch_addr = addr;
+
+	while (ch_addr < (addr + len)) {
+		pr_debug("Programming subblock of length %d "
+			 "to address 0x%08x. Data @ %p\n",
+			 ch_len, ch_addr, &buf[ch_addr - addr]);
+
+		err = ezusb_program_bytes(hw, &buf[ch_addr - addr],
+					  ch_addr, ch_len);
+		if (err)
+			break;
+
+		ch_addr += ch_len;
+		ch_len = ((addr + len - ch_addr) < MAX_DL_SIZE) ?
+			(addr + len - ch_addr) : MAX_DL_SIZE;
+	}
+
+	return err;
+}
+
+static netdev_tx_t ezusb_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct orinoco_private *priv = ndev_priv(dev);
+	struct net_device_stats *stats = &priv->stats;
+	struct ezusb_priv *upriv = priv->card;
+	int err = 0;
+	char *p;
+	struct ethhdr *eh;
+	int len, data_len, data_off;
+	__le16 tx_control;
+	unsigned long flags;
+	struct request_context *ctx;
+	u8 *buf;
+	int tx_size;
+
+	if (!netif_running(dev)) {
+		printk(KERN_ERR "%s: Tx on stopped device!\n",
+		       dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (netif_queue_stopped(dev)) {
+		printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
+		       dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (orinoco_lock(priv, &flags) != 0) {
+		printk(KERN_ERR
+		       "%s: orinoco_xmit() called while hw_unavailable\n",
+		       dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	if (!netif_carrier_ok(dev) ||
+	    (priv->iw_mode == NL80211_IFTYPE_MONITOR)) {
+		/* Oops, the firmware hasn't established a connection,
+		   silently drop the packet (this seems to be the
+		   safest approach). */
+		stats->tx_errors++;
+		orinoco_unlock(priv, &flags);
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_TX, 0);
+	if (!ctx)
+		goto fail;
+
+	memset(ctx->buf, 0, BULK_BUF_SIZE);
+	buf = ctx->buf->data;
+
+	/* Length of the packet body */
+	/* FIXME: what if the skb is smaller than this? */
+	len = max_t(int, skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
+
+	eh = (struct ethhdr *) skb->data;
+
+	tx_control = cpu_to_le16(0);
+	memcpy(buf, &tx_control, sizeof(tx_control));
+	buf += sizeof(tx_control);
+	/* Encapsulate Ethernet-II frames */
+	if (ntohs(eh->h_proto) > ETH_DATA_LEN) {	/* Ethernet-II frame */
+		struct header_struct *hdr = (void *) buf;
+		buf += sizeof(*hdr);
+		data_len = len;
+		data_off = sizeof(tx_control) + sizeof(*hdr);
+		p = skb->data + ETH_HLEN;
+
+		/* 802.3 header */
+		memcpy(hdr->dest, eh->h_dest, ETH_ALEN);
+		memcpy(hdr->src, eh->h_source, ETH_ALEN);
+		hdr->len = htons(data_len + ENCAPS_OVERHEAD);
+
+		/* 802.2 header */
+		memcpy(&hdr->dsap, &encaps_hdr, sizeof(encaps_hdr));
+
+		hdr->ethertype = eh->h_proto;
+	} else {		/* IEEE 802.3 frame */
+		data_len = len + ETH_HLEN;
+		data_off = sizeof(tx_control);
+		p = skb->data;
+	}
+
+	memcpy(buf, p, data_len);
+	buf += data_len;
+
+	/* Finally, we actually initiate the send */
+	netif_stop_queue(dev);
+
+	/* The card may behave better if we send evenly sized usb transfers */
+	tx_size = ALIGN(buf - ctx->buf->data, 2);
+
+	err = ezusb_access_ltv(upriv, ctx, tx_size, NULL,
+			       EZUSB_FRAME_DATA, NULL, 0, NULL);
+
+	if (err) {
+		netif_start_queue(dev);
+		if (net_ratelimit())
+			printk(KERN_ERR "%s: Error %d transmitting packet\n",
+				dev->name, err);
+		stats->tx_errors++;
+		goto fail;
+	}
+
+	dev->trans_start = jiffies;
+	stats->tx_bytes += data_off + data_len;
+
+	orinoco_unlock(priv, &flags);
+
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+
+ fail:
+	orinoco_unlock(priv, &flags);
+	return NETDEV_TX_BUSY;
+}
+
+static int ezusb_allocate(struct hermes *hw, u16 size, u16 *fid)
+{
+	*fid = EZUSB_RID_TX;
+	return 0;
+}
+
+
+static int ezusb_hard_reset(struct orinoco_private *priv)
+{
+	struct ezusb_priv *upriv = priv->card;
+	int retval = ezusb_8051_cpucs(upriv, 1);
+
+	if (retval < 0) {
+		err("Failed to reset");
+		return retval;
+	}
+
+	retval = ezusb_8051_cpucs(upriv, 0);
+	if (retval < 0) {
+		err("Failed to unreset");
+		return retval;
+	}
+
+	dbg("sending control message");
+	retval = usb_control_msg(upriv->udev,
+				 usb_sndctrlpipe(upriv->udev, 0),
+				 EZUSB_REQUEST_TRIGER,
+				 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+				 USB_DIR_OUT, 0x0, 0x0, NULL, 0,
+				 DEF_TIMEOUT);
+	if (retval < 0) {
+		err("EZUSB_REQUEST_TRIGER failed retval %d", retval);
+		return retval;
+	}
+#if 0
+	dbg("Sending EZUSB_REQUEST_TRIG_AC");
+	retval = usb_control_msg(upriv->udev,
+				 usb_sndctrlpipe(upriv->udev, 0),
+				 EZUSB_REQUEST_TRIG_AC,
+				 USB_TYPE_VENDOR | USB_RECIP_DEVICE |
+				 USB_DIR_OUT, 0x00FA, 0x0, NULL, 0,
+				 DEF_TIMEOUT);
+	if (retval < 0) {
+		err("EZUSB_REQUEST_TRIG_AC failed retval %d", retval);
+		return retval;
+	}
+#endif
+
+	return 0;
+}
+
+
+static int ezusb_init(hermes_t *hw)
+{
+	struct ezusb_priv *upriv = hw->priv;
+	int retval;
+
+	BUG_ON(in_interrupt());
+	BUG_ON(!upriv);
+
+	upriv->reply_count = 0;
+	/* Write the MAGIC number on the simulated registers to keep
+	 * orinoco.c happy */
+	hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
+	hermes_write_regn(hw, RXFID, EZUSB_RID_RX);
+
+	usb_kill_urb(upriv->read_urb);
+	ezusb_submit_in_urb(upriv);
+
+	retval = ezusb_write_ltv(hw, 0, EZUSB_RID_INIT1,
+				 HERMES_BYTES_TO_RECLEN(2), "\x10\x00");
+	if (retval < 0) {
+		printk(KERN_ERR PFX "EZUSB_RID_INIT1 error %d\n", retval);
+		return retval;
+	}
+
+	retval = ezusb_docmd_wait(hw, HERMES_CMD_INIT, 0, NULL);
+	if (retval < 0) {
+		printk(KERN_ERR PFX "HERMES_CMD_INIT error %d\n", retval);
+		return retval;
+	}
+
+	return 0;
+}
+
+static void ezusb_bulk_in_callback(struct urb *urb)
+{
+	struct ezusb_priv *upriv = (struct ezusb_priv *) urb->context;
+	struct ezusb_packet *ans = urb->transfer_buffer;
+	u16 crc;
+	u16 hermes_rid;
+
+	if (upriv->udev == NULL) {
+		dbg("disconnected");
+		return;
+	}
+
+	if (urb->status == -ETIMEDOUT) {
+		/* When a device gets unplugged we get this every time
+		 * we resubmit, flooding the logs.  Since we don't use
+		 * USB timeouts, it shouldn't happen any other time*/
+		pr_warning("%s: urb timed out, not resubmiting", __func__);
+		return;
+	}
+	if (urb->status == -ECONNABORTED) {
+		pr_warning("%s: connection abort, resubmiting urb",
+		     __func__);
+		goto resubmit;
+	}
+	if ((urb->status == -EILSEQ)
+	    || (urb->status == -ENOENT)
+	    || (urb->status == -ECONNRESET)) {
+		dbg("status %d, not resubmiting", urb->status);
+		return;
+	}
+	if (urb->status)
+		dbg("status: %d length: %d",
+		    urb->status, urb->actual_length);
+	if (urb->actual_length < sizeof(*ans)) {
+		err("%s: short read, ignoring", __func__);
+		goto resubmit;
+	}
+	crc = build_crc(ans);
+	if (le16_to_cpu(ans->crc) != crc) {
+		err("CRC error, ignoring packet");
+		goto resubmit;
+	}
+
+	hermes_rid = le16_to_cpu(ans->hermes_rid);
+	if ((hermes_rid != EZUSB_RID_RX) && !EZUSB_IS_INFO(hermes_rid)) {
+		ezusb_request_in_callback(upriv, urb);
+	} else if (upriv->dev) {
+		struct net_device *dev = upriv->dev;
+		struct orinoco_private *priv = ndev_priv(dev);
+		hermes_t *hw = &priv->hw;
+
+		if (hermes_rid == EZUSB_RID_RX) {
+			__orinoco_ev_rx(dev, hw);
+		} else {
+			hermes_write_regn(hw, INFOFID,
+					  le16_to_cpu(ans->hermes_rid));
+			__orinoco_ev_info(dev, hw);
+		}
+	}
+
+ resubmit:
+	if (upriv->udev)
+		ezusb_submit_in_urb(upriv);
+}
+
+static inline void ezusb_delete(struct ezusb_priv *upriv)
+{
+	struct net_device *dev;
+	struct list_head *item;
+	struct list_head *tmp_item;
+	unsigned long flags;
+
+	BUG_ON(in_interrupt());
+	BUG_ON(!upriv);
+
+	dev = upriv->dev;
+	mutex_lock(&upriv->mtx);
+
+	upriv->udev = NULL;	/* No timer will be rearmed from here */
+
+	usb_kill_urb(upriv->read_urb);
+
+	spin_lock_irqsave(&upriv->req_lock, flags);
+	list_for_each_safe(item, tmp_item, &upriv->req_active) {
+		struct request_context *ctx;
+		int err;
+
+		ctx = list_entry(item, struct request_context, list);
+		atomic_inc(&ctx->refcount);
+
+		ctx->outurb->transfer_flags |= URB_ASYNC_UNLINK;
+		err = usb_unlink_urb(ctx->outurb);
+
+		spin_unlock_irqrestore(&upriv->req_lock, flags);
+		if (err == -EINPROGRESS)
+			wait_for_completion(&ctx->done);
+
+		del_timer_sync(&ctx->timer);
+		/* FIXME: there is an slight chance for the irq handler to
+		 * be running */
+		if (!list_empty(&ctx->list))
+			ezusb_ctx_complete(ctx);
+
+		ezusb_request_context_put(ctx);
+		spin_lock_irqsave(&upriv->req_lock, flags);
+	}
+	spin_unlock_irqrestore(&upriv->req_lock, flags);
+
+	list_for_each_safe(item, tmp_item, &upriv->req_pending)
+	    ezusb_ctx_complete(list_entry(item,
+					  struct request_context, list));
+
+	if (upriv->read_urb->status == -EINPROGRESS)
+		printk(KERN_ERR PFX "Some URB in progress\n");
+
+	mutex_unlock(&upriv->mtx);
+
+	kfree(upriv->read_urb->transfer_buffer);
+	if (upriv->bap_buf != NULL)
+		kfree(upriv->bap_buf);
+	if (upriv->read_urb != NULL)
+		usb_free_urb(upriv->read_urb);
+	if (upriv->dev) {
+		struct orinoco_private *priv = ndev_priv(upriv->dev);
+		orinoco_if_del(priv);
+		free_orinocodev(priv);
+	}
+}
+
+static void ezusb_lock_irqsave(spinlock_t *lock,
+			       unsigned long *flags) __acquires(lock)
+{
+	spin_lock_bh(lock);
+}
+
+static void ezusb_unlock_irqrestore(spinlock_t *lock,
+				    unsigned long *flags) __releases(lock)
+{
+	spin_unlock_bh(lock);
+}
+
+static void ezusb_lock_irq(spinlock_t *lock) __acquires(lock)
+{
+	spin_lock_bh(lock);
+}
+
+static void ezusb_unlock_irq(spinlock_t *lock) __releases(lock)
+{
+	spin_unlock_bh(lock);
+}
+
+static const struct hermes_ops ezusb_ops = {
+	.init = ezusb_init,
+	.cmd_wait = ezusb_docmd_wait,
+	.init_cmd_wait = ezusb_doicmd_wait,
+	.allocate = ezusb_allocate,
+	.read_ltv = ezusb_read_ltv,
+	.write_ltv = ezusb_write_ltv,
+	.bap_pread = ezusb_bap_pread,
+	.read_pda = ezusb_read_pda,
+	.program_init = ezusb_program_init,
+	.program_end = ezusb_program_end,
+	.program = ezusb_program,
+	.lock_irqsave = ezusb_lock_irqsave,
+	.unlock_irqrestore = ezusb_unlock_irqrestore,
+	.lock_irq = ezusb_lock_irq,
+	.unlock_irq = ezusb_unlock_irq,
+};
+
+static const struct net_device_ops ezusb_netdev_ops = {
+	.ndo_open		= orinoco_open,
+	.ndo_stop		= orinoco_stop,
+	.ndo_start_xmit		= ezusb_xmit,
+	.ndo_set_multicast_list	= orinoco_set_multicast_list,
+	.ndo_change_mtu		= orinoco_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_tx_timeout		= orinoco_tx_timeout,
+	.ndo_get_stats		= orinoco_get_stats,
+};
+
+static int ezusb_probe(struct usb_interface *interface,
+		       const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct orinoco_private *priv;
+	hermes_t *hw;
+	struct ezusb_priv *upriv = NULL;
+	struct usb_interface_descriptor *iface_desc;
+	struct usb_endpoint_descriptor *ep;
+	const struct firmware *fw_entry;
+	int retval = 0;
+	int i;
+
+	priv = alloc_orinocodev(sizeof(*upriv), &udev->dev,
+				ezusb_hard_reset, NULL);
+	if (!priv) {
+		err("Couldn't allocate orinocodev");
+		goto exit;
+	}
+
+	hw = &priv->hw;
+
+	upriv = priv->card;
+
+	mutex_init(&upriv->mtx);
+	spin_lock_init(&upriv->reply_count_lock);
+
+	spin_lock_init(&upriv->req_lock);
+	INIT_LIST_HEAD(&upriv->req_pending);
+	INIT_LIST_HEAD(&upriv->req_active);
+
+	upriv->udev = udev;
+
+	hw->iobase = (void __force __iomem *) &upriv->hermes_reg_fake;
+	hw->reg_spacing = HERMES_16BIT_REGSPACING;
+	hw->priv = upriv;
+	hw->ops = &ezusb_ops;
+
+	/* set up the endpoint information */
+	/* check out the endpoints */
+
+	iface_desc = &interface->altsetting[0].desc;
+	for (i = 0; i < iface_desc->bNumEndpoints; ++i) {
+		ep = &interface->altsetting[0].endpoint[i].desc;
+
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		     == USB_DIR_IN) &&
+		    ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+		     == USB_ENDPOINT_XFER_BULK)) {
+			/* we found a bulk in endpoint */
+			if (upriv->read_urb != NULL) {
+				pr_warning("Found a second bulk in ep, ignored");
+				continue;
+			}
+
+			upriv->read_urb = usb_alloc_urb(0, GFP_KERNEL);
+			if (!upriv->read_urb) {
+				err("No free urbs available");
+				goto error;
+			}
+			if (le16_to_cpu(ep->wMaxPacketSize) != 64)
+				pr_warning("bulk in: wMaxPacketSize!= 64");
+			if (ep->bEndpointAddress != (2 | USB_DIR_IN))
+				pr_warning("bulk in: bEndpointAddress: %d",
+				     ep->bEndpointAddress);
+			upriv->read_pipe = usb_rcvbulkpipe(udev,
+							 ep->
+							 bEndpointAddress);
+			upriv->read_urb->transfer_buffer =
+			    kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
+			if (!upriv->read_urb->transfer_buffer) {
+				err("Couldn't allocate IN buffer");
+				goto error;
+			}
+		}
+
+		if (((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+		     == USB_DIR_OUT) &&
+		    ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+		     == USB_ENDPOINT_XFER_BULK)) {
+			/* we found a bulk out endpoint */
+			if (upriv->bap_buf != NULL) {
+				pr_warning("Found a second bulk out ep, ignored");
+				continue;
+			}
+
+			if (le16_to_cpu(ep->wMaxPacketSize) != 64)
+				pr_warning("bulk out: wMaxPacketSize != 64");
+			if (ep->bEndpointAddress != 2)
+				pr_warning("bulk out: bEndpointAddress: %d",
+				     ep->bEndpointAddress);
+			upriv->write_pipe = usb_sndbulkpipe(udev,
+							  ep->
+							  bEndpointAddress);
+			upriv->bap_buf = kmalloc(BULK_BUF_SIZE, GFP_KERNEL);
+			if (!upriv->bap_buf) {
+				err("Couldn't allocate bulk_out_buffer");
+				goto error;
+			}
+		}
+	}
+	if (!upriv->bap_buf || !upriv->read_urb) {
+		err("Didn't find the required bulk endpoints");
+		goto error;
+	}
+
+	if (request_firmware(&fw_entry, "orinoco_ezusb_fw",
+			     &interface->dev) == 0) {
+		firmware.size = fw_entry->size;
+		firmware.code = fw_entry->data;
+	}
+	if (firmware.size && firmware.code) {
+		ezusb_firmware_download(upriv, &firmware);
+	} else {
+		err("No firmware to download");
+		goto error;
+	}
+
+	if (ezusb_hard_reset(priv) < 0) {
+		err("Cannot reset the device");
+		goto error;
+	}
+
+	/* If the firmware is already downloaded orinoco.c will call
+	 * ezusb_init but if the firmware is not already there, that will make
+	 * the kernel very unstable, so we try initializing here and quit in
+	 * case of error */
+	if (ezusb_init(hw) < 0) {
+		err("Couldn't initialize the device");
+		err("Firmware may not be downloaded or may be wrong.");
+		goto error;
+	}
+
+	/* Initialise the main driver */
+	if (orinoco_init(priv) != 0) {
+		err("orinoco_init() failed\n");
+		goto error;
+	}
+
+	if (orinoco_if_add(priv, 0, 0, &ezusb_netdev_ops) != 0) {
+		upriv->dev = NULL;
+		err("%s: orinoco_if_add() failed", __func__);
+		goto error;
+	}
+	upriv->dev = priv->ndev;
+
+	goto exit;
+
+ error:
+	ezusb_delete(upriv);
+	if (upriv->dev) {
+		/* upriv->dev was 0, so ezusb_delete() didn't free it */
+		free_orinocodev(priv);
+	}
+	upriv = NULL;
+	retval = -EFAULT;
+ exit:
+	if (fw_entry) {
+		firmware.code = NULL;
+		firmware.size = 0;
+		release_firmware(fw_entry);
+	}
+	usb_set_intfdata(interface, upriv);
+	return retval;
+}
+
+
+static void ezusb_disconnect(struct usb_interface *intf)
+{
+	struct ezusb_priv *upriv = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+	ezusb_delete(upriv);
+	printk(KERN_INFO PFX "Disconnected\n");
+}
+
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver orinoco_driver = {
+	.name = DRIVER_NAME,
+	.probe = ezusb_probe,
+	.disconnect = ezusb_disconnect,
+	.id_table = ezusb_table,
+};
+
+/* Can't be declared "const" or the whole __initdata section will
+ * become const */
+static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
+    " (Manuel Estrada Sainz)";
+
+static int __init ezusb_module_init(void)
+{
+	int err;
+
+	printk(KERN_DEBUG "%s\n", version);
+
+	/* register this driver with the USB subsystem */
+	err = usb_register(&orinoco_driver);
+	if (err < 0) {
+		printk(KERN_ERR PFX "usb_register failed, error %d\n",
+		       err);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit ezusb_module_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&orinoco_driver);
+}
+
+
+module_init(ezusb_module_init);
+module_exit(ezusb_module_exit);
+
+MODULE_AUTHOR("Manuel Estrada Sainz");
+MODULE_DESCRIPTION
+    ("Driver for Orinoco wireless LAN cards using EZUSB bridge");
+MODULE_LICENSE("Dual MPL/GPL");

+ 4 - 3
drivers/net/wireless/orinoco/spectrum_cs.c

@@ -349,6 +349,7 @@ spectrum_cs_config(struct pcmcia_device *link)
 		goto failed;
 		goto failed;
 
 
 	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
+	hw->eeprom_pda = true;
 
 
 	/*
 	/*
 	 * This actually configures the PCMCIA socket -- setting up
 	 * This actually configures the PCMCIA socket -- setting up
@@ -374,7 +375,7 @@ spectrum_cs_config(struct pcmcia_device *link)
 
 
 	/* Register an interface with the stack */
 	/* Register an interface with the stack */
 	if (orinoco_if_add(priv, link->io.BasePort1,
 	if (orinoco_if_add(priv, link->io.BasePort1,
-			   link->irq.AssignedIRQ) != 0) {
+			   link->irq.AssignedIRQ, NULL) != 0) {
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		printk(KERN_ERR PFX "orinoco_if_add() failed\n");
 		goto failed;
 		goto failed;
 	}
 	}
@@ -405,9 +406,9 @@ spectrum_cs_release(struct pcmcia_device *link)
 
 
 	/* We're committed to taking the device away now, so mark the
 	/* We're committed to taking the device away now, so mark the
 	 * hardware as unavailable */
 	 * hardware as unavailable */
-	spin_lock_irqsave(&priv->lock, flags);
+	priv->hw.ops->lock_irqsave(&priv->lock, &flags);
 	priv->hw_unavailable++;
 	priv->hw_unavailable++;
-	spin_unlock_irqrestore(&priv->lock, flags);
+	priv->hw.ops->unlock_irqrestore(&priv->lock, &flags);
 
 
 	pcmcia_disable_device(link);
 	pcmcia_disable_device(link);
 	if (priv->hw.iobase)
 	if (priv->hw.iobase)

+ 3 - 3
drivers/net/wireless/orinoco/wext.c

@@ -458,7 +458,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 		/* Fast channel change - no commit if successful */
 		/* Fast channel change - no commit if successful */
 		hermes_t *hw = &priv->hw;
 		hermes_t *hw = &priv->hw;
-		err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
+		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 					    HERMES_TEST_SET_CHANNEL,
 					    HERMES_TEST_SET_CHANNEL,
 					chan, NULL);
 					chan, NULL);
 	}
 	}
@@ -1273,8 +1273,8 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
 	if (orinoco_lock(priv, &flags) != 0)
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
 		return -EBUSY;
 
 
-	err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
-			      extra);
+	err = hw->ops->read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
+				extra);
 	if (err)
 	if (err)
 		goto out;
 		goto out;
 
 

+ 1 - 2
drivers/net/wireless/p54/main.c

@@ -546,8 +546,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
 		     IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_SUPPORTS_PS |
 		     IEEE80211_HW_PS_NULLFUNC_STACK |
 		     IEEE80211_HW_PS_NULLFUNC_STACK |
 		     IEEE80211_HW_BEACON_FILTER |
 		     IEEE80211_HW_BEACON_FILTER |
-		     IEEE80211_HW_REPORTS_TX_ACK_STATUS |
-		     IEEE80211_HW_NOISE_DBM;
+		     IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
 
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 	dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
 				      BIT(NL80211_IFTYPE_ADHOC) |
 				      BIT(NL80211_IFTYPE_ADHOC) |

+ 8 - 8
drivers/net/wireless/p54/p54pci.c

@@ -277,6 +277,14 @@ static void p54p_tasklet(unsigned long dev_id)
 	struct p54p_priv *priv = dev->priv;
 	struct p54p_priv *priv = dev->priv;
 	struct p54p_ring_control *ring_control = priv->ring_control;
 	struct p54p_ring_control *ring_control = priv->ring_control;
 
 
+	p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
+			   ARRAY_SIZE(ring_control->tx_mgmt),
+			   priv->tx_buf_mgmt);
+
+	p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
+			   ARRAY_SIZE(ring_control->tx_data),
+			   priv->tx_buf_data);
+
 	p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
 	p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt,
 		ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
 		ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt);
 
 
@@ -285,14 +293,6 @@ static void p54p_tasklet(unsigned long dev_id)
 
 
 	wmb();
 	wmb();
 	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
 	P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
-
-	p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, 3, ring_control->tx_mgmt,
-			   ARRAY_SIZE(ring_control->tx_mgmt),
-			   priv->tx_buf_mgmt);
-
-	p54p_check_tx_ring(dev, &priv->tx_idx_data, 1, ring_control->tx_data,
-			   ARRAY_SIZE(ring_control->tx_data),
-			   priv->tx_buf_data);
 }
 }
 
 
 static irqreturn_t p54p_interrupt(int irq, void *dev_id)
 static irqreturn_t p54p_interrupt(int irq, void *dev_id)

+ 0 - 1
drivers/net/wireless/p54/txrx.c

@@ -350,7 +350,6 @@ static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb)
 		rx_status->flag |= RX_FLAG_MMIC_ERROR;
 		rx_status->flag |= RX_FLAG_MMIC_ERROR;
 
 
 	rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
 	rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi);
-	rx_status->noise = priv->noise;
 	if (hdr->rate & 0x10)
 	if (hdr->rate & 0x10)
 		rx_status->flag |= RX_FLAG_SHORTPRE;
 		rx_status->flag |= RX_FLAG_SHORTPRE;
 	if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)
 	if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ)

+ 2 - 2
drivers/net/wireless/rt2x00/Kconfig

@@ -87,7 +87,7 @@ if RT2800PCI
 
 
 config RT2800PCI_RT30XX
 config RT2800PCI_RT30XX
 	bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
 	bool "rt2800pci - Include support for rt30xx (PCI/PCIe/PCMCIA) devices"
-	default n
+	default y
 	---help---
 	---help---
 	  This adds support for rt30xx wireless chipset family to the
 	  This adds support for rt30xx wireless chipset family to the
 	  rt2800pci driver.
 	  rt2800pci driver.
@@ -156,7 +156,7 @@ if RT2800USB
 
 
 config RT2800USB_RT30XX
 config RT2800USB_RT30XX
 	bool "rt2800usb - Include support for rt30xx (USB) devices"
 	bool "rt2800usb - Include support for rt30xx (USB) devices"
-	default n
+	default y
 	---help---
 	---help---
 	  This adds support for rt30xx wireless chipset family to the
 	  This adds support for rt30xx wireless chipset family to the
 	  rt2800usb driver.
 	  rt2800usb driver.

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

@@ -1018,8 +1018,8 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_desc_write(entry_priv->desc, 1, word);
 	rt2x00_desc_write(entry_priv->desc, 1, word);
 
 
 	rt2x00_desc_read(txd, 2, &word);
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len);
-	rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len);
+	rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, txdesc->length);
+	rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, txdesc->length);
 	rt2x00_desc_write(txd, 2, word);
 	rt2x00_desc_write(txd, 2, word);
 
 
 	rt2x00_desc_read(txd, 3, &word);
 	rt2x00_desc_read(txd, 3, &word);

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

@@ -1209,7 +1209,7 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
-	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
+	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE);
 	rt2x00_desc_write(txd, 0, word);
 	rt2x00_desc_write(txd, 0, word);
 }
 }

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

@@ -1072,7 +1072,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
 	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
 			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
 			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
 	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
-	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
+	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
 	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
 	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
 	rt2x00_desc_write(txd, 0, word);
 	rt2x00_desc_write(txd, 0, word);

+ 8 - 3
drivers/net/wireless/rt2x00/rt2800.h

@@ -107,7 +107,7 @@
 /*
 /*
  * INT_SOURCE_CSR: Interrupt source register.
  * INT_SOURCE_CSR: Interrupt source register.
  * Write one to clear corresponding bit.
  * Write one to clear corresponding bit.
- * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c
+ * TX_FIFO_STATUS: FIFO Statistics is full, sw should read TX_STA_FIFO
  */
  */
 #define INT_SOURCE_CSR			0x0200
 #define INT_SOURCE_CSR			0x0200
 #define INT_SOURCE_CSR_RXDELAYINT	FIELD32(0x00000001)
 #define INT_SOURCE_CSR_RXDELAYINT	FIELD32(0x00000001)
@@ -845,7 +845,7 @@
  * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
  * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
  */
  */
 #define TX_BAND_CFG			0x132c
 #define TX_BAND_CFG			0x132c
-#define TX_BAND_CFG_HT40_PLUS		FIELD32(0x00000001)
+#define TX_BAND_CFG_HT40_MINUS		FIELD32(0x00000001)
 #define TX_BAND_CFG_A			FIELD32(0x00000002)
 #define TX_BAND_CFG_A			FIELD32(0x00000002)
 #define TX_BAND_CFG_BG			FIELD32(0x00000004)
 #define TX_BAND_CFG_BG			FIELD32(0x00000004)
 
 
@@ -1519,7 +1519,7 @@ struct mac_iveiv_entry {
  * BBP 3: RX Antenna
  * BBP 3: RX Antenna
  */
  */
 #define BBP3_RX_ANTENNA			FIELD8(0x18)
 #define BBP3_RX_ANTENNA			FIELD8(0x18)
-#define BBP3_HT40_PLUS			FIELD8(0x20)
+#define BBP3_HT40_MINUS			FIELD8(0x20)
 
 
 /*
 /*
  * BBP 4: Bandwidth
  * BBP 4: Bandwidth
@@ -1565,6 +1565,11 @@ struct mac_iveiv_entry {
  */
  */
 #define RFCSR12_TX_POWER		FIELD8(0x1f)
 #define RFCSR12_TX_POWER		FIELD8(0x1f)
 
 
+/*
+ * RFCSR 13:
+ */
+#define RFCSR13_TX_POWER		FIELD8(0x1f)
+
 /*
 /*
  * RFCSR 15:
  * RFCSR 15:
  */
  */

+ 76 - 15
drivers/net/wireless/rt2x00/rt2800lib.c

@@ -41,9 +41,6 @@
 #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
 #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE)
 #include "rt2x00usb.h"
 #include "rt2x00usb.h"
 #endif
 #endif
-#if defined(CONFIG_RT2X00_LIB_PCI) || defined(CONFIG_RT2X00_LIB_PCI_MODULE)
-#include "rt2x00pci.h"
-#endif
 #include "rt2800lib.h"
 #include "rt2800lib.h"
 #include "rt2800.h"
 #include "rt2800.h"
 #include "rt2800usb.h"
 #include "rt2800usb.h"
@@ -76,6 +73,23 @@ MODULE_LICENSE("GPL");
 	rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
 	rt2800_regbusy_read((__dev), H2M_MAILBOX_CSR, \
 			    H2M_MAILBOX_CSR_OWNER, (__reg))
 			    H2M_MAILBOX_CSR_OWNER, (__reg))
 
 
+static inline bool rt2800_is_305x_soc(struct rt2x00_dev *rt2x00dev)
+{
+	/* check for rt2872 on SoC */
+	if (!rt2x00_is_soc(rt2x00dev) ||
+	    !rt2x00_rt(rt2x00dev, RT2872))
+		return false;
+
+	/* we know for sure that these rf chipsets are used on rt305x boards */
+	if (rt2x00_rf(rt2x00dev, RF3020) ||
+	    rt2x00_rf(rt2x00dev, RF3021) ||
+	    rt2x00_rf(rt2x00dev, RF3022))
+		return true;
+
+	NOTICE(rt2x00dev, "Unknown RF chipset on rt305x\n");
+	return false;
+}
+
 static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
 static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
 			     const unsigned int word, const u8 value)
 			     const unsigned int word, const u8 value)
 {
 {
@@ -794,6 +808,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
 			  TXPOWER_G_TO_DEV(info->tx_power1));
 			  TXPOWER_G_TO_DEV(info->tx_power1));
 	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
 
 
+	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
+			  TXPOWER_G_TO_DEV(info->tx_power2));
+	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
+
 	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
 	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
 	rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset);
 	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
 	rt2800_rfcsr_write(rt2x00dev, 23, rfcsr);
@@ -849,7 +868,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	}
 	}
 
 
 	rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
 	rt2800_register_read(rt2x00dev, TX_BAND_CFG, &reg);
-	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2x00_set_field32(&reg, TX_BAND_CFG_HT40_MINUS, conf_is_ht40_minus(conf));
 	rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
 	rt2x00_set_field32(&reg, TX_BAND_CFG_A, rf->channel > 14);
 	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
 	rt2x00_set_field32(&reg, TX_BAND_CFG_BG, rf->channel <= 14);
 	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
 	rt2800_register_write(rt2x00dev, TX_BAND_CFG, reg);
@@ -882,7 +901,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
 
 
 	rt2800_bbp_read(rt2x00dev, 3, &bbp);
 	rt2800_bbp_read(rt2x00dev, 3, &bbp);
-	rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf));
+	rt2x00_set_field8(&bbp, BBP3_HT40_MINUS, conf_is_ht40_minus(conf));
 	rt2800_bbp_write(rt2x00dev, 3, bbp);
 	rt2800_bbp_write(rt2x00dev, 3, bbp);
 
 
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
@@ -1551,6 +1570,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		     rt2800_wait_bbp_ready(rt2x00dev)))
 		     rt2800_wait_bbp_ready(rt2x00dev)))
 		return -EACCES;
 		return -EACCES;
 
 
+	if (rt2800_is_305x_soc(rt2x00dev))
+		rt2800_bbp_write(rt2x00dev, 31, 0x08);
+
 	rt2800_bbp_write(rt2x00dev, 65, 0x2c);
 	rt2800_bbp_write(rt2x00dev, 65, 0x2c);
 	rt2800_bbp_write(rt2x00dev, 66, 0x38);
 	rt2800_bbp_write(rt2x00dev, 66, 0x38);
 
 
@@ -1571,6 +1593,9 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 79, 0x13);
 		rt2800_bbp_write(rt2x00dev, 79, 0x13);
 		rt2800_bbp_write(rt2x00dev, 80, 0x05);
 		rt2800_bbp_write(rt2x00dev, 80, 0x05);
 		rt2800_bbp_write(rt2x00dev, 81, 0x33);
 		rt2800_bbp_write(rt2x00dev, 81, 0x33);
+	} else if (rt2800_is_305x_soc(rt2x00dev)) {
+		rt2800_bbp_write(rt2x00dev, 78, 0x0e);
+		rt2800_bbp_write(rt2x00dev, 80, 0x08);
 	} else {
 	} else {
 		rt2800_bbp_write(rt2x00dev, 81, 0x37);
 		rt2800_bbp_write(rt2x00dev, 81, 0x37);
 	}
 	}
@@ -1591,12 +1616,16 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
 	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
-	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E))
+	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+	    rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 	else
 	else
 		rt2800_bbp_write(rt2x00dev, 103, 0x00);
 		rt2800_bbp_write(rt2x00dev, 103, 0x00);
 
 
-	rt2800_bbp_write(rt2x00dev, 105, 0x05);
+	if (rt2800_is_305x_soc(rt2x00dev))
+		rt2800_bbp_write(rt2x00dev, 105, 0x01);
+	else
+		rt2800_bbp_write(rt2x00dev, 105, 0x05);
 	rt2800_bbp_write(rt2x00dev, 106, 0x35);
 	rt2800_bbp_write(rt2x00dev, 106, 0x35);
 
 
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
@@ -1613,11 +1642,6 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
 		rt2800_bbp_write(rt2x00dev, 138, value);
 		rt2800_bbp_write(rt2x00dev, 138, value);
 	}
 	}
 
 
-	if (rt2x00_rt(rt2x00dev, RT2872)) {
-		rt2800_bbp_write(rt2x00dev, 31, 0x08);
-		rt2800_bbp_write(rt2x00dev, 78, 0x0e);
-		rt2800_bbp_write(rt2x00dev, 80, 0x08);
-	}
 
 
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
@@ -1703,7 +1727,8 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 	if (!rt2x00_rt(rt2x00dev, RT3070) &&
 	if (!rt2x00_rt(rt2x00dev, RT3070) &&
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
-	    !rt2x00_rt(rt2x00dev, RT3390))
+	    !rt2x00_rt(rt2x00dev, RT3390) &&
+	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
 		return 0;
 
 
 	/*
 	/*
@@ -1771,6 +1796,40 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
 		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
 		rt2800_rfcsr_write(rt2x00dev, 29, 0x8f);
 		rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
 		rt2800_rfcsr_write(rt2x00dev, 30, 0x20);
 		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
 		rt2800_rfcsr_write(rt2x00dev, 31, 0x0f);
+	} else if (rt2800_is_305x_soc(rt2x00dev)) {
+		rt2800_rfcsr_write(rt2x00dev, 0, 0x50);
+		rt2800_rfcsr_write(rt2x00dev, 1, 0x01);
+		rt2800_rfcsr_write(rt2x00dev, 2, 0xf7);
+		rt2800_rfcsr_write(rt2x00dev, 3, 0x75);
+		rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
+		rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
+		rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x50);
+		rt2800_rfcsr_write(rt2x00dev, 8, 0x39);
+		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0x60);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
+		rt2800_rfcsr_write(rt2x00dev, 12, 0x75);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x75);
+		rt2800_rfcsr_write(rt2x00dev, 14, 0x90);
+		rt2800_rfcsr_write(rt2x00dev, 15, 0x58);
+		rt2800_rfcsr_write(rt2x00dev, 16, 0xb3);
+		rt2800_rfcsr_write(rt2x00dev, 17, 0x92);
+		rt2800_rfcsr_write(rt2x00dev, 18, 0x2c);
+		rt2800_rfcsr_write(rt2x00dev, 19, 0x02);
+		rt2800_rfcsr_write(rt2x00dev, 20, 0xba);
+		rt2800_rfcsr_write(rt2x00dev, 21, 0xdb);
+		rt2800_rfcsr_write(rt2x00dev, 22, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 23, 0x31);
+		rt2800_rfcsr_write(rt2x00dev, 24, 0x08);
+		rt2800_rfcsr_write(rt2x00dev, 25, 0x01);
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x25);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x23);
+		rt2800_rfcsr_write(rt2x00dev, 28, 0x13);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x83);
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
+		return 0;
 	}
 	}
 
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -1986,7 +2045,6 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
 		EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word);
 	} else if (rt2x00_rt(rt2x00dev, RT2860) ||
 	} else if (rt2x00_rt(rt2x00dev, RT2860) ||
 		   rt2x00_rt(rt2x00dev, RT2870) ||
 		   rt2x00_rt(rt2x00dev, RT2870) ||
-		   rt2x00_rt(rt2x00dev, RT2872) ||
 		   rt2x00_rt(rt2x00dev, RT2872)) {
 		   rt2x00_rt(rt2x00dev, RT2872)) {
 		/*
 		/*
 		 * There is a max of 2 RX streams for RT28x0 series
 		 * There is a max of 2 RX streams for RT28x0 series
@@ -2318,8 +2376,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	else
 	else
 		spec->ht.ht_supported = false;
 		spec->ht.ht_supported = false;
 
 
+	/*
+	 * Don't set IEEE80211_HT_CAP_SUP_WIDTH_20_40 for now as it causes
+	 * reception problems with HT40 capable 11n APs
+	 */
 	spec->ht.cap =
 	spec->ht.cap =
-	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
 	    IEEE80211_HT_CAP_GRN_FLD |
 	    IEEE80211_HT_CAP_GRN_FLD |
 	    IEEE80211_HT_CAP_SGI_20 |
 	    IEEE80211_HT_CAP_SGI_20 |
 	    IEEE80211_HT_CAP_SGI_40 |
 	    IEEE80211_HT_CAP_SGI_40 |

+ 1 - 5
drivers/net/wireless/rt2x00/rt2800pci.c

@@ -663,7 +663,7 @@ static int rt2800pci_write_tx_data(struct queue_entry* entry,
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   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,
-			   skb->len - txdesc->l2pad);
+			   txdesc->length);
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID,
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID,
 			   skbdesc->entry->queue->qid + 1);
 			   skbdesc->entry->queue->qid + 1);
 	rt2x00_desc_write(txwi, 1, word);
 	rt2x00_desc_write(txwi, 1, word);
@@ -895,10 +895,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry,
 	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
 	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
 	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
 	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
 
 
-	rxdesc->noise =
-	    (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) +
-	     rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2;
-
 	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
 	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
 
 
 	/*
 	/*

+ 7 - 6
drivers/net/wireless/rt2x00/rt2800usb.c

@@ -437,7 +437,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   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,
-			   skb->len - txdesc->l2pad);
+			   txdesc->length);
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID,
 	rt2x00_set_field32(&word, TXWI_W1_PACKETID,
 			   skbdesc->entry->queue->qid + 1);
 			   skbdesc->entry->queue->qid + 1);
 	rt2x00_desc_write(txwi, 1, word);
 	rt2x00_desc_write(txwi, 1, word);
@@ -645,10 +645,6 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
 	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
 	    (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) +
 	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
 	     rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2;
 
 
-	rxdesc->noise =
-	    (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) +
-	     rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2;
-
 	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
 	rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT);
 
 
 	/*
 	/*
@@ -1027,7 +1023,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 #ifdef CONFIG_RT2800USB_UNKNOWN
 #ifdef CONFIG_RT2800USB_UNKNOWN
 	/*
 	/*
 	 * Unclear what kind of devices these are (they aren't supported by the
 	 * Unclear what kind of devices these are (they aren't supported by the
-	 * vendor driver).
+	 * vendor linux driver).
 	 */
 	 */
 	/* Amigo */
 	/* Amigo */
 	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -1040,6 +1036,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	/* AzureWave */
 	/* AzureWave */
 	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x13d3, 0x3322), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Belkin */
 	/* Belkin */
 	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Buffalo */
 	/* Buffalo */
@@ -1058,6 +1055,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Encore */
 	/* Encore */
 	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Gemtek */
 	/* Gemtek */
@@ -1074,11 +1072,13 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	/* Motorola */
 	/* Motorola */
 	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Ovislink */
 	/* Ovislink */
+	{ USB_DEVICE(0x1b75, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Pegatron */
 	/* Pegatron */
 	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Planex */
 	/* Planex */
 	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Qcom */
 	/* Qcom */
@@ -1087,6 +1087,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
 	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x083a, 0xd522), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x083a, 0xf511), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Sweex */
 	/* Sweex */
 	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },

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