Browse Source

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

Conflicts:
	drivers/net/wireless/libertas/host.h
David S. Miller 15 years ago
parent
commit
05318bc905
100 changed files with 3380 additions and 7625 deletions
  1. 72 36
      drivers/net/wireless/at76c50x-usb.c
  2. 1 0
      drivers/net/wireless/at76c50x-usb.h
  3. 1 1
      drivers/net/wireless/ath/ath5k/phy.c
  4. 20 0
      drivers/net/wireless/ath/ath9k/ar9003_hw.c
  5. 5 1
      drivers/net/wireless/ath/ath9k/ath9k.h
  6. 6 3
      drivers/net/wireless/ath/ath9k/gpio.c
  7. 24 9
      drivers/net/wireless/ath/ath9k/hif_usb.c
  8. 1 0
      drivers/net/wireless/ath/ath9k/htc.h
  9. 2 7
      drivers/net/wireless/ath/ath9k/htc_drv_init.c
  10. 2 0
      drivers/net/wireless/ath/ath9k/htc_drv_main.c
  11. 83 36
      drivers/net/wireless/ath/ath9k/hw.c
  12. 7 2
      drivers/net/wireless/ath/ath9k/hw.h
  13. 4 0
      drivers/net/wireless/ath/ath9k/init.c
  14. 17 5
      drivers/net/wireless/ath/ath9k/main.c
  15. 28 0
      drivers/net/wireless/ath/ath9k/reg.h
  16. 16 5
      drivers/net/wireless/ath/ath9k/xmit.c
  17. 1 1
      drivers/net/wireless/b43/main.c
  18. 1 0
      drivers/net/wireless/b43/sdio.c
  19. 1 2
      drivers/net/wireless/hostap/hostap_ap.c
  20. 0 2
      drivers/net/wireless/hostap/hostap_main.c
  21. 2 2
      drivers/net/wireless/iwlwifi/Makefile
  22. 3 0
      drivers/net/wireless/iwlwifi/iwl-1000.c
  23. 5 0
      drivers/net/wireless/iwlwifi/iwl-3945.c
  24. 9 4
      drivers/net/wireless/iwlwifi/iwl-4965.c
  25. 7 2
      drivers/net/wireless/iwlwifi/iwl-5000.c
  26. 36 124
      drivers/net/wireless/iwlwifi/iwl-6000.c
  27. 9 18
      drivers/net/wireless/iwlwifi/iwl-agn-calib.c
  28. 36 36
      drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
  29. 1 5
      drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
  30. 2 1
      drivers/net/wireless/iwlwifi/iwl-agn-lib.c
  31. 5 12
      drivers/net/wireless/iwlwifi/iwl-agn-rs.c
  32. 284 0
      drivers/net/wireless/iwlwifi/iwl-agn-rx.c
  33. 4 1
      drivers/net/wireless/iwlwifi/iwl-agn-tx.c
  34. 49 24
      drivers/net/wireless/iwlwifi/iwl-agn.c
  35. 10 0
      drivers/net/wireless/iwlwifi/iwl-agn.h
  36. 21 9
      drivers/net/wireless/iwlwifi/iwl-commands.h
  37. 21 1
      drivers/net/wireless/iwlwifi/iwl-core.c
  38. 2 10
      drivers/net/wireless/iwlwifi/iwl-core.h
  39. 2 2
      drivers/net/wireless/iwlwifi/iwl-debugfs.c
  40. 9 8
      drivers/net/wireless/iwlwifi/iwl-dev.h
  41. 3 0
      drivers/net/wireless/iwlwifi/iwl-eeprom.c
  42. 0 238
      drivers/net/wireless/iwlwifi/iwl-rx.c
  43. 9 0
      drivers/net/wireless/iwlwifi/iwl-scan.c
  44. 80 26
      drivers/net/wireless/iwlwifi/iwl-sta.c
  45. 2 1
      drivers/net/wireless/iwlwifi/iwl-sta.h
  46. 1 1
      drivers/net/wireless/iwlwifi/iwl3945-base.c
  47. 8 4
      drivers/net/wireless/iwmc3200wifi/cfg80211.c
  48. 0 3
      drivers/net/wireless/libertas/Makefile
  49. 0 2264
      drivers/net/wireless/libertas/assoc.c
  50. 0 155
      drivers/net/wireless/libertas/assoc.h
  51. 1828 21
      drivers/net/wireless/libertas/cfg.c
  52. 16 5
      drivers/net/wireless/libertas/cfg.h
  53. 76 11
      drivers/net/wireless/libertas/cmd.c
  54. 56 27
      drivers/net/wireless/libertas/cmdresp.c
  55. 1 53
      drivers/net/wireless/libertas/debugfs.c
  56. 8 0
      drivers/net/wireless/libertas/decl.h
  57. 12 50
      drivers/net/wireless/libertas/dev.h
  58. 0 5
      drivers/net/wireless/libertas/ethtool.c
  59. 27 1
      drivers/net/wireless/libertas/host.h
  60. 7 219
      drivers/net/wireless/libertas/main.c
  61. 2 4
      drivers/net/wireless/libertas/mesh.c
  62. 0 5
      drivers/net/wireless/libertas/mesh.h
  63. 11 110
      drivers/net/wireless/libertas/rx.c
  64. 0 1354
      drivers/net/wireless/libertas/scan.c
  65. 0 63
      drivers/net/wireless/libertas/scan.h
  66. 7 5
      drivers/net/wireless/libertas/tx.c
  67. 0 2353
      drivers/net/wireless/libertas/wext.c
  68. 0 17
      drivers/net/wireless/libertas/wext.h
  69. 5 0
      drivers/net/wireless/mac80211_hwsim.c
  70. 13 7
      drivers/net/wireless/rndis_wlan.c
  71. 1 2
      drivers/net/wireless/rt2x00/rt2400pci.c
  72. 1 2
      drivers/net/wireless/rt2x00/rt2500pci.c
  73. 10 1
      drivers/net/wireless/rt2x00/rt2500usb.c
  74. 73 31
      drivers/net/wireless/rt2x00/rt2800lib.c
  75. 25 8
      drivers/net/wireless/rt2x00/rt2800pci.c
  76. 10 7
      drivers/net/wireless/rt2x00/rt2800usb.c
  77. 2 4
      drivers/net/wireless/rt2x00/rt2x00.h
  78. 30 0
      drivers/net/wireless/rt2x00/rt2x00dev.c
  79. 4 4
      drivers/net/wireless/rt2x00/rt2x00link.c
  80. 4 6
      drivers/net/wireless/rt2x00/rt2x00mac.c
  81. 0 74
      drivers/net/wireless/rt2x00/rt2x00pci.c
  82. 0 18
      drivers/net/wireless/rt2x00/rt2x00pci.h
  83. 41 2
      drivers/net/wireless/rt2x00/rt2x00queue.c
  84. 13 38
      drivers/net/wireless/rt2x00/rt2x00usb.c
  85. 0 10
      drivers/net/wireless/rt2x00/rt2x00usb.h
  86. 8 3
      drivers/net/wireless/rt2x00/rt61pci.c
  87. 0 1
      drivers/net/wireless/rt2x00/rt73usb.c
  88. 1 1
      drivers/net/wireless/rtl818x/rtl8180_dev.c
  89. 1 0
      include/linux/eeprom_93cx6.h
  90. 22 0
      include/linux/nl80211.h
  91. 1 14
      include/net/cfg80211.h
  92. 39 0
      include/net/mac80211.h
  93. 1 0
      net/mac80211/Kconfig
  94. 11 14
      net/mac80211/cfg.c
  95. 6 1
      net/mac80211/driver-ops.h
  96. 22 0
      net/mac80211/driver-trace.h
  97. 2 0
      net/mac80211/ieee80211_i.h
  98. 31 11
      net/mac80211/mesh_plink.c
  99. 38 1
      net/mac80211/mlme.c
  100. 2 1
      net/mac80211/rc80211_minstrel_ht.c

+ 72 - 36
drivers/net/wireless/at76c50x-usb.c

@@ -7,6 +7,7 @@
  * Copyright (c) 2004 Balint Seeber <n0_5p4m_p13453@hotmail.com>
  * Copyright (c) 2007 Guido Guenther <agx@sigxcpu.org>
  * Copyright (c) 2007 Kalle Valo <kalle.valo@iki.fi>
+ * Copyright (c) 2010 Sebastian Smolorz <sesmo@gmx.net>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -1649,6 +1650,58 @@ exit:
 		return NULL;
 }
 
+static int at76_join(struct at76_priv *priv)
+{
+	struct at76_req_join join;
+	int ret;
+
+	memset(&join, 0, sizeof(struct at76_req_join));
+	memcpy(join.essid, priv->essid, priv->essid_size);
+	join.essid_size = priv->essid_size;
+	memcpy(join.bssid, priv->bssid, ETH_ALEN);
+	join.bss_type = INFRASTRUCTURE_MODE;
+	join.channel = priv->channel;
+	join.timeout = cpu_to_le16(2000);
+
+	at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
+	ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
+				    sizeof(struct at76_req_join));
+
+	if (ret < 0) {
+		printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
+		       wiphy_name(priv->hw->wiphy), ret);
+		return 0;
+	}
+
+	ret = at76_wait_completion(priv, CMD_JOIN);
+	at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
+	if (ret != CMD_STATUS_COMPLETE) {
+		printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
+		       wiphy_name(priv->hw->wiphy), ret);
+		return 0;
+	}
+
+	at76_set_pm_mode(priv);
+
+	return 0;
+}
+
+static void at76_work_join_bssid(struct work_struct *work)
+{
+	struct at76_priv *priv = container_of(work, struct at76_priv,
+					      work_join_bssid);
+
+	if (priv->device_unplugged)
+		return;
+
+	mutex_lock(&priv->mtx);
+
+	if (is_valid_ether_addr(priv->bssid))
+		at76_join(priv);
+
+	mutex_unlock(&priv->mtx);
+}
+
 static void at76_mac80211_tx_callback(struct urb *urb)
 {
 	struct at76_priv *priv = urb->context;
@@ -1686,6 +1739,7 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	struct at76_priv *priv = hw->priv;
 	struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
 	int padding, submit_len, ret;
 
 	at76_dbg(DBG_MAC80211, "%s()", __func__);
@@ -1696,6 +1750,21 @@ static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		return NETDEV_TX_BUSY;
 	}
 
+	/* The following code lines are important when the device is going to
+	 * authenticate with a new bssid. The driver must send CMD_JOIN before
+	 * an authentication frame is transmitted. For this to succeed, the
+	 * correct bssid of the AP must be known. As mac80211 does not inform
+	 * drivers about the bssid prior to the authentication process the
+	 * following workaround is necessary. If the TX frame is an
+	 * authentication frame extract the bssid and send the CMD_JOIN. */
+	if (mgmt->frame_control & cpu_to_le16(IEEE80211_STYPE_AUTH)) {
+		if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
+			memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
+			ieee80211_queue_work(hw, &priv->work_join_bssid);
+			return NETDEV_TX_BUSY;
+		}
+	}
+
 	ieee80211_stop_queues(hw);
 
 	at76_ledtrig_tx_activity();	/* tell ledtrigger we send a packet */
@@ -1770,6 +1839,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw)
 	at76_dbg(DBG_MAC80211, "%s()", __func__);
 
 	cancel_delayed_work(&priv->dwork_hw_scan);
+	cancel_work_sync(&priv->work_join_bssid);
 	cancel_work_sync(&priv->work_set_promisc);
 
 	mutex_lock(&priv->mtx);
@@ -1818,42 +1888,6 @@ static void at76_remove_interface(struct ieee80211_hw *hw,
 	at76_dbg(DBG_MAC80211, "%s()", __func__);
 }
 
-static int at76_join(struct at76_priv *priv)
-{
-	struct at76_req_join join;
-	int ret;
-
-	memset(&join, 0, sizeof(struct at76_req_join));
-	memcpy(join.essid, priv->essid, priv->essid_size);
-	join.essid_size = priv->essid_size;
-	memcpy(join.bssid, priv->bssid, ETH_ALEN);
-	join.bss_type = INFRASTRUCTURE_MODE;
-	join.channel = priv->channel;
-	join.timeout = cpu_to_le16(2000);
-
-	at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__);
-	ret = at76_set_card_command(priv->udev, CMD_JOIN, &join,
-				    sizeof(struct at76_req_join));
-
-	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
-		return 0;
-	}
-
-	ret = at76_wait_completion(priv, CMD_JOIN);
-	at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret);
-	if (ret != CMD_STATUS_COMPLETE) {
-		printk(KERN_ERR "%s: at76_wait_completion failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
-		return 0;
-	}
-
-	at76_set_pm_mode(priv);
-
-	return 0;
-}
-
 static void at76_dwork_hw_scan(struct work_struct *work)
 {
 	struct at76_priv *priv = container_of(work, struct at76_priv,
@@ -2107,6 +2141,7 @@ static struct at76_priv *at76_alloc_new_device(struct usb_device *udev)
 	mutex_init(&priv->mtx);
 	INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc);
 	INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx);
+	INIT_WORK(&priv->work_join_bssid, at76_work_join_bssid);
 	INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan);
 
 	tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0);
@@ -2508,5 +2543,6 @@ MODULE_AUTHOR("Balint Seeber <n0_5p4m_p13453@hotmail.com>");
 MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
 MODULE_AUTHOR("Guido Guenther <agx@sigxcpu.org>");
 MODULE_AUTHOR("Kalle Valo <kalle.valo@iki.fi>");
+MODULE_AUTHOR("Sebastian Smolorz <sesmo@gmx.net>");
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");

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

@@ -387,6 +387,7 @@ struct at76_priv {
 	/* work queues */
 	struct work_struct work_set_promisc;
 	struct work_struct work_submit_rx;
+	struct work_struct work_join_bssid;
 	struct delayed_work dwork_hw_scan;
 
 	struct tasklet_struct rx_tasklet;

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

@@ -1768,7 +1768,7 @@ ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable)
 
 	if (enable) {
 		AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART,
-				AR5K_PHY_RESTART_DIV_GC, 1);
+				AR5K_PHY_RESTART_DIV_GC, 4);
 
 		AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV,
 					AR5K_PHY_FAST_ANT_DIV_EN);

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

@@ -295,6 +295,26 @@ static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
 		/* Several PCIe massages to ensure proper behaviour */
 		if (ah->config.pcie_waen)
 			REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
+		else
+			REG_WRITE(ah, AR_WA, ah->WARegVal);
+	}
+
+	/*
+	 * Configire PCIE after Ini init. SERDES values now come from ini file
+	 * This enables PCIe low power mode.
+	 */
+	if (ah->config.pcieSerDesWrite) {
+		unsigned int i;
+		struct ar5416IniArray *array;
+
+		array = power_off ? &ah->iniPcieSerdes :
+				    &ah->iniPcieSerdesLowPower;
+
+		for (i = 0; i < array->ia_rows; i++) {
+			REG_WRITE(ah,
+				  INI_RA(array, i, 0),
+				  INI_RA(array, i, 1));
+		}
 	}
 }
 

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

@@ -226,6 +226,7 @@ struct ath_buf_state {
 	int bfs_retries;
 	u8 bf_type;
 	u8 bfs_paprd;
+	unsigned long bfs_paprd_timestamp;
 	u32 bfs_keyix;
 	enum ath9k_key_type bfs_keytype;
 };
@@ -425,6 +426,8 @@ int ath_beaconq_config(struct ath_softc *sc);
 #define ATH_LONG_CALINTERVAL      30000   /* 30 seconds */
 #define ATH_RESTART_CALINTERVAL   1200000 /* 20 minutes */
 
+#define ATH_PAPRD_TIMEOUT	100 /* msecs */
+
 void ath_paprd_calibrate(struct work_struct *work);
 void ath_ani_calibrate(unsigned long data);
 
@@ -516,6 +519,7 @@ void ath_deinit_leds(struct ath_softc *sc);
 #define SC_OP_TSF_RESET              BIT(11)
 #define SC_OP_BT_PRIORITY_DETECTED   BIT(12)
 #define SC_OP_BT_SCAN		     BIT(13)
+#define SC_OP_ANI_RUN		     BIT(14)
 
 /* Powersave flags */
 #define PS_WAIT_FOR_BEACON        BIT(0)
@@ -559,7 +563,6 @@ struct ath_softc {
 	struct mutex mutex;
 	struct work_struct paprd_work;
 	struct completion paprd_complete;
-	int paprd_txok;
 
 	u32 intrstatus;
 	u32 sc_flags; /* SC_OP_* */
@@ -628,6 +631,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
 
 extern struct ieee80211_ops ath9k_ops;
 extern int modparam_nohwcrypt;
+extern int led_blink;
 
 irqreturn_t ath_isr(int irq, void *dev);
 int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,

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

@@ -76,7 +76,8 @@ static void ath_led_brightness(struct led_classdev *led_cdev,
 	case LED_FULL:
 		if (led->led_type == ATH_LED_ASSOC) {
 			sc->sc_flags |= SC_OP_LED_ASSOCIATED;
-			ieee80211_queue_delayed_work(sc->hw,
+			if (led_blink)
+				ieee80211_queue_delayed_work(sc->hw,
 						     &sc->ath_led_blink_work, 0);
 		} else if (led->led_type == ATH_LED_RADIO) {
 			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
@@ -143,7 +144,8 @@ void ath_init_leds(struct ath_softc *sc)
 	/* LED off, active low */
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
-	INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
+	if (led_blink)
+		INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
 
 	trigger = ieee80211_get_radio_led_name(sc->hw);
 	snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
@@ -180,7 +182,8 @@ void ath_init_leds(struct ath_softc *sc)
 	return;
 
 fail:
-	cancel_delayed_work_sync(&sc->ath_led_blink_work);
+	if (led_blink)
+		cancel_delayed_work_sync(&sc->ath_led_blink_work);
 	ath_deinit_leds(sc);
 }
 

+ 24 - 9
drivers/net/wireless/ath/ath9k/hif_usb.c

@@ -16,10 +16,27 @@
 
 #include "htc.h"
 
+/* identify firmware images */
+#define FIRMWARE_AR7010		"ar7010.fw"
+#define FIRMWARE_AR7010_1_1	"ar7010_1_1.fw"
+#define FIRMWARE_AR9271		"ar9271.fw"
+
+MODULE_FIRMWARE(FIRMWARE_AR7010);
+MODULE_FIRMWARE(FIRMWARE_AR7010_1_1);
+MODULE_FIRMWARE(FIRMWARE_AR9271);
+
 static struct usb_device_id ath9k_hif_usb_ids[] = {
-	{ USB_DEVICE(0x0cf3, 0x9271) },
-	{ USB_DEVICE(0x0cf3, 0x1006) },
-	{ USB_DEVICE(0x0cf3, 0x7010) },
+	{ USB_DEVICE(0x0cf3, 0x9271) }, /* Atheros */
+	{ USB_DEVICE(0x0cf3, 0x1006) }, /* Atheros */
+	{ USB_DEVICE(0x0cf3, 0x7010) }, /* Atheros */
+	{ USB_DEVICE(0x0cf3, 0x7015) }, /* Atheros */
+	{ USB_DEVICE(0x0846, 0x9030) }, /* Netgear N150 */
+	{ USB_DEVICE(0x0846, 0x9018) }, /* Netgear WNDA3200 */
+	{ USB_DEVICE(0x07D1, 0x3A10) }, /* Dlink Wireless 150 */
+	{ USB_DEVICE(0x13D3, 0x3327) }, /* Azurewave */
+	{ USB_DEVICE(0x13D3, 0x3328) }, /* Azurewave */
+	{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
+	{ USB_DEVICE(0x083A, 0xA704) }, /* SMC Networks */
 	{ },
 };
 
@@ -879,17 +896,15 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
 	/* Find out which firmware to load */
 
 	switch(hif_dev->device_id) {
-	case 0x9271:
-	case 0x1006:
-		hif_dev->fw_name = "ar9271.fw";
-		break;
 	case 0x7010:
+	case 0x9018:
 		if (le16_to_cpu(udev->descriptor.bcdDevice) == 0x0202)
-			hif_dev->fw_name = "ar7010_1_1.fw";
+			hif_dev->fw_name = FIRMWARE_AR7010_1_1;
 		else
-			hif_dev->fw_name = "ar7010.fw";
+			hif_dev->fw_name = FIRMWARE_AR7010;
 		break;
 	default:
+		hif_dev->fw_name = FIRMWARE_AR9271;
 		break;
 	}
 

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

@@ -287,6 +287,7 @@ struct ath9k_debug {
 #define ATH_LED_PIN_DEF             1
 #define ATH_LED_PIN_9287            8
 #define ATH_LED_PIN_9271            15
+#define ATH_LED_PIN_7010            12
 #define ATH_LED_ON_DURATION_IDLE    350	/* in msecs */
 #define ATH_LED_OFF_DURATION_IDLE   250	/* in msecs */
 

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

@@ -244,17 +244,12 @@ static int ath9k_init_htc_services(struct ath9k_htc_priv *priv, u16 devid)
 	 */
 
 	switch(devid) {
-	case 0x9271:
-	case 0x1006:
-		priv->htc->credits = 33;
-		break;
 	case 0x7010:
+	case 0x9018:
 		priv->htc->credits = 45;
 		break;
 	default:
-		dev_err(priv->dev, "ath9k_htc: Unsupported device id: 0x%x\n",
-			devid);
-		goto err;
+		priv->htc->credits = 33;
 	}
 
 	ret = htc_init(priv->htc);

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

@@ -931,6 +931,8 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
 		priv->ah->led_pin = ATH_LED_PIN_9287;
 	else if (AR_SREV_9271(priv->ah))
 		priv->ah->led_pin = ATH_LED_PIN_9271;
+	else if (AR_DEVID_7010(priv->ah))
+		priv->ah->led_pin = ATH_LED_PIN_7010;
 	else
 		priv->ah->led_pin = ATH_LED_PIN_DEF;
 

+ 83 - 36
drivers/net/wireless/ath/ath9k/hw.c

@@ -388,6 +388,7 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
 		ah->config.ht_enable = 0;
 
 	ah->config.rx_intr_mitigation = true;
+	ah->config.pcieSerDesWrite = true;
 
 	/*
 	 * We need this for PCI devices only (Cardbus, PCI, miniPCI)
@@ -571,24 +572,13 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 	ath9k_hw_init_mode_regs(ah);
 
 	/*
-	 * Configire PCIE after Ini init. SERDES values now come from ini file
-	 * This enables PCIe low power mode.
+	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
+	 * We need to do this to avoid RMW of this register. We cannot
+	 * read the reg when chip is asleep.
 	 */
-	if (AR_SREV_9300_20_OR_LATER(ah)) {
-		u32 regval;
-		unsigned int i;
-
-		/* Set Bits 16 and 17 in the AR_WA register. */
-		regval = REG_READ(ah, AR_WA);
-		regval |= 0x00030000;
-		REG_WRITE(ah, AR_WA, regval);
-
-		for (i = 0; i < ah->iniPcieSerdesLowPower.ia_rows; i++) {
-			REG_WRITE(ah,
-				  INI_RA(&ah->iniPcieSerdesLowPower, i, 0),
-				  INI_RA(&ah->iniPcieSerdesLowPower, i, 1));
-		}
-	}
+	ah->WARegVal = REG_READ(ah, AR_WA);
+	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+			 AR_WA_ASPM_TIMER_BASED_DISABLE);
 
 	if (ah->is_pciexpress)
 		ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -1009,6 +999,11 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type)
 
 	ENABLE_REGWRITE_BUFFER(ah);
 
+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+		REG_WRITE(ah, AR_WA, ah->WARegVal);
+		udelay(10);
+	}
+
 	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
 		  AR_RTC_FORCE_WAKE_ON_INT);
 
@@ -1063,6 +1058,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 {
 	ENABLE_REGWRITE_BUFFER(ah);
 
+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+		REG_WRITE(ah, AR_WA, ah->WARegVal);
+		udelay(10);
+	}
+
 	REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
 		  AR_RTC_FORCE_WAKE_ON_INT);
 
@@ -1070,6 +1070,7 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 		REG_WRITE(ah, AR_RC, AR_RC_AHB);
 
 	REG_WRITE(ah, AR_RTC_RESET, 0);
+	udelay(2);
 
 	REGWRITE_BUFFER_FLUSH(ah);
 	DISABLE_REGWRITE_BUFFER(ah);
@@ -1099,6 +1100,11 @@ static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah)
 
 static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
 {
+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+		REG_WRITE(ah, AR_WA, ah->WARegVal);
+		udelay(10);
+	}
+
 	REG_WRITE(ah, AR_RTC_FORCE_WAKE,
 		  AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
 
@@ -1262,7 +1268,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B;
 
 	/* For chips on which RTC reset is done, save TSF before it gets cleared */
-	if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+	if (AR_SREV_9100(ah) ||
+	    (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)))
 		tsf = ath9k_hw_gettsf64(ah);
 
 	saveLedState = REG_READ(ah, AR_CFG_LED) &
@@ -1294,7 +1301,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	}
 
 	/* Restore TSF */
-	if (tsf && AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))
+	if (tsf)
 		ath9k_hw_settsf64(ah, tsf);
 
 	if (AR_SREV_9280_10_OR_LATER(ah))
@@ -1307,6 +1314,17 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
 	if (r)
 		return r;
 
+	/*
+	 * Some AR91xx SoC devices frequently fail to accept TSF writes
+	 * right after the chip reset. When that happens, write a new
+	 * value after the initvals have been applied, with an offset
+	 * based on measured time difference
+	 */
+	if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) {
+		tsf += 1500;
+		ath9k_hw_settsf64(ah, tsf);
+	}
+
 	/* Setup MFP options for CCMP */
 	if (AR_SREV_9280_20_OR_LATER(ah)) {
 		/* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt
@@ -1492,7 +1510,7 @@ bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry)
 }
 EXPORT_SYMBOL(ath9k_hw_keyreset);
 
-bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
+static bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
 {
 	u32 macHi, macLo;
 	u32 unicast_flag = AR_KEYTABLE_VALID;
@@ -1530,7 +1548,6 @@ bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac)
 
 	return true;
 }
-EXPORT_SYMBOL(ath9k_hw_keysetmac);
 
 bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 				 const struct ath9k_keyval *k,
@@ -1731,17 +1748,6 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 }
 EXPORT_SYMBOL(ath9k_hw_set_keycache_entry);
 
-bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry)
-{
-	if (entry < ah->caps.keycache_size) {
-		u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
-		if (val & AR_KEYTABLE_VALID)
-			return true;
-	}
-	return false;
-}
-EXPORT_SYMBOL(ath9k_hw_keyisvalid);
-
 /******************************/
 /* Power Management (Chipset) */
 /******************************/
@@ -1768,6 +1774,11 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
 			REG_CLR_BIT(ah, (AR_RTC_RESET),
 				    AR_RTC_RESET_EN);
 	}
+
+	/* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		REG_WRITE(ah, AR_WA,
+			  ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 /*
@@ -1794,6 +1805,10 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip)
 				    AR_RTC_FORCE_WAKE_EN);
 		}
 	}
+
+	/* Clear Bit 14 of AR_WA after putting chip into Net Sleep mode. */
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
@@ -1801,6 +1816,12 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
 	u32 val;
 	int i;
 
+	/* Set Bits 14 and 17 of AR_WA before powering on the chip. */
+	if (AR_SREV_9300_20_OR_LATER(ah)) {
+		REG_WRITE(ah, AR_WA, ah->WARegVal);
+		udelay(10);
+	}
+
 	if (setChip) {
 		if ((REG_READ(ah, AR_RTC_STATUS) &
 		     AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
@@ -2155,6 +2176,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
 
 	if (AR_SREV_9271(ah))
 		pCap->num_gpio_pins = AR9271_NUM_GPIO;
+	else if (AR_DEVID_7010(ah))
+		pCap->num_gpio_pins = AR7010_NUM_GPIO;
 	else if (AR_SREV_9285_10_OR_LATER(ah))
 		pCap->num_gpio_pins = AR9285_NUM_GPIO;
 	else if (AR_SREV_9280_10_OR_LATER(ah))
@@ -2295,8 +2318,15 @@ void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio)
 
 	BUG_ON(gpio >= ah->caps.num_gpio_pins);
 
-	gpio_shift = gpio << 1;
+	if (AR_DEVID_7010(ah)) {
+		gpio_shift = gpio;
+		REG_RMW(ah, AR7010_GPIO_OE,
+			(AR7010_GPIO_OE_AS_INPUT << gpio_shift),
+			(AR7010_GPIO_OE_MASK << gpio_shift));
+		return;
+	}
 
+	gpio_shift = gpio << 1;
 	REG_RMW(ah,
 		AR_GPIO_OE_OUT,
 		(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
@@ -2312,7 +2342,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
 	if (gpio >= ah->caps.num_gpio_pins)
 		return 0xffffffff;
 
-	if (AR_SREV_9300_20_OR_LATER(ah))
+	if (AR_DEVID_7010(ah)) {
+		u32 val;
+		val = REG_READ(ah, AR7010_GPIO_IN);
+		return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0;
+	} else if (AR_SREV_9300_20_OR_LATER(ah))
 		return MS_REG_READ(AR9300, gpio) != 0;
 	else if (AR_SREV_9271(ah))
 		return MS_REG_READ(AR9271, gpio) != 0;
@@ -2332,10 +2366,16 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
 {
 	u32 gpio_shift;
 
-	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
+	if (AR_DEVID_7010(ah)) {
+		gpio_shift = gpio;
+		REG_RMW(ah, AR7010_GPIO_OE,
+			(AR7010_GPIO_OE_AS_OUTPUT << gpio_shift),
+			(AR7010_GPIO_OE_MASK << gpio_shift));
+		return;
+	}
 
+	ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
 	gpio_shift = 2 * gpio;
-
 	REG_RMW(ah,
 		AR_GPIO_OE_OUT,
 		(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
@@ -2345,6 +2385,13 @@ EXPORT_SYMBOL(ath9k_hw_cfg_output);
 
 void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
 {
+	if (AR_DEVID_7010(ah)) {
+		val = val ? 0 : 1;
+		REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio),
+			AR_GPIO_BIT(gpio));
+		return;
+	}
+
 	if (AR_SREV_9271(ah))
 		val = ~val;
 

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

@@ -235,6 +235,7 @@ struct ath9k_ops_config {
 	int ack_6mb;
 	u32 cwm_ignore_extcca;
 	u8 pcie_powersave_enable;
+	bool pcieSerDesWrite;
 	u8 pcie_clock_req;
 	u32 pcie_waen;
 	u8 analog_shiftreg;
@@ -819,6 +820,12 @@ struct ath_hw {
 
 	u32 paprd_gain_table_entries[PAPRD_GAIN_TABLE_ENTRIES];
 	u8 paprd_gain_table_index[PAPRD_GAIN_TABLE_ENTRIES];
+	/*
+	 * Store the permanent value of Reg 0x4004in WARegVal
+	 * so we dont have to R/M/W. We should not be reading
+	 * this register when in sleep states.
+	 */
+	u32 WARegVal;
 };
 
 static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
@@ -852,11 +859,9 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
 
 /* Key Cache Management */
 bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry);
-bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac);
 bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
 				 const struct ath9k_keyval *k,
 				 const u8 *mac);
-bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry);
 
 /* GPIO / RFKILL / Antennae */
 void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio);

+ 4 - 0
drivers/net/wireless/ath/ath9k/init.c

@@ -33,6 +33,10 @@ int modparam_nohwcrypt;
 module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
 
+int led_blink = 1;
+module_param_named(blink, led_blink, int, 0444);
+MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+
 /* We use the hw_value as an index into our private channel structure */
 
 #define CHAN2G(_freq, _idx)  { \

+ 17 - 5
drivers/net/wireless/ath/ath9k/main.c

@@ -268,7 +268,6 @@ void ath_paprd_calibrate(struct work_struct *work)
 	int time_left;
 	int i;
 
-	ath9k_ps_wakeup(sc);
 	skb = alloc_skb(len, GFP_KERNEL);
 	if (!skb)
 		return;
@@ -289,6 +288,7 @@ void ath_paprd_calibrate(struct work_struct *work)
 	qnum = sc->tx.hwq_map[WME_AC_BE];
 	txctl.txq = &sc->tx.txq[qnum];
 
+	ath9k_ps_wakeup(sc);
 	ar9003_paprd_init_table(ah);
 	for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 		if (!(ah->caps.tx_chainmask & BIT(chain)))
@@ -310,13 +310,13 @@ void ath_paprd_calibrate(struct work_struct *work)
 			break;
 
 		time_left = wait_for_completion_timeout(&sc->paprd_complete,
-							100);
+				msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
 		if (!time_left) {
 			ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
 				  "Timeout waiting for paprd training on "
 				  "TX chain %d\n",
 				  chain);
-			break;
+			goto fail_paprd;
 		}
 
 		if (!ar9003_paprd_is_done(ah))
@@ -334,6 +334,7 @@ void ath_paprd_calibrate(struct work_struct *work)
 		ath_paprd_activate(sc);
 	}
 
+fail_paprd:
 	ath9k_ps_restore(sc);
 }
 
@@ -451,6 +452,10 @@ static void ath_start_ani(struct ath_common *common)
 {
 	struct ath_hw *ah = common->ah;
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
+	struct ath_softc *sc = (struct ath_softc *) common->priv;
+
+	if (!(sc->sc_flags & SC_OP_ANI_RUN))
+		return;
 
 	common->ani.longcal_timer = timestamp;
 	common->ani.shortcal_timer = timestamp;
@@ -766,11 +771,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
 		/* Reset rssi stats */
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
+		sc->sc_flags |= SC_OP_ANI_RUN;
 		ath_start_ani(common);
 	} else {
 		ath_print(common, ATH_DBG_CONFIG, "Bss Info DISASSOC\n");
 		common->curaid = 0;
 		/* Stop ANI */
+		sc->sc_flags &= ~SC_OP_ANI_RUN;
 		del_timer_sync(&common->ani.timer);
 	}
 }
@@ -1241,7 +1248,9 @@ static void ath9k_stop(struct ieee80211_hw *hw)
 
 	aphy->state = ATH_WIPHY_INACTIVE;
 
-	cancel_delayed_work_sync(&sc->ath_led_blink_work);
+	if (led_blink)
+		cancel_delayed_work_sync(&sc->ath_led_blink_work);
+
 	cancel_delayed_work_sync(&sc->tx_complete_work);
 	cancel_work_sync(&sc->paprd_work);
 
@@ -1374,8 +1383,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
 
 	if (vif->type == NL80211_IFTYPE_AP    ||
 	    vif->type == NL80211_IFTYPE_ADHOC ||
-	    vif->type == NL80211_IFTYPE_MONITOR)
+	    vif->type == NL80211_IFTYPE_MONITOR) {
+		sc->sc_flags |= SC_OP_ANI_RUN;
 		ath_start_ani(common);
+	}
 
 out:
 	mutex_unlock(&sc->mutex);
@@ -1396,6 +1407,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 	mutex_lock(&sc->mutex);
 
 	/* Stop ANI */
+	sc->sc_flags &= ~SC_OP_ANI_RUN;
 	del_timer_sync(&common->ani.timer);
 
 	/* Reclaim beacon resources */

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

@@ -704,6 +704,11 @@
 #define AR_WA_BIT7			(1 << 7)
 #define AR_WA_BIT23			(1 << 23)
 #define AR_WA_D3_L1_DISABLE		(1 << 14)
+#define AR_WA_D3_TO_L1_DISABLE_REAL     (1 << 16)
+#define AR_WA_ASPM_TIMER_BASED_DISABLE  (1 << 17)
+#define AR_WA_RESET_EN                  (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
+#define AR_WA_ANALOG_SHIFT              (1 << 20)
+#define AR_WA_POR_SHORT                 (1 << 21) /* PCI-E Phy reset control */
 #define AR9285_WA_DEFAULT		0x004a050b
 #define AR9280_WA_DEFAULT           	0x0040073b
 #define AR_WA_DEFAULT               	0x0000073f
@@ -877,6 +882,7 @@
 #define AR_SREV_9271_11(_ah) \
     (AR_SREV_9271(_ah) && \
      ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11))
+
 #define AR_SREV_9300(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
 #define AR_SREV_9300_20(_ah) \
@@ -891,6 +897,10 @@
     (AR_SREV_9285_12_OR_LATER(_ah) && \
      ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
 
+#define AR_DEVID_7010(_ah) \
+	(((_ah)->hw_version.devid == 0x7010) || \
+	 ((_ah)->hw_version.devid == 0x9018))
+
 #define AR_RADIO_SREV_MAJOR                   0xf0
 #define AR_RAD5133_SREV_MAJOR                 0xc0
 #define AR_RAD2133_SREV_MAJOR                 0xd0
@@ -988,6 +998,7 @@ enum {
 #define AR9287_NUM_GPIO                          11
 #define AR9271_NUM_GPIO                          16
 #define AR9300_NUM_GPIO                          17
+#define AR7010_NUM_GPIO                          16
 
 #define AR_GPIO_IN_OUT                           0x4048
 #define AR_GPIO_IN_VAL                           0x0FFFC000
@@ -1002,6 +1013,8 @@ enum {
 #define AR9271_GPIO_IN_VAL_S                     16
 #define AR9300_GPIO_IN_VAL                       0x0001FFFF
 #define AR9300_GPIO_IN_VAL_S                     0
+#define AR7010_GPIO_IN_VAL                       0x0000FFFF
+#define AR7010_GPIO_IN_VAL_S                     0
 
 #define AR_GPIO_OE_OUT                           (AR_SREV_9300_20_OR_LATER(ah) ? 0x4050 : 0x404c)
 #define AR_GPIO_OE_OUT_DRV                       0x3
@@ -1010,6 +1023,21 @@ enum {
 #define AR_GPIO_OE_OUT_DRV_HI                    0x2
 #define AR_GPIO_OE_OUT_DRV_ALL                   0x3
 
+#define AR7010_GPIO_OE                           0x52000
+#define AR7010_GPIO_OE_MASK                      0x1
+#define AR7010_GPIO_OE_AS_OUTPUT                 0x0
+#define AR7010_GPIO_OE_AS_INPUT                  0x1
+#define AR7010_GPIO_IN                           0x52004
+#define AR7010_GPIO_OUT                          0x52008
+#define AR7010_GPIO_SET                          0x5200C
+#define AR7010_GPIO_CLEAR                        0x52010
+#define AR7010_GPIO_INT                          0x52014
+#define AR7010_GPIO_INT_TYPE                     0x52018
+#define AR7010_GPIO_INT_POLARITY                 0x5201C
+#define AR7010_GPIO_PENDING                      0x52020
+#define AR7010_GPIO_INT_MASK                     0x52024
+#define AR7010_GPIO_FUNCTION                     0x52028
+
 #define AR_GPIO_INTR_POL                         (AR_SREV_9300_20_OR_LATER(ah) ? 0x4058 : 0x4050)
 #define AR_GPIO_INTR_POL_VAL                     0x0001FFFF
 #define AR_GPIO_INTR_POL_VAL_S                   0

+ 16 - 5
drivers/net/wireless/ath/ath9k/xmit.c

@@ -328,6 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	u32 ba[WME_BA_BMP_SIZE >> 5];
 	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0;
 	bool rc_update = true;
+	struct ieee80211_tx_rate rates[4];
 
 	skb = bf->bf_mpdu;
 	hdr = (struct ieee80211_hdr *)skb->data;
@@ -335,6 +336,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 	tx_info = IEEE80211_SKB_CB(skb);
 	hw = bf->aphy->hw;
 
+	memcpy(rates, tx_info->control.rates, sizeof(rates));
+
 	rcu_read_lock();
 
 	/* XXX: use ieee80211_find_sta! */
@@ -375,6 +378,9 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 		txfail = txpending = 0;
 		bf_next = bf->bf_next;
 
+		skb = bf->bf_mpdu;
+		tx_info = IEEE80211_SKB_CB(skb);
+
 		if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) {
 			/* transmit completion, subframe is
 			 * acked by block ack */
@@ -428,6 +434,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
 			spin_unlock_bh(&txq->axq_lock);
 
 			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
+				memcpy(tx_info->control.rates, rates, sizeof(rates));
 				ath_tx_rc_status(bf, ts, nbad, txok, true);
 				rc_update = false;
 			} else {
@@ -1644,6 +1651,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
 	}
 
 	bf->bf_state.bfs_paprd = txctl->paprd;
+	if (txctl->paprd)
+		bf->bf_state.bfs_paprd_timestamp = jiffies;
 	bf->bf_flags = setup_tx_flags(skb, use_ldpc);
 
 	bf->bf_keytype = get_hw_crypto_keytype(skb);
@@ -1944,8 +1953,12 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
 	dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
 
 	if (bf->bf_state.bfs_paprd) {
-		sc->paprd_txok = txok;
-		complete(&sc->paprd_complete);
+		if (time_after(jiffies,
+			       bf->bf_state.bfs_paprd_timestamp +
+			       msecs_to_jiffies(ATH_PAPRD_TIMEOUT)))
+			dev_kfree_skb_any(skb);
+		else
+			complete(&sc->paprd_complete);
 	} else {
 		ath_tx_complete(sc, skb, bf->aphy, tx_flags);
 		ath_debug_stat_tx(sc, txq, bf, ts);
@@ -2027,7 +2040,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
 		tx_info->status.rates[i].idx = -1;
 	}
 
-	tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
+	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 
 static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
@@ -2138,7 +2151,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
 			 * This frame is sent out as a single frame.
 			 * Use hardware retry status for this frame.
 			 */
-			bf->bf_retries = ts.ts_longretry;
 			if (ts.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
 			ath_tx_rc_status(bf, &ts, 0, txok, true);
@@ -2268,7 +2280,6 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
 		}
 
 		if (!bf_isampdu(bf)) {
-			bf->bf_retries = txs.ts_longretry;
 			if (txs.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
 			ath_tx_rc_status(bf, &txs, 0, txok, true);

+ 1 - 1
drivers/net/wireless/b43/main.c

@@ -1804,7 +1804,7 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
 			       dma_reason[2], dma_reason[3],
 			       dma_reason[4], dma_reason[5]);
 			b43err(dev->wl, "This device does not support DMA "
-			       "on your system. Please use PIO instead.\n");
+			       "on your system. It will now be switched to PIO.\n");
 			/* Fall back to PIO transfers if we get fatal DMA errors! */
 			dev->use_pio = 1;
 			b43_controller_restart(dev, "DMA error");

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

@@ -182,6 +182,7 @@ static void b43_sdio_remove(struct sdio_func *func)
 
 static const struct sdio_device_id b43_sdio_ids[] = {
 	{ SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */
+	{ SDIO_DEVICE(0x0092, 0x0004) }, /* C-guys, Inc. EW-CG1102GC */
 	{ },
 };
 

+ 1 - 2
drivers/net/wireless/hostap/hostap_ap.c

@@ -688,7 +688,7 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
 	struct ap_data *ap = data;
 	struct net_device *dev = ap->local->dev;
 	struct ieee80211_hdr *hdr;
-	u16 fc, status;
+	u16 status;
 	__le16 *pos;
 	struct sta_info *sta = NULL;
 	char *txt = NULL;
@@ -699,7 +699,6 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
 	}
 
 	hdr = (struct ieee80211_hdr *) skb->data;
-	fc = le16_to_cpu(hdr->frame_control);
 	if ((!ieee80211_is_assoc_resp(hdr->frame_control) &&
 	     !ieee80211_is_reassoc_resp(hdr->frame_control)) ||
 	    skb->len < IEEE80211_MGMT_HDR_LEN + 4) {

+ 0 - 2
drivers/net/wireless/hostap/hostap_main.c

@@ -741,9 +741,7 @@ void hostap_set_multicast_list_queue(struct work_struct *work)
 	local_info_t *local =
 		container_of(work, local_info_t, set_multicast_list_queue);
 	struct net_device *dev = local->dev;
-	struct hostap_interface *iface;
 
-	iface = netdev_priv(dev);
 	if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE,
 			    local->is_promisc)) {
 		printk(KERN_INFO "%s: %sabling promiscuous mode failed\n",

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

@@ -1,6 +1,6 @@
 obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
 iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o
+iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
 iwlcore-objs 		+= iwl-scan.o iwl-led.o
 iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
 iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
@@ -11,7 +11,7 @@ CFLAGS_iwl-devtrace.o := -I$(src)
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o
-iwlagn-objs		+= iwl-agn-lib.o
+iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
 iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
 iwlagn-$(CONFIG_IWL4965) += iwl-4965.o

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

@@ -157,6 +157,8 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
 			BIT(IWL_CALIB_TX_IQ) 		|
 			BIT(IWL_CALIB_TX_IQ_PERD)	|
 			BIT(IWL_CALIB_BASE_BAND);
+	if (priv->cfg->need_dc_calib)
+		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
 
 	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
 
@@ -215,6 +217,7 @@ static struct iwl_lib_ops iwl1000_lib = {
 		.set_ct_kill = iwl1000_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_station = iwl_update_bcast_station,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,

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

@@ -406,6 +406,11 @@ static bool iwl3945_good_plcp_health(struct iwl_priv *priv,
 	unsigned int plcp_msec;
 	unsigned long plcp_received_jiffies;
 
+	if (priv->cfg->plcp_delta_threshold ==
+	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return rc;
+	}
 	memcpy(&current_stat, pkt->u.raw, sizeof(struct
 			iwl3945_notif_statistics));
 	/*

+ 9 - 4
drivers/net/wireless/iwlwifi/iwl-4965.c

@@ -1580,7 +1580,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	u32 R4;
 
 	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-		(priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+	    (priv->_agn.statistics.flag &
+			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
 		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
 		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
 		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
@@ -1604,8 +1605,8 @@ static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
 	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
 		vt = sign_extend(R4, 23);
 	else
-		vt = sign_extend(
-			le32_to_cpu(priv->statistics.general.temperature), 23);
+		vt = sign_extend(le32_to_cpu(
+				priv->_agn.statistics.general.temperature), 23);
 
 	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
 
@@ -1785,6 +1786,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 {
 	unsigned long flags;
 	u16 ra_tid;
+	int ret;
 
 	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWL49_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -1800,7 +1802,9 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 	ra_tid = BUILD_RAxTID(sta_id, tid);
 
 	/* Modify device's station table to Tx this TID */
-	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
@@ -2276,6 +2280,7 @@ static struct iwl_lib_ops iwl4965_lib = {
 		.set_ct_kill = iwl4965_set_ct_threshold,
 	},
 	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_station = iwl_update_bcast_station,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,

+ 7 - 2
drivers/net/wireless/iwlwifi/iwl-5000.c

@@ -249,10 +249,11 @@ static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
 	/* 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);
+	if (priv->cfg->need_dc_calib)
+		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
 
 	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
 
@@ -264,7 +265,7 @@ static void iwl5150_temperature(struct iwl_priv *priv)
 	u32 vt = 0;
 	s32 offset =  iwl_temp_calib_to_offset(priv);
 
-	vt = le32_to_cpu(priv->statistics.general.temperature);
+	vt = le32_to_cpu(priv->_agn.statistics.general.temperature);
 	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
 	/* now vt hold the temperature in Kelvin */
 	priv->temperature = KELVIN_TO_CELSIUS(vt);
@@ -392,6 +393,7 @@ static struct iwl_lib_ops iwl5000_lib = {
 		.set_ct_kill = iwl5000_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_station = iwl_update_bcast_station,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -454,6 +456,7 @@ static struct iwl_lib_ops iwl5150_lib = {
 		.set_ct_kill = iwl5150_set_ct_threshold,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_station = iwl_update_bcast_station,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -660,6 +663,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl5150_abg_cfg = {
@@ -689,6 +693,7 @@ struct iwl_cfg iwl5150_abg_cfg = {
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));

+ 36 - 124
drivers/net/wireless/iwlwifi/iwl-6000.c

@@ -84,9 +84,10 @@ static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 }
 
 /* Indicate calibration version to uCode. */
-static void iwl6050_set_calib_version(struct iwl_priv *priv)
+static void iwl6000_set_calib_version(struct iwl_priv *priv)
 {
-	if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
+	if (priv->cfg->need_dc_calib &&
+	    (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6))
 		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
 				CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
 }
@@ -186,53 +187,8 @@ static int iwl6000_hw_set_hw_params(struct iwl_priv *priv)
 		BIT(IWL_CALIB_LO)		|
 		BIT(IWL_CALIB_TX_IQ)		|
 		BIT(IWL_CALIB_BASE_BAND);
-
-	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
-	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);
+	if (priv->cfg->need_dc_calib)
+		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
 
 	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
 
@@ -359,8 +315,10 @@ static struct iwl_lib_ops iwl6000_lib = {
 	.temp_ops = {
 		.temperature = iwlagn_temperature,
 		.set_ct_kill = iwl6000_set_ct_threshold,
+		.set_calib_version = iwl6000_set_calib_version,
 	 },
 	.manage_ibss_station = iwlagn_manage_ibss_station,
+	.update_bcast_station = iwl_update_bcast_station,
 	.debugfs_ops = {
 		.rx_stats_read = iwl_ucode_rx_stats_read,
 		.tx_stats_read = iwl_ucode_tx_stats_read,
@@ -397,79 +355,6 @@ static const struct iwl_ops iwl6000g2b_ops = {
 	.led = &iwlagn_led_ops,
 };
 
-static struct iwl_lib_ops iwl6050_lib = {
-	.set_hw_params = iwl6050_hw_set_hw_params,
-	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
-	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
-	.txq_set_sched = iwlagn_txq_set_sched,
-	.txq_agg_enable = iwlagn_txq_agg_enable,
-	.txq_agg_disable = iwlagn_txq_agg_disable,
-	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
-	.txq_free_tfd = iwl_hw_txq_free_tfd,
-	.txq_init = iwl_hw_tx_queue_init,
-	.rx_handler_setup = iwlagn_rx_handler_setup,
-	.setup_deferred_work = iwlagn_setup_deferred_work,
-	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
-	.load_ucode = iwlagn_load_ucode,
-	.dump_nic_event_log = iwl_dump_nic_event_log,
-	.dump_nic_error_log = iwl_dump_nic_error_log,
-	.dump_csr = iwl_dump_csr,
-	.dump_fh = iwl_dump_fh,
-	.init_alive_start = iwlagn_init_alive_start,
-	.alive_notify = iwlagn_alive_notify,
-	.send_tx_power = iwlagn_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
-	.set_channel_switch = iwl6000_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.stop = iwl_apm_stop,
-		.config = iwl6000_nic_config,
-		.set_pwr_src = iwl_set_pwr_src,
-	},
-	.eeprom_ops = {
-		.regulatory_bands = {
-			EEPROM_REG_BAND_1_CHANNELS,
-			EEPROM_REG_BAND_2_CHANNELS,
-			EEPROM_REG_BAND_3_CHANNELS,
-			EEPROM_REG_BAND_4_CHANNELS,
-			EEPROM_REG_BAND_5_CHANNELS,
-			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
-			EEPROM_REG_BAND_52_HT40_CHANNELS
-		},
-		.verify_signature  = iwlcore_eeprom_verify_signature,
-		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
-		.release_semaphore = iwlcore_eeprom_release_semaphore,
-		.calib_version	= iwlagn_eeprom_calib_version,
-		.query_addr = iwlagn_eeprom_query_addr,
-		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
-	},
-	.post_associate = iwl_post_associate,
-	.isr = iwl_isr_ict,
-	.config_ap = iwl_config_ap,
-	.temp_ops = {
-		.temperature = iwlagn_temperature,
-		.set_ct_kill = iwl6000_set_ct_threshold,
-		.set_calib_version = iwl6050_set_calib_version,
-	 },
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.debugfs_ops = {
-		.rx_stats_read = iwl_ucode_rx_stats_read,
-		.tx_stats_read = iwl_ucode_tx_stats_read,
-		.general_stats_read = iwl_ucode_general_stats_read,
-	},
-	.recover_from_tx_stall = iwl_bg_monitor_recover,
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
-};
-
-static const struct iwl_ops iwl6050_ops = {
-	.lib = &iwl6050_lib,
-	.hcmd = &iwlagn_hcmd,
-	.utils = &iwlagn_hcmd_utils,
-	.led = &iwlagn_led_ops,
-};
-
-
 struct iwl_cfg iwl6000g2a_2agn_cfg = {
 	.name = "6000 Series 2x2 AGN Gen2a",
 	.fw_name_pre = IWL6000G2A_FW_PRE,
@@ -505,6 +390,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2a_2abg_cfg = {
@@ -537,6 +423,9 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2a_2bg_cfg = {
@@ -569,6 +458,9 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_2agn_cfg = {
@@ -603,6 +495,9 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -635,6 +530,9 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -669,6 +567,9 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -701,6 +602,9 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -735,6 +639,9 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -767,6 +674,9 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
 	.chain_noise_scale = 1000,
 	.monitor_recover_period = IWL_MONITORING_PERIOD,
 	.max_event_log_size = 512,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 /*
@@ -885,7 +795,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.ops = &iwl6050_ops,
+	.ops = &iwl6000_ops,
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@@ -914,6 +824,7 @@ struct iwl_cfg iwl6050_2agn_cfg = {
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6050_2abg_cfg = {
@@ -922,7 +833,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
 	.sku = IWL_SKU_A|IWL_SKU_G,
-	.ops = &iwl6050_ops,
+	.ops = &iwl6000_ops,
 	.eeprom_size = OTP_LOW_IMAGE_SIZE,
 	.eeprom_ver = EEPROM_6050_EEPROM_VERSION,
 	.eeprom_calib_ver = EEPROM_6050_TX_POWER_VERSION,
@@ -949,6 +860,7 @@ struct iwl_cfg iwl6050_2abg_cfg = {
 	.ucode_tracing = true,
 	.sensitivity_calib_by_driver = true,
 	.chain_noise_calib_by_driver = true,
+	.need_dc_calib = true,
 };
 
 struct iwl_cfg iwl6000_3agn_cfg = {

+ 9 - 18
drivers/net/wireless/iwlwifi/iwl-calib.c → drivers/net/wireless/iwlwifi/iwl-agn-calib.c

@@ -96,17 +96,16 @@ int iwl_send_calib_results(struct iwl_priv *priv)
 			hcmd.len = priv->calib_results[i].buf_len;
 			hcmd.data = priv->calib_results[i].buf;
 			ret = iwl_send_cmd_sync(priv, &hcmd);
-			if (ret)
-				goto err;
+			if (ret) {
+				IWL_ERR(priv, "Error %d iteration %d\n",
+					ret, i);
+				break;
+			}
 		}
 	}
 
-	return 0;
-err:
-	IWL_ERR(priv, "Error %d iteration %d\n", ret, i);
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_calib_results);
 
 int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
 {
@@ -121,7 +120,6 @@ int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len)
 	memcpy(res->buf, buf, len);
 	return 0;
 }
-EXPORT_SYMBOL(iwl_calib_set);
 
 void iwl_calib_free_results(struct iwl_priv *priv)
 {
@@ -133,7 +131,6 @@ void iwl_calib_free_results(struct iwl_priv *priv)
 		priv->calib_results[i].buf_len = 0;
 	}
 }
-EXPORT_SYMBOL(iwl_calib_free_results);
 
 /*****************************************************************************
  * RUNTIME calibrations framework
@@ -533,7 +530,6 @@ void iwl_init_sensitivity(struct iwl_priv *priv)
 	ret |= iwl_sensitivity_write(priv);
 	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
 }
-EXPORT_SYMBOL(iwl_init_sensitivity);
 
 void iwl_sensitivity_calibration(struct iwl_priv *priv,
 				    struct iwl_notif_statistics *resp)
@@ -639,7 +635,6 @@ void iwl_sensitivity_calibration(struct iwl_priv *priv,
 	iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
 	iwl_sensitivity_write(priv);
 }
-EXPORT_SYMBOL(iwl_sensitivity_calibration);
 
 static inline u8 find_first_chain(u8 mask)
 {
@@ -848,10 +843,10 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
 
 	if (active_chains != priv->hw_params.valid_rx_ant &&
 	    active_chains != priv->chain_noise_data.active_chains)
-		IWL_WARN(priv,
-			 "Detected that not all antennas are connected! "
-			 "Connected: %#x, valid: %#x.\n",
-			 active_chains, priv->hw_params.valid_rx_ant);
+		IWL_DEBUG_CALIB(priv,
+				"Detected that not all antennas are connected! "
+				"Connected: %#x, valid: %#x.\n",
+				active_chains, priv->hw_params.valid_rx_ant);
 
 	/* Save for use within RXON, TX, SCAN commands, etc. */
 	priv->chain_noise_data.active_chains = active_chains;
@@ -897,8 +892,6 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
 	data->state = IWL_CHAIN_NOISE_DONE;
 	iwl_power_update_mode(priv, false);
 }
-EXPORT_SYMBOL(iwl_chain_noise_calibration);
-
 
 void iwl_reset_run_time_calib(struct iwl_priv *priv)
 {
@@ -915,5 +908,3 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv)
 	 * periodically after association */
 	iwl_send_statistics_request(priv, CMD_ASYNC, true);
 }
-EXPORT_SYMBOL(iwl_reset_run_time_calib);
-

+ 36 - 36
drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c

@@ -33,17 +33,17 @@ static int iwl_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
 	int p = 0;
 
 	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
-		       le32_to_cpu(priv->statistics.flag));
-	if (le32_to_cpu(priv->statistics.flag) &
+		       le32_to_cpu(priv->_agn.statistics.flag));
+	if (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_CLEAR_MSK)
 		p += scnprintf(buf + p, bufsz - p,
 			       "\tStatistics have been cleared\n");
 	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-		       (le32_to_cpu(priv->statistics.flag) &
+		       (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_FREQUENCY_MSK)
 			? "2.4 GHz" : "5.2 GHz");
 	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-		       (le32_to_cpu(priv->statistics.flag) &
+		       (le32_to_cpu(priv->_agn.statistics.flag) &
 			UCODE_STATISTICS_NARROW_BAND_MSK)
 			? "enabled" : "disabled");
 	return p;
@@ -79,22 +79,22 @@ ssize_t iwl_ucode_rx_stats_read(struct file *file, char __user *user_buf,
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
-	ofdm = &priv->statistics.rx.ofdm;
-	cck = &priv->statistics.rx.cck;
-	general = &priv->statistics.rx.general;
-	ht = &priv->statistics.rx.ofdm_ht;
-	accum_ofdm = &priv->accum_statistics.rx.ofdm;
-	accum_cck = &priv->accum_statistics.rx.cck;
-	accum_general = &priv->accum_statistics.rx.general;
-	accum_ht = &priv->accum_statistics.rx.ofdm_ht;
-	delta_ofdm = &priv->delta_statistics.rx.ofdm;
-	delta_cck = &priv->delta_statistics.rx.cck;
-	delta_general = &priv->delta_statistics.rx.general;
-	delta_ht = &priv->delta_statistics.rx.ofdm_ht;
-	max_ofdm = &priv->max_delta.rx.ofdm;
-	max_cck = &priv->max_delta.rx.cck;
-	max_general = &priv->max_delta.rx.general;
-	max_ht = &priv->max_delta.rx.ofdm_ht;
+	ofdm = &priv->_agn.statistics.rx.ofdm;
+	cck = &priv->_agn.statistics.rx.cck;
+	general = &priv->_agn.statistics.rx.general;
+	ht = &priv->_agn.statistics.rx.ofdm_ht;
+	accum_ofdm = &priv->_agn.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_agn.accum_statistics.rx.cck;
+	accum_general = &priv->_agn.accum_statistics.rx.general;
+	accum_ht = &priv->_agn.accum_statistics.rx.ofdm_ht;
+	delta_ofdm = &priv->_agn.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_agn.delta_statistics.rx.cck;
+	delta_general = &priv->_agn.delta_statistics.rx.general;
+	delta_ht = &priv->_agn.delta_statistics.rx.ofdm_ht;
+	max_ofdm = &priv->_agn.max_delta.rx.ofdm;
+	max_cck = &priv->_agn.max_delta.rx.cck;
+	max_general = &priv->_agn.max_delta.rx.general;
+	max_ht = &priv->_agn.max_delta.rx.ofdm_ht;
 
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
@@ -560,10 +560,10 @@ ssize_t iwl_ucode_tx_stats_read(struct file *file,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	tx = &priv->statistics.tx;
-	accum_tx = &priv->accum_statistics.tx;
-	delta_tx = &priv->delta_statistics.tx;
-	max_tx = &priv->max_delta.tx;
+	tx = &priv->_agn.statistics.tx;
+	accum_tx = &priv->_agn.accum_statistics.tx;
+	delta_tx = &priv->_agn.delta_statistics.tx;
+	max_tx = &priv->_agn.max_delta.tx;
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos,  "%-32s     current"
 			 "acumulative       delta         max\n",
@@ -777,18 +777,18 @@ ssize_t iwl_ucode_general_stats_read(struct file *file, char __user *user_buf,
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	general = &priv->statistics.general;
-	dbg = &priv->statistics.general.dbg;
-	div = &priv->statistics.general.div;
-	accum_general = &priv->accum_statistics.general;
-	delta_general = &priv->delta_statistics.general;
-	max_general = &priv->max_delta.general;
-	accum_dbg = &priv->accum_statistics.general.dbg;
-	delta_dbg = &priv->delta_statistics.general.dbg;
-	max_dbg = &priv->max_delta.general.dbg;
-	accum_div = &priv->accum_statistics.general.div;
-	delta_div = &priv->delta_statistics.general.div;
-	max_div = &priv->max_delta.general.div;
+	general = &priv->_agn.statistics.general;
+	dbg = &priv->_agn.statistics.general.dbg;
+	div = &priv->_agn.statistics.general.div;
+	accum_general = &priv->_agn.accum_statistics.general;
+	delta_general = &priv->_agn.delta_statistics.general;
+	max_general = &priv->_agn.max_delta.general;
+	accum_dbg = &priv->_agn.accum_statistics.general.dbg;
+	delta_dbg = &priv->_agn.delta_statistics.general.dbg;
+	max_dbg = &priv->_agn.max_delta.general.dbg;
+	accum_div = &priv->_agn.accum_statistics.general.div;
+	delta_div = &priv->_agn.delta_statistics.general.div;
+	max_div = &priv->_agn.max_delta.general.div;
 	pos += iwl_statistics_flag(priv, buf, bufsz);
 	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
 			 "acumulative       delta         max\n",

+ 1 - 5
drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c

@@ -214,11 +214,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
 static void iwlagn_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
 			__le32 *tx_flags)
 {
-	if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
-	    (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
-		*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
-	else
-		*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
+	*tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
 }
 
 /* Calc max signal level (dBm) among 3 possible receivers */

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

@@ -361,7 +361,8 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
 void iwlagn_temperature(struct iwl_priv *priv)
 {
 	/* store temperature from statistics (in Celsius) */
-	priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
+	priv->temperature =
+		le32_to_cpu(priv->_agn.statistics.general.temperature);
 	iwl_tt_handler(priv);
 }
 

+ 5 - 12
drivers/net/wireless/iwlwifi/iwl-agn-rs.c

@@ -324,18 +324,11 @@ static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
 			      struct iwl_lq_sta *lq_data,
 			      struct ieee80211_sta *sta)
 {
-	if ((tid < TID_MAX_LOAD_COUNT) &&
-	    !rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta)) {
-		if (priv->cfg->use_rts_for_ht) {
-			/*
-			 * switch to RTS/CTS if it is the prefer protection
-			 * method for HT traffic
-			 */
-			IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n");
-			priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
-			iwlcore_commit_rxon(priv);
-		}
-	}
+	if (tid < TID_MAX_LOAD_COUNT)
+		rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+	else
+		IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
+			tid, TID_MAX_LOAD_COUNT);
 }
 
 static inline int get_num_of_ant_from_rate(u32 rate_n_flags)

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

@@ -0,0 +1,284 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-calib.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-agn-hw.h"
+#include "iwl-agn.h"
+
+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl_init_sensitivity(priv);
+	}
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info
+				= &(priv->_agn.statistics.rx.general);
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	int bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	int bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+	int last_rx_noise;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+/*
+ *  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 iwl_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+	int i;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+
+	prev_stats = (__le32 *)&priv->_agn.statistics;
+	accum_stats = (u32 *)&priv->_agn.accum_statistics;
+	delta = (u32 *)&priv->_agn.delta_statistics;
+	max_delta = (u32 *)&priv->_agn.max_delta;
+
+	for (i = sizeof(__le32); i < sizeof(struct iwl_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->_agn.accum_statistics.general.temperature =
+		priv->_agn.statistics.general.temperature;
+	priv->_agn.accum_statistics.general.temperature_m =
+		priv->_agn.statistics.general.temperature_m;
+	priv->_agn.accum_statistics.general.ttl_timestamp =
+		priv->_agn.statistics.general.ttl_timestamp;
+	priv->_agn.accum_statistics.tx.tx_power.ant_a =
+		priv->_agn.statistics.tx.tx_power.ant_a;
+	priv->_agn.accum_statistics.tx.tx_power.ant_b =
+		priv->_agn.statistics.tx.tx_power.ant_b;
+	priv->_agn.accum_statistics.tx.tx_power.ant_c =
+		priv->_agn.statistics.tx.tx_power.ant_c;
+}
+#endif
+
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+bool iwl_good_plcp_health(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	bool rc = true;
+	int combined_plcp_delta;
+	unsigned int plcp_msec;
+	unsigned long plcp_received_jiffies;
+
+	if (priv->cfg->plcp_delta_threshold ==
+	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return rc;
+	}
+
+	/*
+	 * check for plcp_err and trigger radio reset if it exceeds
+	 * the plcp error threshold plcp_delta.
+	 */
+	plcp_received_jiffies = jiffies;
+	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
+					(long) priv->plcp_jiffies);
+	priv->plcp_jiffies = plcp_received_jiffies;
+	/*
+	 * check to make sure plcp_msec is not 0 to prevent division
+	 * by zero.
+	 */
+	if (plcp_msec) {
+		combined_plcp_delta =
+			(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
+			le32_to_cpu(priv->_agn.statistics.rx.ofdm.plcp_err)) +
+			(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
+			le32_to_cpu(priv->_agn.statistics.rx.ofdm_ht.plcp_err));
+
+		if ((combined_plcp_delta > 0) &&
+		    ((combined_plcp_delta * 100) / plcp_msec) >
+			priv->cfg->plcp_delta_threshold) {
+			/*
+			 * if plcp_err exceed the threshold,
+			 * the following data is printed in csv format:
+			 *    Text: plcp_err exceeded %d,
+			 *    Received ofdm.plcp_err,
+			 *    Current ofdm.plcp_err,
+			 *    Received ofdm_ht.plcp_err,
+			 *    Current ofdm_ht.plcp_err,
+			 *    combined_plcp_delta,
+			 *    plcp_msec
+			 */
+			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
+				"%u, %u, %u, %u, %d, %u mSecs\n",
+				priv->cfg->plcp_delta_threshold,
+				le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
+				le32_to_cpu(
+				       priv->_agn.statistics.rx.ofdm.plcp_err),
+				le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
+				le32_to_cpu(
+				  priv->_agn.statistics.rx.ofdm_ht.plcp_err),
+				combined_plcp_delta, plcp_msec);
+			rc = false;
+		}
+	}
+	return rc;
+}
+
+void iwl_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+
+	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(priv->_agn.statistics),
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+
+	change = ((priv->_agn.statistics.general.temperature !=
+		   pkt->u.stats.general.temperature) ||
+		  ((priv->_agn.statistics.flag &
+		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+#endif
+	iwl_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->_agn.statistics, &pkt->u.stats,
+	       sizeof(priv->_agn.statistics));
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * REG_RECALIB_PERIOD seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+void iwl_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		memset(&priv->_agn.accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl_rx_statistics(priv, rxb);
+}

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

@@ -233,6 +233,7 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 {
 	unsigned long flags;
 	u16 ra_tid;
+	int ret;
 
 	if ((IWLAGN_FIRST_AMPDU_QUEUE > txq_id) ||
 	    (IWLAGN_FIRST_AMPDU_QUEUE + priv->cfg->num_of_ampdu_queues
@@ -248,7 +249,9 @@ int iwlagn_txq_agg_enable(struct iwl_priv *priv, int txq_id,
 	ra_tid = BUILD_RAxTID(sta_id, tid);
 
 	/* Modify device's station table to Tx this TID */
-	iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
 
 	spin_lock_irqsave(&priv->lock, flags);
 

+ 49 - 24
drivers/net/wireless/iwlwifi/iwl-agn.c

@@ -1461,13 +1461,13 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 
 	actual_ack_cnt_delta =
 		le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-		le32_to_cpu(priv->statistics.tx.actual_ack_cnt);
+		le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
 	expected_ack_cnt_delta =
 		le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-		le32_to_cpu(priv->statistics.tx.expected_ack_cnt);
+		le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
 	ba_timeout_delta =
 		le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-		le32_to_cpu(priv->statistics.tx.agg.ba_timeout);
+		le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
 	if ((priv->_agn.agg_tids_count > 0) &&
 	    (expected_ack_cnt_delta > 0) &&
 	    (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
@@ -1484,10 +1484,10 @@ bool iwl_good_ack_health(struct iwl_priv *priv,
 		 * DEBUG is not, these will just compile out.
 		 */
 		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-				priv->delta_statistics.tx.rx_detected_cnt);
+				priv->_agn.delta_statistics.tx.rx_detected_cnt);
 		IWL_DEBUG_RADIO(priv,
 				"ack_or_ba_timeout_collision delta = %d\n",
-				priv->delta_statistics.tx.
+				priv->_agn.delta_statistics.tx.
 				ack_or_ba_timeout_collision);
 #endif
 		IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
@@ -2310,9 +2310,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
 	trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, data2, line,
 				      blink1, blink2, ilink1, ilink2);
 
-	IWL_ERR(priv, "Desc                               Time       "
+	IWL_ERR(priv, "Desc                                  Time       "
 		"data1      data2      line\n");
-	IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
+	IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
 		desc_lookup(desc), desc, time, data1, data2, line);
 	IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
 	IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
@@ -2935,9 +2935,9 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
 	}
 
 	if (priv->start_calib) {
-		iwl_chain_noise_calibration(priv, &priv->statistics);
+		iwl_chain_noise_calibration(priv, &priv->_agn.statistics);
 
-		iwl_sensitivity_calibration(priv, &priv->statistics);
+		iwl_sensitivity_calibration(priv, &priv->_agn.statistics);
 	}
 
 	mutex_unlock(&priv->mutex);
@@ -3368,13 +3368,32 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	return ret;
 }
 
+/*
+ * switch to RTS/CTS for TX
+ */
+static void iwl_enable_rts_cts(struct iwl_priv *priv)
+{
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN;
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_INFO(priv, "use RTS/CTS protection\n");
+		iwlcore_commit_rxon(priv);
+	} else {
+		/* scanning, defer the request until scan completed */
+		IWL_DEBUG_INFO(priv, "defer setting RTS/CTS protection\n");
+	}
+}
+
 static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 				struct ieee80211_vif *vif,
 				enum ieee80211_ampdu_mlme_action action,
 				struct ieee80211_sta *sta, u16 tid, u16 *ssn)
 {
 	struct iwl_priv *priv = hw->priv;
-	int ret;
+	int ret = -EINVAL;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
@@ -3382,17 +3401,19 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 	if (!(priv->cfg->sku & IWL_SKU_N))
 		return -EACCES;
 
+	mutex_lock(&priv->mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		IWL_DEBUG_HT(priv, "start Rx\n");
-		return iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
+		ret = iwl_sta_rx_agg_start(priv, sta, tid, *ssn);
+		break;
 	case IEEE80211_AMPDU_RX_STOP:
 		IWL_DEBUG_HT(priv, "stop Rx\n");
 		ret = iwl_sta_rx_agg_stop(priv, sta, tid);
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return 0;
-		else
-			return ret;
+			ret = 0;
+		break;
 	case IEEE80211_AMPDU_TX_START:
 		IWL_DEBUG_HT(priv, "start Tx\n");
 		ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
@@ -3401,7 +3422,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 			IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n",
 				     priv->_agn.agg_tids_count);
 		}
-		return ret;
+		break;
 	case IEEE80211_AMPDU_TX_STOP:
 		IWL_DEBUG_HT(priv, "stop Tx\n");
 		ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
@@ -3411,18 +3432,22 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
 				     priv->_agn.agg_tids_count);
 		}
 		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return 0;
-		else
-			return ret;
+			ret = 0;
+		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
-		/* do nothing */
-		return -EOPNOTSUPP;
-	default:
-		IWL_DEBUG_HT(priv, "unknown\n");
-		return -EINVAL;
+		if (priv->cfg->use_rts_for_ht) {
+			/*
+			 * switch to RTS/CTS if it is the prefer protection
+			 * method for HT traffic
+			 */
+			iwl_enable_rts_cts(priv);
+		}
+		ret = 0;
 		break;
 	}
-	return 0;
+	mutex_unlock(&priv->mutex);
+
+	return ret;
 }
 
 static void iwl_mac_sta_notify(struct ieee80211_hw *hw,

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

@@ -201,6 +201,16 @@ static inline bool iwl_is_tx_success(u32 status)
 	       (status == TX_STATUS_DIRECT_DONE);
 }
 
+/* rx */
+void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+bool iwl_good_plcp_health(struct iwl_priv *priv,
+			  struct iwl_rx_packet *pkt);
+void iwl_rx_statistics(struct iwl_priv *priv,
+		       struct iwl_rx_mem_buffer *rxb);
+void iwl_reply_statistics(struct iwl_priv *priv,
+			  struct iwl_rx_mem_buffer *rxb);
+
 /* scan */
 void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
 

+ 21 - 9
drivers/net/wireless/iwlwifi/iwl-commands.h

@@ -1399,18 +1399,27 @@ struct iwl_rx_mpdu_res_start {
 
 /* REPLY_TX Tx flags field */
 
-/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
+/*
+ * 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
  * before this frame. if CTS-to-self required check
- * RXON_FLG_SELF_CTS_EN status. */
-#define TX_CMD_FLG_RTS_CTS_MSK cpu_to_le32(1 << 0)
+ * RXON_FLG_SELF_CTS_EN status.
+ * unused in 3945/4965, used in 5000 series and after
+ */
+#define TX_CMD_FLG_PROT_REQUIRE_MSK cpu_to_le32(1 << 0)
 
-/* 1: Use Request-To-Send protocol before this frame.
- * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
+/*
+ * 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
+ * used in 3945/4965, unused in 5000 series and after
+ */
 #define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
 
-/* 1: Transmit Clear-To-Send to self before this frame.
+/*
+ * 1: Transmit Clear-To-Send to self before this frame.
  * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
- * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
+ * used in 3945/4965, unused in 5000 series and after
+ */
 #define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
 
 /* 1: Expect ACK from receiving station
@@ -1430,8 +1439,11 @@ struct iwl_rx_mpdu_res_start {
  * Set when Txing a block-ack request frame.  Also set TX_CMD_FLG_ACK_MSK. */
 #define TX_CMD_FLG_IMM_BA_RSP_MASK  cpu_to_le32(1 << 6)
 
-/* 1: Frame requires full Tx-Op protection.
- * Set this if either RTS or CTS Tx Flag gets set. */
+/*
+ * 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set.
+ * used in 3945/4965, unused in 5000 series and after
+ */
 #define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
 
 /* Tx antenna selection field; used only for 3945, reserved (0) for 4965.

+ 21 - 1
drivers/net/wireless/iwlwifi/iwl-core.c

@@ -1331,7 +1331,6 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
 			changed_flags, *total_flags);
 
 	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-	CHK(FIF_ALLMULTI, RXON_FILTER_ACCEPT_GRP_MSK);
 	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
 	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
 
@@ -1346,6 +1345,12 @@ void iwl_configure_filter(struct ieee80211_hw *hw,
 
 	mutex_unlock(&priv->mutex);
 
+	/*
+	 * Receiving all multicast frames is always enabled by the
+	 * default flags setup in iwl_connection_init_rx_config()
+	 * since we currently do not support programming multicast
+	 * filters into the device.
+	 */
 	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
 			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
 }
@@ -2105,6 +2110,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
 		iwl_set_flags_for_band(priv, conf->channel->band, priv->vif);
 		spin_unlock_irqrestore(&priv->lock, flags);
 
+		if (priv->cfg->ops->lib->update_bcast_station)
+			ret = priv->cfg->ops->lib->update_bcast_station(priv);
+
  set_ch_out:
 		/* The list of supported rates and rate mask can be different
 		 * for each band; since the band may have changed, reset
@@ -2837,6 +2845,7 @@ int iwl_pci_resume(struct pci_dev *pdev)
 {
 	struct iwl_priv *priv = pci_get_drvdata(pdev);
 	int ret;
+	bool hw_rfkill = false;
 
 	/*
 	 * We disable the RETRY_TIMEOUT register (0x41) to keep
@@ -2851,6 +2860,17 @@ int iwl_pci_resume(struct pci_dev *pdev)
 	pci_restore_state(pdev);
 	iwl_enable_interrupts(priv);
 
+	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+		hw_rfkill = true;
+
+	if (hw_rfkill)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rfkill);
+
 	return 0;
 }
 EXPORT_SYMBOL(iwl_pci_resume);

+ 2 - 10
drivers/net/wireless/iwlwifi/iwl-core.h

@@ -196,6 +196,7 @@ struct iwl_lib_ops {
 	/* station management */
 	int (*manage_ibss_station)(struct iwl_priv *priv,
 				   struct ieee80211_vif *vif, bool add);
+	int (*update_bcast_station)(struct iwl_priv *priv);
 	/* recover from tx queue stall */
 	void (*recover_from_tx_stall)(unsigned long data);
 	/* check for plcp health */
@@ -330,6 +331,7 @@ struct iwl_cfg {
 	const bool chain_noise_calib_by_driver;
 	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
 	u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
+	const bool need_dc_calib;
 };
 
 /***************************
@@ -455,20 +457,10 @@ void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
 int iwl_rx_queue_space(const struct iwl_rx_queue *q);
 void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 /* Handlers */
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb);
 void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb);
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				 struct iwl_rx_packet *pkt);
-bool iwl_good_ack_health(struct iwl_priv *priv,
-				 struct iwl_rx_packet *pkt);
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt);
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb);
-void iwl_reply_statistics(struct iwl_priv *priv,
-			  struct iwl_rx_mem_buffer *rxb);
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
 void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 

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

@@ -1430,10 +1430,10 @@ static ssize_t iwl_dbgfs_plcp_delta_write(struct file *file,
 		return -EFAULT;
 	if (sscanf(buf, "%d", &plcp) != 1)
 		return -EINVAL;
-	if ((plcp <= IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
+	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
 		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
 		priv->cfg->plcp_delta_threshold =
-			IWL_MAX_PLCP_ERR_THRESHOLD_DEF;
+			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
 	else
 		priv->cfg->plcp_delta_threshold = plcp;
 	return count;

+ 9 - 8
drivers/net/wireless/iwlwifi/iwl-dev.h

@@ -1036,11 +1036,12 @@ struct iwl_event_log {
  * This is the threshold value of plcp error rate per 100mSecs.  It is
  * used to set and check for the validity of plcp_delta.
  */
-#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(0)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(1)
 #define IWL_MAX_PLCP_ERR_THRESHOLD_DEF	(50)
 #define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100)
 #define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF	(200)
 #define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	(0)
 
 #define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
 #define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
@@ -1224,13 +1225,6 @@ struct iwl_priv {
 	struct iwl_power_mgr power_data;
 	struct iwl_tt_mgmt thermal_throttle;
 
-	struct iwl_notif_statistics statistics;
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	struct iwl_notif_statistics accum_statistics;
-	struct iwl_notif_statistics delta_statistics;
-	struct iwl_notif_statistics max_delta;
-#endif
-
 	/* context information */
 	u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
 
@@ -1323,6 +1317,13 @@ struct iwl_priv {
 
 			u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
 			u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
+
+			struct iwl_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+			struct iwl_notif_statistics accum_statistics;
+			struct iwl_notif_statistics delta_statistics;
+			struct iwl_notif_statistics max_delta;
+#endif
 		} _agn;
 #endif
 	};

+ 3 - 0
drivers/net/wireless/iwlwifi/iwl-eeprom.c

@@ -629,6 +629,9 @@ int iwl_eeprom_check_version(struct iwl_priv *priv)
 	    calib_ver < priv->cfg->eeprom_calib_ver)
 		goto err;
 
+	IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+		 eeprom_ver, calib_ver);
+
 	return 0;
 err:
 	IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",

+ 0 - 238
drivers/net/wireless/iwlwifi/iwl-rx.c

@@ -205,26 +205,6 @@ err_bd:
 }
 EXPORT_SYMBOL(iwl_rx_queue_alloc);
 
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_missed_beacon_notif *missed_beacon;
-
-	missed_beacon = &pkt->u.missed_beacon;
-	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
-	    priv->missed_beacon_threshold) {
-		IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
-		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
-		    le32_to_cpu(missed_beacon->total_missed_becons),
-		    le32_to_cpu(missed_beacon->num_recvd_beacons),
-		    le32_to_cpu(missed_beacon->num_expected_beacons));
-		if (!test_bit(STATUS_SCANNING, &priv->status))
-			iwl_init_sensitivity(priv);
-	}
-}
-EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
 
 void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb)
@@ -243,161 +223,6 @@ void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
 
-
-
-/* Calculate noise level, based on measurements during network silence just
- *   before arriving beacon.  This measurement can be done only if we know
- *   exactly when to expect beacons, therefore only when we're associated. */
-static void iwl_rx_calc_noise(struct iwl_priv *priv)
-{
-	struct statistics_rx_non_phy *rx_info
-				= &(priv->statistics.rx.general);
-	int num_active_rx = 0;
-	int total_silence = 0;
-	int bcn_silence_a =
-		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
-	int bcn_silence_b =
-		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
-	int bcn_silence_c =
-		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-	int last_rx_noise;
-
-	if (bcn_silence_a) {
-		total_silence += bcn_silence_a;
-		num_active_rx++;
-	}
-	if (bcn_silence_b) {
-		total_silence += bcn_silence_b;
-		num_active_rx++;
-	}
-	if (bcn_silence_c) {
-		total_silence += bcn_silence_c;
-		num_active_rx++;
-	}
-
-	/* Average among active antennas */
-	if (num_active_rx)
-		last_rx_noise = (total_silence / num_active_rx) - 107;
-	else
-		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
-			bcn_silence_a, bcn_silence_b, bcn_silence_c,
-			last_rx_noise);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  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 iwl_accumulative_statistics(struct iwl_priv *priv,
-					__le32 *stats)
-{
-	int i;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-
-	prev_stats = (__le32 *)&priv->statistics;
-	accum_stats = (u32 *)&priv->accum_statistics;
-	delta = (u32 *)&priv->delta_statistics;
-	max_delta = (u32 *)&priv->max_delta;
-
-	for (i = sizeof(__le32); i < sizeof(struct iwl_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->accum_statistics.general.temperature =
-		priv->statistics.general.temperature;
-	priv->accum_statistics.general.temperature_m =
-		priv->statistics.general.temperature_m;
-	priv->accum_statistics.general.ttl_timestamp =
-		priv->statistics.general.ttl_timestamp;
-	priv->accum_statistics.tx.tx_power.ant_a =
-		priv->statistics.tx.tx_power.ant_a;
-	priv->accum_statistics.tx.tx_power.ant_b =
-		priv->statistics.tx.tx_power.ant_b;
-	priv->accum_statistics.tx.tx_power.ant_c =
-		priv->statistics.tx.tx_power.ant_c;
-}
-#endif
-
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		combined_plcp_delta =
-			(le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm.plcp_err)) +
-			(le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err) -
-			le32_to_cpu(priv->statistics.rx.ofdm_ht.plcp_err));
-
-		if ((combined_plcp_delta > 0) &&
-		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold,
-			 * the following data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    Received ofdm_ht.plcp_err,
-			 *    Current ofdm_ht.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %u, %u, %u, %d, %u mSecs\n",
-				priv->cfg->plcp_delta_threshold,
-				le32_to_cpu(pkt->u.stats.rx.ofdm.plcp_err),
-				le32_to_cpu(priv->statistics.rx.ofdm.plcp_err),
-				le32_to_cpu(pkt->u.stats.rx.ofdm_ht.plcp_err),
-				le32_to_cpu(
-				  priv->statistics.rx.ofdm_ht.plcp_err),
-				combined_plcp_delta, plcp_msec);
-			rc = false;
-		}
-	}
-	return rc;
-}
-EXPORT_SYMBOL(iwl_good_plcp_health);
-
 void iwl_recover_from_statistics(struct iwl_priv *priv,
 				struct iwl_rx_packet *pkt)
 {
@@ -431,69 +256,6 @@ void iwl_recover_from_statistics(struct iwl_priv *priv,
 }
 EXPORT_SYMBOL(iwl_recover_from_statistics);
 
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	int change;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-
-	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(priv->statistics),
-		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-
-	change = ((priv->statistics.general.temperature !=
-		   pkt->u.stats.general.temperature) ||
-		  ((priv->statistics.flag &
-		    STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-		   (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
-#endif
-	iwl_recover_from_statistics(priv, pkt);
-
-	memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics));
-
-	set_bit(STATUS_STATISTICS, &priv->status);
-
-	/* Reschedule the statistics timer to occur in
-	 * REG_RECALIB_PERIOD seconds to ensure we get a
-	 * thermal update even if the uCode doesn't give
-	 * us one */
-	mod_timer(&priv->statistics_periodic, jiffies +
-		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
-	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
-		iwl_rx_calc_noise(priv);
-		queue_work(priv->workqueue, &priv->run_time_calib_work);
-	}
-	if (priv->cfg->ops->lib->temp_ops.temperature && change)
-		priv->cfg->ops->lib->temp_ops.temperature(priv);
-}
-EXPORT_SYMBOL(iwl_rx_statistics);
-
-void iwl_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->accum_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->delta_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->max_delta, 0,
-			sizeof(struct iwl_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl_rx_statistics(priv, rxb);
-}
-EXPORT_SYMBOL(iwl_reply_statistics);
-
 /*
  * returns non-zero if packet should be dropped
  */

+ 9 - 0
drivers/net/wireless/iwlwifi/iwl-scan.c

@@ -537,6 +537,15 @@ void iwl_bg_scan_completed(struct work_struct *work)
 	/* Since setting the TXPOWER may have been deferred while
 	 * performing the scan, fire one off */
 	iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	if (memcmp(&priv->active_rxon,
+		   &priv->staging_rxon, sizeof(priv->staging_rxon)))
+		iwlcore_commit_rxon(priv);
+
  out:
 	mutex_unlock(&priv->mutex);
 

+ 80 - 26
drivers/net/wireless/iwlwifi/iwl-sta.c

@@ -30,6 +30,7 @@
 #include <net/mac80211.h>
 #include <linux/etherdevice.h>
 #include <linux/sched.h>
+#include <linux/lockdep.h>
 
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -54,18 +55,19 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
 	}
 }
 
-static void iwl_process_add_sta_resp(struct iwl_priv *priv,
-				     struct iwl_addsta_cmd *addsta,
-				     struct iwl_rx_packet *pkt,
-				     bool sync)
+static int iwl_process_add_sta_resp(struct iwl_priv *priv,
+				    struct iwl_addsta_cmd *addsta,
+				    struct iwl_rx_packet *pkt,
+				    bool sync)
 {
 	u8 sta_id = addsta->sta.sta_id;
 	unsigned long flags;
+	int ret = -EIO;
 
 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
 		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
 			pkt->hdr.flags);
-		return;
+		return ret;
 	}
 
 	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
@@ -77,6 +79,7 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
 	case ADD_STA_SUCCESS_MSK:
 		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
 		iwl_sta_ucode_activate(priv, sta_id);
+		ret = 0;
 		break;
 	case ADD_STA_NO_ROOM_IN_TABLE:
 		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
@@ -114,6 +117,8 @@ static void iwl_process_add_sta_resp(struct iwl_priv *priv,
 		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
 		       addsta->sta.addr);
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
 }
 
 static void iwl_add_sta_callback(struct iwl_priv *priv,
@@ -145,8 +150,10 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
 	if (flags & CMD_ASYNC)
 		cmd.callback = iwl_add_sta_callback;
-	else
+	else {
 		cmd.flags |= CMD_WANT_SKB;
+		might_sleep();
+	}
 
 	cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
 	ret = iwl_send_cmd(priv, &cmd);
@@ -156,7 +163,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
 
 	if (ret == 0) {
 		pkt = (struct iwl_rx_packet *)cmd.reply_page;
-		iwl_process_add_sta_resp(priv, sta, pkt, true);
+		ret = iwl_process_add_sta_resp(priv, sta, pkt, true);
 	}
 	iwl_free_pages(priv, cmd.reply_page);
 
@@ -831,7 +838,9 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
 {
 	unsigned long flags;
 	__le16 key_flags = 0;
-	int ret;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
 
@@ -871,11 +880,10 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
 static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
@@ -884,7 +892,9 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 {
 	unsigned long flags;
 	__le16 key_flags = 0;
-	int ret;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
 	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
@@ -919,11 +929,10 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
 
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 
 static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
@@ -1013,9 +1022,11 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 				u8 sta_id)
 {
 	unsigned long flags;
-	int ret = 0;
 	u16 key_flags;
 	u8 keyidx;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	priv->key_mapping_key--;
 
@@ -1062,9 +1073,10 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
 		spin_unlock_irqrestore(&priv->sta_lock, flags);
 		return 0;
 	}
-	ret =  iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return ret;
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_remove_dynamic_key);
 
@@ -1073,6 +1085,8 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
 {
 	int ret;
 
+	lockdep_assert_held(&priv->mutex);
+
 	priv->key_mapping_key++;
 	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
 
@@ -1245,6 +1259,36 @@ int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq)
 }
 EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
 
+/**
+ * iwl_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwlagn. Placed here to have all bcast station management
+ * code together.
+ */
+int iwl_update_bcast_station(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	struct iwl_link_quality_cmd *link_cmd;
+	u8 sta_id = priv->hw_params.bcast_sta_id;
+
+	link_cmd = iwl_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv, "Unable to initialize rate scaling for bcast station.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (priv->stations[sta_id].lq)
+		kfree(priv->stations[sta_id].lq);
+	else
+		IWL_DEBUG_INFO(priv, "Bcast station rate scaling has not been initialized yet.\n");
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iwl_update_bcast_station);
+
 void iwl_dealloc_bcast_station(struct iwl_priv *priv)
 {
 	unsigned long flags;
@@ -1268,17 +1312,22 @@ EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station);
 /**
  * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
  */
-void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
 {
 	unsigned long flags;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	/* Remove "disable" flag, to enable Tx for this TID */
 	spin_lock_irqsave(&priv->sta_lock, flags);
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
 	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
 
@@ -1287,6 +1336,9 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 {
 	unsigned long flags;
 	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION)
@@ -1298,10 +1350,10 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
-				CMD_ASYNC);
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_rx_agg_start);
 
@@ -1309,7 +1361,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			int tid)
 {
 	unsigned long flags;
-	int sta_id, ret;
+	int sta_id;
+	struct iwl_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
 
 	sta_id = iwl_sta_id(sta);
 	if (sta_id == IWL_INVALID_STATION) {
@@ -1322,11 +1377,10 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
 	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
 	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
 	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-	ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 
-	return ret;
-
+	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
 }
 EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
 

+ 2 - 1
drivers/net/wireless/iwlwifi/iwl-sta.h

@@ -60,6 +60,7 @@ void iwl_restore_stations(struct iwl_priv *priv);
 void iwl_clear_ucode_stations(struct iwl_priv *priv);
 int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
 void iwl_dealloc_bcast_station(struct iwl_priv *priv);
+int iwl_update_bcast_station(struct iwl_priv *priv);
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
 int iwl_send_add_sta(struct iwl_priv *priv,
 		     struct iwl_addsta_cmd *sta, u8 flags);
@@ -73,7 +74,7 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
 		       const u8 *addr);
 int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
-void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
+int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
 int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
 			 int tid, u16 ssn);
 int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,

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

@@ -1424,7 +1424,7 @@ void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
 		    iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
 
 		IWL_ERR(priv,
-			"%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
 			desc_lookup(desc), desc, time, blink1, blink2,
 			ilink1, ilink2, data1);
 		trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,

+ 8 - 4
drivers/net/wireless/iwmc3200wifi/cfg80211.c

@@ -670,20 +670,24 @@ static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
-				    enum tx_power_setting type, int dbm)
+				    enum nl80211_tx_power_setting type, int mbm)
 {
 	struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
 	int ret;
 
 	switch (type) {
-	case TX_POWER_AUTOMATIC:
+	case NL80211_TX_POWER_AUTOMATIC:
 		return 0;
-	case TX_POWER_FIXED:
+	case NL80211_TX_POWER_FIXED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
+
 		if (!test_bit(IWM_STATUS_READY, &iwm->status))
 			return 0;
 
 		ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
-					      CFG_TX_PWR_LIMIT_USR, dbm * 2);
+					      CFG_TX_PWR_LIMIT_USR,
+					      MBM_TO_DBM(mbm) * 2);
 		if (ret < 0)
 			return ret;
 

+ 0 - 3
drivers/net/wireless/libertas/Makefile

@@ -1,4 +1,3 @@
-libertas-y += assoc.o
 libertas-y += cfg.o
 libertas-y += cmd.o
 libertas-y += cmdresp.o
@@ -6,9 +5,7 @@ libertas-y += debugfs.o
 libertas-y += ethtool.o
 libertas-y += main.o
 libertas-y += rx.o
-libertas-y += scan.o
 libertas-y += tx.o
-libertas-y += wext.o
 libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
 
 usb8xxx-objs += if_usb.o

+ 0 - 2264
drivers/net/wireless/libertas/assoc.c

@@ -1,2264 +0,0 @@
-/* Copyright (C) 2006, Red Hat, Inc. */
-
-#include <linux/types.h>
-#include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <linux/if_arp.h>
-#include <linux/slab.h>
-#include <net/lib80211.h>
-
-#include "assoc.h"
-#include "decl.h"
-#include "host.h"
-#include "scan.h"
-#include "cmd.h"
-
-static const u8 bssid_any[ETH_ALEN]  __attribute__ ((aligned (2))) =
-	{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-/* The firmware needs the following bits masked out of the beacon-derived
- * capability field when associating/joining to a BSS:
- *  9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
- */
-#define CAPINFO_MASK	(~(0xda00))
-
-/**
- * 802.11b/g supported bitrates (in 500Kb/s units)
- */
-u8 lbs_bg_rates[MAX_RATES] =
-    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0x00, 0x00 };
-
-
-static int assoc_helper_wep_keys(struct lbs_private *priv,
-		struct assoc_request *assoc_req);
-
-/**
- *  @brief This function finds common rates between rates and card rates.
- *
- * It will fill common rates in rates as output if found.
- *
- * NOTE: Setting the MSB of the basic rates need to be taken
- *   care, either before or after calling this function
- *
- *  @param priv     A pointer to struct lbs_private structure
- *  @param rates       the buffer which keeps input and output
- *  @param rates_size  the size of rates buffer; new size of buffer on return,
- *                     which will be less than or equal to original rates_size
- *
- *  @return            0 on success, or -1 on error
- */
-static int get_common_rates(struct lbs_private *priv,
-	u8 *rates,
-	u16 *rates_size)
-{
-	int i, j;
-	u8 intersection[MAX_RATES];
-	u16 intersection_size;
-	u16 num_rates = 0;
-
-	intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection));
-
-	/* Allow each rate from 'rates' that is supported by the hardware */
-	for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) {
-		for (j = 0; j < intersection_size && rates[j]; j++) {
-			if (rates[j] == lbs_bg_rates[i])
-				intersection[num_rates++] = rates[j];
-		}
-	}
-
-	lbs_deb_hex(LBS_DEB_JOIN, "AP rates    ", rates, *rates_size);
-	lbs_deb_hex(LBS_DEB_JOIN, "card rates  ", lbs_bg_rates,
-			ARRAY_SIZE(lbs_bg_rates));
-	lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates);
-	lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
-
-	if (!priv->enablehwauto) {
-		for (i = 0; i < num_rates; i++) {
-			if (intersection[i] == priv->cur_rate)
-				goto done;
-		}
-		lbs_pr_alert("Previously set fixed data rate %#x isn't "
-		       "compatible with the network.\n", priv->cur_rate);
-		return -1;
-	}
-
-done:
-	memset(rates, 0, *rates_size);
-	*rates_size = num_rates;
-	memcpy(rates, intersection, num_rates);
-	return 0;
-}
-
-
-/**
- *  @brief Sets the MSB on basic rates as the firmware requires
- *
- * Scan through an array and set the MSB for basic data rates.
- *
- *  @param rates     buffer of data rates
- *  @param len       size of buffer
- */
-static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
-{
-	int i;
-
-	for (i = 0; i < len; i++) {
-		if (rates[i] == 0x02 || rates[i] == 0x04 ||
-		    rates[i] == 0x0b || rates[i] == 0x16)
-			rates[i] |= 0x80;
-	}
-}
-
-
-static u8 iw_auth_to_ieee_auth(u8 auth)
-{
-	if (auth == IW_AUTH_ALG_OPEN_SYSTEM)
-		return 0x00;
-	else if (auth == IW_AUTH_ALG_SHARED_KEY)
-		return 0x01;
-	else if (auth == IW_AUTH_ALG_LEAP)
-		return 0x80;
-
-	lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth);
-	return 0;
-}
-
-/**
- *  @brief This function prepares the authenticate command.  AUTHENTICATE only
- *  sets the authentication suite for future associations, as the firmware
- *  handles authentication internally during the ASSOCIATE command.
- *
- *  @param priv      A pointer to struct lbs_private structure
- *  @param bssid     The peer BSSID with which to authenticate
- *  @param auth      The authentication mode to use (from wireless.h)
- *
- *  @return         0 or -1
- */
-static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth)
-{
-	struct cmd_ds_802_11_authenticate cmd;
-	int ret = -1;
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	memcpy(cmd.bssid, bssid, ETH_ALEN);
-
-	cmd.authtype = iw_auth_to_ieee_auth(auth);
-
-	lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
-
-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-	return ret;
-}
-
-
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
-			   struct assoc_request *assoc)
-{
-	struct cmd_ds_802_11_set_wep cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.action = cpu_to_le16(cmd_action);
-
-	if (cmd_action == CMD_ACT_ADD) {
-		int i;
-
-		/* default tx key index */
-		cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
-					   CMD_WEP_KEY_INDEX_MASK);
-
-		/* Copy key types and material to host command structure */
-		for (i = 0; i < 4; i++) {
-			struct enc_key *pkey = &assoc->wep_keys[i];
-
-			switch (pkey->len) {
-			case KEY_LEN_WEP_40:
-				cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
-				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
-				lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
-				break;
-			case KEY_LEN_WEP_104:
-				cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
-				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
-				lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
-				break;
-			case 0:
-				break;
-			default:
-				lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
-					    i, pkey->len);
-				ret = -1;
-				goto done;
-				break;
-			}
-		}
-	} else if (cmd_action == CMD_ACT_REMOVE) {
-		/* ACT_REMOVE clears _all_ WEP keys */
-
-		/* default tx key index */
-		cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
-					   CMD_WEP_KEY_INDEX_MASK);
-		lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
-done:
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
-			      uint16_t *enable)
-{
-	struct cmd_ds_802_11_enable_rsn cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(cmd_action);
-
-	if (cmd_action == CMD_ACT_GET)
-		cmd.enable = 0;
-	else {
-		if (*enable)
-			cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
-		else
-			cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
-		lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
-	if (!ret && cmd_action == CMD_ACT_GET)
-		*enable = le16_to_cpu(cmd.enable);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
-		struct enc_key *key)
-{
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (key->flags & KEY_INFO_WPA_ENABLED)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
-	if (key->flags & KEY_INFO_WPA_UNICAST)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
-	if (key->flags & KEY_INFO_WPA_MCAST)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
-
-	keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-	keyparam->keytypeid = cpu_to_le16(key->type);
-	keyparam->keylen = cpu_to_le16(key->len);
-	memcpy(keyparam->key, key->key, key->len);
-
-	/* Length field doesn't include the {type,length} header */
-	keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
-	lbs_deb_leave(LBS_DEB_CMD);
-}
-
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-				struct assoc_request *assoc)
-{
-	struct cmd_ds_802_11_key_material cmd;
-	int ret = 0;
-	int index = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	cmd.action = cpu_to_le16(cmd_action);
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	if (cmd_action == CMD_ACT_GET) {
-		cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
-	} else {
-		memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
-
-		if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
-			set_one_wpa_key(&cmd.keyParamSet[index],
-					&assoc->wpa_unicast_key);
-			index++;
-		}
-
-		if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
-			set_one_wpa_key(&cmd.keyParamSet[index],
-					&assoc->wpa_mcast_key);
-			index++;
-		}
-
-		/* The common header and as many keys as we included */
-		cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
-						    keyParamSet[index]));
-	}
-	ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
-	/* Copy the returned key to driver private data */
-	if (!ret && cmd_action == CMD_ACT_GET) {
-		void *buf_ptr = cmd.keyParamSet;
-		void *resp_end = &(&cmd)[1];
-
-		while (buf_ptr < resp_end) {
-			struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
-			struct enc_key *key;
-			uint16_t param_set_len = le16_to_cpu(keyparam->length);
-			uint16_t key_len = le16_to_cpu(keyparam->keylen);
-			uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
-			uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
-			void *end;
-
-			end = (void *)keyparam + sizeof(keyparam->type)
-				+ sizeof(keyparam->length) + param_set_len;
-
-			/* Make sure we don't access past the end of the IEs */
-			if (end > resp_end)
-				break;
-
-			if (key_flags & KEY_INFO_WPA_UNICAST)
-				key = &priv->wpa_unicast_key;
-			else if (key_flags & KEY_INFO_WPA_MCAST)
-				key = &priv->wpa_mcast_key;
-			else
-				break;
-
-			/* Copy returned key into driver */
-			memset(key, 0, sizeof(struct enc_key));
-			if (key_len > sizeof(key->key))
-				break;
-			key->type = key_type;
-			key->flags = key_flags;
-			key->len = key_len;
-			memcpy(key->key, keyparam->key, key->len);
-
-			buf_ptr = end + 1;
-		}
-	}
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
-{
-/*		Bit  	Rate
-*		15:13 Reserved
-*		12    54 Mbps
-*		11    48 Mbps
-*		10    36 Mbps
-*		9     24 Mbps
-*		8     18 Mbps
-*		7     12 Mbps
-*		6     9 Mbps
-*		5     6 Mbps
-*		4     Reserved
-*		3     11 Mbps
-*		2     5.5 Mbps
-*		1     2 Mbps
-*		0     1 Mbps
-**/
-
-	uint16_t ratemask;
-	int i = lbs_data_rate_to_fw_index(rate);
-	if (lower_rates_ok)
-		ratemask = (0x1fef >> (12 - i));
-	else
-		ratemask = (1 << i);
-	return cpu_to_le16(ratemask);
-}
-
-int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
-				      uint16_t cmd_action)
-{
-	struct cmd_ds_802_11_rate_adapt_rateset cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (!priv->cur_rate && !priv->enablehwauto)
-		return -EINVAL;
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.action = cpu_to_le16(cmd_action);
-	cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
-	cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
-	ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
-	if (!ret && cmd_action == CMD_ACT_GET)
-		priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Set the data rate
- *
- *  @param priv    	A pointer to struct lbs_private structure
- *  @param rate  	The desired data rate, or 0 to clear a locked rate
- *
- *  @return 	   	0 on success, error on failure
- */
-int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
-{
-	struct cmd_ds_802_11_data_rate cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	if (rate > 0) {
-		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
-		cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
-		if (cmd.rates[0] == 0) {
-			lbs_deb_cmd("DATA_RATE: invalid requested rate of"
-				" 0x%02X\n", rate);
-			ret = 0;
-			goto out;
-		}
-		lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
-	} else {
-		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
-		lbs_deb_cmd("DATA_RATE: setting auto\n");
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
-	if (ret)
-		goto out;
-
-	lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
-
-	/* FIXME: get actual rates FW can do if this command actually returns
-	 * all data rates supported.
-	 */
-	priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
-	lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-
-int lbs_cmd_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *cmd)
-{
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	cmd->command = cpu_to_le16(CMD_802_11_RSSI);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
-		sizeof(struct cmd_header));
-	cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
-
-	/* reset Beacon SNR/NF/RSSI values */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
-	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-int lbs_ret_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *resp)
-{
-	struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	/* store the non average value */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] =
-		get_unaligned_le16(&rssirsp->noisefloor);
-
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
-	priv->NF[TYPE_BEACON][TYPE_AVG] =
-		get_unaligned_le16(&rssirsp->avgnoisefloor);
-
-	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
-	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
-		     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
-	priv->RSSI[TYPE_BEACON][TYPE_AVG] =
-	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
-		     priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
-
-	lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
-	       priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
-	       priv->RSSI[TYPE_BEACON][TYPE_AVG]);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-
-int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
-				struct cmd_ds_command *cmd,
-				u16 cmd_action)
-{
-	struct cmd_ds_802_11_beacon_control
-		*bcn_ctrl = &cmd->params.bcn_ctrl;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
-			     + sizeof(struct cmd_header));
-	cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
-
-	bcn_ctrl->action = cpu_to_le16(cmd_action);
-	bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
-	bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
-					struct cmd_ds_command *resp)
-{
-	struct cmd_ds_802_11_beacon_control *bcn_ctrl =
-	    &resp->params.bcn_ctrl;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (bcn_ctrl->action == CMD_ACT_GET) {
-		priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
-		priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
-	}
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	return 0;
-}
-
-
-
-static int lbs_assoc_post(struct lbs_private *priv,
-			  struct cmd_ds_802_11_associate_response *resp)
-{
-	int ret = 0;
-	union iwreq_data wrqu;
-	struct bss_descriptor *bss;
-	u16 status_code;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	if (!priv->in_progress_assoc_req) {
-		lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
-		ret = -1;
-		goto done;
-	}
-	bss = &priv->in_progress_assoc_req->bss;
-
-	/*
-	 * Older FW versions map the IEEE 802.11 Status Code in the association
-	 * response to the following values returned in resp->statuscode:
-	 *
-	 *    IEEE Status Code                Marvell Status Code
-	 *    0                       ->      0x0000 ASSOC_RESULT_SUCCESS
-	 *    13                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    14                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    15                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    16                      ->      0x0004 ASSOC_RESULT_AUTH_REFUSED
-	 *    others                  ->      0x0003 ASSOC_RESULT_REFUSED
-	 *
-	 * Other response codes:
-	 *    0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
-	 *    0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
-	 *                                    association response from the AP)
-	 */
-
-	status_code = le16_to_cpu(resp->statuscode);
-	if (priv->fwrelease < 0x09000000) {
-		switch (status_code) {
-		case 0x00:
-			break;
-		case 0x01:
-			lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
-			break;
-		case 0x02:
-			lbs_deb_assoc("ASSOC_RESP: internal timer "
-				"expired while waiting for the AP\n");
-			break;
-		case 0x03:
-			lbs_deb_assoc("ASSOC_RESP: association "
-				"refused by AP\n");
-			break;
-		case 0x04:
-			lbs_deb_assoc("ASSOC_RESP: authentication "
-				"refused by AP\n");
-			break;
-		default:
-			lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
-				" unknown\n", status_code);
-			break;
-		}
-	} else {
-		/* v9+ returns the AP's association response */
-		lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code);
-	}
-
-	if (status_code) {
-		lbs_mac_event_disconnected(priv);
-		ret = status_code;
-		goto done;
-	}
-
-	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP",
-		    (void *) (resp + sizeof (resp->hdr)),
-		    le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr));
-
-	/* Send a Media Connected event, according to the Spec */
-	priv->connect_status = LBS_CONNECTED;
-
-	/* Update current SSID and BSSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
-	priv->curbssparams.ssid_len = bss->ssid_len;
-	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
-	priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
-	priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
-
-	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
-	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
-	priv->nextSNRNF = 0;
-	priv->numSNRNF = 0;
-
-	netif_carrier_on(priv->dev);
-	if (!priv->tx_pending_len)
-		netif_wake_queue(priv->dev);
-
-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief This function prepares an association-class command.
- *
- *  @param priv      A pointer to struct lbs_private structure
- *  @param assoc_req The association request describing the BSS to associate
- *                   or reassociate with
- *  @param command   The actual command, either CMD_802_11_ASSOCIATE or
- *                   CMD_802_11_REASSOCIATE
- *
- *  @return         0 or -1
- */
-static int lbs_associate(struct lbs_private *priv,
-			 struct assoc_request *assoc_req,
-			 u16 command)
-{
-	struct cmd_ds_802_11_associate cmd;
-	int ret = 0;
-	struct bss_descriptor *bss = &assoc_req->bss;
-	u8 *pos = &(cmd.iebuf[0]);
-	u16 tmpcap, tmplen, tmpauth;
-	struct mrvl_ie_ssid_param_set *ssid;
-	struct mrvl_ie_ds_param_set *ds;
-	struct mrvl_ie_cf_param_set *cf;
-	struct mrvl_ie_rates_param_set *rates;
-	struct mrvl_ie_rsn_param_set *rsn;
-	struct mrvl_ie_auth_type *auth;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	BUG_ON((command != CMD_802_11_ASSOCIATE) &&
-		(command != CMD_802_11_REASSOCIATE));
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.command = cpu_to_le16(command);
-
-	/* Fill in static fields */
-	memcpy(cmd.bssid, bss->bssid, ETH_ALEN);
-	cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
-
-	/* Capability info */
-	tmpcap = (bss->capability & CAPINFO_MASK);
-	if (bss->mode == IW_MODE_INFRA)
-		tmpcap |= WLAN_CAPABILITY_ESS;
-	cmd.capability = cpu_to_le16(tmpcap);
-	lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
-
-	/* SSID */
-	ssid = (struct mrvl_ie_ssid_param_set *) pos;
-	ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
-	tmplen = bss->ssid_len;
-	ssid->header.len = cpu_to_le16(tmplen);
-	memcpy(ssid->ssid, bss->ssid, tmplen);
-	pos += sizeof(ssid->header) + tmplen;
-
-	ds = (struct mrvl_ie_ds_param_set *) pos;
-	ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
-	ds->header.len = cpu_to_le16(1);
-	ds->channel = bss->phy.ds.channel;
-	pos += sizeof(ds->header) + 1;
-
-	cf = (struct mrvl_ie_cf_param_set *) pos;
-	cf->header.type = cpu_to_le16(TLV_TYPE_CF);
-	tmplen = sizeof(*cf) - sizeof (cf->header);
-	cf->header.len = cpu_to_le16(tmplen);
-	/* IE payload should be zeroed, firmware fills it in for us */
-	pos += sizeof(*cf);
-
-	rates = (struct mrvl_ie_rates_param_set *) pos;
-	rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
-	tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES);
-	memcpy(&rates->rates, &bss->rates, tmplen);
-	if (get_common_rates(priv, rates->rates, &tmplen)) {
-		ret = -1;
-		goto done;
-	}
-	pos += sizeof(rates->header) + tmplen;
-	rates->header.len = cpu_to_le16(tmplen);
-	lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
-
-	/* Copy the infra. association rates into Current BSS state structure */
-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-	memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
-
-	/* Set MSB on basic rates as the firmware requires, but _after_
-	 * copying to current bss rates.
-	 */
-	lbs_set_basic_rate_flags(rates->rates, tmplen);
-
-	/* Firmware v9+ indicate authentication suites as a TLV */
-	if (priv->fwrelease >= 0x09000000) {
-		auth = (struct mrvl_ie_auth_type *) pos;
-		auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
-		auth->header.len = cpu_to_le16(2);
-		tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode);
-		auth->auth = cpu_to_le16(tmpauth);
-		pos += sizeof(auth->header) + 2;
-
-		lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
-			bss->bssid, priv->secinfo.auth_mode);
-	}
-
-	/* WPA/WPA2 IEs */
-	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
-		rsn = (struct mrvl_ie_rsn_param_set *) pos;
-		/* WPA_IE or WPA2_IE */
-		rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
-		tmplen = (u16) assoc_req->wpa_ie[1];
-		rsn->header.len = cpu_to_le16(tmplen);
-		memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
-		lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn,
-			sizeof(rsn->header) + tmplen);
-		pos += sizeof(rsn->header) + tmplen;
-	}
-
-	cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) +
-				   (u16)(pos - (u8 *) &cmd.iebuf));
-
-	/* update curbssparams */
-	priv->channel = bss->phy.ds.channel;
-
-	ret = lbs_cmd_with_response(priv, command, &cmd);
-	if (ret == 0) {
-		ret = lbs_assoc_post(priv,
-			(struct cmd_ds_802_11_associate_response *) &cmd);
-	}
-
-done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Associate to a specific BSS discovered in a scan
- *
- *  @param priv      A pointer to struct lbs_private structure
- *  @param assoc_req The association request describing the BSS to associate with
- *
- *  @return          0-success, otherwise fail
- */
-static int lbs_try_associate(struct lbs_private *priv,
-	struct assoc_request *assoc_req)
-{
-	int ret;
-	u8 preamble = RADIO_PREAMBLE_LONG;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	/* FW v9 and higher indicate authentication suites as a TLV in the
-	 * association command, not as a separate authentication command.
-	 */
-	if (priv->fwrelease < 0x09000000) {
-		ret = lbs_set_authentication(priv, assoc_req->bss.bssid,
-					     priv->secinfo.auth_mode);
-		if (ret)
-			goto out;
-	}
-
-	/* Use short preamble only when both the BSS and firmware support it */
-	if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
-		preamble = RADIO_PREAMBLE_SHORT;
-
-	ret = lbs_set_radio(priv, preamble, 1);
-	if (ret)
-		goto out;
-
-	ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE);
-	/* If the association fails with current auth mode, let's
-	 * try by changing the auth mode
-	 */
-	if ((priv->authtype_auto) &&
-			(ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) &&
-			(assoc_req->secinfo.wep_enabled) &&
-			(priv->connect_status != LBS_CONNECTED)) {
-		if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM)
-			priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
-		else
-			priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-		if (!assoc_helper_wep_keys(priv, assoc_req))
-			ret = lbs_associate(priv, assoc_req,
-						CMD_802_11_ASSOCIATE);
-	}
-
-	if (ret)
-		ret = -1;
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_adhoc_post(struct lbs_private *priv,
-			  struct cmd_ds_802_11_ad_hoc_result *resp)
-{
-	int ret = 0;
-	u16 command = le16_to_cpu(resp->hdr.command);
-	u16 result = le16_to_cpu(resp->hdr.result);
-	union iwreq_data wrqu;
-	struct bss_descriptor *bss;
-	DECLARE_SSID_BUF(ssid);
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	if (!priv->in_progress_assoc_req) {
-		lbs_deb_join("ADHOC_RESP: no in-progress association "
-			"request\n");
-		ret = -1;
-		goto done;
-	}
-	bss = &priv->in_progress_assoc_req->bss;
-
-	/*
-	 * Join result code 0 --> SUCCESS
-	 */
-	if (result) {
-		lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
-		if (priv->connect_status == LBS_CONNECTED)
-			lbs_mac_event_disconnected(priv);
-		ret = -1;
-		goto done;
-	}
-
-	/* Send a Media Connected event, according to the Spec */
-	priv->connect_status = LBS_CONNECTED;
-
-	if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
-		/* Update the created network descriptor with the new BSSID */
-		memcpy(bss->bssid, resp->bssid, ETH_ALEN);
-	}
-
-	/* Set the BSSID from the joined/started descriptor */
-	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
-
-	/* Set the new SSID to current SSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
-	priv->curbssparams.ssid_len = bss->ssid_len;
-
-	netif_carrier_on(priv->dev);
-	if (!priv->tx_pending_len)
-		netif_wake_queue(priv->dev);
-
-	memset(&wrqu, 0, sizeof(wrqu));
-	memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-
-	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
-		     print_ssid(ssid, bss->ssid, bss->ssid_len),
-		     priv->curbssparams.bssid,
-		     priv->channel);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Join an adhoc network found in a previous scan
- *
- *  @param priv         A pointer to struct lbs_private structure
- *  @param assoc_req    The association request describing the BSS to join
- *
- *  @return             0 on success, error on failure
- */
-static int lbs_adhoc_join(struct lbs_private *priv,
-	struct assoc_request *assoc_req)
-{
-	struct cmd_ds_802_11_ad_hoc_join cmd;
-	struct bss_descriptor *bss = &assoc_req->bss;
-	u8 preamble = RADIO_PREAMBLE_LONG;
-	DECLARE_SSID_BUF(ssid);
-	u16 ratesize = 0;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	lbs_deb_join("current SSID '%s', ssid length %u\n",
-		print_ssid(ssid, priv->curbssparams.ssid,
-		priv->curbssparams.ssid_len),
-		priv->curbssparams.ssid_len);
-	lbs_deb_join("requested ssid '%s', ssid length %u\n",
-		print_ssid(ssid, bss->ssid, bss->ssid_len),
-		bss->ssid_len);
-
-	/* check if the requested SSID is already joined */
-	if (priv->curbssparams.ssid_len &&
-	    !lbs_ssid_cmp(priv->curbssparams.ssid,
-			priv->curbssparams.ssid_len,
-			bss->ssid, bss->ssid_len) &&
-	    (priv->mode == IW_MODE_ADHOC) &&
-	    (priv->connect_status == LBS_CONNECTED)) {
-		union iwreq_data wrqu;
-
-		lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
-			"current, not attempting to re-join");
-
-		/* Send the re-association event though, because the association
-		 * request really was successful, even if just a null-op.
-		 */
-		memset(&wrqu, 0, sizeof(wrqu));
-		memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
-		       ETH_ALEN);
-		wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-		wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-		goto out;
-	}
-
-	/* Use short preamble only when both the BSS and firmware support it */
-	if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
-		lbs_deb_join("AdhocJoin: Short preamble\n");
-		preamble = RADIO_PREAMBLE_SHORT;
-	}
-
-	ret = lbs_set_radio(priv, preamble, 1);
-	if (ret)
-		goto out;
-
-	lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
-	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
-
-	priv->adhoccreate = 0;
-	priv->channel = bss->channel;
-
-	/* Build the join command */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.bss.type = CMD_BSS_TYPE_IBSS;
-	cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
-
-	memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
-	memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
-
-	memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set));
-
-	memcpy(&cmd.bss.ibss, &bss->ss.ibss,
-	       sizeof(struct ieee_ie_ibss_param_set));
-
-	cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
-	lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
-	       bss->capability, CAPINFO_MASK);
-
-	/* information on BSSID descriptor passed to FW */
-	lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
-			cmd.bss.bssid, cmd.bss.ssid);
-
-	/* Only v8 and below support setting these */
-	if (priv->fwrelease < 0x09000000) {
-		/* failtimeout */
-		cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
-		/* probedelay */
-		cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-	}
-
-	/* Copy Data rates from the rates recorded in scan response */
-	memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
-	ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates));
-	memcpy(cmd.bss.rates, bss->rates, ratesize);
-	if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
-		lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
-		ret = -1;
-		goto out;
-	}
-
-	/* Copy the ad-hoc creation rates into Current BSS state structure */
-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-	memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
-
-	/* Set MSB on basic rates as the firmware requires, but _after_
-	 * copying to current bss rates.
-	 */
-	lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
-
-	cmd.bss.ibss.atimwindow = bss->atimwindow;
-
-	if (assoc_req->secinfo.wep_enabled) {
-		u16 tmp = le16_to_cpu(cmd.bss.capability);
-		tmp |= WLAN_CAPABILITY_PRIVACY;
-		cmd.bss.capability = cpu_to_le16(tmp);
-	}
-
-	if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
-		__le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
-
-		/* wake up first */
-		ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
-						   CMD_ACT_SET, 0, 0,
-						   &local_ps_mode);
-		if (ret) {
-			ret = -1;
-			goto out;
-		}
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
-	if (ret == 0) {
-		ret = lbs_adhoc_post(priv,
-				     (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Start an Adhoc Network
- *
- *  @param priv         A pointer to struct lbs_private structure
- *  @param assoc_req    The association request describing the BSS to start
- *
- *  @return             0 on success, error on failure
- */
-static int lbs_adhoc_start(struct lbs_private *priv,
-	struct assoc_request *assoc_req)
-{
-	struct cmd_ds_802_11_ad_hoc_start cmd;
-	u8 preamble = RADIO_PREAMBLE_SHORT;
-	size_t ratesize = 0;
-	u16 tmpcap = 0;
-	int ret = 0;
-	DECLARE_SSID_BUF(ssid);
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	ret = lbs_set_radio(priv, preamble, 1);
-	if (ret)
-		goto out;
-
-	/* Build the start command */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
-
-	lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
-		print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
-		assoc_req->ssid_len);
-
-	cmd.bsstype = CMD_BSS_TYPE_IBSS;
-
-	if (priv->beacon_period == 0)
-		priv->beacon_period = MRVDRV_BEACON_INTERVAL;
-	cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
-
-	WARN_ON(!assoc_req->channel);
-
-	/* set Physical parameter set */
-	cmd.ds.header.id = WLAN_EID_DS_PARAMS;
-	cmd.ds.header.len = 1;
-	cmd.ds.channel = assoc_req->channel;
-
-	/* set IBSS parameter set */
-	cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
-	cmd.ibss.header.len = 2;
-	cmd.ibss.atimwindow = cpu_to_le16(0);
-
-	/* set capability info */
-	tmpcap = WLAN_CAPABILITY_IBSS;
-	if (assoc_req->secinfo.wep_enabled ||
-	    assoc_req->secinfo.WPAenabled ||
-	    assoc_req->secinfo.WPA2enabled) {
-		lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n");
-		tmpcap |= WLAN_CAPABILITY_PRIVACY;
-	} else
-		lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n");
-
-	cmd.capability = cpu_to_le16(tmpcap);
-
-	/* Only v8 and below support setting probe delay */
-	if (priv->fwrelease < 0x09000000)
-		cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
-
-	ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
-	memcpy(cmd.rates, lbs_bg_rates, ratesize);
-
-	/* Copy the ad-hoc creating rates into Current BSS state structure */
-	memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
-	memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
-
-	/* Set MSB on basic rates as the firmware requires, but _after_
-	 * copying to current bss rates.
-	 */
-	lbs_set_basic_rate_flags(cmd.rates, ratesize);
-
-	lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
-	       cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
-
-	lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
-		     assoc_req->channel, assoc_req->band);
-
-	priv->adhoccreate = 1;
-	priv->mode = IW_MODE_ADHOC;
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
-	if (ret == 0)
-		ret = lbs_adhoc_post(priv,
-				     (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
- *
- *  @param priv         A pointer to struct lbs_private structure
- *  @return             0 on success, or an error
- */
-int lbs_adhoc_stop(struct lbs_private *priv)
-{
-	struct cmd_ds_802_11_ad_hoc_stop cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	memset(&cmd, 0, sizeof (cmd));
-	cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
-
-	/* Clean up everything even if there was an error */
-	lbs_mac_event_disconnected(priv);
-
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
-					struct bss_descriptor *match_bss)
-{
-	if (!secinfo->wep_enabled &&
-	    !secinfo->WPAenabled && !secinfo->WPA2enabled &&
-	    match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
-	    match_bss->rsn_ie[0] != WLAN_EID_RSN &&
-	    !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-		return 1;
-	else
-		return 0;
-}
-
-static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
-				       struct bss_descriptor *match_bss)
-{
-	if (secinfo->wep_enabled &&
-	    !secinfo->WPAenabled && !secinfo->WPA2enabled &&
-	    (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-		return 1;
-	else
-		return 0;
-}
-
-static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
-				struct bss_descriptor *match_bss)
-{
-	if (!secinfo->wep_enabled && secinfo->WPAenabled &&
-	    (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
-	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-	    && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
-	   )
-		return 1;
-	else
-		return 0;
-}
-
-static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
-				 struct bss_descriptor *match_bss)
-{
-	if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
-	    (match_bss->rsn_ie[0] == WLAN_EID_RSN)
-	    /* privacy bit may NOT be set in some APs like LinkSys WRT54G
-	    (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
-	   )
-		return 1;
-	else
-		return 0;
-}
-
-static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
-					struct bss_descriptor *match_bss)
-{
-	if (!secinfo->wep_enabled &&
-	    !secinfo->WPAenabled && !secinfo->WPA2enabled &&
-	    (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
-	    (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
-	    (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
-		return 1;
-	else
-		return 0;
-}
-
-/**
- *  @brief Check if a scanned network compatible with the driver settings
- *
- *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
- * enabled enabled  enabled   AES     mode   privacy  WPA  WPA2  Compatible
- *    0       0        0       0      NONE      0      0    0   yes No security
- *    1       0        0       0      NONE      1      0    0   yes Static WEP
- *    0       1        0       0       x        1x     1    x   yes WPA
- *    0       0        1       0       x        1x     x    1   yes WPA2
- *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES
- *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP
- *
- *
- *  @param priv A pointer to struct lbs_private
- *  @param index   Index in scantable to check against current driver settings
- *  @param mode    Network mode: Infrastructure or IBSS
- *
- *  @return        Index in scantable, or error code if negative
- */
-static int is_network_compatible(struct lbs_private *priv,
-				 struct bss_descriptor *bss, uint8_t mode)
-{
-	int matched = 0;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	if (bss->mode != mode)
-		goto done;
-
-	matched = match_bss_no_security(&priv->secinfo, bss);
-	if (matched)
-		goto done;
-	matched = match_bss_static_wep(&priv->secinfo, bss);
-	if (matched)
-		goto done;
-	matched = match_bss_wpa(&priv->secinfo, bss);
-	if (matched) {
-		lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
-			     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-			     "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-			     priv->secinfo.wep_enabled ? "e" : "d",
-			     priv->secinfo.WPAenabled ? "e" : "d",
-			     priv->secinfo.WPA2enabled ? "e" : "d",
-			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
-		goto done;
-	}
-	matched = match_bss_wpa2(&priv->secinfo, bss);
-	if (matched) {
-		lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
-			     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
-			     "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
-			     priv->secinfo.wep_enabled ? "e" : "d",
-			     priv->secinfo.WPAenabled ? "e" : "d",
-			     priv->secinfo.WPA2enabled ? "e" : "d",
-			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
-		goto done;
-	}
-	matched = match_bss_dynamic_wep(&priv->secinfo, bss);
-	if (matched) {
-		lbs_deb_scan("is_network_compatible() dynamic WEP: "
-			     "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
-			     bss->wpa_ie[0], bss->rsn_ie[0],
-			     (bss->capability & WLAN_CAPABILITY_PRIVACY));
-		goto done;
-	}
-
-	/* bss security settings don't match those configured on card */
-	lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
-		     "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
-		     bss->wpa_ie[0], bss->rsn_ie[0],
-		     priv->secinfo.wep_enabled ? "e" : "d",
-		     priv->secinfo.WPAenabled ? "e" : "d",
-		     priv->secinfo.WPA2enabled ? "e" : "d",
-		     (bss->capability & WLAN_CAPABILITY_PRIVACY));
-
-done:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
-	return matched;
-}
-
-/**
- *  @brief This function finds a specific compatible BSSID in the scan list
- *
- *  Used in association code
- *
- *  @param priv  A pointer to struct lbs_private
- *  @param bssid    BSSID to find in the scan list
- *  @param mode     Network mode: Infrastructure or IBSS
- *
- *  @return         index in BSSID list, or error return code (< 0)
- */
-static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
-					      uint8_t *bssid, uint8_t mode)
-{
-	struct bss_descriptor *iter_bss;
-	struct bss_descriptor *found_bss = NULL;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	if (!bssid)
-		goto out;
-
-	lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
-
-	/* Look through the scan table for a compatible match.  The loop will
-	 *   continue past a matched bssid that is not compatible in case there
-	 *   is an AP with multiple SSIDs assigned to the same BSSID
-	 */
-	mutex_lock(&priv->lock);
-	list_for_each_entry(iter_bss, &priv->network_list, list) {
-		if (compare_ether_addr(iter_bss->bssid, bssid))
-			continue; /* bssid doesn't match */
-		switch (mode) {
-		case IW_MODE_INFRA:
-		case IW_MODE_ADHOC:
-			if (!is_network_compatible(priv, iter_bss, mode))
-				break;
-			found_bss = iter_bss;
-			break;
-		default:
-			found_bss = iter_bss;
-			break;
-		}
-	}
-	mutex_unlock(&priv->lock);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-	return found_bss;
-}
-
-/**
- *  @brief This function finds ssid in ssid list.
- *
- *  Used in association code
- *
- *  @param priv  A pointer to struct lbs_private
- *  @param ssid     SSID to find in the list
- *  @param bssid    BSSID to qualify the SSID selection (if provided)
- *  @param mode     Network mode: Infrastructure or IBSS
- *
- *  @return         index in BSSID list
- */
-static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
-					     uint8_t *ssid, uint8_t ssid_len,
-					     uint8_t *bssid, uint8_t mode,
-					     int channel)
-{
-	u32 bestrssi = 0;
-	struct bss_descriptor *iter_bss = NULL;
-	struct bss_descriptor *found_bss = NULL;
-	struct bss_descriptor *tmp_oldest = NULL;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	mutex_lock(&priv->lock);
-
-	list_for_each_entry(iter_bss, &priv->network_list, list) {
-		if (!tmp_oldest ||
-		    (iter_bss->last_scanned < tmp_oldest->last_scanned))
-			tmp_oldest = iter_bss;
-
-		if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
-				 ssid, ssid_len) != 0)
-			continue; /* ssid doesn't match */
-		if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
-			continue; /* bssid doesn't match */
-		if ((channel > 0) && (iter_bss->channel != channel))
-			continue; /* channel doesn't match */
-
-		switch (mode) {
-		case IW_MODE_INFRA:
-		case IW_MODE_ADHOC:
-			if (!is_network_compatible(priv, iter_bss, mode))
-				break;
-
-			if (bssid) {
-				/* Found requested BSSID */
-				found_bss = iter_bss;
-				goto out;
-			}
-
-			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-				bestrssi = SCAN_RSSI(iter_bss->rssi);
-				found_bss = iter_bss;
-			}
-			break;
-		case IW_MODE_AUTO:
-		default:
-			if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
-				bestrssi = SCAN_RSSI(iter_bss->rssi);
-				found_bss = iter_bss;
-			}
-			break;
-		}
-	}
-
-out:
-	mutex_unlock(&priv->lock);
-	lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
-	return found_bss;
-}
-
-static int assoc_helper_essid(struct lbs_private *priv,
-                              struct assoc_request * assoc_req)
-{
-	int ret = 0;
-	struct bss_descriptor * bss;
-	int channel = -1;
-	DECLARE_SSID_BUF(ssid);
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	/* FIXME: take channel into account when picking SSIDs if a channel
-	 * is set.
-	 */
-
-	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
-		channel = assoc_req->channel;
-
-	lbs_deb_assoc("SSID '%s' requested\n",
-	              print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
-	if (assoc_req->mode == IW_MODE_INFRA) {
-		lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
-			assoc_req->ssid_len);
-
-		bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
-				assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
-		if (bss != NULL) {
-			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
-			ret = lbs_try_associate(priv, assoc_req);
-		} else {
-			lbs_deb_assoc("SSID not found; cannot associate\n");
-		}
-	} else if (assoc_req->mode == IW_MODE_ADHOC) {
-		/* Scan for the network, do not save previous results.  Stale
-		 *   scan data will cause us to join a non-existant adhoc network
-		 */
-		lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
-			assoc_req->ssid_len);
-
-		/* Search for the requested SSID in the scan table */
-		bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
-				assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
-		if (bss != NULL) {
-			lbs_deb_assoc("SSID found, will join\n");
-			memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
-			lbs_adhoc_join(priv, assoc_req);
-		} else {
-			/* else send START command */
-			lbs_deb_assoc("SSID not found, creating adhoc network\n");
-			memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
-				IEEE80211_MAX_SSID_LEN);
-			assoc_req->bss.ssid_len = assoc_req->ssid_len;
-			lbs_adhoc_start(priv, assoc_req);
-		}
-	}
-
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_bssid(struct lbs_private *priv,
-                              struct assoc_request * assoc_req)
-{
-	int ret = 0;
-	struct bss_descriptor * bss;
-
-	lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
-
-	/* Search for index position in list for requested MAC */
-	bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
-			    assoc_req->mode);
-	if (bss == NULL) {
-		lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
-			"cannot associate.\n", assoc_req->bssid);
-		goto out;
-	}
-
-	memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
-	if (assoc_req->mode == IW_MODE_INFRA) {
-		ret = lbs_try_associate(priv, assoc_req);
-		lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n",
-			      ret);
-	} else if (assoc_req->mode == IW_MODE_ADHOC) {
-		lbs_adhoc_join(priv, assoc_req);
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_associate(struct lbs_private *priv,
-                                  struct assoc_request * assoc_req)
-{
-	int ret = 0, done = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	/* If we're given and 'any' BSSID, try associating based on SSID */
-
-	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
-		    compare_ether_addr(bssid_off, assoc_req->bssid)) {
-			ret = assoc_helper_bssid(priv, assoc_req);
-			done = 1;
-		}
-	}
-
-	if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		ret = assoc_helper_essid(priv, assoc_req);
-	}
-
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_mode(struct lbs_private *priv,
-                             struct assoc_request * assoc_req)
-{
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	if (assoc_req->mode == priv->mode)
-		goto done;
-
-	if (assoc_req->mode == IW_MODE_INFRA) {
-		if (priv->psstate != PS_STATE_FULL_POWER)
-			lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
-		priv->psmode = LBS802_11POWERMODECAM;
-	}
-
-	priv->mode = assoc_req->mode;
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
-		assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-static int assoc_helper_channel(struct lbs_private *priv,
-                                struct assoc_request * assoc_req)
-{
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	ret = lbs_update_channel(priv);
-	if (ret) {
-		lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
-		goto done;
-	}
-
-	if (assoc_req->channel == priv->channel)
-		goto done;
-
-	if (priv->mesh_dev) {
-		/* Change mesh channel first; 21.p21 firmware won't let
-		   you change channel otherwise (even though it'll return
-		   an error to this */
-		lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
-				assoc_req->channel);
-	}
-
-	lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
-		      priv->channel, assoc_req->channel);
-
-	ret = lbs_set_channel(priv, assoc_req->channel);
-	if (ret < 0)
-		lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
-
-	/* FIXME: shouldn't need to grab the channel _again_ after setting
-	 * it since the firmware is supposed to return the new channel, but
-	 * whatever... */
-	ret = lbs_update_channel(priv);
-	if (ret) {
-		lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
-		goto done;
-	}
-
-	if (assoc_req->channel != priv->channel) {
-		lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
-		              assoc_req->channel);
-		goto restore_mesh;
-	}
-
-	if (assoc_req->secinfo.wep_enabled &&
-	    (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
-	     assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
-		/* Make sure WEP keys are re-sent to firmware */
-		set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
-	}
-
-	/* Must restart/rejoin adhoc networks after channel change */
- 	set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
-
- restore_mesh:
-	if (priv->mesh_dev)
-		lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				priv->channel);
-
- done:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_wep_keys(struct lbs_private *priv,
-				 struct assoc_request *assoc_req)
-{
-	int i;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	/* Set or remove WEP keys */
-	if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
-	    assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
-		ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
-	else
-		ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
-
-	if (ret)
-		goto out;
-
-	/* enable/disable the MAC's WEP packet filter */
-	if (assoc_req->secinfo.wep_enabled)
-		priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
-	else
-		priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
-
-	lbs_set_mac_control(priv);
-
-	mutex_lock(&priv->lock);
-
-	/* Copy WEP keys into priv wep key fields */
-	for (i = 0; i < 4; i++) {
-		memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
-		       sizeof(struct enc_key));
-	}
-	priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
-
-	mutex_unlock(&priv->lock);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-static int assoc_helper_secinfo(struct lbs_private *priv,
-                                struct assoc_request * assoc_req)
-{
-	int ret = 0;
-	uint16_t do_wpa;
-	uint16_t rsn = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	memcpy(&priv->secinfo, &assoc_req->secinfo,
-		sizeof(struct lbs_802_11_security));
-
-	lbs_set_mac_control(priv);
-
-	/* If RSN is already enabled, don't try to enable it again, since
-	 * ENABLE_RSN resets internal state machines and will clobber the
-	 * 4-way WPA handshake.
-	 */
-
-	/* Get RSN enabled/disabled */
-	ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
-	if (ret) {
-		lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
-		goto out;
-	}
-
-	/* Don't re-enable RSN if it's already enabled */
-	do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
-	if (do_wpa == rsn)
-		goto out;
-
-	/* Set RSN enabled/disabled */
-	ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_wpa_keys(struct lbs_private *priv,
-                                 struct assoc_request * assoc_req)
-{
-	int ret = 0;
-	unsigned int flags = assoc_req->flags;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	/* Work around older firmware bug where WPA unicast and multicast
-	 * keys must be set independently.  Seen in SDIO parts with firmware
-	 * version 5.0.11p0.
-	 */
-
-	if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
-		clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-		ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
-		assoc_req->flags = flags;
-	}
-
-	if (ret)
-		goto out;
-
-	memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
-			sizeof(struct enc_key));
-
-	if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
-		clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
-		ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
-		assoc_req->flags = flags;
-
-		memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
-				sizeof(struct enc_key));
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int assoc_helper_wpa_ie(struct lbs_private *priv,
-                               struct assoc_request * assoc_req)
-{
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
-		memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
-		priv->wpa_ie_len = assoc_req->wpa_ie_len;
-	} else {
-		memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
-		priv->wpa_ie_len = 0;
-	}
-
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int should_deauth_infrastructure(struct lbs_private *priv,
-                                        struct assoc_request * assoc_req)
-{
-	int ret = 0;
-
-	if (priv->connect_status != LBS_CONNECTED)
-		return 0;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		lbs_deb_assoc("Deauthenticating due to new SSID\n");
-		ret = 1;
-		goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
-		if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
-			lbs_deb_assoc("Deauthenticating due to new security\n");
-			ret = 1;
-			goto out;
-		}
-	}
-
-	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		lbs_deb_assoc("Deauthenticating due to new BSSID\n");
-		ret = 1;
-		goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
-		lbs_deb_assoc("Deauthenticating due to channel switch\n");
-		ret = 1;
-		goto out;
-	}
-
-	/* FIXME: deal with 'auto' mode somehow */
-	if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
-		if (assoc_req->mode != IW_MODE_INFRA) {
-			lbs_deb_assoc("Deauthenticating due to leaving "
-				"infra mode\n");
-			ret = 1;
-			goto out;
-		}
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
-	return ret;
-}
-
-
-static int should_stop_adhoc(struct lbs_private *priv,
-                             struct assoc_request * assoc_req)
-{
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	if (priv->connect_status != LBS_CONNECTED)
-		return 0;
-
-	if (lbs_ssid_cmp(priv->curbssparams.ssid,
-	                      priv->curbssparams.ssid_len,
-	                      assoc_req->ssid, assoc_req->ssid_len) != 0)
-		return 1;
-
-	/* FIXME: deal with 'auto' mode somehow */
-	if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
-		if (assoc_req->mode != IW_MODE_ADHOC)
-			return 1;
-	}
-
-	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
-		if (assoc_req->channel != priv->channel)
-			return 1;
-	}
-
-	lbs_deb_leave(LBS_DEB_ASSOC);
-	return 0;
-}
-
-
-/**
- *  @brief This function finds the best SSID in the Scan List
- *
- *  Search the scan table for the best SSID that also matches the current
- *   adapter network preference (infrastructure or adhoc)
- *
- *  @param priv  A pointer to struct lbs_private
- *
- *  @return         index in BSSID list
- */
-static struct bss_descriptor *lbs_find_best_ssid_in_list(
-	struct lbs_private *priv, uint8_t mode)
-{
-	uint8_t bestrssi = 0;
-	struct bss_descriptor *iter_bss;
-	struct bss_descriptor *best_bss = NULL;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	mutex_lock(&priv->lock);
-
-	list_for_each_entry(iter_bss, &priv->network_list, list) {
-		switch (mode) {
-		case IW_MODE_INFRA:
-		case IW_MODE_ADHOC:
-			if (!is_network_compatible(priv, iter_bss, mode))
-				break;
-			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-				break;
-			bestrssi = SCAN_RSSI(iter_bss->rssi);
-			best_bss = iter_bss;
-			break;
-		case IW_MODE_AUTO:
-		default:
-			if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
-				break;
-			bestrssi = SCAN_RSSI(iter_bss->rssi);
-			best_bss = iter_bss;
-			break;
-		}
-	}
-
-	mutex_unlock(&priv->lock);
-	lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
-	return best_bss;
-}
-
-/**
- *  @brief Find the best AP
- *
- *  Used from association worker.
- *
- *  @param priv         A pointer to struct lbs_private structure
- *  @param pSSID        A pointer to AP's ssid
- *
- *  @return             0--success, otherwise--fail
- */
-static int lbs_find_best_network_ssid(struct lbs_private *priv,
-	uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
-	uint8_t *out_mode)
-{
-	int ret = -1;
-	struct bss_descriptor *found;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	priv->scan_ssid_len = 0;
-	lbs_scan_networks(priv, 1);
-	if (priv->surpriseremoved)
-		goto out;
-
-	found = lbs_find_best_ssid_in_list(priv, preferred_mode);
-	if (found && (found->ssid_len > 0)) {
-		memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
-		*out_ssid_len = found->ssid_len;
-		*out_mode = found->mode;
-		ret = 0;
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}
-
-
-void lbs_association_worker(struct work_struct *work)
-{
-	struct lbs_private *priv = container_of(work, struct lbs_private,
-		assoc_work.work);
-	struct assoc_request * assoc_req = NULL;
-	int ret = 0;
-	int find_any_ssid = 0;
-	DECLARE_SSID_BUF(ssid);
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-
-	mutex_lock(&priv->lock);
-	assoc_req = priv->pending_assoc_req;
-	priv->pending_assoc_req = NULL;
-	priv->in_progress_assoc_req = assoc_req;
-	mutex_unlock(&priv->lock);
-
-	if (!assoc_req)
-		goto done;
-
-	lbs_deb_assoc(
-		"Association Request:\n"
-		"    flags:     0x%08lx\n"
-		"    SSID:      '%s'\n"
-		"    chann:     %d\n"
-		"    band:      %d\n"
-		"    mode:      %d\n"
-		"    BSSID:     %pM\n"
-		"    secinfo:  %s%s%s\n"
-		"    auth_mode: %d\n",
-		assoc_req->flags,
-		print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
-		assoc_req->channel, assoc_req->band, assoc_req->mode,
-		assoc_req->bssid,
-		assoc_req->secinfo.WPAenabled ? " WPA" : "",
-		assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
-		assoc_req->secinfo.wep_enabled ? " WEP" : "",
-		assoc_req->secinfo.auth_mode);
-
-	/* If 'any' SSID was specified, find an SSID to associate with */
-	if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
-	    !assoc_req->ssid_len)
-		find_any_ssid = 1;
-
-	/* But don't use 'any' SSID if there's a valid locked BSSID to use */
-	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
-		    compare_ether_addr(assoc_req->bssid, bssid_off))
-			find_any_ssid = 0;
-	}
-
-	if (find_any_ssid) {
-		u8 new_mode = assoc_req->mode;
-
-		ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
-				&assoc_req->ssid_len, assoc_req->mode, &new_mode);
-		if (ret) {
-			lbs_deb_assoc("Could not find best network\n");
-			ret = -ENETUNREACH;
-			goto out;
-		}
-
-		/* Ensure we switch to the mode of the AP */
-		if (assoc_req->mode == IW_MODE_AUTO) {
-			set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
-			assoc_req->mode = new_mode;
-		}
-	}
-
-	/*
-	 * Check if the attributes being changing require deauthentication
-	 * from the currently associated infrastructure access point.
-	 */
-	if (priv->mode == IW_MODE_INFRA) {
-		if (should_deauth_infrastructure(priv, assoc_req)) {
-			ret = lbs_cmd_80211_deauthenticate(priv,
-							   priv->curbssparams.bssid,
-							   WLAN_REASON_DEAUTH_LEAVING);
-			if (ret) {
-				lbs_deb_assoc("Deauthentication due to new "
-					"configuration request failed: %d\n",
-					ret);
-			}
-		}
-	} else if (priv->mode == IW_MODE_ADHOC) {
-		if (should_stop_adhoc(priv, assoc_req)) {
-			ret = lbs_adhoc_stop(priv);
-			if (ret) {
-				lbs_deb_assoc("Teardown of AdHoc network due to "
-					"new configuration request failed: %d\n",
-					ret);
-			}
-
-		}
-	}
-
-	/* Send the various configuration bits to the firmware */
-	if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
-		ret = assoc_helper_mode(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
-		ret = assoc_helper_channel(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
-		ret = assoc_helper_secinfo(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
-		ret = assoc_helper_wpa_ie(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-	/*
-	 * v10 FW wants WPA keys to be set/cleared before WEP key operations,
-	 * otherwise it will fail to correctly associate to WEP networks.
-	 * Other firmware versions don't appear to care.
-	 */
-	if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
-	    test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
-		ret = assoc_helper_wpa_keys(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-	if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
-	    test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
-		ret = assoc_helper_wep_keys(priv, assoc_req);
-		if (ret)
-			goto out;
-	}
-
-
-	/* SSID/BSSID should be the _last_ config option set, because they
-	 * trigger the association attempt.
-	 */
-	if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
-	    test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		int success = 1;
-
-		ret = assoc_helper_associate(priv, assoc_req);
-		if (ret) {
-			lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
-				ret);
-			success = 0;
-		}
-
-		if (priv->connect_status != LBS_CONNECTED) {
-			lbs_deb_assoc("ASSOC: association unsuccessful, "
-				"not connected\n");
-			success = 0;
-		}
-
-		if (success) {
-			lbs_deb_assoc("associated to %pM\n",
-				priv->curbssparams.bssid);
-			lbs_prepare_and_send_command(priv,
-				CMD_802_11_RSSI,
-				0, CMD_OPTION_WAITFORRSP, 0, NULL);
-		} else {
-			ret = -1;
-		}
-	}
-
-out:
-	if (ret) {
-		lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
-			ret);
-	}
-
-	mutex_lock(&priv->lock);
-	priv->in_progress_assoc_req = NULL;
-	mutex_unlock(&priv->lock);
-	kfree(assoc_req);
-
-done:
-	lbs_deb_leave(LBS_DEB_ASSOC);
-}
-
-
-/*
- * Caller MUST hold any necessary locks
- */
-struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
-{
-	struct assoc_request * assoc_req;
-
-	lbs_deb_enter(LBS_DEB_ASSOC);
-	if (!priv->pending_assoc_req) {
-		priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
-		                                     GFP_KERNEL);
-		if (!priv->pending_assoc_req) {
-			lbs_pr_info("Not enough memory to allocate association"
-				" request!\n");
-			return NULL;
-		}
-	}
-
-	/* Copy current configuration attributes to the association request,
-	 * but don't overwrite any that are already set.
-	 */
-	assoc_req = priv->pending_assoc_req;
-	if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
-		memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
-		       IEEE80211_MAX_SSID_LEN);
-		assoc_req->ssid_len = priv->curbssparams.ssid_len;
-	}
-
-	if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
-		assoc_req->channel = priv->channel;
-
-	if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
-		assoc_req->band = priv->curbssparams.band;
-
-	if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
-		assoc_req->mode = priv->mode;
-
-	if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
-		memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
-			ETH_ALEN);
-	}
-
-	if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
-		int i;
-		for (i = 0; i < 4; i++) {
-			memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
-				sizeof(struct enc_key));
-		}
-	}
-
-	if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
-		assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
-
-	if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
-		memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
-			sizeof(struct enc_key));
-	}
-
-	if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
-		memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
-			sizeof(struct enc_key));
-	}
-
-	if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
-		memcpy(&assoc_req->secinfo, &priv->secinfo,
-			sizeof(struct lbs_802_11_security));
-	}
-
-	if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
-		memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
-			MAX_WPA_IE_LEN);
-		assoc_req->wpa_ie_len = priv->wpa_ie_len;
-	}
-
-	lbs_deb_leave(LBS_DEB_ASSOC);
-	return assoc_req;
-}
-
-
-/**
- *  @brief Deauthenticate from a specific BSS
- *
- *  @param priv        A pointer to struct lbs_private structure
- *  @param bssid       The specific BSS to deauthenticate from
- *  @param reason      The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
- *
- *  @return            0 on success, error on failure
- */
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
-				 u16 reason)
-{
-	struct cmd_ds_802_11_deauthenticate cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_JOIN);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
-	cmd.reasoncode = cpu_to_le16(reason);
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
-
-	/* Clean up everything even if there was an error; can't assume that
-	 * we're still authenticated to the AP after trying to deauth.
-	 */
-	lbs_mac_event_disconnected(priv);
-
-	lbs_deb_leave(LBS_DEB_JOIN);
-	return ret;
-}
-

+ 0 - 155
drivers/net/wireless/libertas/assoc.h

@@ -1,155 +0,0 @@
-/* Copyright (C) 2006, Red Hat, Inc. */
-
-#ifndef _LBS_ASSOC_H_
-#define _LBS_ASSOC_H_
-
-
-#include "defs.h"
-#include "host.h"
-
-
-struct lbs_private;
-
-/*
- * In theory, the IE is limited to the IE length, 255,
- * but in practice 64 bytes are enough.
- */
-#define MAX_WPA_IE_LEN 64
-
-
-
-struct lbs_802_11_security {
-	u8 WPAenabled;
-	u8 WPA2enabled;
-	u8 wep_enabled;
-	u8 auth_mode;
-	u32 key_mgmt;
-};
-
-/** Current Basic Service Set State Structure */
-struct current_bss_params {
-	/** bssid */
-	u8 bssid[ETH_ALEN];
-	/** ssid */
-	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
-	u8 ssid_len;
-
-	/** band */
-	u8 band;
-	/** channel is directly in priv->channel */
-	/** zero-terminated array of supported data rates */
-	u8 rates[MAX_RATES + 1];
-};
-
-/**
- *  @brief Structure used to store information for each beacon/probe response
- */
-struct bss_descriptor {
-	u8 bssid[ETH_ALEN];
-
-	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
-	u8 ssid_len;
-
-	u16 capability;
-	u32 rssi;
-	u32 channel;
-	u16 beaconperiod;
-	__le16 atimwindow;
-
-	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
-	u8 mode;
-
-	/* zero-terminated array of supported data rates */
-	u8 rates[MAX_RATES + 1];
-
-	unsigned long last_scanned;
-
-	union ieee_phy_param_set phy;
-	union ieee_ss_param_set ss;
-
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	size_t wpa_ie_len;
-	u8 rsn_ie[MAX_WPA_IE_LEN];
-	size_t rsn_ie_len;
-
-	u8 mesh;
-
-	struct list_head list;
-};
-
-/** Association request
- *
- * Encapsulates all the options that describe a specific assocation request
- * or configuration of the wireless card's radio, mode, and security settings.
- */
-struct assoc_request {
-#define ASSOC_FLAG_SSID			1
-#define ASSOC_FLAG_CHANNEL		2
-#define ASSOC_FLAG_BAND			3
-#define ASSOC_FLAG_MODE			4
-#define ASSOC_FLAG_BSSID		5
-#define ASSOC_FLAG_WEP_KEYS		6
-#define ASSOC_FLAG_WEP_TX_KEYIDX	7
-#define ASSOC_FLAG_WPA_MCAST_KEY	8
-#define ASSOC_FLAG_WPA_UCAST_KEY	9
-#define ASSOC_FLAG_SECINFO		10
-#define ASSOC_FLAG_WPA_IE		11
-	unsigned long flags;
-
-	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
-	u8 ssid_len;
-	u8 channel;
-	u8 band;
-	u8 mode;
-	u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
-
-	/** WEP keys */
-	struct enc_key wep_keys[4];
-	u16 wep_tx_keyidx;
-
-	/** WPA keys */
-	struct enc_key wpa_mcast_key;
-	struct enc_key wpa_unicast_key;
-
-	struct lbs_802_11_security secinfo;
-
-	/** WPA Information Elements*/
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	u8 wpa_ie_len;
-
-	/* BSS to associate with for infrastructure of Ad-Hoc join */
-	struct bss_descriptor bss;
-};
-
-
-extern u8 lbs_bg_rates[MAX_RATES];
-
-void lbs_association_worker(struct work_struct *work);
-struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
-
-int lbs_adhoc_stop(struct lbs_private *priv);
-
-int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
-				 u8 bssid[ETH_ALEN], u16 reason);
-
-int lbs_cmd_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *cmd);
-int lbs_ret_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *resp);
-
-int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
-				struct cmd_ds_command *cmd,
-				u16 cmd_action);
-int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
-					struct cmd_ds_command *resp);
-
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
-			   struct assoc_request *assoc);
-
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
-			      uint16_t *enable);
-
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-				struct assoc_request *assoc);
-
-#endif /* _LBS_ASSOC_H */

File diff suppressed because it is too large
+ 1828 - 21
drivers/net/wireless/libertas/cfg.c


+ 16 - 5
drivers/net/wireless/libertas/cfg.h

@@ -1,16 +1,27 @@
 #ifndef __LBS_CFG80211_H__
 #define __LBS_CFG80211_H__
 
-#include "dev.h"
+struct device;
+struct lbs_private;
+struct regulatory_request;
+struct wiphy;
 
 struct wireless_dev *lbs_cfg_alloc(struct device *dev);
 int lbs_cfg_register(struct lbs_private *priv);
 void lbs_cfg_free(struct lbs_private *priv);
 
-int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
-	u8 ssid_len);
-int lbs_scan_networks(struct lbs_private *priv, int full_scan);
-void lbs_cfg_scan_worker(struct work_struct *work);
+int lbs_reg_notifier(struct wiphy *wiphy,
+		struct regulatory_request *request);
 
+/* All of those are TODOs: */
+#define lbs_cmd_802_11_rssi(priv, cmdptr) (0)
+#define lbs_ret_802_11_rssi(priv, resp) (0)
+#define lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action) (0)
+#define lbs_ret_802_11_bcn_ctrl(priv, resp) (0)
+
+void lbs_send_disconnect_notification(struct lbs_private *priv);
+void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
+
+void lbs_scan_deinit(struct lbs_private *priv);
 
 #endif

+ 76 - 11
drivers/net/wireless/libertas/cmd.c

@@ -7,13 +7,8 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#include "host.h"
 #include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "assoc.h"
-#include "wext.h"
-#include "scan.h"
+#include "cfg.h"
 #include "cmd.h"
 
 
@@ -177,11 +172,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
 	if (priv->mesh_dev)
 		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
 
-	if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
-		ret = -1;
-		goto out;
-	}
-
 out:
 	lbs_deb_leave(LBS_DEB_CMD);
 	return ret;
@@ -908,6 +898,66 @@ void lbs_set_mac_control(struct lbs_private *priv)
 	lbs_deb_leave(LBS_DEB_CMD);
 }
 
+/**
+ *  @brief This function implements command CMD_802_11D_DOMAIN_INFO
+ *  @param priv       pointer to struct lbs_private
+ *  @param cmd        pointer to cmd buffer
+ *  @param cmdno      cmd ID
+ *  @param cmdOption  cmd action
+ *  @return           0
+*/
+int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
+				 struct cmd_ds_command *cmd,
+				 u16 cmdoption)
+{
+	struct cmd_ds_802_11d_domain_info *pdomaininfo =
+	    &cmd->params.domaininfo;
+	struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
+	u8 nr_triplet = priv->domain_reg.no_triplet;
+
+	lbs_deb_enter(LBS_DEB_11D);
+
+	lbs_deb_11d("nr_triplet=%x\n", nr_triplet);
+
+	pdomaininfo->action = cpu_to_le16(cmdoption);
+	if (cmdoption == CMD_ACT_GET) {
+		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
+					sizeof(struct cmd_header));
+		lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
+			le16_to_cpu(cmd->size));
+		goto done;
+	}
+
+	domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
+	memcpy(domain->countrycode, priv->domain_reg.country_code,
+	       sizeof(domain->countrycode));
+
+	domain->header.len = cpu_to_le16(nr_triplet
+				* sizeof(struct ieee80211_country_ie_triplet)
+				+ sizeof(domain->countrycode));
+
+	if (nr_triplet) {
+		memcpy(domain->triplet, priv->domain_reg.triplet,
+				nr_triplet *
+				sizeof(struct ieee80211_country_ie_triplet));
+
+		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
+					     le16_to_cpu(domain->header.len) +
+					     sizeof(struct mrvl_ie_header) +
+					     sizeof(struct cmd_header));
+	} else {
+		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
+					sizeof(struct cmd_header));
+	}
+
+	lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
+			le16_to_cpu(cmd->size));
+
+done:
+	lbs_deb_enter(LBS_DEB_11D);
+	return 0;
+}
+
 /**
  *  @brief This function prepare the command before send to firmware.
  *
@@ -1006,6 +1056,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 		ret = 0;
 		goto done;
 
+	case CMD_802_11D_DOMAIN_INFO:
+		cmdptr->command = cpu_to_le16(cmd_no);
+		ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, cmd_action);
+		break;
+
 	case CMD_802_11_TPC_CFG:
 		cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
 		cmdptr->size =
@@ -1325,6 +1380,15 @@ int lbs_execute_next_command(struct lbs_private *priv)
 		 * check if in power save mode, if yes, put the device back
 		 * to PS mode
 		 */
+#ifdef TODO
+		/*
+		 * This was the old code for libertas+wext. Someone that
+		 * understands this beast should re-code it in a sane way.
+		 *
+		 * I actually don't understand why this is related to WPA
+		 * and to connection status, shouldn't powering should be
+		 * independ of such things?
+		 */
 		if ((priv->psmode != LBS802_11POWERMODECAM) &&
 		    (priv->psstate == PS_STATE_FULL_POWER) &&
 		    ((priv->connect_status == LBS_CONNECTED) ||
@@ -1346,6 +1410,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
 				lbs_ps_sleep(priv, 0);
 			}
 		}
+#endif
 	}
 
 	ret = 0;

+ 56 - 27
drivers/net/wireless/libertas/cmdresp.c

@@ -5,18 +5,10 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/if_arp.h>
-#include <linux/netdevice.h>
 #include <asm/unaligned.h>
-#include <net/iw_handler.h>
+#include <net/cfg80211.h>
 
-#include "host.h"
-#include "decl.h"
-#include "cmd.h"
-#include "defs.h"
-#include "dev.h"
-#include "assoc.h"
-#include "wext.h"
+#include "cfg.h"
 #include "cmd.h"
 
 /**
@@ -39,7 +31,9 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
 	 * It causes problem in the Supplicant
 	 */
 	msleep_interruptible(1000);
-	lbs_send_disconnect_notification(priv);
+
+	if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
+		lbs_send_disconnect_notification(priv);
 
 	/* report disconnect to upper layer */
 	netif_stop_queue(priv->dev);
@@ -50,23 +44,8 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
 	priv->currenttxskb = NULL;
 	priv->tx_pending_len = 0;
 
-	/* reset SNR/NF/RSSI values */
-	memset(priv->SNR, 0x00, sizeof(priv->SNR));
-	memset(priv->NF, 0x00, sizeof(priv->NF));
-	memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
-	memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
-	memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
-	priv->nextSNRNF = 0;
-	priv->numSNRNF = 0;
 	priv->connect_status = LBS_DISCONNECTED;
 
-	/* Clear out associated SSID and BSSID since connection is
-	 * no longer valid.
-	 */
-	memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
-	memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
-	priv->curbssparams.ssid_len = 0;
-
 	if (priv->psstate != PS_STATE_FULL_POWER) {
 		/* make firmware to exit PS mode */
 		lbs_deb_cmd("disconnected, so exit PS mode\n");
@@ -118,6 +97,52 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
 	return ret;
 }
 
+/**
+ *  @brief This function parses countryinfo from AP and download country info to FW
+ *  @param priv    pointer to struct lbs_private
+ *  @param resp    pointer to command response buffer
+ *  @return        0; -1
+ */
+static int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
+{
+	struct cmd_ds_802_11d_domain_info *domaininfo =
+			&resp->params.domaininforesp;
+	struct mrvl_ie_domain_param_set *domain = &domaininfo->domain;
+	u16 action = le16_to_cpu(domaininfo->action);
+	s16 ret = 0;
+	u8 nr_triplet = 0;
+
+	lbs_deb_enter(LBS_DEB_11D);
+
+	lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
+			(int)le16_to_cpu(resp->size));
+
+	nr_triplet = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
+		sizeof(struct ieee80211_country_ie_triplet);
+
+	lbs_deb_11d("domain info resp: nr_triplet %d\n", nr_triplet);
+
+	if (nr_triplet > MRVDRV_MAX_TRIPLET_802_11D) {
+		lbs_deb_11d("invalid number of triplets returned!!\n");
+		return -1;
+	}
+
+	switch (action) {
+	case CMD_ACT_SET:	/*Proc set action */
+		break;
+
+	case CMD_ACT_GET:
+		break;
+	default:
+		lbs_deb_11d("invalid action:%d\n", domaininfo->action);
+		ret = -1;
+		break;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+	return ret;
+}
+
 static inline int handle_cmd_response(struct lbs_private *priv,
 				      struct cmd_header *cmd_response)
 {
@@ -151,6 +176,10 @@ static inline int handle_cmd_response(struct lbs_private *priv,
 		ret = lbs_ret_802_11_rssi(priv, resp);
 		break;
 
+	case CMD_RET(CMD_802_11D_DOMAIN_INFO):
+		ret = lbs_ret_802_11d_domain_info(resp);
+		break;
+
 	case CMD_RET(CMD_802_11_TPC_CFG):
 		spin_lock_irqsave(&priv->driver_lock, flags);
 		memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
@@ -262,7 +291,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 			 * ad-hoc mode. It takes place in
 			 * lbs_execute_next_command().
 			 */
-			if (priv->mode == IW_MODE_ADHOC &&
+			if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
 			    action == CMD_SUBCMD_ENTER_PS)
 				priv->psmode = LBS802_11POWERMODECAM;
 		} else if (action == CMD_SUBCMD_ENTER_PS) {

+ 1 - 53
drivers/net/wireless/libertas/debugfs.c

@@ -1,18 +1,13 @@
-#include <linux/module.h>
 #include <linux/dcache.h>
 #include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/slab.h>
-#include <net/iw_handler.h>
-#include <net/lib80211.h>
 
-#include "dev.h"
 #include "decl.h"
-#include "host.h"
-#include "debugfs.h"
 #include "cmd.h"
+#include "debugfs.h"
 
 static struct dentry *lbs_dir;
 static char *szStates[] = {
@@ -60,51 +55,6 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
 	return res;
 }
 
-
-static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
-				  size_t count, loff_t *ppos)
-{
-	struct lbs_private *priv = file->private_data;
-	size_t pos = 0;
-	int numscansdone = 0, res;
-	unsigned long addr = get_zeroed_page(GFP_KERNEL);
-	char *buf = (char *)addr;
-	DECLARE_SSID_BUF(ssid);
-	struct bss_descriptor * iter_bss;
-	if (!buf)
-		return -ENOMEM;
-
-	pos += snprintf(buf+pos, len-pos,
-		"# | ch  | rssi |       bssid       |   cap    | Qual | SSID\n");
-
-	mutex_lock(&priv->lock);
-	list_for_each_entry (iter_bss, &priv->network_list, list) {
-		u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
-		u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
-		u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
-
-		pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
-			numscansdone, iter_bss->channel, iter_bss->rssi,
-			iter_bss->bssid);
-		pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
-		pos += snprintf(buf+pos, len-pos, "%c%c%c |",
-				ibss ? 'A' : 'I', privacy ? 'P' : ' ',
-				spectrum_mgmt ? 'S' : ' ');
-		pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
-		pos += snprintf(buf+pos, len-pos, " %s\n",
-		                print_ssid(ssid, iter_bss->ssid,
-					   iter_bss->ssid_len));
-
-		numscansdone++;
-	}
-	mutex_unlock(&priv->lock);
-
-	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
-
-	free_page(addr);
-	return res;
-}
-
 static ssize_t lbs_sleepparams_write(struct file *file,
 				const char __user *user_buf, size_t count,
 				loff_t *ppos)
@@ -723,8 +673,6 @@ struct lbs_debugfs_files {
 
 static const struct lbs_debugfs_files debugfs_files[] = {
 	{ "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
-	{ "getscantable", 0444, FOPS(lbs_getscantable,
-					write_file_dummy), },
 	{ "sleepparams", 0644, FOPS(lbs_sleepparams_read,
 				lbs_sleepparams_write), },
 };

+ 8 - 0
drivers/net/wireless/libertas/decl.h

@@ -1,3 +1,4 @@
+
 /**
   *  This file contains declaration referring to
   *  functions defined in other source files
@@ -12,6 +13,7 @@
 struct lbs_private;
 struct sk_buff;
 struct net_device;
+struct cmd_ds_command;
 
 
 /* ethtool.c */
@@ -34,6 +36,8 @@ int lbs_start_card(struct lbs_private *priv);
 void lbs_stop_card(struct lbs_private *priv);
 void lbs_host_to_card_done(struct lbs_private *priv);
 
+int lbs_rtap_supported(struct lbs_private *priv);
+
 int lbs_set_mac_address(struct net_device *dev, void *addr);
 void lbs_set_multicast_list(struct net_device *dev);
 
@@ -49,5 +53,9 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
 u32 lbs_fw_index_to_data_rate(u8 index);
 u8 lbs_data_rate_to_fw_index(u32 rate);
 
+int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
+		struct cmd_ds_command *cmd, u16 cmdoption);
+
+int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
 
 #endif

+ 12 - 50
drivers/net/wireless/libertas/dev.h

@@ -7,8 +7,8 @@
 #define _LBS_DEV_H_
 
 #include "mesh.h"
-#include "scan.h"
-#include "assoc.h"
+#include "defs.h"
+#include "host.h"
 
 #include <linux/kfifo.h>
 
@@ -29,7 +29,6 @@ struct lbs_private {
 	/* Basic networking */
 	struct net_device *dev;
 	u32 connect_status;
-	int infra_open;
 	struct work_struct mcast_work;
 	u32 nr_of_multicastmacaddr;
 	u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
@@ -37,6 +36,9 @@ struct lbs_private {
 	/* CFG80211 */
 	struct wireless_dev *wdev;
 	bool wiphy_registered;
+	struct cfg80211_scan_request *scan_req;
+	u8 assoc_bss[ETH_ALEN];
+	u8 disassoc_reason;
 
 	/* Mesh */
 	struct net_device *mesh_dev; /* Virtual device */
@@ -49,10 +51,6 @@ struct lbs_private {
 	u8 mesh_ssid_len;
 #endif
 
-	/* Monitor mode */
-	struct net_device *rtap_net_dev;
-	u32 monitormode;
-
 	/* Debugfs */
 	struct dentry *debugfs_dir;
 	struct dentry *debugfs_debug;
@@ -62,6 +60,9 @@ struct lbs_private {
 	struct dentry *regs_dir;
 	struct dentry *debugfs_regs_files[6];
 
+	/** 11D and domain regulatory data */
+	struct lbs_802_11d_domain_reg domain_reg;
+
 	/* Hardware debugging */
 	u32 mac_offset;
 	u32 bbp_offset;
@@ -133,14 +134,10 @@ struct lbs_private {
 	struct workqueue_struct *work_thread;
 
 	/** Encryption stuff */
-	struct lbs_802_11_security secinfo;
-	struct enc_key wpa_mcast_key;
-	struct enc_key wpa_unicast_key;
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	u8 wpa_ie_len;
-	u16 wep_tx_keyidx;
-	struct enc_key wep_keys[4];
 	u8 authtype_auto;
+	u8 wep_tx_key;
+	u8 wep_key[4][WLAN_KEY_LEN_WEP104];
+	u8 wep_key_len[4];
 
 	/* Wake On LAN */
 	uint32_t wol_criteria;
@@ -161,6 +158,7 @@ struct lbs_private {
 	/* NIC/link operation characteristics */
 	u16 mac_control;
 	u8 radio_on;
+	u8 cur_rate;
 	u8 channel;
 	s16 txpower_cur;
 	s16 txpower_min;
@@ -169,42 +167,6 @@ struct lbs_private {
 	/** Scanning */
 	struct delayed_work scan_work;
 	int scan_channel;
-	/* remember which channel was scanned last, != 0 if currently scanning */
-	u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
-	u8 scan_ssid_len;
-
-	/* Associating */
-	struct delayed_work assoc_work;
-	struct current_bss_params curbssparams;
-	u8 mode;
-	struct list_head network_list;
-	struct list_head network_free_list;
-	struct bss_descriptor *networks;
-	struct assoc_request * pending_assoc_req;
-	struct assoc_request * in_progress_assoc_req;
-	uint16_t enablehwauto;
-
-	/* ADHOC */
-	u16 beacon_period;
-	u8 beacon_enable;
-	u8 adhoccreate;
-
-	/* WEXT */
-	char name[DEV_NAME_LEN];
-	u8 nodename[16];
-	struct iw_statistics wstats;
-	u8 cur_rate;
-#define	MAX_REGION_CHANNEL_NUM	2
-	struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
-
-	/** Requested Signal Strength*/
-	u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
-	u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
-	u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
-	u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
-	u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
-	u16 nextSNRNF;
-	u16 numSNRNF;
 };
 
 extern struct cmd_confirm_sleep confirm_sleep;

+ 0 - 5
drivers/net/wireless/libertas/ethtool.c

@@ -2,13 +2,8 @@
 #include <linux/ethtool.h>
 #include <linux/delay.h>
 
-#include "host.h"
 #include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
 #include "cmd.h"
-#include "mesh.h"
 
 
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,

+ 27 - 1
drivers/net/wireless/libertas/host.h

@@ -389,6 +389,30 @@ struct lbs_offset_value {
 	u32 value;
 } __packed;
 
+#define MRVDRV_MAX_TRIPLET_802_11D              83
+
+#define COUNTRY_CODE_LEN                        3
+
+struct mrvl_ie_domain_param_set {
+	struct mrvl_ie_header header;
+
+	u8 countrycode[COUNTRY_CODE_LEN];
+	struct ieee80211_country_ie_triplet triplet[1];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11d_domain_info {
+	__le16 action;
+	struct mrvl_ie_domain_param_set domain;
+} __attribute__ ((packed));
+
+struct lbs_802_11d_domain_reg {
+	/** Country code*/
+	u8 country_code[COUNTRY_CODE_LEN];
+	/** No. of triplet*/
+	u8 no_triplet;
+	struct ieee80211_country_ie_triplet triplet[MRVDRV_MAX_TRIPLET_802_11D];
+} __attribute__ ((packed));
+
 /*
  * Define data structure for CMD_GET_HW_SPEC
  * This structure defines the response for the GET_HW_SPEC command
@@ -949,6 +973,9 @@ struct cmd_ds_command {
 		struct cmd_ds_bbp_reg_access bbpreg;
 		struct cmd_ds_rf_reg_access rfreg;
 
+		struct cmd_ds_802_11d_domain_info domaininfo;
+		struct cmd_ds_802_11d_domain_info domaininforesp;
+
 		struct cmd_ds_802_11_tpc_cfg tpccfg;
 		struct cmd_ds_802_11_afc afc;
 		struct cmd_ds_802_11_led_ctrl ledgpio;
@@ -958,5 +985,4 @@ struct cmd_ds_command {
 		struct cmd_ds_802_11_beacon_control bcn_ctrl;
 	} params;
 } __packed;
-
 #endif

+ 7 - 219
drivers/net/wireless/libertas/main.c

@@ -11,20 +11,14 @@
 #include <linux/if_arp.h>
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
-#include <linux/stddef.h>
-#include <linux/ieee80211.h>
 #include <linux/slab.h>
-#include <net/iw_handler.h>
 #include <net/cfg80211.h>
 
 #include "host.h"
 #include "decl.h"
 #include "dev.h"
-#include "wext.h"
 #include "cfg.h"
 #include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
 #include "cmd.h"
 
 #define DRIVER_RELEASE_VERSION "323.p0"
@@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
 }
 
 
-static int lbs_add_rtap(struct lbs_private *priv);
-static void lbs_remove_rtap(struct lbs_private *priv);
-
-
-/**
- * Get function for sysfs attribute rtap
- */
-static ssize_t lbs_rtap_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	return snprintf(buf, 5, "0x%X\n", priv->monitormode);
-}
-
-/**
- *  Set function for sysfs attribute rtap
- */
-static ssize_t lbs_rtap_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	int monitor_mode;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-
-	sscanf(buf, "%x", &monitor_mode);
-	if (monitor_mode) {
-		if (priv->monitormode == monitor_mode)
-			return strlen(buf);
-		if (!priv->monitormode) {
-			if (priv->infra_open || lbs_mesh_open(priv))
-				return -EBUSY;
-			if (priv->mode == IW_MODE_INFRA)
-				lbs_cmd_80211_deauthenticate(priv,
-							     priv->curbssparams.bssid,
-							     WLAN_REASON_DEAUTH_LEAVING);
-			else if (priv->mode == IW_MODE_ADHOC)
-				lbs_adhoc_stop(priv);
-			lbs_add_rtap(priv);
-		}
-		priv->monitormode = monitor_mode;
-	} else {
-		if (!priv->monitormode)
-			return strlen(buf);
-		priv->monitormode = 0;
-		lbs_remove_rtap(priv);
-
-		if (priv->currenttxskb) {
-			dev_kfree_skb_any(priv->currenttxskb);
-			priv->currenttxskb = NULL;
-		}
-
-		/* Wake queues, command thread, etc. */
-		lbs_host_to_card_done(priv);
-	}
-
-	lbs_prepare_and_send_command(priv,
-			CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
-			CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
-	return strlen(buf);
-}
-
-/**
- * lbs_rtap attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_rtap)
- */
-static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
-
 /**
  *  @brief This function opens the ethX interface
  *
@@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev)
 
 	spin_lock_irq(&priv->driver_lock);
 
-	if (priv->monitormode) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	priv->infra_open = 1;
-
 	if (priv->connect_status == LBS_CONNECTED)
 		netif_carrier_on(dev);
 	else
@@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev)
 
 	if (!priv->tx_pending_len)
 		netif_wake_queue(dev);
- out:
 
 	spin_unlock_irq(&priv->driver_lock);
 	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev)
 	lbs_deb_enter(LBS_DEB_NET);
 
 	spin_lock_irq(&priv->driver_lock);
-	priv->infra_open = 0;
 	netif_stop_queue(dev);
 	spin_unlock_irq(&priv->driver_lock);
 
@@ -733,6 +652,9 @@ static int lbs_setup_firmware(struct lbs_private *priv)
 		priv->txpower_max = maxlevel;
 	}
 
+	/* Send cmd to FW to enable 11D function */
+	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
+
 	lbs_set_mac_control(priv);
 done:
 	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -822,37 +744,16 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
 
 static int lbs_init_adapter(struct lbs_private *priv)
 {
-	size_t bufsize;
-	int i, ret = 0;
+	int ret;
 
 	lbs_deb_enter(LBS_DEB_MAIN);
 
-	/* Allocate buffer to store the BSSID list */
-	bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
-	priv->networks = kzalloc(bufsize, GFP_KERNEL);
-	if (!priv->networks) {
-		lbs_pr_err("Out of memory allocating beacons\n");
-		ret = -1;
-		goto out;
-	}
-
-	/* Initialize scan result lists */
-	INIT_LIST_HEAD(&priv->network_free_list);
-	INIT_LIST_HEAD(&priv->network_list);
-	for (i = 0; i < MAX_NETWORK_COUNT; i++) {
-		list_add_tail(&priv->networks[i].list,
-			      &priv->network_free_list);
-	}
-
 	memset(priv->current_addr, 0xff, ETH_ALEN);
 
 	priv->connect_status = LBS_DISCONNECTED;
-	priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-	priv->mode = IW_MODE_INFRA;
 	priv->channel = DEFAULT_AD_HOC_CHANNEL;
 	priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
 	priv->radio_on = 1;
-	priv->enablehwauto = 1;
 	priv->psmode = LBS802_11POWERMODECAM;
 	priv->psstate = PS_STATE_FULL_POWER;
 	priv->is_deep_sleep = 0;
@@ -907,8 +808,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
 	kfifo_free(&priv->event_fifo);
 	del_timer(&priv->command_timer);
 	del_timer(&priv->auto_deepsleep_timer);
-	kfree(priv->networks);
-	priv->networks = NULL;
 
 	lbs_deb_leave(LBS_DEB_MAIN);
 }
@@ -945,7 +844,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 		lbs_pr_err("cfg80211 init failed\n");
 		goto done;
 	}
-	/* TODO? */
+
 	wdev->iftype = NL80211_IFTYPE_STATION;
 	priv = wdev_priv(wdev);
 	priv->wdev = wdev;
@@ -955,7 +854,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 		goto err_wdev;
 	}
 
-	//TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
 	dev = alloc_netdev(0, "wlan%d", ether_setup);
 	if (!dev) {
 		dev_err(dmdev, "no memory for network device instance\n");
@@ -971,20 +869,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
  	dev->netdev_ops = &lbs_netdev_ops;
 	dev->watchdog_timeo = 5 * HZ;
 	dev->ethtool_ops = &lbs_ethtool_ops;
-#ifdef	WIRELESS_EXT
-	dev->wireless_handlers = &lbs_handler_def;
-#endif
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
 
-
-	// TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
-
-
 	priv->card = card;
-	priv->infra_open = 0;
-
 
-	priv->rtap_net_dev = NULL;
 	strcpy(dev->name, "wlan%d");
 
 	lbs_deb_thread("Starting main thread...\n");
@@ -996,8 +884,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 	}
 
 	priv->work_thread = create_singlethread_workqueue("lbs_worker");
-	INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
-	INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
 	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 
 	priv->wol_criteria = 0xffffffff;
@@ -1031,12 +917,10 @@ void lbs_remove_card(struct lbs_private *priv)
 	lbs_deb_enter(LBS_DEB_MAIN);
 
 	lbs_remove_mesh(priv);
-	lbs_remove_rtap(priv);
+	lbs_scan_deinit(priv);
 
 	dev = priv->dev;
 
-	cancel_delayed_work_sync(&priv->scan_work);
-	cancel_delayed_work_sync(&priv->assoc_work);
 	cancel_work_sync(&priv->mcast_work);
 
 	/* worker thread destruction blocks on the in-flight command which
@@ -1051,8 +935,6 @@ void lbs_remove_card(struct lbs_private *priv)
 		lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
 	}
 
-	lbs_send_disconnect_notification(priv);
-
 	if (priv->is_deep_sleep) {
 		priv->is_deep_sleep = 0;
 		wake_up_interruptible(&priv->ds_awake_q);
@@ -1077,7 +959,7 @@ void lbs_remove_card(struct lbs_private *priv)
 EXPORT_SYMBOL_GPL(lbs_remove_card);
 
 
-static int lbs_rtap_supported(struct lbs_private *priv)
+int lbs_rtap_supported(struct lbs_private *priv)
 {
 	if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
 		return 1;
@@ -1109,16 +991,6 @@ int lbs_start_card(struct lbs_private *priv)
 
 	lbs_init_mesh(priv);
 
-	/*
-	 * While rtap isn't related to mesh, only mesh-enabled
-	 * firmware implements the rtap functionality via
-	 * CMD_802_11_MONITOR_MODE.
-	 */
-	if (lbs_rtap_supported(priv)) {
-		if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
-			lbs_pr_err("cannot register lbs_rtap attribute\n");
-	}
-
 	lbs_debugfs_init_one(priv, dev);
 
 	lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@@ -1150,9 +1022,6 @@ void lbs_stop_card(struct lbs_private *priv)
 	lbs_debugfs_remove_one(priv);
 	lbs_deinit_mesh(priv);
 
-	if (lbs_rtap_supported(priv))
-		device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
-
 	/* Delete the timeout of the currently processing command */
 	del_timer_sync(&priv->command_timer);
 	del_timer_sync(&priv->auto_deepsleep_timer);
@@ -1239,87 +1108,6 @@ static void __exit lbs_exit_module(void)
 	lbs_deb_leave(LBS_DEB_MAIN);
 }
 
-/*
- * rtap interface support fuctions
- */
-
-static int lbs_rtap_open(struct net_device *dev)
-{
-	/* Yes, _stop_ the queue. Because we don't support injection */
-	lbs_deb_enter(LBS_DEB_MAIN);
-	netif_carrier_off(dev);
-	netif_stop_queue(dev);
-	lbs_deb_leave(LBS_DEB_LEAVE);
-	return 0;
-}
-
-static int lbs_rtap_stop(struct net_device *dev)
-{
-	lbs_deb_enter(LBS_DEB_MAIN);
-	lbs_deb_leave(LBS_DEB_MAIN);
-	return 0;
-}
-
-static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb,
-					    struct net_device *dev)
-{
-	netif_stop_queue(dev);
-	return NETDEV_TX_BUSY;
-}
-
-static void lbs_remove_rtap(struct lbs_private *priv)
-{
-	lbs_deb_enter(LBS_DEB_MAIN);
-	if (priv->rtap_net_dev == NULL)
-		goto out;
-	unregister_netdev(priv->rtap_net_dev);
-	free_netdev(priv->rtap_net_dev);
-	priv->rtap_net_dev = NULL;
-out:
-	lbs_deb_leave(LBS_DEB_MAIN);
-}
-
-static const struct net_device_ops rtap_netdev_ops = {
-	.ndo_open = lbs_rtap_open,
-	.ndo_stop = lbs_rtap_stop,
-	.ndo_start_xmit = lbs_rtap_hard_start_xmit,
-};
-
-static int lbs_add_rtap(struct lbs_private *priv)
-{
-	int ret = 0;
-	struct net_device *rtap_dev;
-
-	lbs_deb_enter(LBS_DEB_MAIN);
-	if (priv->rtap_net_dev) {
-		ret = -EPERM;
-		goto out;
-	}
-
-	rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
-	if (rtap_dev == NULL) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
-	rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
-	rtap_dev->netdev_ops = &rtap_netdev_ops;
-	rtap_dev->ml_priv = priv;
-	SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
-
-	ret = register_netdev(rtap_dev);
-	if (ret) {
-		free_netdev(rtap_dev);
-		goto out;
-	}
-	priv->rtap_net_dev = rtap_dev;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-	return ret;
-}
-
 module_init(lbs_init_module);
 module_exit(lbs_exit_module);
 

+ 2 - 4
drivers/net/wireless/libertas/mesh.c

@@ -5,6 +5,7 @@
 #include <linux/if_arp.h>
 #include <linux/kthread.h>
 #include <linux/kfifo.h>
+#include <net/cfg80211.h>
 
 #include "mesh.h"
 #include "decl.h"
@@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev)
 
 	spin_lock_irq(&priv->driver_lock);
 
-	if (priv->monitormode) {
+	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv)
 
 	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
-#ifdef	WIRELESS_EXT
-	mesh_dev->wireless_handlers = &mesh_handler_def;
-#endif
 	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
 	/* Register virtual mesh interface */
 	ret = register_netdev(mesh_dev);

+ 0 - 5
drivers/net/wireless/libertas/mesh.h

@@ -70,11 +70,6 @@ void lbs_persist_config_init(struct net_device *net);
 void lbs_persist_config_remove(struct net_device *net);
 
 
-/* WEXT handler */
-
-extern struct iw_handler_def mesh_handler_def;
-
-
 /* Ethtool statistics */
 
 struct ethtool_stats;

+ 11 - 110
drivers/net/wireless/libertas/rx.c

@@ -4,12 +4,13 @@
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <net/cfg80211.h>
 
+#include "defs.h"
 #include "host.h"
 #include "radiotap.h"
 #include "decl.h"
 #include "dev.h"
-#include "wext.h"
 
 struct eth803hdr {
 	u8 dest_addr[6];
@@ -38,98 +39,6 @@ struct rx80211packethdr {
 static int process_rxed_802_11_packet(struct lbs_private *priv,
 	struct sk_buff *skb);
 
-/**
- *  @brief	This function computes the avgSNR .
- *
- *  @param	priv	A pointer to struct lbs_private structure
- *  @return	avgSNR
- */
-static u8 lbs_getavgsnr(struct lbs_private *priv)
-{
-	u8 i;
-	u16 temp = 0;
-	if (priv->numSNRNF == 0)
-		return 0;
-	for (i = 0; i < priv->numSNRNF; i++)
-		temp += priv->rawSNR[i];
-	return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- *  @brief	This function computes the AvgNF
- *
- *  @param	priv	A pointer to struct lbs_private structure
- *  @return	AvgNF
- */
-static u8 lbs_getavgnf(struct lbs_private *priv)
-{
-	u8 i;
-	u16 temp = 0;
-	if (priv->numSNRNF == 0)
-		return 0;
-	for (i = 0; i < priv->numSNRNF; i++)
-		temp += priv->rawNF[i];
-	return (u8) (temp / priv->numSNRNF);
-
-}
-
-/**
- *  @brief	This function save the raw SNR/NF to our internel buffer
- *
- *  @param	priv	A pointer to struct lbs_private structure
- *  @param	prxpd	A pointer to rxpd structure of received packet
- *  @return	n/a
- */
-static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
-	if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
-		priv->numSNRNF++;
-	priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
-	priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
-	priv->nextSNRNF++;
-	if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
-		priv->nextSNRNF = 0;
-}
-
-/**
- *  @brief	This function computes the RSSI in received packet.
- *
- *  @param	priv	A pointer to struct lbs_private structure
- *  @param	prxpd	A pointer to rxpd structure of received packet
- *  @return	n/a
- */
-static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
-{
-
-	lbs_deb_enter(LBS_DEB_RX);
-
-	lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
-	lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
-	       priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
-	       priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
-	priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
-	priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
-	lbs_save_rawSNRNF(priv, p_rx_pd);
-
-	priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
-	priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
-	lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
-	       priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
-	       priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
-	priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
-	    CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
-		     priv->NF[TYPE_RXPD][TYPE_NOAVG]);
-
-	priv->RSSI[TYPE_RXPD][TYPE_AVG] =
-	    CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
-		     priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
-
-	lbs_deb_leave(LBS_DEB_RX);
-}
-
 /**
  *  @brief This function processes received packet and forwards it
  *  to kernel/upper layer
@@ -154,7 +63,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 
 	skb->ip_summed = CHECKSUM_NONE;
 
-	if (priv->monitormode)
+	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
 		return process_rxed_802_11_packet(priv, skb);
 
 	p_rx_pd = (struct rxpd *) skb->data;
@@ -225,13 +134,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 	 */
 	skb_pull(skb, hdrchop);
 
-	/* Take the data rate from the rxpd structure
-	 * only if the rate is auto
-	 */
-	if (priv->enablehwauto)
-		priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
-
-	lbs_compute_rssi(priv, p_rx_pd);
+	priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
 
 	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 	dev->stats.rx_bytes += skb->len;
@@ -352,20 +255,18 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
 	pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
 	memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
 
-	/* Take the data rate from the rxpd structure
-	 * only if the rate is auto
-	 */
-	if (priv->enablehwauto)
-		priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
-
-	lbs_compute_rssi(priv, prxpd);
+	priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
 
 	lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
 	dev->stats.rx_bytes += skb->len;
 	dev->stats.rx_packets++;
 
-	skb->protocol = eth_type_trans(skb, priv->rtap_net_dev);
-	netif_rx(skb);
+	skb->protocol = eth_type_trans(skb, priv->dev);
+
+	if (in_interrupt())
+		netif_rx(skb);
+	else
+		netif_rx_ni(skb);
 
 	ret = 0;
 

+ 0 - 1354
drivers/net/wireless/libertas/scan.c

@@ -1,1354 +0,0 @@
-/**
-  * Functions implementing wlan scan IOCTL and firmware command APIs
-  *
-  * IOCTL handlers as well as command preperation and response routines
-  *  for sending scan commands to the firmware.
-  */
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-#include <asm/unaligned.h>
-#include <net/lib80211.h>
-
-#include "host.h"
-#include "dev.h"
-#include "scan.h"
-#include "assoc.h"
-#include "wext.h"
-#include "cmd.h"
-
-//! Approximate amount of data needed to pass a scan result back to iwlist
-#define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \
-                             + IEEE80211_MAX_SSID_LEN   \
-                             + IW_EV_UINT_LEN           \
-                             + IW_EV_FREQ_LEN           \
-                             + IW_EV_QUAL_LEN           \
-                             + IEEE80211_MAX_SSID_LEN   \
-                             + IW_EV_PARAM_LEN          \
-                             + 40)	/* 40 for WPAIE */
-
-//! Memory needed to store a max sized channel List TLV for a firmware scan
-#define CHAN_TLV_MAX_SIZE  (sizeof(struct mrvl_ie_header)    \
-                            + (MRVDRV_MAX_CHANNELS_PER_SCAN     \
-                               * sizeof(struct chanscanparamset)))
-
-//! Memory needed to store a max number/size SSID TLV for a firmware scan
-#define SSID_TLV_MAX_SIZE  (1 * sizeof(struct mrvl_ie_ssid_param_set))
-
-//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
-#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan)	\
-                            + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
-
-//! The maximum number of channels the firmware can scan per command
-#define MRVDRV_MAX_CHANNELS_PER_SCAN   14
-
-/**
- * @brief Number of channels to scan per firmware scan command issuance.
- *
- *  Number restricted to prevent hitting the limit on the amount of scan data
- *  returned in a single firmware scan command.
- */
-#define MRVDRV_CHANNELS_PER_SCAN_CMD   4
-
-//! Scan time specified in the channel TLV for each channel for passive scans
-#define MRVDRV_PASSIVE_SCAN_CHAN_TIME  100
-
-//! Scan time specified in the channel TLV for each channel for active scans
-#define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
-
-#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
-
-static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
-			      struct cmd_header *resp);
-
-/*********************************************************************/
-/*                                                                   */
-/*  Misc helper functions                                            */
-/*                                                                   */
-/*********************************************************************/
-
-/**
- *  @brief Unsets the MSB on basic rates
- *
- * Scan through an array and unset the MSB for basic data rates.
- *
- *  @param rates     buffer of data rates
- *  @param len       size of buffer
- */
-static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		rates[i] &= 0x7f;
-}
-
-
-static inline void clear_bss_descriptor(struct bss_descriptor *bss)
-{
-	/* Don't blow away ->list, just BSS data */
-	memset(bss, 0, offsetof(struct bss_descriptor, list));
-}
-
-/**
- *  @brief Compare two SSIDs
- *
- *  @param ssid1    A pointer to ssid to compare
- *  @param ssid2    A pointer to ssid to compare
- *
- *  @return         0: ssid is same, otherwise is different
- */
-int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
-		 uint8_t ssid2_len)
-{
-	if (ssid1_len != ssid2_len)
-		return -1;
-
-	return memcmp(ssid1, ssid2, ssid1_len);
-}
-
-static inline int is_same_network(struct bss_descriptor *src,
-				  struct bss_descriptor *dst)
-{
-	/* A network is only a duplicate if the channel, BSSID, and ESSID
-	 * all match.  We treat all <hidden> with the same BSSID and channel
-	 * as one network */
-	return ((src->ssid_len == dst->ssid_len) &&
-		(src->channel == dst->channel) &&
-		!compare_ether_addr(src->bssid, dst->bssid) &&
-		!memcmp(src->ssid, dst->ssid, src->ssid_len));
-}
-
-
-
-/*********************************************************************/
-/*                                                                   */
-/* Region channel support                                            */
-/*                                                                   */
-/*********************************************************************/
-
-#define LBS_TX_PWR_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_US_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_JP_DEFAULT		16	/*50mW */
-#define LBS_TX_PWR_FR_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_EMEA_DEFAULT	20	/*100mW */
-
-/* Format { channel, frequency (MHz), maxtxpower } */
-/* band: 'B/G', region: USA FCC/Canada IC */
-static struct chan_freq_power channel_freq_power_US_BG[] = {
-	{1, 2412, LBS_TX_PWR_US_DEFAULT},
-	{2, 2417, LBS_TX_PWR_US_DEFAULT},
-	{3, 2422, LBS_TX_PWR_US_DEFAULT},
-	{4, 2427, LBS_TX_PWR_US_DEFAULT},
-	{5, 2432, LBS_TX_PWR_US_DEFAULT},
-	{6, 2437, LBS_TX_PWR_US_DEFAULT},
-	{7, 2442, LBS_TX_PWR_US_DEFAULT},
-	{8, 2447, LBS_TX_PWR_US_DEFAULT},
-	{9, 2452, LBS_TX_PWR_US_DEFAULT},
-	{10, 2457, LBS_TX_PWR_US_DEFAULT},
-	{11, 2462, LBS_TX_PWR_US_DEFAULT}
-};
-
-/* band: 'B/G', region: Europe ETSI */
-static struct chan_freq_power channel_freq_power_EU_BG[] = {
-	{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
-	{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
-	{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
-	{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
-	{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
-	{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
-	{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
-	{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
-	{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
-	{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
-	{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
-	{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
-	{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
-};
-
-/* band: 'B/G', region: Spain */
-static struct chan_freq_power channel_freq_power_SPN_BG[] = {
-	{10, 2457, LBS_TX_PWR_DEFAULT},
-	{11, 2462, LBS_TX_PWR_DEFAULT}
-};
-
-/* band: 'B/G', region: France */
-static struct chan_freq_power channel_freq_power_FR_BG[] = {
-	{10, 2457, LBS_TX_PWR_FR_DEFAULT},
-	{11, 2462, LBS_TX_PWR_FR_DEFAULT},
-	{12, 2467, LBS_TX_PWR_FR_DEFAULT},
-	{13, 2472, LBS_TX_PWR_FR_DEFAULT}
-};
-
-/* band: 'B/G', region: Japan */
-static struct chan_freq_power channel_freq_power_JPN_BG[] = {
-	{1, 2412, LBS_TX_PWR_JP_DEFAULT},
-	{2, 2417, LBS_TX_PWR_JP_DEFAULT},
-	{3, 2422, LBS_TX_PWR_JP_DEFAULT},
-	{4, 2427, LBS_TX_PWR_JP_DEFAULT},
-	{5, 2432, LBS_TX_PWR_JP_DEFAULT},
-	{6, 2437, LBS_TX_PWR_JP_DEFAULT},
-	{7, 2442, LBS_TX_PWR_JP_DEFAULT},
-	{8, 2447, LBS_TX_PWR_JP_DEFAULT},
-	{9, 2452, LBS_TX_PWR_JP_DEFAULT},
-	{10, 2457, LBS_TX_PWR_JP_DEFAULT},
-	{11, 2462, LBS_TX_PWR_JP_DEFAULT},
-	{12, 2467, LBS_TX_PWR_JP_DEFAULT},
-	{13, 2472, LBS_TX_PWR_JP_DEFAULT},
-	{14, 2484, LBS_TX_PWR_JP_DEFAULT}
-};
-
-/**
- * the structure for channel, frequency and power
- */
-struct region_cfp_table {
-	u8 region;
-	struct chan_freq_power *cfp_BG;
-	int cfp_no_BG;
-};
-
-/**
- * the structure for the mapping between region and CFP
- */
-static struct region_cfp_table region_cfp_table[] = {
-	{0x10,			/*US FCC */
-	 channel_freq_power_US_BG,
-	 ARRAY_SIZE(channel_freq_power_US_BG),
-	 }
-	,
-	{0x20,			/*CANADA IC */
-	 channel_freq_power_US_BG,
-	 ARRAY_SIZE(channel_freq_power_US_BG),
-	 }
-	,
-	{0x30, /*EU*/ channel_freq_power_EU_BG,
-	 ARRAY_SIZE(channel_freq_power_EU_BG),
-	 }
-	,
-	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
-	 ARRAY_SIZE(channel_freq_power_SPN_BG),
-	 }
-	,
-	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
-	 ARRAY_SIZE(channel_freq_power_FR_BG),
-	 }
-	,
-	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
-	 ARRAY_SIZE(channel_freq_power_JPN_BG),
-	 }
-	,
-/*Add new region here */
-};
-
-/**
- *  @brief This function finds the CFP in
- *  region_cfp_table based on region and band parameter.
- *
- *  @param region  The region code
- *  @param band	   The band
- *  @param cfp_no  A pointer to CFP number
- *  @return 	   A pointer to CFP
- */
-static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
-{
-	int i, end;
-
-	lbs_deb_enter(LBS_DEB_MAIN);
-
-	end = ARRAY_SIZE(region_cfp_table);
-
-	for (i = 0; i < end ; i++) {
-		lbs_deb_main("region_cfp_table[i].region=%d\n",
-			region_cfp_table[i].region);
-		if (region_cfp_table[i].region == region) {
-			*cfp_no = region_cfp_table[i].cfp_no_BG;
-			lbs_deb_leave(LBS_DEB_MAIN);
-			return region_cfp_table[i].cfp_BG;
-		}
-	}
-
-	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
-	return NULL;
-}
-
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
-{
-	int ret = 0;
-	int i = 0;
-
-	struct chan_freq_power *cfp;
-	int cfp_no;
-
-	lbs_deb_enter(LBS_DEB_MAIN);
-
-	memset(priv->region_channel, 0, sizeof(priv->region_channel));
-
-	cfp = lbs_get_region_cfp_table(region, &cfp_no);
-	if (cfp != NULL) {
-		priv->region_channel[i].nrcfp = cfp_no;
-		priv->region_channel[i].CFP = cfp;
-	} else {
-		lbs_deb_main("wrong region code %#x in band B/G\n",
-		       region);
-		ret = -1;
-		goto out;
-	}
-	priv->region_channel[i].valid = 1;
-	priv->region_channel[i].region = region;
-	priv->region_channel[i].band = band;
-	i++;
-out:
-	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-	return ret;
-}
-
-
-
-
-/*********************************************************************/
-/*                                                                   */
-/*  Main scanning support                                            */
-/*                                                                   */
-/*********************************************************************/
-
-/**
- *  @brief Create a channel list for the driver to scan based on region info
- *
- *  Only used from lbs_scan_setup_scan_config()
- *
- *  Use the driver region/band information to construct a comprehensive list
- *    of channels to scan.  This routine is used for any scan that is not
- *    provided a specific channel list to scan.
- *
- *  @param priv          A pointer to struct lbs_private structure
- *  @param scanchanlist  Output parameter: resulting channel list to scan
- *
- *  @return              void
- */
-static int lbs_scan_create_channel_list(struct lbs_private *priv,
-					struct chanscanparamset *scanchanlist)
-{
-	struct region_channel *scanregion;
-	struct chan_freq_power *cfp;
-	int rgnidx;
-	int chanidx;
-	int nextchan;
-	uint8_t scantype;
-
-	chanidx = 0;
-
-	/* Set the default scan type to the user specified type, will later
-	 *   be changed to passive on a per channel basis if restricted by
-	 *   regulatory requirements (11d or 11h)
-	 */
-	scantype = CMD_SCAN_TYPE_ACTIVE;
-
-	for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
-		if (!priv->region_channel[rgnidx].valid)
-			continue;
-		scanregion = &priv->region_channel[rgnidx];
-
-		for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
-			struct chanscanparamset *chan = &scanchanlist[chanidx];
-
-			cfp = scanregion->CFP + nextchan;
-
-			if (scanregion->band == BAND_B || scanregion->band == BAND_G)
-				chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
-
-			if (scantype == CMD_SCAN_TYPE_PASSIVE) {
-				chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
-				chan->chanscanmode.passivescan = 1;
-			} else {
-				chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
-				chan->chanscanmode.passivescan = 0;
-			}
-
-			chan->channumber = cfp->channel;
-		}
-	}
-	return chanidx;
-}
-
-/*
- * Add SSID TLV of the form:
- *
- * TLV-ID SSID     00 00
- * length          06 00
- * ssid            4d 4e 54 45 53 54
- */
-static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
-{
-	struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
-
-	ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
-	ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
-	memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
-	return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
-}
-
-/*
- * Add CHANLIST TLV of the form
- *
- * TLV-ID CHANLIST 01 01
- * length          5b 00
- * channel 1       00 01 00 00 00 64 00
- *   radio type    00
- *   channel          01
- *   scan type           00
- *   min scan time          00 00
- *   max scan time                64 00
- * channel 2       00 02 00 00 00 64 00
- * channel 3       00 03 00 00 00 64 00
- * channel 4       00 04 00 00 00 64 00
- * channel 5       00 05 00 00 00 64 00
- * channel 6       00 06 00 00 00 64 00
- * channel 7       00 07 00 00 00 64 00
- * channel 8       00 08 00 00 00 64 00
- * channel 9       00 09 00 00 00 64 00
- * channel 10      00 0a 00 00 00 64 00
- * channel 11      00 0b 00 00 00 64 00
- * channel 12      00 0c 00 00 00 64 00
- * channel 13      00 0d 00 00 00 64 00
- *
- */
-static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
-				     struct chanscanparamset *chan_list,
-				     int chan_count)
-{
-	size_t size = sizeof(struct chanscanparamset) *chan_count;
-	struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv;
-
-	chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
-	memcpy(chan_tlv->chanscanparam, chan_list, size);
-	chan_tlv->header.len = cpu_to_le16(size);
-	return sizeof(chan_tlv->header) + size;
-}
-
-/*
- * Add RATES TLV of the form
- *
- * TLV-ID RATES    01 00
- * length          0e 00
- * rates           82 84 8b 96 0c 12 18 24 30 48 60 6c
- *
- * The rates are in lbs_bg_rates[], but for the 802.11b
- * rates the high bit isn't set.
- */
-static int lbs_scan_add_rates_tlv(uint8_t *tlv)
-{
-	int i;
-	struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
-
-	rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
-	tlv += sizeof(rate_tlv->header);
-	for (i = 0; i < MAX_RATES; i++) {
-		*tlv = lbs_bg_rates[i];
-		if (*tlv == 0)
-			break;
-		/* This code makes sure that the 802.11b rates (1 MBit/s, 2
-		   MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
-		   Note that the values are MBit/s * 2, to mark them as
-		   basic rates so that the firmware likes it better */
-		if (*tlv == 0x02 || *tlv == 0x04 ||
-		    *tlv == 0x0b || *tlv == 0x16)
-			*tlv |= 0x80;
-		tlv++;
-	}
-	rate_tlv->header.len = cpu_to_le16(i);
-	return sizeof(rate_tlv->header) + i;
-}
-
-/*
- * Generate the CMD_802_11_SCAN command with the proper tlv
- * for a bunch of channels.
- */
-static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
-		       struct chanscanparamset *chan_list, int chan_count)
-{
-	int ret = -ENOMEM;
-	struct cmd_ds_802_11_scan *scan_cmd;
-	uint8_t *tlv;	/* pointer into our current, growing TLV storage area */
-
-	lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
-		bsstype, chan_list ? chan_list[0].channumber : -1,
-		chan_count);
-
-	/* create the fixed part for scan command */
-	scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
-	if (scan_cmd == NULL)
-		goto out;
-
-	tlv = scan_cmd->tlvbuffer;
-	/* TODO: do we need to scan for a specific BSSID?
-	memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
-	scan_cmd->bsstype = bsstype;
-
-	/* add TLVs */
-	if (priv->scan_ssid_len)
-		tlv += lbs_scan_add_ssid_tlv(priv, tlv);
-	if (chan_list && chan_count)
-		tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
-	tlv += lbs_scan_add_rates_tlv(tlv);
-
-	/* This is the final data we are about to send */
-	scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
-	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
-		    sizeof(*scan_cmd));
-	lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
-		    tlv - scan_cmd->tlvbuffer);
-
-	ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
-			le16_to_cpu(scan_cmd->hdr.size),
-			lbs_ret_80211_scan, 0);
-
-out:
-	kfree(scan_cmd);
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Internal function used to start a scan based on an input config
- *
- *  Use the input user scan configuration information when provided in
- *    order to send the appropriate scan commands to firmware to populate or
- *    update the internal driver scan table
- *
- *  @param priv          A pointer to struct lbs_private structure
- *  @param full_scan     Do a full-scan (blocking)
- *
- *  @return              0 or < 0 if error
- */
-int lbs_scan_networks(struct lbs_private *priv, int full_scan)
-{
-	int ret = -ENOMEM;
-	struct chanscanparamset *chan_list;
-	struct chanscanparamset *curr_chans;
-	int chan_count;
-	uint8_t bsstype = CMD_BSS_TYPE_ANY;
-	int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
-	union iwreq_data wrqu;
-#ifdef CONFIG_LIBERTAS_DEBUG
-	struct bss_descriptor *iter;
-	int i = 0;
-	DECLARE_SSID_BUF(ssid);
-#endif
-
-	lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
-
-	/* Cancel any partial outstanding partial scans if this scan
-	 * is a full scan.
-	 */
-	if (full_scan && delayed_work_pending(&priv->scan_work))
-		cancel_delayed_work(&priv->scan_work);
-
-	/* User-specified bsstype or channel list
-	TODO: this can be implemented if some user-space application
-	need the feature. Formerly, it was accessible from debugfs,
-	but then nowhere used.
-	if (user_cfg) {
-		if (user_cfg->bsstype)
-		bsstype = user_cfg->bsstype;
-	} */
-
-	lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
-
-	/* Create list of channels to scan */
-	chan_list = kzalloc(sizeof(struct chanscanparamset) *
-			    LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
-	if (!chan_list) {
-		lbs_pr_alert("SCAN: chan_list empty\n");
-		goto out;
-	}
-
-	/* We want to scan all channels */
-	chan_count = lbs_scan_create_channel_list(priv, chan_list);
-
-	netif_stop_queue(priv->dev);
-	if (priv->mesh_dev)
-		netif_stop_queue(priv->mesh_dev);
-
-	/* Prepare to continue an interrupted scan */
-	lbs_deb_scan("chan_count %d, scan_channel %d\n",
-		     chan_count, priv->scan_channel);
-	curr_chans = chan_list;
-	/* advance channel list by already-scanned-channels */
-	if (priv->scan_channel > 0) {
-		curr_chans += priv->scan_channel;
-		chan_count -= priv->scan_channel;
-	}
-
-	/* Send scan command(s)
-	 * numchannels contains the number of channels we should maximally scan
-	 * chan_count is the total number of channels to scan
-	 */
-
-	while (chan_count) {
-		int to_scan = min(numchannels, chan_count);
-		lbs_deb_scan("scanning %d of %d channels\n",
-			     to_scan, chan_count);
-		ret = lbs_do_scan(priv, bsstype, curr_chans,
-				  to_scan);
-		if (ret) {
-			lbs_pr_err("SCAN_CMD failed\n");
-			goto out2;
-		}
-		curr_chans += to_scan;
-		chan_count -= to_scan;
-
-		/* somehow schedule the next part of the scan */
-		if (chan_count && !full_scan &&
-		    !priv->surpriseremoved) {
-			/* -1 marks just that we're currently scanning */
-			if (priv->scan_channel < 0)
-				priv->scan_channel = to_scan;
-			else
-				priv->scan_channel += to_scan;
-			cancel_delayed_work(&priv->scan_work);
-			queue_delayed_work(priv->work_thread, &priv->scan_work,
-					   msecs_to_jiffies(300));
-			/* skip over GIWSCAN event */
-			goto out;
-		}
-
-	}
-	memset(&wrqu, 0, sizeof(union iwreq_data));
-	wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
-
-#ifdef CONFIG_LIBERTAS_DEBUG
-	/* Dump the scan table */
-	mutex_lock(&priv->lock);
-	lbs_deb_scan("scan table:\n");
-	list_for_each_entry(iter, &priv->network_list, list)
-		lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
-			     i++, iter->bssid, iter->rssi,
-			     print_ssid(ssid, iter->ssid, iter->ssid_len));
-	mutex_unlock(&priv->lock);
-#endif
-
-out2:
-	priv->scan_channel = 0;
-
-out:
-	if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
-		netif_wake_queue(priv->dev);
-
-	if (priv->mesh_dev && lbs_mesh_connected(priv) &&
-	    !priv->tx_pending_len)
-		netif_wake_queue(priv->mesh_dev);
-
-	kfree(chan_list);
-
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}
-
-void lbs_scan_worker(struct work_struct *work)
-{
-	struct lbs_private *priv =
-		container_of(work, struct lbs_private, scan_work.work);
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-	lbs_scan_networks(priv, 0);
-	lbs_deb_leave(LBS_DEB_SCAN);
-}
-
-
-/*********************************************************************/
-/*                                                                   */
-/*  Result interpretation                                            */
-/*                                                                   */
-/*********************************************************************/
-
-/**
- *  @brief Interpret a BSS scan response returned from the firmware
- *
- *  Parse the various fixed fields and IEs passed back for a BSS probe
- *  response or beacon from the scan command.  Record information as needed
- *  in the scan table struct bss_descriptor for that entry.
- *
- *  @param bss  Output parameter: Pointer to the BSS Entry
- *
- *  @return             0 or -1
- */
-static int lbs_process_bss(struct bss_descriptor *bss,
-			   uint8_t **pbeaconinfo, int *bytesleft)
-{
-	struct ieee_ie_fh_param_set *fh;
-	struct ieee_ie_ds_param_set *ds;
-	struct ieee_ie_cf_param_set *cf;
-	struct ieee_ie_ibss_param_set *ibss;
-	DECLARE_SSID_BUF(ssid);
-	uint8_t *pos, *end, *p;
-	uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
-	uint16_t beaconsize = 0;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	if (*bytesleft >= sizeof(beaconsize)) {
-		/* Extract & convert beacon size from the command buffer */
-		beaconsize = get_unaligned_le16(*pbeaconinfo);
-		*bytesleft -= sizeof(beaconsize);
-		*pbeaconinfo += sizeof(beaconsize);
-	}
-
-	if (beaconsize == 0 || beaconsize > *bytesleft) {
-		*pbeaconinfo += *bytesleft;
-		*bytesleft = 0;
-		ret = -1;
-		goto done;
-	}
-
-	/* Initialize the current working beacon pointer for this BSS iteration */
-	pos = *pbeaconinfo;
-	end = pos + beaconsize;
-
-	/* Advance the return beacon pointer past the current beacon */
-	*pbeaconinfo += beaconsize;
-	*bytesleft -= beaconsize;
-
-	memcpy(bss->bssid, pos, ETH_ALEN);
-	lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
-	pos += ETH_ALEN;
-
-	if ((end - pos) < 12) {
-		lbs_deb_scan("process_bss: Not enough bytes left\n");
-		ret = -1;
-		goto done;
-	}
-
-	/*
-	 * next 4 fields are RSSI, time stamp, beacon interval,
-	 *   and capability information
-	 */
-
-	/* RSSI is 1 byte long */
-	bss->rssi = *pos;
-	lbs_deb_scan("process_bss: RSSI %d\n", *pos);
-	pos++;
-
-	/* time stamp is 8 bytes long */
-	pos += 8;
-
-	/* beacon interval is 2 bytes long */
-	bss->beaconperiod = get_unaligned_le16(pos);
-	pos += 2;
-
-	/* capability information is 2 bytes long */
-	bss->capability = get_unaligned_le16(pos);
-	lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
-	pos += 2;
-
-	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
-		lbs_deb_scan("process_bss: WEP enabled\n");
-	if (bss->capability & WLAN_CAPABILITY_IBSS)
-		bss->mode = IW_MODE_ADHOC;
-	else
-		bss->mode = IW_MODE_INFRA;
-
-	/* rest of the current buffer are IE's */
-	lbs_deb_scan("process_bss: IE len %zd\n", end - pos);
-	lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);
-
-	/* process variable IE */
-	while (pos <= end - 2) {
-		if (pos + pos[1] > end) {
-			lbs_deb_scan("process_bss: error in processing IE, "
-				     "bytes left < IE length\n");
-			break;
-		}
-
-		switch (pos[0]) {
-		case WLAN_EID_SSID:
-			bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
-			memcpy(bss->ssid, pos + 2, bss->ssid_len);
-			lbs_deb_scan("got SSID IE: '%s', len %u\n",
-			             print_ssid(ssid, bss->ssid, bss->ssid_len),
-			             bss->ssid_len);
-			break;
-
-		case WLAN_EID_SUPP_RATES:
-			n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
-			memcpy(bss->rates, pos + 2, n_basic_rates);
-			got_basic_rates = 1;
-			lbs_deb_scan("got RATES IE\n");
-			break;
-
-		case WLAN_EID_FH_PARAMS:
-			fh = (struct ieee_ie_fh_param_set *) pos;
-			memcpy(&bss->phy.fh, fh, sizeof(*fh));
-			lbs_deb_scan("got FH IE\n");
-			break;
-
-		case WLAN_EID_DS_PARAMS:
-			ds = (struct ieee_ie_ds_param_set *) pos;
-			bss->channel = ds->channel;
-			memcpy(&bss->phy.ds, ds, sizeof(*ds));
-			lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
-			break;
-
-		case WLAN_EID_CF_PARAMS:
-			cf = (struct ieee_ie_cf_param_set *) pos;
-			memcpy(&bss->ss.cf, cf, sizeof(*cf));
-			lbs_deb_scan("got CF IE\n");
-			break;
-
-		case WLAN_EID_IBSS_PARAMS:
-			ibss = (struct ieee_ie_ibss_param_set *) pos;
-			bss->atimwindow = ibss->atimwindow;
-			memcpy(&bss->ss.ibss, ibss, sizeof(*ibss));
-			lbs_deb_scan("got IBSS IE\n");
-			break;
-
-		case WLAN_EID_EXT_SUPP_RATES:
-			/* only process extended supported rate if data rate is
-			 * already found. Data rate IE should come before
-			 * extended supported rate IE
-			 */
-			lbs_deb_scan("got RATESEX IE\n");
-			if (!got_basic_rates) {
-				lbs_deb_scan("... but ignoring it\n");
-				break;
-			}
-
-			n_ex_rates = pos[1];
-			if (n_basic_rates + n_ex_rates > MAX_RATES)
-				n_ex_rates = MAX_RATES - n_basic_rates;
-
-			p = bss->rates + n_basic_rates;
-			memcpy(p, pos + 2, n_ex_rates);
-			break;
-
-		case WLAN_EID_GENERIC:
-			if (pos[1] >= 4 &&
-			    pos[2] == 0x00 && pos[3] == 0x50 &&
-			    pos[4] == 0xf2 && pos[5] == 0x01) {
-				bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
-				memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
-				lbs_deb_scan("got WPA IE\n");
-				lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
-					    bss->wpa_ie_len);
-			} else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
-				   pos[2] == 0x00 && pos[3] == 0x50 &&
-				   pos[4] == 0x43 && pos[5] == 0x04) {
-				lbs_deb_scan("got mesh IE\n");
-				bss->mesh = 1;
-			} else {
-				lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
-					pos[2], pos[3],
-					pos[4], pos[5],
-					pos[1]);
-			}
-			break;
-
-		case WLAN_EID_RSN:
-			lbs_deb_scan("got RSN IE\n");
-			bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
-			memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
-			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
-				    bss->rsn_ie, bss->rsn_ie_len);
-			break;
-
-		default:
-			lbs_deb_scan("got IE 0x%04x, len %d\n",
-				     pos[0], pos[1]);
-			break;
-		}
-
-		pos += pos[1] + 2;
-	}
-
-	/* Timestamp */
-	bss->last_scanned = jiffies;
-	lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
-
-	ret = 0;
-
-done:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Send a scan command for all available channels filtered on a spec
- *
- *  Used in association code and from debugfs
- *
- *  @param priv             A pointer to struct lbs_private structure
- *  @param ssid             A pointer to the SSID to scan for
- *  @param ssid_len         Length of the SSID
- *
- *  @return                0-success, otherwise fail
- */
-int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
-				uint8_t ssid_len)
-{
-	DECLARE_SSID_BUF(ssid_buf);
-	int ret = 0;
-
-	lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
-			   print_ssid(ssid_buf, ssid, ssid_len));
-
-	if (!ssid_len)
-		goto out;
-
-	memcpy(priv->scan_ssid, ssid, ssid_len);
-	priv->scan_ssid_len = ssid_len;
-
-	lbs_scan_networks(priv, 1);
-	if (priv->surpriseremoved) {
-		ret = -1;
-		goto out;
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}
-
-
-
-
-/*********************************************************************/
-/*                                                                   */
-/*  Support for Wireless Extensions                                  */
-/*                                                                   */
-/*********************************************************************/
-
-
-#define MAX_CUSTOM_LEN 64
-
-static inline char *lbs_translate_scan(struct lbs_private *priv,
-					    struct iw_request_info *info,
-					    char *start, char *stop,
-					    struct bss_descriptor *bss)
-{
-	struct chan_freq_power *cfp;
-	char *current_val;	/* For rates */
-	struct iw_event iwe;	/* Temporary buffer */
-	int j;
-#define PERFECT_RSSI ((uint8_t)50)
-#define WORST_RSSI   ((uint8_t)0)
-#define RSSI_DIFF    ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
-	uint8_t rssi;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel);
-	if (!cfp) {
-		lbs_deb_scan("Invalid channel number %d\n", bss->channel);
-		start = NULL;
-		goto out;
-	}
-
-	/* First entry *MUST* be the BSSID */
-	iwe.cmd = SIOCGIWAP;
-	iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-	memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
-
-	/* SSID */
-	iwe.cmd = SIOCGIWESSID;
-	iwe.u.data.flags = 1;
-	iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
-	start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
-
-	/* Mode */
-	iwe.cmd = SIOCGIWMODE;
-	iwe.u.mode = bss->mode;
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
-
-	/* Frequency */
-	iwe.cmd = SIOCGIWFREQ;
-	iwe.u.freq.m = (long)cfp->freq * 100000;
-	iwe.u.freq.e = 1;
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
-
-	/* Add quality statistics */
-	iwe.cmd = IWEVQUAL;
-	iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
-	iwe.u.qual.level = SCAN_RSSI(bss->rssi);
-
-	rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
-	iwe.u.qual.qual =
-		(100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
-		 (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
-		(RSSI_DIFF * RSSI_DIFF);
-	if (iwe.u.qual.qual > 100)
-		iwe.u.qual.qual = 100;
-
-	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
-		iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
-	} else {
-		iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-	}
-
-	/* Locally created ad-hoc BSSs won't have beacons if this is the
-	 * only station in the adhoc network; so get signal strength
-	 * from receive statistics.
-	 */
-	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
-	    && !lbs_ssid_cmp(priv->curbssparams.ssid,
-			     priv->curbssparams.ssid_len,
-			     bss->ssid, bss->ssid_len)) {
-		int snr, nf;
-		snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
-		nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
-		iwe.u.qual.level = CAL_RSSI(snr, nf);
-	}
-	start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
-
-	/* Add encryption capability */
-	iwe.cmd = SIOCGIWENCODE;
-	if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
-		iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-	} else {
-		iwe.u.data.flags = IW_ENCODE_DISABLED;
-	}
-	iwe.u.data.length = 0;
-	start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
-
-	current_val = start + iwe_stream_lcp_len(info);
-
-	iwe.cmd = SIOCGIWRATE;
-	iwe.u.bitrate.fixed = 0;
-	iwe.u.bitrate.disabled = 0;
-	iwe.u.bitrate.value = 0;
-
-	for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) {
-		/* Bit rate given in 500 kb/s units */
-		iwe.u.bitrate.value = bss->rates[j] * 500000;
-		current_val = iwe_stream_add_value(info, start, current_val,
-						   stop, &iwe, IW_EV_PARAM_LEN);
-	}
-	if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
-	    && !lbs_ssid_cmp(priv->curbssparams.ssid,
-			     priv->curbssparams.ssid_len,
-			     bss->ssid, bss->ssid_len)) {
-		iwe.u.bitrate.value = 22 * 500000;
-		current_val = iwe_stream_add_value(info, start, current_val,
-						   stop, &iwe, IW_EV_PARAM_LEN);
-	}
-	/* Check if we added any event */
-	if ((current_val - start) > iwe_stream_lcp_len(info))
-		start = current_val;
-
-	memset(&iwe, 0, sizeof(iwe));
-	if (bss->wpa_ie_len) {
-		char buf[MAX_WPA_IE_LEN];
-		memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = bss->wpa_ie_len;
-		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-	}
-
-	memset(&iwe, 0, sizeof(iwe));
-	if (bss->rsn_ie_len) {
-		char buf[MAX_WPA_IE_LEN];
-		memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
-		iwe.cmd = IWEVGENIE;
-		iwe.u.data.length = bss->rsn_ie_len;
-		start = iwe_stream_add_point(info, start, stop, &iwe, buf);
-	}
-
-	if (bss->mesh) {
-		char custom[MAX_CUSTOM_LEN];
-		char *p = custom;
-
-		iwe.cmd = IWEVCUSTOM;
-		p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
-		iwe.u.data.length = p - custom;
-		if (iwe.u.data.length)
-			start = iwe_stream_add_point(info, start, stop,
-						     &iwe, custom);
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start);
-	return start;
-}
-
-
-/**
- *  @brief Handle Scan Network ioctl
- *
- *  @param dev          A pointer to net_device structure
- *  @param info         A pointer to iw_request_info structure
- *  @param vwrq         A pointer to iw_param structure
- *  @param extra        A pointer to extra data buf
- *
- *  @return             0 --success, otherwise fail
- */
-int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
-		 union iwreq_data *wrqu, char *extra)
-{
-	DECLARE_SSID_BUF(ssid);
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!priv->radio_on) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (!netif_running(dev)) {
-		ret = -ENETDOWN;
-		goto out;
-	}
-
-	/* mac80211 does this:
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-	if (sdata->type != IEEE80211_IF_TYPE_xxx) {
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-	*/
-
-	if (wrqu->data.length == sizeof(struct iw_scan_req) &&
-	    wrqu->data.flags & IW_SCAN_THIS_ESSID) {
-		struct iw_scan_req *req = (struct iw_scan_req *)extra;
-		priv->scan_ssid_len = req->essid_len;
-		memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
-		lbs_deb_wext("set_scan, essid '%s'\n",
-			print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
-	} else {
-		priv->scan_ssid_len = 0;
-	}
-
-	if (!delayed_work_pending(&priv->scan_work))
-		queue_delayed_work(priv->work_thread, &priv->scan_work,
-				   msecs_to_jiffies(50));
-	/* set marker that currently a scan is taking place */
-	priv->scan_channel = -1;
-
-	if (priv->surpriseremoved)
-		ret = -EIO;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-
-/**
- *  @brief  Handle Retrieve scan table ioctl
- *
- *  @param dev          A pointer to net_device structure
- *  @param info         A pointer to iw_request_info structure
- *  @param dwrq         A pointer to iw_point structure
- *  @param extra        A pointer to extra data buf
- *
- *  @return             0 --success, otherwise fail
- */
-int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
-		 struct iw_point *dwrq, char *extra)
-{
-#define SCAN_ITEM_SIZE 128
-	struct lbs_private *priv = dev->ml_priv;
-	int err = 0;
-	char *ev = extra;
-	char *stop = ev + dwrq->length;
-	struct bss_descriptor *iter_bss;
-	struct bss_descriptor *safe;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* iwlist should wait until the current scan is finished */
-	if (priv->scan_channel)
-		return -EAGAIN;
-
-	/* Update RSSI if current BSS is a locally created ad-hoc BSS */
-	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
-		err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
-				CMD_OPTION_WAITFORRSP, 0, NULL);
-		if (err)
-			goto out;
-	}
-
-	mutex_lock(&priv->lock);
-	list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
-		char *next_ev;
-		unsigned long stale_time;
-
-		if (stop - ev < SCAN_ITEM_SIZE) {
-			err = -E2BIG;
-			break;
-		}
-
-		/* For mesh device, list only mesh networks */
-		if (dev == priv->mesh_dev && !iter_bss->mesh)
-			continue;
-
-		/* Prune old an old scan result */
-		stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
-		if (time_after(jiffies, stale_time)) {
-			list_move_tail(&iter_bss->list, &priv->network_free_list);
-			clear_bss_descriptor(iter_bss);
-			continue;
-		}
-
-		/* Translate to WE format this entry */
-		next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss);
-		if (next_ev == NULL)
-			continue;
-		ev = next_ev;
-	}
-	mutex_unlock(&priv->lock);
-
-	dwrq->length = (ev - extra);
-	dwrq->flags = 0;
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
-	return err;
-}
-
-
-
-
-/*********************************************************************/
-/*                                                                   */
-/*  Command execution                                                */
-/*                                                                   */
-/*********************************************************************/
-
-
-/**
- *  @brief This function handles the command response of scan
- *
- *  Called from handle_cmd_response() in cmdrespc.
- *
- *   The response buffer for the scan command has the following
- *      memory layout:
- *
- *     .-----------------------------------------------------------.
- *     |  header (4 * sizeof(u16)):  Standard command response hdr |
- *     .-----------------------------------------------------------.
- *     |  bufsize (u16) : sizeof the BSS Description data          |
- *     .-----------------------------------------------------------.
- *     |  NumOfSet (u8) : Number of BSS Descs returned             |
- *     .-----------------------------------------------------------.
- *     |  BSSDescription data (variable, size given in bufsize)    |
- *     .-----------------------------------------------------------.
- *     |  TLV data (variable, size calculated using header->size,  |
- *     |            bufsize and sizeof the fixed fields above)     |
- *     .-----------------------------------------------------------.
- *
- *  @param priv    A pointer to struct lbs_private structure
- *  @param resp    A pointer to cmd_ds_command
- *
- *  @return        0 or -1
- */
-static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
-			      struct cmd_header *resp)
-{
-	struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
-	struct bss_descriptor *iter_bss;
-	struct bss_descriptor *safe;
-	uint8_t *bssinfo;
-	uint16_t scanrespsize;
-	int bytesleft;
-	int idx;
-	int tlvbufsize;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_SCAN);
-
-	/* Prune old entries from scan table */
-	list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
-		unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
-		if (time_before(jiffies, stale_time))
-			continue;
-		list_move_tail (&iter_bss->list, &priv->network_free_list);
-		clear_bss_descriptor(iter_bss);
-	}
-
-	if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
-		lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
-			     scanresp->nr_sets, MAX_NETWORK_COUNT);
-		ret = -1;
-		goto done;
-	}
-
-	bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
-	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
-
-	scanrespsize = le16_to_cpu(resp->size);
-	lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
-
-	bssinfo = scanresp->bssdesc_and_tlvbuffer;
-
-	/* The size of the TLV buffer is equal to the entire command response
-	 *   size (scanrespsize) minus the fixed fields (sizeof()'s), the
-	 *   BSS Descriptions (bssdescriptsize as bytesLef) and the command
-	 *   response header (sizeof(struct cmd_header))
-	 */
-	tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
-				     + sizeof(scanresp->nr_sets)
-				     + sizeof(struct cmd_header));
-
-	/*
-	 *  Process each scan response returned (scanresp->nr_sets). Save
-	 *    the information in the newbssentry and then insert into the
-	 *    driver scan table either as an update to an existing entry
-	 *    or as an addition at the end of the table
-	 */
-	for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
-		struct bss_descriptor new;
-		struct bss_descriptor *found = NULL;
-		struct bss_descriptor *oldest = NULL;
-
-		/* Process the data fields and IEs returned for this BSS */
-		memset(&new, 0, sizeof (struct bss_descriptor));
-		if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
-			/* error parsing the scan response, skipped */
-			lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
-			continue;
-		}
-
-		/* Try to find this bss in the scan table */
-		list_for_each_entry (iter_bss, &priv->network_list, list) {
-			if (is_same_network(iter_bss, &new)) {
-				found = iter_bss;
-				break;
-			}
-
-			if ((oldest == NULL) ||
-			    (iter_bss->last_scanned < oldest->last_scanned))
-				oldest = iter_bss;
-		}
-
-		if (found) {
-			/* found, clear it */
-			clear_bss_descriptor(found);
-		} else if (!list_empty(&priv->network_free_list)) {
-			/* Pull one from the free list */
-			found = list_entry(priv->network_free_list.next,
-					   struct bss_descriptor, list);
-			list_move_tail(&found->list, &priv->network_list);
-		} else if (oldest) {
-			/* If there are no more slots, expire the oldest */
-			found = oldest;
-			clear_bss_descriptor(found);
-			list_move_tail(&found->list, &priv->network_list);
-		} else {
-			continue;
-		}
-
-		lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
-
-		/* Copy the locally created newbssentry to the scan table */
-		memcpy(found, &new, offsetof(struct bss_descriptor, list));
-	}
-
-	ret = 0;
-
-done:
-	lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
-	return ret;
-}

+ 0 - 63
drivers/net/wireless/libertas/scan.h

@@ -1,63 +0,0 @@
-/**
-  * Interface for the wlan network scan routines
-  *
-  * Driver interface functions and type declarations for the scan module
-  * implemented in scan.c.
-  */
-#ifndef _LBS_SCAN_H
-#define _LBS_SCAN_H
-
-#include <net/iw_handler.h>
-
-struct lbs_private;
-
-#define MAX_NETWORK_COUNT 128
-
-/** Chan-freq-TxPower mapping table*/
-struct chan_freq_power {
-	/** channel Number		*/
-	u16 channel;
-	/** frequency of this channel	*/
-	u32 freq;
-	/** Max allowed Tx power level	*/
-	u16 maxtxpower;
-	/** TRUE:channel unsupported;  FLASE:supported*/
-	u8 unsupported;
-};
-
-/** region-band mapping table*/
-struct region_channel {
-	/** TRUE if this entry is valid		     */
-	u8 valid;
-	/** region code for US, Japan ...	     */
-	u8 region;
-	/** band B/G/A, used for BAND_CONFIG cmd	     */
-	u8 band;
-	/** Actual No. of elements in the array below */
-	u8 nrcfp;
-	/** chan-freq-txpower mapping table*/
-	struct chan_freq_power *CFP;
-};
-
-/**
- *  @brief Maximum number of channels that can be sent in a setuserscan ioctl
- */
-#define LBS_IOCTL_USER_SCAN_CHAN_MAX  50
-
-int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
-
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
-
-int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
-				u8 ssid_len);
-
-int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_point *dwrq, char *extra);
-int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
-			 union iwreq_data *wrqu, char *extra);
-
-int lbs_scan_networks(struct lbs_private *priv, int full_scan);
-
-void lbs_scan_worker(struct work_struct *work);
-
-#endif

+ 7 - 5
drivers/net/wireless/libertas/tx.c

@@ -4,13 +4,13 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/sched.h>
+#include <net/cfg80211.h>
 
 #include "host.h"
 #include "radiotap.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
-#include "wext.h"
 
 /**
  *  @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
@@ -111,7 +111,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	p802x_hdr = skb->data;
 	pkt_len = skb->len;
 
-	if (dev == priv->rtap_net_dev) {
+	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
 		struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
 
 		/* set txpd fields from the radiotap header */
@@ -147,7 +147,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	dev->stats.tx_packets++;
 	dev->stats.tx_bytes += skb->len;
 
-	if (priv->monitormode) {
+	if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
 		/* Keep the skb to echo it back once Tx feedback is
 		   received from FW */
 		skb_orphan(skb);
@@ -158,6 +158,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
  free:
 		dev_kfree_skb_any(skb);
 	}
+
  unlock:
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	wake_up(&priv->waitq);
@@ -179,7 +180,8 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
 {
 	struct tx_radiotap_hdr *radiotap_hdr;
 
-	if (!priv->monitormode || priv->currenttxskb == NULL)
+	if (!priv->wdev->iftype == NL80211_IFTYPE_MONITOR ||
+	    priv->currenttxskb == NULL)
 		return;
 
 	radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
@@ -188,7 +190,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
 		(1 + priv->txretrycount - try_count) : 0;
 
 	priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
-						      priv->rtap_net_dev);
+						      priv->dev);
 	netif_rx(priv->currenttxskb);
 
 	priv->currenttxskb = NULL;

+ 0 - 2353
drivers/net/wireless/libertas/wext.c

@@ -1,2353 +0,0 @@
-/**
-  * This file contains ioctl functions
-  */
-#include <linux/ctype.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/if.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/bitops.h>
-
-#include <net/lib80211.h>
-#include <net/iw_handler.h>
-
-#include "host.h"
-#include "radiotap.h"
-#include "decl.h"
-#include "defs.h"
-#include "dev.h"
-#include "wext.h"
-#include "scan.h"
-#include "assoc.h"
-#include "cmd.h"
-
-
-static inline void lbs_postpone_association_work(struct lbs_private *priv)
-{
-	if (priv->surpriseremoved)
-		return;
-	cancel_delayed_work(&priv->assoc_work);
-	queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
-}
-
-static inline void lbs_do_association_work(struct lbs_private *priv)
-{
-	if (priv->surpriseremoved)
-		return;
-	cancel_delayed_work(&priv->assoc_work);
-	queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
-}
-
-static inline void lbs_cancel_association_work(struct lbs_private *priv)
-{
-	cancel_delayed_work(&priv->assoc_work);
-	kfree(priv->pending_assoc_req);
-	priv->pending_assoc_req = NULL;
-}
-
-void lbs_send_disconnect_notification(struct lbs_private *priv)
-{
-	union iwreq_data wrqu;
-
-	memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
-{
-	union iwreq_data iwrq;
-	u8 buf[50];
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	memset(&iwrq, 0, sizeof(union iwreq_data));
-	memset(buf, 0, sizeof(buf));
-
-	snprintf(buf, sizeof(buf) - 1, "%s", str);
-
-	iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
-
-	/* Send Event to upper layer */
-	lbs_deb_wext("event indication string %s\n", (char *)buf);
-	lbs_deb_wext("event indication length %d\n", iwrq.data.length);
-	lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
-
-	wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-/**
- *  @brief This function handles MIC failure event.
- *
- *  @param priv    A pointer to struct lbs_private structure
- *  @para  event   the event id
- *  @return 	   n/a
- */
-void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
-{
-	char buf[50];
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	memset(buf, 0, sizeof(buf));
-
-	sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
-
-	if (event == MACREG_INT_CODE_MIC_ERR_UNICAST)
-		strcat(buf, "unicast ");
-	else
-		strcat(buf, "multicast ");
-
-	lbs_send_iwevcustom_event(priv, buf);
-	lbs_deb_leave(LBS_DEB_CMD);
-}
-
-/**
- *  @brief Find the channel frequency power info with specific channel
- *
- *  @param priv 	A pointer to struct lbs_private structure
- *  @param band		it can be BAND_A, BAND_G or BAND_B
- *  @param channel      the channel for looking
- *  @return 	   	A pointer to struct chan_freq_power structure or NULL if not find.
- */
-struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
-	struct lbs_private *priv,
-	u8 band,
-	u16 channel)
-{
-	struct chan_freq_power *cfp = NULL;
-	struct region_channel *rc;
-	int i, j;
-
-	for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
-		rc = &priv->region_channel[j];
-
-		if (!rc->valid || !rc->CFP)
-			continue;
-		if (rc->band != band)
-			continue;
-		for (i = 0; i < rc->nrcfp; i++) {
-			if (rc->CFP[i].channel == channel) {
-				cfp = &rc->CFP[i];
-				break;
-			}
-		}
-	}
-
-	if (!cfp && channel)
-		lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find "
-		       "cfp by band %d / channel %d\n", band, channel);
-
-	return cfp;
-}
-
-/**
- *  @brief Find the channel frequency power info with specific frequency
- *
- *  @param priv 	A pointer to struct lbs_private structure
- *  @param band		it can be BAND_A, BAND_G or BAND_B
- *  @param freq	        the frequency for looking
- *  @return 	   	A pointer to struct chan_freq_power structure or NULL if not find.
- */
-static struct chan_freq_power *find_cfp_by_band_and_freq(
-	struct lbs_private *priv,
-	u8 band,
-	u32 freq)
-{
-	struct chan_freq_power *cfp = NULL;
-	struct region_channel *rc;
-	int i, j;
-
-	for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
-		rc = &priv->region_channel[j];
-
-		if (!rc->valid || !rc->CFP)
-			continue;
-		if (rc->band != band)
-			continue;
-		for (i = 0; i < rc->nrcfp; i++) {
-			if (rc->CFP[i].freq == freq) {
-				cfp = &rc->CFP[i];
-				break;
-			}
-		}
-	}
-
-	if (!cfp && freq)
-		lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
-		       "band %d / freq %d\n", band, freq);
-
-	return cfp;
-}
-
-/**
- *  @brief Copy active data rates based on adapter mode and status
- *
- *  @param priv              A pointer to struct lbs_private structure
- *  @param rate		        The buf to return the active rates
- */
-static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
-{
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if ((priv->connect_status != LBS_CONNECTED) &&
-		!lbs_mesh_connected(priv))
-		memcpy(rates, lbs_bg_rates, MAX_RATES);
-	else
-		memcpy(rates, priv->curbssparams.rates, MAX_RATES);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
-			 char *cwrq, char *extra)
-{
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* We could add support for 802.11n here as needed. Jean II */
-	snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_freq *fwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct chan_freq_power *cfp;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
-					   priv->channel);
-
-	if (!cfp) {
-		if (priv->channel)
-			lbs_deb_wext("invalid channel %d\n",
-			       priv->channel);
-		return -EINVAL;
-	}
-
-	fwrq->m = (long)cfp->freq * 100000;
-	fwrq->e = 1;
-
-	lbs_deb_wext("freq %u\n", fwrq->m);
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
-			struct sockaddr *awrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (priv->connect_status == LBS_CONNECTED) {
-		memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
-	} else {
-		memset(awrq->sa_data, 0, ETH_ALEN);
-	}
-	awrq->sa_family = ARPHRD_ETHER;
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/*
-	 * Check the size of the string
-	 */
-
-	if (dwrq->length > 16) {
-		return -E2BIG;
-	}
-
-	mutex_lock(&priv->lock);
-	memset(priv->nodename, 0, sizeof(priv->nodename));
-	memcpy(priv->nodename, extra, dwrq->length);
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	dwrq->length = strlen(priv->nodename);
-	memcpy(extra, priv->nodename, dwrq->length);
-	extra[dwrq->length] = '\0';
-
-	dwrq->flags = 1;	/* active */
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-#ifdef CONFIG_LIBERTAS_MESH
-static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* Use nickname to indicate that mesh is on */
-
-	if (lbs_mesh_connected(priv)) {
-		strncpy(extra, "Mesh", 12);
-		extra[12] = '\0';
-		dwrq->length = strlen(extra);
-	}
-
-	else {
-		extra[0] = '\0';
-		dwrq->length = 0;
-	}
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-#endif
-
-static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
-			struct iw_param *vwrq, char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-	u32 val = vwrq->value;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (vwrq->disabled)
-		val = MRVDRV_RTS_MAX_VALUE;
-
-	if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
-		return -EINVAL;
-
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
-			struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u16 val = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
-	if (ret)
-		goto out;
-
-	vwrq->value = val;
-	vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
-	vwrq->fixed = 1;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u32 val = vwrq->value;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (vwrq->disabled)
-		val = MRVDRV_FRAG_MAX_VALUE;
-
-	if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
-		return -EINVAL;
-
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
-			 struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u16 val = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
-	if (ret)
-		goto out;
-
-	vwrq->value = val;
-	vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
-			  || (val > MRVDRV_FRAG_MAX_VALUE));
-	vwrq->fixed = 1;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_mode(struct net_device *dev,
-			 struct iw_request_info *info, u32 * uwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	*uwrq = priv->mode;
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-#ifdef CONFIG_LIBERTAS_MESH
-static int mesh_wlan_get_mode(struct net_device *dev,
-		              struct iw_request_info *info, u32 * uwrq,
-			      char *extra)
-{
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	*uwrq = IW_MODE_REPEAT;
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-#endif
-
-static int lbs_get_txpow(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	s16 curlevel = 0;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!priv->radio_on) {
-		lbs_deb_wext("tx power off\n");
-		vwrq->value = 0;
-		vwrq->disabled = 1;
-		goto out;
-	}
-
-	ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
-	if (ret)
-		goto out;
-
-	lbs_deb_wext("tx power level %d dbm\n", curlevel);
-	priv->txpower_cur = curlevel;
-
-	vwrq->value = curlevel;
-	vwrq->fixed = 1;
-	vwrq->disabled = 0;
-	vwrq->flags = IW_TXPOW_DBM;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
-			  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u16 slimit = 0, llimit = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-        if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
-                return -EOPNOTSUPP;
-
-	/* The MAC has a 4-bit Total_Tx_Count register
-	   Total_Tx_Count = 1 + Tx_Retry_Count */
-#define TX_RETRY_MIN 0
-#define TX_RETRY_MAX 14
-	if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
-		return -EINVAL;
-
-	/* Add 1 to convert retry count to try count */
-	if (vwrq->flags & IW_RETRY_SHORT)
-		slimit = (u16) (vwrq->value + 1);
-	else if (vwrq->flags & IW_RETRY_LONG)
-		llimit = (u16) (vwrq->value + 1);
-	else
-		slimit = llimit = (u16) (vwrq->value + 1); /* set both */
-
-	if (llimit) {
-		ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
-				       llimit);
-		if (ret)
-			goto out;
-	}
-
-	if (slimit) {
-		/* txretrycount follows the short retry limit */
-		priv->txretrycount = slimit;
-		ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
-				       slimit);
-		if (ret)
-			goto out;
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
-			  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u16 val = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	vwrq->disabled = 0;
-
-	if (vwrq->flags & IW_RETRY_LONG) {
-		ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
-		if (ret)
-			goto out;
-
-		/* Subtract 1 to convert try count to retry count */
-		vwrq->value = val - 1;
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
-	} else {
-		ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
-		if (ret)
-			goto out;
-
-		/* txretry count follows the short retry limit */
-		priv->txretrycount = val;
-		/* Subtract 1 to convert try count to retry count */
-		vwrq->value = val - 1;
-		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
-	}
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static inline void sort_channels(struct iw_freq *freq, int num)
-{
-	int i, j;
-	struct iw_freq temp;
-
-	for (i = 0; i < num; i++)
-		for (j = i + 1; j < num; j++)
-			if (freq[i].i > freq[j].i) {
-				temp.i = freq[i].i;
-				temp.m = freq[i].m;
-
-				freq[i].i = freq[j].i;
-				freq[i].m = freq[j].m;
-
-				freq[j].i = temp.i;
-				freq[j].m = temp.m;
-			}
-}
-
-/* data rate listing
-	MULTI_BANDS:
-		abg		a	b	b/g
-   Infra 	G(12)		A(8)	B(4)	G(12)
-   Adhoc 	A+B(12)		A(8)	B(4)	B(4)
-
-	non-MULTI_BANDS:
-					b	b/g
-   Infra 	     		    	B(4)	G(12)
-   Adhoc 	      		    	B(4)	B(4)
- */
-/**
- *  @brief Get Range Info
- *
- *  @param dev                  A pointer to net_device structure
- *  @param info			A pointer to iw_request_info structure
- *  @param vwrq 		A pointer to iw_param structure
- *  @param extra		A pointer to extra data buf
- *  @return 	   		0 --success, otherwise fail
- */
-static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
-			  struct iw_point *dwrq, char *extra)
-{
-	int i, j;
-	struct lbs_private *priv = dev->ml_priv;
-	struct iw_range *range = (struct iw_range *)extra;
-	struct chan_freq_power *cfp;
-	u8 rates[MAX_RATES + 1];
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	dwrq->length = sizeof(struct iw_range);
-	memset(range, 0, sizeof(struct iw_range));
-
-	range->min_nwid = 0;
-	range->max_nwid = 0;
-
-	memset(rates, 0, sizeof(rates));
-	copy_active_data_rates(priv, rates);
-	range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
-	for (i = 0; i < range->num_bitrates; i++)
-		range->bitrate[i] = rates[i] * 500000;
-	range->num_bitrates = i;
-	lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
-	       range->num_bitrates);
-
-	range->num_frequency = 0;
-
-	range->scan_capa = IW_SCAN_CAPA_ESSID;
-
-	for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-	     && (j < ARRAY_SIZE(priv->region_channel)); j++) {
-		cfp = priv->region_channel[j].CFP;
-		for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-		     && priv->region_channel[j].valid
-		     && cfp
-		     && (i < priv->region_channel[j].nrcfp); i++) {
-			range->freq[range->num_frequency].i =
-			    (long)cfp->channel;
-			range->freq[range->num_frequency].m =
-			    (long)cfp->freq * 100000;
-			range->freq[range->num_frequency].e = 1;
-			cfp++;
-			range->num_frequency++;
-		}
-	}
-
-	lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
-	       IW_MAX_FREQUENCIES, range->num_frequency);
-
-	range->num_channels = range->num_frequency;
-
-	sort_channels(&range->freq[0], range->num_frequency);
-
-	/*
-	 * Set an indication of the max TCP throughput in bit/s that we can
-	 * expect using this interface
-	 */
-	if (i > 2)
-		range->throughput = 5000 * 1000;
-	else
-		range->throughput = 1500 * 1000;
-
-	range->min_rts = MRVDRV_RTS_MIN_VALUE;
-	range->max_rts = MRVDRV_RTS_MAX_VALUE;
-	range->min_frag = MRVDRV_FRAG_MIN_VALUE;
-	range->max_frag = MRVDRV_FRAG_MAX_VALUE;
-
-	range->encoding_size[0] = 5;
-	range->encoding_size[1] = 13;
-	range->num_encoding_sizes = 2;
-	range->max_encoding_tokens = 4;
-
-	/*
-	 * Right now we support only "iwconfig ethX power on|off"
-	 */
-	range->pm_capa = IW_POWER_ON;
-
-	/*
-	 * Minimum version we recommend
-	 */
-	range->we_version_source = 15;
-
-	/*
-	 * Version we are compiled with
-	 */
-	range->we_version_compiled = WIRELESS_EXT;
-
-	range->retry_capa = IW_RETRY_LIMIT;
-	range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
-
-	range->min_retry = TX_RETRY_MIN;
-	range->max_retry = TX_RETRY_MAX;
-
-	/*
-	 * Set the qual, level and noise range values
-	 */
-	range->max_qual.qual = 100;
-	range->max_qual.level = 0;
-	range->max_qual.noise = 0;
-	range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-
-	range->avg_qual.qual = 70;
-	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
-	range->avg_qual.level = 0;
-	range->avg_qual.noise = 0;
-	range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-
-	range->sensitivity = 0;
-
-	/* Setup the supported power level ranges */
-	memset(range->txpower, 0, sizeof(range->txpower));
-	range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
-	range->txpower[0] = priv->txpower_min;
-	range->txpower[1] = priv->txpower_max;
-	range->num_txpower = 2;
-
-	range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
-				IW_EVENT_CAPA_MASK(SIOCGIWAP) |
-				IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
-	range->event_capa[1] = IW_EVENT_CAPA_K_1;
-
-	if (priv->fwcapinfo & FW_CAPINFO_WPA) {
-		range->enc_capa =   IW_ENC_CAPA_WPA
-		                  | IW_ENC_CAPA_WPA2
-		                  | IW_ENC_CAPA_CIPHER_TKIP
-		                  | IW_ENC_CAPA_CIPHER_CCMP;
-	}
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
-			  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
-		if (vwrq->disabled)
-			return 0;
-		else
-			return -EINVAL;
-	}
-
-	/* PS is currently supported only in Infrastructure mode
-	 * Remove this check if it is to be supported in IBSS mode also
-	 */
-
-	if (vwrq->disabled) {
-		priv->psmode = LBS802_11POWERMODECAM;
-		if (priv->psstate != PS_STATE_FULL_POWER) {
-			lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
-		}
-
-		return 0;
-	}
-
-	if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
-		lbs_deb_wext(
-		       "setting power timeout is not supported\n");
-		return -EINVAL;
-	} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
-		vwrq->value = vwrq->value / 1000;
-		if (!priv->enter_deep_sleep) {
-			lbs_pr_err("deep sleep feature is not implemented "
-					"for this interface driver\n");
-			return -EINVAL;
-		}
-
-		if (priv->connect_status == LBS_CONNECTED) {
-			if ((priv->is_auto_deep_sleep_enabled) &&
-						(vwrq->value == -1000)) {
-				lbs_exit_auto_deep_sleep(priv);
-				return 0;
-			} else {
-				lbs_pr_err("can't use deep sleep cmd in "
-						"connected state\n");
-				return -EINVAL;
-			}
-		}
-
-		if ((vwrq->value < 0) && (vwrq->value != -1000)) {
-			lbs_pr_err("unknown option\n");
-			return -EINVAL;
-		}
-
-		if (vwrq->value > 0) {
-			if (!priv->is_auto_deep_sleep_enabled) {
-				priv->is_activity_detected = 0;
-				priv->auto_deep_sleep_timeout = vwrq->value;
-				lbs_enter_auto_deep_sleep(priv);
-			} else {
-				priv->auto_deep_sleep_timeout = vwrq->value;
-				lbs_deb_debugfs("auto deep sleep: "
-						"already enabled\n");
-			}
-			return 0;
-		} else {
-			if (priv->is_auto_deep_sleep_enabled) {
-				lbs_exit_auto_deep_sleep(priv);
-				/* Try to exit deep sleep if auto */
-				/*deep sleep disabled */
-				ret = lbs_set_deep_sleep(priv, 0);
-			}
-			if (vwrq->value == 0)
-				ret = lbs_set_deep_sleep(priv, 1);
-			else if (vwrq->value == -1000)
-				ret = lbs_set_deep_sleep(priv, 0);
-			return ret;
-		}
-	}
-
-	if (priv->psmode != LBS802_11POWERMODECAM) {
-		return 0;
-	}
-
-	priv->psmode = LBS802_11POWERMODEMAX_PSP;
-
-	if (priv->connect_status == LBS_CONNECTED) {
-		lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
-	}
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-
-	return 0;
-}
-
-static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
-			  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	vwrq->value = 0;
-	vwrq->flags = 0;
-	vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
-		|| priv->connect_status == LBS_DISCONNECTED;
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
-{
-	enum {
-		POOR = 30,
-		FAIR = 60,
-		GOOD = 80,
-		VERY_GOOD = 90,
-		EXCELLENT = 95,
-		PERFECT = 100
-	};
-	struct lbs_private *priv = dev->ml_priv;
-	u32 rssi_qual;
-	u32 tx_qual;
-	u32 quality = 0;
-	int ret, stats_valid = 0;
-	u8 rssi;
-	u32 tx_retries;
-	struct cmd_ds_802_11_get_log log;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	priv->wstats.status = priv->mode;
-
-	/* If we're not associated, all quality values are meaningless */
-	if ((priv->connect_status != LBS_CONNECTED) &&
-	    !lbs_mesh_connected(priv))
-		goto out;
-
-	/* Quality by RSSI */
-	priv->wstats.qual.level =
-	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
-	     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
-	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
-		priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
-	} else {
-		priv->wstats.qual.noise =
-		    CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-	}
-
-	lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
-	lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
-
-	rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
-	if (rssi < 15)
-		rssi_qual = rssi * POOR / 10;
-	else if (rssi < 20)
-		rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
-	else if (rssi < 30)
-		rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
-	else if (rssi < 40)
-		rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
-		    10 + GOOD;
-	else
-		rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
-		    10 + VERY_GOOD;
-	quality = rssi_qual;
-
-	/* Quality by TX errors */
-	priv->wstats.discard.retries = dev->stats.tx_errors;
-
-	memset(&log, 0, sizeof(log));
-	log.hdr.size = cpu_to_le16(sizeof(log));
-	ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
-	if (ret)
-		goto out;
-
-	tx_retries = le32_to_cpu(log.retry);
-
-	if (tx_retries > 75)
-		tx_qual = (90 - tx_retries) * POOR / 15;
-	else if (tx_retries > 70)
-		tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
-	else if (tx_retries > 65)
-		tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
-	else if (tx_retries > 50)
-		tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
-		    15 + GOOD;
-	else
-		tx_qual = (50 - tx_retries) *
-		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
-	quality = min(quality, tx_qual);
-
-	priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
-	priv->wstats.discard.retries = tx_retries;
-	priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
-
-	/* Calculate quality */
-	priv->wstats.qual.qual = min_t(u8, quality, 100);
-	priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
-	stats_valid = 1;
-
-	/* update stats asynchronously for future calls */
-	ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
-					0, 0, NULL);
-	if (ret)
-		lbs_pr_err("RSSI command failed\n");
-out:
-	if (!stats_valid) {
-		priv->wstats.miss.beacon = 0;
-		priv->wstats.discard.retries = 0;
-		priv->wstats.qual.qual = 0;
-		priv->wstats.qual.level = 0;
-		priv->wstats.qual.noise = 0;
-		priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
-		priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
-		    IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
-	}
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return &priv->wstats;
-
-
-}
-
-static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
-		  struct iw_freq *fwrq, char *extra)
-{
-	int ret = -EINVAL;
-	struct lbs_private *priv = dev->ml_priv;
-	struct chan_freq_power *cfp;
-	struct assoc_request * assoc_req;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* If setting by frequency, convert to a channel */
-	if (fwrq->e == 1) {
-		long f = fwrq->m / 100000;
-
-		cfp = find_cfp_by_band_and_freq(priv, 0, f);
-		if (!cfp) {
-			lbs_deb_wext("invalid freq %ld\n", f);
-			goto out;
-		}
-
-		fwrq->e = 0;
-		fwrq->m = (int) cfp->channel;
-	}
-
-	/* Setting by channel number */
-	if (fwrq->m > 1000 || fwrq->e > 0) {
-		goto out;
-	}
-
-	cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
-	if (!cfp) {
-		goto out;
-	}
-
-	assoc_req->channel = fwrq->m;
-	ret = 0;
-
-out:
-	if (ret == 0) {
-		set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-	} else {
-		lbs_cancel_association_work(priv);
-	}
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-#ifdef CONFIG_LIBERTAS_MESH
-static int lbs_mesh_set_freq(struct net_device *dev,
-			     struct iw_request_info *info,
-			     struct iw_freq *fwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct chan_freq_power *cfp;
-	int ret = -EINVAL;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* If setting by frequency, convert to a channel */
-	if (fwrq->e == 1) {
-		long f = fwrq->m / 100000;
-
-		cfp = find_cfp_by_band_and_freq(priv, 0, f);
-		if (!cfp) {
-			lbs_deb_wext("invalid freq %ld\n", f);
-			goto out;
-		}
-
-		fwrq->e = 0;
-		fwrq->m = (int) cfp->channel;
-	}
-
-	/* Setting by channel number */
-	if (fwrq->m > 1000 || fwrq->e > 0) {
-		goto out;
-	}
-
-	cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
-	if (!cfp) {
-		goto out;
-	}
-
-	if (fwrq->m != priv->channel) {
-		lbs_deb_wext("mesh channel change forces eth disconnect\n");
-		if (priv->mode == IW_MODE_INFRA)
-			lbs_cmd_80211_deauthenticate(priv,
-						     priv->curbssparams.bssid,
-						     WLAN_REASON_DEAUTH_LEAVING);
-		else if (priv->mode == IW_MODE_ADHOC)
-			lbs_adhoc_stop(priv);
-	}
-	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
-	lbs_update_channel(priv);
-	ret = 0;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-#endif
-
-static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
-		  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	u8 new_rate = 0;
-	int ret = -EINVAL;
-	u8 rates[MAX_RATES + 1];
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	lbs_deb_wext("vwrq->value %d\n", vwrq->value);
-	lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
-
-	if (vwrq->fixed && vwrq->value == -1)
-		goto out;
-
-	/* Auto rate? */
-	priv->enablehwauto = !vwrq->fixed;
-
-	if (vwrq->value == -1)
-		priv->cur_rate = 0;
-	else {
-		if (vwrq->value % 100000)
-			goto out;
-
-		new_rate = vwrq->value / 500000;
-		priv->cur_rate = new_rate;
-		/* the rest is only needed for lbs_set_data_rate() */
-		memset(rates, 0, sizeof(rates));
-		copy_active_data_rates(priv, rates);
-		if (!memchr(rates, new_rate, sizeof(rates))) {
-			lbs_pr_alert("fixed data rate 0x%X out of range\n",
-				new_rate);
-			goto out;
-		}
-		if (priv->fwrelease < 0x09000000) {
-			ret = lbs_set_power_adapt_cfg(priv, 0,
-					POW_ADAPT_DEFAULT_P0,
-					POW_ADAPT_DEFAULT_P1,
-					POW_ADAPT_DEFAULT_P2);
-			if (ret)
-				goto out;
-		}
-		ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
-				TPC_DEFAULT_P2, 1);
-		if (ret)
-			goto out;
-	}
-
-	/* Try the newer command first (Firmware Spec 5.1 and above) */
-	ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET);
-
-	/* Fallback to older version */
-	if (ret)
-		ret = lbs_set_data_rate(priv, new_rate);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
-		  struct iw_param *vwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (priv->connect_status == LBS_CONNECTED) {
-		vwrq->value = priv->cur_rate * 500000;
-
-		if (priv->enablehwauto)
-			vwrq->fixed = 0;
-		else
-			vwrq->fixed = 1;
-
-	} else {
-		vwrq->fixed = 0;
-		vwrq->value = 0;
-	}
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_set_mode(struct net_device *dev,
-		  struct iw_request_info *info, u32 * uwrq, char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-	struct assoc_request * assoc_req;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (   (*uwrq != IW_MODE_ADHOC)
-	    && (*uwrq != IW_MODE_INFRA)
-	    && (*uwrq != IW_MODE_AUTO)) {
-		lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		lbs_cancel_association_work(priv);
-	} else {
-		assoc_req->mode = *uwrq;
-		set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-		lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
-	}
-	mutex_unlock(&priv->lock);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-
-/**
- *  @brief Get Encryption key
- *
- *  @param dev                  A pointer to net_device structure
- *  @param info			A pointer to iw_request_info structure
- *  @param vwrq 		A pointer to iw_param structure
- *  @param extra		A pointer to extra data buf
- *  @return 	   		0 --success, otherwise fail
- */
-static int lbs_get_encode(struct net_device *dev,
-			   struct iw_request_info *info,
-			   struct iw_point *dwrq, u8 * extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
-	       dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx);
-
-	dwrq->flags = 0;
-
-	/* Authentication method */
-	switch (priv->secinfo.auth_mode) {
-	case IW_AUTH_ALG_OPEN_SYSTEM:
-		dwrq->flags = IW_ENCODE_OPEN;
-		break;
-
-	case IW_AUTH_ALG_SHARED_KEY:
-	case IW_AUTH_ALG_LEAP:
-		dwrq->flags = IW_ENCODE_RESTRICTED;
-		break;
-	default:
-		dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
-		break;
-	}
-
-	memset(extra, 0, 16);
-
-	mutex_lock(&priv->lock);
-
-	/* Default to returning current transmit key */
-	if (index < 0)
-		index = priv->wep_tx_keyidx;
-
-	if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) {
-		memcpy(extra, priv->wep_keys[index].key,
-		       priv->wep_keys[index].len);
-		dwrq->length = priv->wep_keys[index].len;
-
-		dwrq->flags |= (index + 1);
-		/* Return WEP enabled */
-		dwrq->flags &= ~IW_ENCODE_DISABLED;
-	} else if ((priv->secinfo.WPAenabled)
-		   || (priv->secinfo.WPA2enabled)) {
-		/* return WPA enabled */
-		dwrq->flags &= ~IW_ENCODE_DISABLED;
-		dwrq->flags |= IW_ENCODE_NOKEY;
-	} else {
-		dwrq->flags |= IW_ENCODE_DISABLED;
-	}
-
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
-	       extra[0], extra[1], extra[2],
-	       extra[3], extra[4], extra[5], dwrq->length);
-
-	lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-/**
- *  @brief Set Encryption key (internal)
- *
- *  @param priv			A pointer to private card structure
- *  @param key_material		A pointer to key material
- *  @param key_length		length of key material
- *  @param index		key index to set
- *  @param set_tx_key		Force set TX key (1 = yes, 0 = no)
- *  @return 	   		0 --success, otherwise fail
- */
-static int lbs_set_wep_key(struct assoc_request *assoc_req,
-			    const char *key_material,
-			    u16 key_length,
-			    u16 index,
-			    int set_tx_key)
-{
-	int ret = 0;
-	struct enc_key *pkey;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* Paranoid validation of key index */
-	if (index > 3) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* validate max key length */
-	if (key_length > KEY_LEN_WEP_104) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	pkey = &assoc_req->wep_keys[index];
-
-	if (key_length > 0) {
-		memset(pkey, 0, sizeof(struct enc_key));
-		pkey->type = KEY_TYPE_ID_WEP;
-
-		/* Standardize the key length */
-		pkey->len = (key_length > KEY_LEN_WEP_40) ?
-		                KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
-		memcpy(pkey->key, key_material, key_length);
-	}
-
-	if (set_tx_key) {
-		/* Ensure the chosen key is valid */
-		if (!pkey->len) {
-			lbs_deb_wext("key not set, so cannot enable it\n");
-			ret = -EINVAL;
-			goto out;
-		}
-		assoc_req->wep_tx_keyidx = index;
-	}
-
-	assoc_req->secinfo.wep_enabled = 1;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int validate_key_index(u16 def_index, u16 raw_index,
-			      u16 *out_index, u16 *is_default)
-{
-	if (!out_index || !is_default)
-		return -EINVAL;
-
-	/* Verify index if present, otherwise use default TX key index */
-	if (raw_index > 0) {
-		if (raw_index > 4)
-			return -EINVAL;
-		*out_index = raw_index - 1;
-	} else {
-		*out_index = def_index;
-		*is_default = 1;
-	}
-	return 0;
-}
-
-static void disable_wep(struct assoc_request *assoc_req)
-{
-	int i;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/* Set Open System auth mode */
-	assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-
-	/* Clear WEP keys and mark WEP as disabled */
-	assoc_req->secinfo.wep_enabled = 0;
-	for (i = 0; i < 4; i++)
-		assoc_req->wep_keys[i].len = 0;
-
-	set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-	set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-static void disable_wpa(struct assoc_request *assoc_req)
-{
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
-	assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
-	set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-
-	memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
-	assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
-	set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-
-	assoc_req->secinfo.WPAenabled = 0;
-	assoc_req->secinfo.WPA2enabled = 0;
-	set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-}
-
-/**
- *  @brief Set Encryption key
- *
- *  @param dev                  A pointer to net_device structure
- *  @param info			A pointer to iw_request_info structure
- *  @param vwrq 		A pointer to iw_param structure
- *  @param extra		A pointer to extra data buf
- *  @return 	   		0 --success, otherwise fail
- */
-static int lbs_set_encode(struct net_device *dev,
-		    struct iw_request_info *info,
-		    struct iw_point *dwrq, char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-	struct assoc_request * assoc_req;
-	u16 is_default = 0, index = 0, set_tx_key = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (dwrq->flags & IW_ENCODE_DISABLED) {
-		disable_wep (assoc_req);
-		disable_wpa (assoc_req);
-		goto out;
-	}
-
-	ret = validate_key_index(assoc_req->wep_tx_keyidx,
-	                         (dwrq->flags & IW_ENCODE_INDEX),
-	                         &index, &is_default);
-	if (ret) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* If WEP isn't enabled, or if there is no key data but a valid
-	 * index, set the TX key.
-	 */
-	if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
-		set_tx_key = 1;
-
-	ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
-	if (ret)
-		goto out;
-
-	if (dwrq->length)
-		set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
-	if (set_tx_key)
-		set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
-
-	if (dwrq->flags & IW_ENCODE_RESTRICTED) {
-		priv->authtype_auto = 0;
-		assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
-	} else if (dwrq->flags & IW_ENCODE_OPEN) {
-		priv->authtype_auto = 0;
-		assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-	}
-
-out:
-	if (ret == 0) {
-		set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-	} else {
-		lbs_cancel_association_work(priv);
-	}
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Get Extended Encryption key (WPA/802.1x and WEP)
- *
- *  @param dev                  A pointer to net_device structure
- *  @param info			A pointer to iw_request_info structure
- *  @param vwrq 		A pointer to iw_param structure
- *  @param extra		A pointer to extra data buf
- *  @return 	   		0 on success, otherwise failure
- */
-static int lbs_get_encodeext(struct net_device *dev,
-			      struct iw_request_info *info,
-			      struct iw_point *dwrq,
-			      char *extra)
-{
-	int ret = -EINVAL;
-	struct lbs_private *priv = dev->ml_priv;
-	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-	int index, max_key_len;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	max_key_len = dwrq->length - sizeof(*ext);
-	if (max_key_len < 0)
-		goto out;
-
-	index = dwrq->flags & IW_ENCODE_INDEX;
-	if (index) {
-		if (index < 1 || index > 4)
-			goto out;
-		index--;
-	} else {
-		index = priv->wep_tx_keyidx;
-	}
-
-	if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
-	    ext->alg != IW_ENCODE_ALG_WEP) {
-		if (index != 0 || priv->mode != IW_MODE_INFRA)
-			goto out;
-	}
-
-	dwrq->flags = index + 1;
-	memset(ext, 0, sizeof(*ext));
-
-	if (   !priv->secinfo.wep_enabled
-	    && !priv->secinfo.WPAenabled
-	    && !priv->secinfo.WPA2enabled) {
-		ext->alg = IW_ENCODE_ALG_NONE;
-		ext->key_len = 0;
-		dwrq->flags |= IW_ENCODE_DISABLED;
-	} else {
-		u8 *key = NULL;
-
-		if (   priv->secinfo.wep_enabled
-		    && !priv->secinfo.WPAenabled
-		    && !priv->secinfo.WPA2enabled) {
-			/* WEP */
-			ext->alg = IW_ENCODE_ALG_WEP;
-			ext->key_len = priv->wep_keys[index].len;
-			key = &priv->wep_keys[index].key[0];
-		} else if (   !priv->secinfo.wep_enabled
-		           && (priv->secinfo.WPAenabled ||
-		               priv->secinfo.WPA2enabled)) {
-			/* WPA */
-			struct enc_key * pkey = NULL;
-
-			if (   priv->wpa_mcast_key.len
-			    && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
-				pkey = &priv->wpa_mcast_key;
-			else if (   priv->wpa_unicast_key.len
-			         && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
-				pkey = &priv->wpa_unicast_key;
-
-			if (pkey) {
-				if (pkey->type == KEY_TYPE_ID_AES) {
-					ext->alg = IW_ENCODE_ALG_CCMP;
-				} else {
-					ext->alg = IW_ENCODE_ALG_TKIP;
-				}
-				ext->key_len = pkey->len;
-				key = &pkey->key[0];
-			} else {
-				ext->alg = IW_ENCODE_ALG_TKIP;
-				ext->key_len = 0;
-			}
-		} else {
-			goto out;
-		}
-
-		if (ext->key_len > max_key_len) {
-			ret = -E2BIG;
-			goto out;
-		}
-
-		if (ext->key_len)
-			memcpy(ext->key, key, ext->key_len);
-		else
-			dwrq->flags |= IW_ENCODE_NOKEY;
-		dwrq->flags |= IW_ENCODE_ENABLED;
-	}
-	ret = 0;
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief Set Encryption key Extended (WPA/802.1x and WEP)
- *
- *  @param dev                  A pointer to net_device structure
- *  @param info			A pointer to iw_request_info structure
- *  @param vwrq 		A pointer to iw_param structure
- *  @param extra		A pointer to extra data buf
- *  @return 	   		0 --success, otherwise fail
- */
-static int lbs_set_encodeext(struct net_device *dev,
-			      struct iw_request_info *info,
-			      struct iw_point *dwrq,
-			      char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-	struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
-	int alg = ext->alg;
-	struct assoc_request * assoc_req;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
-		disable_wep (assoc_req);
-		disable_wpa (assoc_req);
-	} else if (alg == IW_ENCODE_ALG_WEP) {
-		u16 is_default = 0, index, set_tx_key = 0;
-
-		ret = validate_key_index(assoc_req->wep_tx_keyidx,
-		                         (dwrq->flags & IW_ENCODE_INDEX),
-		                         &index, &is_default);
-		if (ret)
-			goto out;
-
-		/* If WEP isn't enabled, or if there is no key data but a valid
-		 * index, or if the set-TX-key flag was passed, set the TX key.
-		 */
-		if (   !assoc_req->secinfo.wep_enabled
-		    || (dwrq->length == 0 && !is_default)
-		    || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
-			set_tx_key = 1;
-
-		/* Copy key to driver */
-		ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index,
-					set_tx_key);
-		if (ret)
-			goto out;
-
-		if (dwrq->flags & IW_ENCODE_RESTRICTED) {
-			priv->authtype_auto = 0;
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
-		} else if (dwrq->flags & IW_ENCODE_OPEN) {
-			priv->authtype_auto = 0;
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-		}
-
-		/* Mark the various WEP bits as modified */
-		set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-		if (dwrq->length)
-			set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
-		if (set_tx_key)
-			set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
-	} else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
-		struct enc_key * pkey;
-
-		/* validate key length */
-		if (((alg == IW_ENCODE_ALG_TKIP)
-			&& (ext->key_len != KEY_LEN_WPA_TKIP))
-		    || ((alg == IW_ENCODE_ALG_CCMP)
-		        && (ext->key_len != KEY_LEN_WPA_AES))) {
-				lbs_deb_wext("invalid size %d for key of alg "
-				       "type %d\n",
-				       ext->key_len,
-				       alg);
-				ret = -EINVAL;
-				goto out;
-		}
-
-		if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
-			pkey = &assoc_req->wpa_mcast_key;
-			set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
-		} else {
-			pkey = &assoc_req->wpa_unicast_key;
-			set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
-		}
-
-		memset(pkey, 0, sizeof (struct enc_key));
-		memcpy(pkey->key, ext->key, ext->key_len);
-		pkey->len = ext->key_len;
-		if (pkey->len)
-			pkey->flags |= KEY_INFO_WPA_ENABLED;
-
-		/* Do this after zeroing key structure */
-		if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
-			pkey->flags |= KEY_INFO_WPA_MCAST;
-		} else {
-			pkey->flags |= KEY_INFO_WPA_UNICAST;
-		}
-
-		if (alg == IW_ENCODE_ALG_TKIP) {
-			pkey->type = KEY_TYPE_ID_TKIP;
-		} else if (alg == IW_ENCODE_ALG_CCMP) {
-			pkey->type = KEY_TYPE_ID_AES;
-		}
-
-		/* If WPA isn't enabled yet, do that now */
-		if (   assoc_req->secinfo.WPAenabled == 0
-		    && assoc_req->secinfo.WPA2enabled == 0) {
-			assoc_req->secinfo.WPAenabled = 1;
-			assoc_req->secinfo.WPA2enabled = 1;
-			set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-		}
-
-		/* Only disable wep if necessary: can't waste time here. */
-		if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
-			disable_wep(assoc_req);
-	}
-
-out:
-	if (ret == 0) {
-		/* 802.1x and WPA rekeying must happen as quickly as possible,
-		 * especially during the 4-way handshake; thus if in
-		 * infrastructure mode, and either (a) 802.1x is enabled or
-		 * (b) WPA is being used, set the key right away.
-		 */
-		if (assoc_req->mode == IW_MODE_INFRA &&
-		    ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
-		     (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
-		      assoc_req->secinfo.WPAenabled ||
-		      assoc_req->secinfo.WPA2enabled)) {
-			lbs_do_association_work(priv);
-		} else
-			lbs_postpone_association_work(priv);
-	} else {
-		lbs_cancel_association_work(priv);
-	}
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-
-static int lbs_set_genie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *dwrq,
-			  char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	struct assoc_request * assoc_req;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (dwrq->length > MAX_WPA_IE_LEN ||
-	    (dwrq->length && extra == NULL)) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (dwrq->length) {
-		memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
-		assoc_req->wpa_ie_len = dwrq->length;
-	} else {
-		memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie));
-		assoc_req->wpa_ie_len = 0;
-	}
-
-out:
-	if (ret == 0) {
-		set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-	} else {
-		lbs_cancel_association_work(priv);
-	}
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_genie(struct net_device *dev,
-			  struct iw_request_info *info,
-			  struct iw_point *dwrq,
-			  char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (priv->wpa_ie_len == 0) {
-		dwrq->length = 0;
-		goto out;
-	}
-
-	if (dwrq->length < priv->wpa_ie_len) {
-		ret = -E2BIG;
-		goto out;
-	}
-
-	dwrq->length = priv->wpa_ie_len;
-	memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-
-static int lbs_set_auth(struct net_device *dev,
-			 struct iw_request_info *info,
-			 struct iw_param *dwrq,
-			 char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct assoc_request * assoc_req;
-	int ret = 0;
-	int updated = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	mutex_lock(&priv->lock);
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	switch (dwrq->flags & IW_AUTH_INDEX) {
-	case IW_AUTH_PRIVACY_INVOKED:
-	case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-	case IW_AUTH_TKIP_COUNTERMEASURES:
-	case IW_AUTH_CIPHER_PAIRWISE:
-	case IW_AUTH_CIPHER_GROUP:
-	case IW_AUTH_DROP_UNENCRYPTED:
-		/*
-		 * libertas does not use these parameters
-		 */
-		break;
-
-	case IW_AUTH_KEY_MGMT:
-		assoc_req->secinfo.key_mgmt = dwrq->value;
-		updated = 1;
-		break;
-
-	case IW_AUTH_WPA_VERSION:
-		if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
-			assoc_req->secinfo.WPAenabled = 0;
-			assoc_req->secinfo.WPA2enabled = 0;
-			disable_wpa (assoc_req);
-		}
-		if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
-			assoc_req->secinfo.WPAenabled = 1;
-			assoc_req->secinfo.wep_enabled = 0;
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-		}
-		if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
-			assoc_req->secinfo.WPA2enabled = 1;
-			assoc_req->secinfo.wep_enabled = 0;
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-		}
-		updated = 1;
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
-		} else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-		} else if (dwrq->value & IW_AUTH_ALG_LEAP) {
-			assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
-		} else {
-			ret = -EINVAL;
-		}
-		updated = 1;
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		if (dwrq->value) {
-			if (!assoc_req->secinfo.WPAenabled &&
-			    !assoc_req->secinfo.WPA2enabled) {
-				assoc_req->secinfo.WPAenabled = 1;
-				assoc_req->secinfo.WPA2enabled = 1;
-				assoc_req->secinfo.wep_enabled = 0;
-				assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
-			}
-		} else {
-			assoc_req->secinfo.WPAenabled = 0;
-			assoc_req->secinfo.WPA2enabled = 0;
-			disable_wpa (assoc_req);
-		}
-		updated = 1;
-		break;
-
-	default:
-		ret = -EOPNOTSUPP;
-		break;
-	}
-
-out:
-	if (ret == 0) {
-		if (updated)
-			set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-	} else if (ret != -EOPNOTSUPP) {
-		lbs_cancel_association_work(priv);
-	}
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_auth(struct net_device *dev,
-			 struct iw_request_info *info,
-			 struct iw_param *dwrq,
-			 char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	switch (dwrq->flags & IW_AUTH_INDEX) {
-	case IW_AUTH_KEY_MGMT:
-		dwrq->value = priv->secinfo.key_mgmt;
-		break;
-
-	case IW_AUTH_WPA_VERSION:
-		dwrq->value = 0;
-		if (priv->secinfo.WPAenabled)
-			dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
-		if (priv->secinfo.WPA2enabled)
-			dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
-		if (!dwrq->value)
-			dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
-		break;
-
-	case IW_AUTH_80211_AUTH_ALG:
-		dwrq->value = priv->secinfo.auth_mode;
-		break;
-
-	case IW_AUTH_WPA_ENABLED:
-		if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
-			dwrq->value = 1;
-		break;
-
-	default:
-		ret = -EOPNOTSUPP;
-	}
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-
-static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
-		   struct iw_param *vwrq, char *extra)
-{
-	int ret = 0;
-	struct lbs_private *priv = dev->ml_priv;
-	s16 dbm = (s16) vwrq->value;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (vwrq->disabled) {
-		lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
-		goto out;
-	}
-
-	if (vwrq->fixed == 0) {
-		/* User requests automatic tx power control, however there are
-		 * many auto tx settings.  For now use firmware defaults until
-		 * we come up with a good way to expose these to the user. */
-		if (priv->fwrelease < 0x09000000) {
-			ret = lbs_set_power_adapt_cfg(priv, 1,
-					POW_ADAPT_DEFAULT_P0,
-					POW_ADAPT_DEFAULT_P1,
-					POW_ADAPT_DEFAULT_P2);
-			if (ret)
-				goto out;
-		}
-		ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
-				TPC_DEFAULT_P2, 1);
-		if (ret)
-			goto out;
-		dbm = priv->txpower_max;
-	} else {
-		/* Userspace check in iwrange if it should use dBm or mW,
-		 * therefore this should never happen... Jean II */
-		if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
-			ret = -EOPNOTSUPP;
-			goto out;
-		}
-
-		/* Validate requested power level against firmware allowed
-		 * levels */
-		if (priv->txpower_min && (dbm < priv->txpower_min)) {
-			ret = -EINVAL;
-			goto out;
-		}
-
-		if (priv->txpower_max && (dbm > priv->txpower_max)) {
-			ret = -EINVAL;
-			goto out;
-		}
-		if (priv->fwrelease < 0x09000000) {
-			ret = lbs_set_power_adapt_cfg(priv, 0,
-					POW_ADAPT_DEFAULT_P0,
-					POW_ADAPT_DEFAULT_P1,
-					POW_ADAPT_DEFAULT_P2);
-			if (ret)
-				goto out;
-		}
-		ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
-				TPC_DEFAULT_P2, 1);
-		if (ret)
-			goto out;
-	}
-
-	/* If the radio was off, turn it on */
-	if (!priv->radio_on) {
-		ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
-		if (ret)
-			goto out;
-	}
-
-	lbs_deb_wext("txpower set %d dBm\n", dbm);
-
-	ret = lbs_set_tx_power(priv, dbm);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
-		   struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	/*
-	 * Note : if dwrq->flags != 0, we should get the relevant SSID from
-	 * the SSID list...
-	 */
-
-	/*
-	 * Get the current SSID
-	 */
-	if (priv->connect_status == LBS_CONNECTED) {
-		memcpy(extra, priv->curbssparams.ssid,
-		       priv->curbssparams.ssid_len);
-	} else {
-		memset(extra, 0, 32);
-	}
-	/*
-	 * If none, we may want to get the one that was set
-	 */
-
-	dwrq->length = priv->curbssparams.ssid_len;
-
-	dwrq->flags = 1;	/* active */
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
-		   struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-	u8 ssid[IEEE80211_MAX_SSID_LEN];
-	u8 ssid_len = 0;
-	struct assoc_request * assoc_req;
-	int in_ssid_len = dwrq->length;
-	DECLARE_SSID_BUF(ssid_buf);
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!priv->radio_on) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* Check the size of the string */
-	if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
-		ret = -E2BIG;
-		goto out;
-	}
-
-	memset(&ssid, 0, sizeof(ssid));
-
-	if (!dwrq->flags || !in_ssid_len) {
-		/* "any" SSID requested; leave SSID blank */
-	} else {
-		/* Specific SSID requested */
-		memcpy(&ssid, extra, in_ssid_len);
-		ssid_len = in_ssid_len;
-	}
-
-	if (!ssid_len) {
-		lbs_deb_wext("requested any SSID\n");
-	} else {
-		lbs_deb_wext("requested SSID '%s'\n",
-		             print_ssid(ssid_buf, ssid, ssid_len));
-	}
-
-out:
-	mutex_lock(&priv->lock);
-	if (ret == 0) {
-		/* Get or create the current association request */
-		assoc_req = lbs_get_association_request(priv);
-		if (!assoc_req) {
-			ret = -ENOMEM;
-		} else {
-			/* Copy the SSID to the association request */
-			memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
-			assoc_req->ssid_len = ssid_len;
-			set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
-			lbs_postpone_association_work(priv);
-		}
-	}
-
-	/* Cancel the association request if there was an error */
-	if (ret != 0) {
-		lbs_cancel_association_work(priv);
-	}
-
-	mutex_unlock(&priv->lock);
-
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-
-#ifdef CONFIG_LIBERTAS_MESH
-static int lbs_mesh_get_essid(struct net_device *dev,
-			      struct iw_request_info *info,
-			      struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len);
-
-	dwrq->length = priv->mesh_ssid_len;
-
-	dwrq->flags = 1;	/* active */
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-	return 0;
-}
-
-static int lbs_mesh_set_essid(struct net_device *dev,
-			      struct iw_request_info *info,
-			      struct iw_point *dwrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!priv->radio_on) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	/* Check the size of the string */
-	if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
-		ret = -E2BIG;
-		goto out;
-	}
-
-	if (!dwrq->flags || !dwrq->length) {
-		ret = -EINVAL;
-		goto out;
-	} else {
-		/* Specific SSID requested */
-		memcpy(priv->mesh_ssid, extra, dwrq->length);
-		priv->mesh_ssid_len = dwrq->length;
-	}
-
-	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-			priv->channel);
- out:
-	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
-	return ret;
-}
-#endif
-
-/**
- *  @brief Connect to the AP or Ad-hoc Network with specific bssid
- *
- *  @param dev          A pointer to net_device structure
- *  @param info         A pointer to iw_request_info structure
- *  @param awrq         A pointer to iw_param structure
- *  @param extra        A pointer to extra data buf
- *  @return             0 --success, otherwise fail
- */
-static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
-		 struct sockaddr *awrq, char *extra)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct assoc_request * assoc_req;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	if (!priv->radio_on)
-		return -EINVAL;
-
-	if (awrq->sa_family != ARPHRD_ETHER)
-		return -EINVAL;
-
-	lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
-
-	mutex_lock(&priv->lock);
-
-	/* Get or create the current association request */
-	assoc_req = lbs_get_association_request(priv);
-	if (!assoc_req) {
-		lbs_cancel_association_work(priv);
-		ret = -ENOMEM;
-	} else {
-		/* Copy the BSSID to the association request */
-		memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
-		set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
-		lbs_postpone_association_work(priv);
-	}
-
-	mutex_unlock(&priv->lock);
-
-	return ret;
-}
-
-/*
- * iwconfig settable callbacks
- */
-static const iw_handler lbs_handler[] = {
-	(iw_handler) NULL,	/* SIOCSIWCOMMIT */
-	(iw_handler) lbs_get_name,	/* SIOCGIWNAME */
-	(iw_handler) NULL,	/* SIOCSIWNWID */
-	(iw_handler) NULL,	/* SIOCGIWNWID */
-	(iw_handler) lbs_set_freq,	/* SIOCSIWFREQ */
-	(iw_handler) lbs_get_freq,	/* SIOCGIWFREQ */
-	(iw_handler) lbs_set_mode,	/* SIOCSIWMODE */
-	(iw_handler) lbs_get_mode,	/* SIOCGIWMODE */
-	(iw_handler) NULL,	/* SIOCSIWSENS */
-	(iw_handler) NULL,	/* SIOCGIWSENS */
-	(iw_handler) NULL,	/* SIOCSIWRANGE */
-	(iw_handler) lbs_get_range,	/* SIOCGIWRANGE */
-	(iw_handler) NULL,	/* SIOCSIWPRIV */
-	(iw_handler) NULL,	/* SIOCGIWPRIV */
-	(iw_handler) NULL,	/* SIOCSIWSTATS */
-	(iw_handler) NULL,	/* SIOCGIWSTATS */
-	iw_handler_set_spy,	/* SIOCSIWSPY */
-	iw_handler_get_spy,	/* SIOCGIWSPY */
-	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
-	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
-	(iw_handler) lbs_set_wap,	/* SIOCSIWAP */
-	(iw_handler) lbs_get_wap,	/* SIOCGIWAP */
-	(iw_handler) NULL,	/* SIOCSIWMLME */
-	(iw_handler) NULL,	/* SIOCGIWAPLIST - deprecated */
-	(iw_handler) lbs_set_scan,	/* SIOCSIWSCAN */
-	(iw_handler) lbs_get_scan,	/* SIOCGIWSCAN */
-	(iw_handler) lbs_set_essid,	/* SIOCSIWESSID */
-	(iw_handler) lbs_get_essid,	/* SIOCGIWESSID */
-	(iw_handler) lbs_set_nick,	/* SIOCSIWNICKN */
-	(iw_handler) lbs_get_nick,	/* SIOCGIWNICKN */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) lbs_set_rate,	/* SIOCSIWRATE */
-	(iw_handler) lbs_get_rate,	/* SIOCGIWRATE */
-	(iw_handler) lbs_set_rts,	/* SIOCSIWRTS */
-	(iw_handler) lbs_get_rts,	/* SIOCGIWRTS */
-	(iw_handler) lbs_set_frag,	/* SIOCSIWFRAG */
-	(iw_handler) lbs_get_frag,	/* SIOCGIWFRAG */
-	(iw_handler) lbs_set_txpow,	/* SIOCSIWTXPOW */
-	(iw_handler) lbs_get_txpow,	/* SIOCGIWTXPOW */
-	(iw_handler) lbs_set_retry,	/* SIOCSIWRETRY */
-	(iw_handler) lbs_get_retry,	/* SIOCGIWRETRY */
-	(iw_handler) lbs_set_encode,	/* SIOCSIWENCODE */
-	(iw_handler) lbs_get_encode,	/* SIOCGIWENCODE */
-	(iw_handler) lbs_set_power,	/* SIOCSIWPOWER */
-	(iw_handler) lbs_get_power,	/* SIOCGIWPOWER */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) lbs_set_genie,	/* SIOCSIWGENIE */
-	(iw_handler) lbs_get_genie,	/* SIOCGIWGENIE */
-	(iw_handler) lbs_set_auth,	/* SIOCSIWAUTH */
-	(iw_handler) lbs_get_auth,	/* SIOCGIWAUTH */
-	(iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
-	(iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
-	(iw_handler) NULL,		/* SIOCSIWPMKSA */
-};
-struct iw_handler_def lbs_handler_def = {
-	.num_standard	= ARRAY_SIZE(lbs_handler),
-	.standard	= (iw_handler *) lbs_handler,
-	.get_wireless_stats = lbs_get_wireless_stats,
-};
-
-#ifdef CONFIG_LIBERTAS_MESH
-static const iw_handler mesh_wlan_handler[] = {
-	(iw_handler) NULL,	/* SIOCSIWCOMMIT */
-	(iw_handler) lbs_get_name,	/* SIOCGIWNAME */
-	(iw_handler) NULL,	/* SIOCSIWNWID */
-	(iw_handler) NULL,	/* SIOCGIWNWID */
-	(iw_handler) lbs_mesh_set_freq,	/* SIOCSIWFREQ */
-	(iw_handler) lbs_get_freq,	/* SIOCGIWFREQ */
-	(iw_handler) NULL,		/* SIOCSIWMODE */
-	(iw_handler) mesh_wlan_get_mode,	/* SIOCGIWMODE */
-	(iw_handler) NULL,	/* SIOCSIWSENS */
-	(iw_handler) NULL,	/* SIOCGIWSENS */
-	(iw_handler) NULL,	/* SIOCSIWRANGE */
-	(iw_handler) lbs_get_range,	/* SIOCGIWRANGE */
-	(iw_handler) NULL,	/* SIOCSIWPRIV */
-	(iw_handler) NULL,	/* SIOCGIWPRIV */
-	(iw_handler) NULL,	/* SIOCSIWSTATS */
-	(iw_handler) NULL,	/* SIOCGIWSTATS */
-	iw_handler_set_spy,	/* SIOCSIWSPY */
-	iw_handler_get_spy,	/* SIOCGIWSPY */
-	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
-	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
-	(iw_handler) NULL,	/* SIOCSIWAP */
-	(iw_handler) NULL,	/* SIOCGIWAP */
-	(iw_handler) NULL,	/* SIOCSIWMLME */
-	(iw_handler) NULL,	/* SIOCGIWAPLIST - deprecated */
-	(iw_handler) lbs_set_scan,	/* SIOCSIWSCAN */
-	(iw_handler) lbs_get_scan,	/* SIOCGIWSCAN */
-	(iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
-	(iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
-	(iw_handler) NULL,		/* SIOCSIWNICKN */
-	(iw_handler) mesh_get_nick,	/* SIOCGIWNICKN */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) lbs_set_rate,	/* SIOCSIWRATE */
-	(iw_handler) lbs_get_rate,	/* SIOCGIWRATE */
-	(iw_handler) lbs_set_rts,	/* SIOCSIWRTS */
-	(iw_handler) lbs_get_rts,	/* SIOCGIWRTS */
-	(iw_handler) lbs_set_frag,	/* SIOCSIWFRAG */
-	(iw_handler) lbs_get_frag,	/* SIOCGIWFRAG */
-	(iw_handler) lbs_set_txpow,	/* SIOCSIWTXPOW */
-	(iw_handler) lbs_get_txpow,	/* SIOCGIWTXPOW */
-	(iw_handler) lbs_set_retry,	/* SIOCSIWRETRY */
-	(iw_handler) lbs_get_retry,	/* SIOCGIWRETRY */
-	(iw_handler) lbs_set_encode,	/* SIOCSIWENCODE */
-	(iw_handler) lbs_get_encode,	/* SIOCGIWENCODE */
-	(iw_handler) lbs_set_power,	/* SIOCSIWPOWER */
-	(iw_handler) lbs_get_power,	/* SIOCGIWPOWER */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) NULL,	/* -- hole -- */
-	(iw_handler) lbs_set_genie,	/* SIOCSIWGENIE */
-	(iw_handler) lbs_get_genie,	/* SIOCGIWGENIE */
-	(iw_handler) lbs_set_auth,	/* SIOCSIWAUTH */
-	(iw_handler) lbs_get_auth,	/* SIOCGIWAUTH */
-	(iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
-	(iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
-	(iw_handler) NULL,		/* SIOCSIWPMKSA */
-};
-
-struct iw_handler_def mesh_handler_def = {
-	.num_standard	= ARRAY_SIZE(mesh_wlan_handler),
-	.standard	= (iw_handler *) mesh_wlan_handler,
-	.get_wireless_stats = lbs_get_wireless_stats,
-};
-#endif

+ 0 - 17
drivers/net/wireless/libertas/wext.h

@@ -1,17 +0,0 @@
-/**
-  * This file contains definition for IOCTL call.
-  */
-#ifndef	_LBS_WEXT_H_
-#define	_LBS_WEXT_H_
-
-void lbs_send_disconnect_notification(struct lbs_private *priv);
-void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
-
-struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
-	struct lbs_private *priv,
-	u8 band,
-	u16 channel);
-
-extern struct iw_handler_def lbs_handler_def;
-
-#endif

+ 5 - 0
drivers/net/wireless/mac80211_hwsim.c

@@ -1291,6 +1291,11 @@ static int __init init_mac80211_hwsim(void)
 		hw->wiphy->n_addresses = 2;
 		hw->wiphy->addresses = data->addresses;
 
+		if (fake_hw_scan) {
+			hw->wiphy->max_scan_ssids = 255;
+			hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
+		}
+
 		hw->channel_change_time = 1;
 		hw->queues = 4;
 		hw->wiphy->interface_modes =

+ 13 - 7
drivers/net/wireless/rndis_wlan.c

@@ -520,8 +520,9 @@ static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
 
 static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
 
-static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
-				int dbm);
+static int rndis_set_tx_power(struct wiphy *wiphy,
+			      enum nl80211_tx_power_setting type,
+			      int mbm);
 static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm);
 
 static int rndis_connect(struct wiphy *wiphy, struct net_device *dev,
@@ -1856,20 +1857,25 @@ static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 	return 0;
 }
 
-static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type,
-				int dbm)
+static int rndis_set_tx_power(struct wiphy *wiphy,
+			      enum nl80211_tx_power_setting type,
+			      int mbm)
 {
 	struct rndis_wlan_private *priv = wiphy_priv(wiphy);
 	struct usbnet *usbdev = priv->usbdev;
 
-	netdev_dbg(usbdev->net, "%s(): type:0x%x dbm:%i\n",
-		   __func__, type, dbm);
+	netdev_dbg(usbdev->net, "%s(): type:0x%x mbm:%i\n",
+		   __func__, type, mbm);
+
+	if (mbm < 0 || (mbm % 100))
+		return -ENOTSUPP;
 
 	/* Device doesn't support changing txpower after initialization, only
 	 * turn off/on radio. Support 'auto' mode and setting same dBm that is
 	 * currently used.
 	 */
-	if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) {
+	if (type == NL80211_TX_POWER_AUTOMATIC ||
+	    MBM_TO_DBM(mbm) == get_bcm4320_power_dbm(priv)) {
 		if (!priv->radio_on)
 			disassociate(usbdev, true); /* turn on radio */
 

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

@@ -1229,7 +1229,7 @@ static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 		}
 		txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
 
-		rt2x00pci_txdone(entry, &txdesc);
+		rt2x00lib_txdone(entry, &txdesc);
 	}
 }
 
@@ -1588,7 +1588,6 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 	.reset_tuner		= rt2400pci_reset_tuner,
 	.link_tuner		= rt2400pci_link_tuner,
 	.write_tx_desc		= rt2400pci_write_tx_desc,
-	.write_tx_data		= rt2x00pci_write_tx_data,
 	.write_beacon		= rt2400pci_write_beacon,
 	.kick_tx_queue		= rt2400pci_kick_tx_queue,
 	.kill_tx_queue		= rt2400pci_kill_tx_queue,

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

@@ -1365,7 +1365,7 @@ static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 		}
 		txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT);
 
-		rt2x00pci_txdone(entry, &txdesc);
+		rt2x00lib_txdone(entry, &txdesc);
 	}
 }
 
@@ -1886,7 +1886,6 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 	.reset_tuner		= rt2500pci_reset_tuner,
 	.link_tuner		= rt2500pci_link_tuner,
 	.write_tx_desc		= rt2500pci_write_tx_desc,
-	.write_tx_data		= rt2x00pci_write_tx_data,
 	.write_beacon		= rt2500pci_write_beacon,
 	.kick_tx_queue		= rt2500pci_kick_tx_queue,
 	.kill_tx_queue		= rt2500pci_kill_tx_queue,

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

@@ -347,6 +347,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
 {
 	u32 mask;
 	u16 reg;
+	enum cipher curr_cipher;
 
 	if (crypto->cmd == SET_KEY) {
 		/*
@@ -357,6 +358,7 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
 		mask = TXRX_CSR0_KEY_ID.bit_mask;
 
 		rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+		curr_cipher = rt2x00_get_field16(reg, TXRX_CSR0_ALGORITHM);
 		reg &= mask;
 
 		if (reg && reg == mask)
@@ -365,6 +367,14 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
 		reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
 
 		key->hw_key_idx += reg ? ffz(reg) : 0;
+		/*
+		 * Hardware requires that all keys use the same cipher
+		 * (e.g. TKIP-only, AES-only, but not TKIP+AES).
+		 * If this is not the first key, compare the cipher with the
+		 * first one and fall back to SW crypto if not the same.
+		 */
+		if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
+			return -EOPNOTSUPP;
 
 		rt2500usb_register_multiwrite(rt2x00dev, reg,
 					      crypto->key, sizeof(crypto->key));
@@ -1769,7 +1779,6 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
 	.link_stats		= rt2500usb_link_stats,
 	.reset_tuner		= rt2500usb_reset_tuner,
 	.write_tx_desc		= rt2500usb_write_tx_desc,
-	.write_tx_data		= rt2x00usb_write_tx_data,
 	.write_beacon		= rt2500usb_write_beacon,
 	.get_tx_data_len	= rt2500usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,

+ 73 - 31
drivers/net/wireless/rt2x00/rt2800lib.c

@@ -99,8 +99,7 @@ static void rt2800_bbp_write(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 0);
-		if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
-			rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
 
 		rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
 	}
@@ -128,8 +127,7 @@ static void rt2800_bbp_read(struct rt2x00_dev *rt2x00dev,
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_REGNUM, word);
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_BUSY, 1);
 		rt2x00_set_field32(&reg, BBP_CSR_CFG_READ_CONTROL, 1);
-		if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
-			rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
+		rt2x00_set_field32(&reg, BBP_CSR_CFG_BBP_RW_MODE, 1);
 
 		rt2800_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg);
 
@@ -432,6 +430,20 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc)
 }
 EXPORT_SYMBOL(rt2800_write_beacon);
 
+static void inline rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
+				       unsigned int beacon_base)
+{
+	int i;
+
+	/*
+	 * For the Beacon base registers we only need to clear
+	 * the whole TXWI which (when set to 0) will invalidate
+	 * the entire beacon.
+	 */
+	for (i = 0; i < TXWI_DESC_SIZE; i += sizeof(__le32))
+		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
+}
+
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 const struct rt2x00debug rt2800_rt2x00debug = {
 	.owner	= THIS_MODULE,
@@ -733,19 +745,14 @@ EXPORT_SYMBOL_GPL(rt2800_config_filter);
 void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 			struct rt2x00intf_conf *conf, const unsigned int flags)
 {
-	unsigned int beacon_base;
 	u32 reg;
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
 		 * Clear current synchronisation setup.
-		 * For the Beacon base registers we only need to clear
-		 * the first byte since that byte contains the VALID and OWNER
-		 * bits which (when set to 0) will invalidate the entire beacon.
 		 */
-		beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-		rt2800_register_write(rt2x00dev, beacon_base, 0);
-
+		rt2800_clear_beacon(rt2x00dev,
+				    HW_BEACON_OFFSET(intf->beacon->entry_idx));
 		/*
 		 * Enable synchronisation.
 		 */
@@ -768,8 +775,8 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
 
 	if (flags & CONFIG_UPDATE_BSSID) {
 		reg = le32_to_cpu(conf->bssid[1]);
-		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 0);
-		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 0);
+		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_ID_MASK, 3);
+		rt2x00_set_field32(&reg, MAC_BSSID_DW1_BSS_BCN_NUM, 7);
 		conf->bssid[1] = cpu_to_le32(reg);
 
 		rt2800_register_multiwrite(rt2x00dev, MAC_BSSID_DW0,
@@ -827,14 +834,12 @@ void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 	switch ((int)ant->tx) {
 	case 1:
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
-		if (rt2x00_is_pci(rt2x00dev) || rt2x00_is_soc(rt2x00dev))
-			rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
 		break;
 	case 2:
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2);
 		break;
 	case 3:
-		/* Do nothing */
+		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
 		break;
 	}
 
@@ -1565,18 +1570,15 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
 
 	/*
 	 * Clear all beacons
-	 * For the Beacon base registers we only need to clear
-	 * the first byte since that byte contains the VALID and OWNER
-	 * bits which (when set to 0) will invalidate the entire beacon.
 	 */
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE4, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE5, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE6, 0);
-	rt2800_register_write(rt2x00dev, HW_BEACON_BASE7, 0);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
+	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
 
 	if (rt2x00_is_usb(rt2x00dev)) {
 		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
@@ -2185,6 +2187,8 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0);
 		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0);
 		rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_ANT_DIVERSITY, 0);
+		rt2x00_set_field16(&word, EEPROM_NIC_DAC_TEST, 0);
 		rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word);
 		EEPROM(rt2x00dev, "NIC: 0x%04x\n", word);
 	}
@@ -2192,6 +2196,10 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word);
 	if ((word & 0x00ff) == 0x00ff) {
 		rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0);
+		rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word);
+		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+	}
+	if ((word & 0xff00) == 0xff00) {
 		rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE,
 				   LED_MODE_TXRX_ACTIVITY);
 		rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0);
@@ -2199,7 +2207,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555);
 		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221);
 		rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8);
-		EEPROM(rt2x00dev, "Freq: 0x%04x\n", word);
+		EEPROM(rt2x00dev, "Led Mode: 0x%04x\n", word);
 	}
 
 	/*
@@ -2499,7 +2507,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 	    IEEE80211_HW_SIGNAL_DBM |
 	    IEEE80211_HW_SUPPORTS_PS |
-	    IEEE80211_HW_PS_NULLFUNC_STACK;
+	    IEEE80211_HW_PS_NULLFUNC_STACK |
+	    IEEE80211_HW_AMPDU_AGGREGATION;
 
 	SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
 	SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2559,12 +2568,15 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 	    IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
 	    IEEE80211_HT_CAP_GRN_FLD |
 	    IEEE80211_HT_CAP_SGI_20 |
-	    IEEE80211_HT_CAP_SGI_40 |
-	    IEEE80211_HT_CAP_RX_STBC;
+	    IEEE80211_HT_CAP_SGI_40;
 
 	if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) >= 2)
 		spec->ht.cap |= IEEE80211_HT_CAP_TX_STBC;
 
+	spec->ht.cap |=
+	    rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH) <<
+		IEEE80211_HT_CAP_RX_STBC_SHIFT;
+
 	spec->ht.ampdu_factor = 3;
 	spec->ht.ampdu_density = 4;
 	spec->ht.mcs.tx_params =
@@ -2751,6 +2763,35 @@ static u64 rt2800_get_tsf(struct ieee80211_hw *hw)
 	return tsf;
 }
 
+static int rt2800_ampdu_action(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       enum ieee80211_ampdu_mlme_action action,
+			       struct ieee80211_sta *sta,
+			       u16 tid, u16 *ssn)
+{
+	int ret = 0;
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+	case IEEE80211_AMPDU_RX_STOP:
+		/* we don't support RX aggregation yet */
+		ret = -ENOTSUPP;
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_STOP:
+		ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		break;
+	default:
+		WARNING((struct rt2x00_dev *)hw->priv, "Unknown AMPDU action\n");
+	}
+
+	return ret;
+}
+
 const struct ieee80211_ops rt2800_mac80211_ops = {
 	.tx			= rt2x00mac_tx,
 	.start			= rt2x00mac_start,
@@ -2768,6 +2809,7 @@ const struct ieee80211_ops rt2800_mac80211_ops = {
 	.conf_tx		= rt2800_conf_tx,
 	.get_tsf		= rt2800_get_tsf,
 	.rfkill_poll		= rt2x00mac_rfkill_poll,
+	.ampdu_action		= rt2800_ampdu_action,
 };
 EXPORT_SYMBOL_GPL(rt2800_mac80211_ops);
 

+ 25 - 8
drivers/net/wireless/rt2x00/rt2800pci.c

@@ -139,8 +139,18 @@ static void rt2800pci_read_eeprom_pci(struct rt2x00_dev *rt2x00dev)
 	eeprom.data = rt2x00dev;
 	eeprom.register_read = rt2800pci_eepromregister_read;
 	eeprom.register_write = rt2800pci_eepromregister_write;
-	eeprom.width = !rt2x00_get_field32(reg, E2PROM_CSR_TYPE) ?
-	    PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66;
+	switch (rt2x00_get_field32(reg, E2PROM_CSR_TYPE))
+	{
+	case 0:
+		eeprom.width = PCI_EEPROM_WIDTH_93C46;
+		break;
+	case 1:
+		eeprom.width = PCI_EEPROM_WIDTH_93C66;
+		break;
+	default:
+		eeprom.width = PCI_EEPROM_WIDTH_93C86;
+		break;
+	}
 	eeprom.reg_data_in = 0;
 	eeprom.reg_data_out = 0;
 	eeprom.reg_data_clock = 0;
@@ -645,10 +655,12 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev,
 /*
  * TX descriptor initialization
  */
-static void rt2800pci_write_tx_datadesc(struct queue_entry* entry,
-					 struct txentry_desc *txdesc)
+static void rt2800pci_write_tx_data(struct queue_entry* entry,
+				    struct txentry_desc *txdesc)
 {
-	rt2800_write_txwi((__le32 *) entry->skb->data, txdesc);
+	__le32 *txwi = (__le32 *) entry->skb->data;
+
+	rt2800_write_txwi(txwi, txdesc);
 }
 
 
@@ -905,7 +917,7 @@ static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev)
 		if (txdesc.retry)
 			__set_bit(TXDONE_FALLBACK, &txdesc.flags);
 
-		rt2x00pci_txdone(entry, &txdesc);
+		rt2x00lib_txdone(entry, &txdesc);
 	}
 }
 
@@ -941,6 +953,12 @@ static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
 		rt2800pci_txdone(rt2x00dev);
 
+	/*
+	 * Current beacon was sent out, fetch the next one
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+		rt2x00lib_beacondone(rt2x00dev);
+
 	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
 		rt2800pci_wakeup(rt2x00dev);
 
@@ -1044,8 +1062,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.reset_tuner		= rt2800_reset_tuner,
 	.link_tuner		= rt2800_link_tuner,
 	.write_tx_desc		= rt2800pci_write_tx_desc,
-	.write_tx_data		= rt2x00pci_write_tx_data,
-	.write_tx_datadesc	= rt2800pci_write_tx_datadesc,
+	.write_tx_data		= rt2800pci_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
 	.kick_tx_queue		= rt2800pci_kick_tx_queue,
 	.kill_tx_queue		= rt2800pci_kill_tx_queue,

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

@@ -430,20 +430,23 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev,
 /*
  * TX descriptor initialization
  */
+static void rt2800usb_write_tx_data(struct queue_entry* entry,
+				    struct txentry_desc *txdesc)
+{
+	__le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE);
+
+	rt2800_write_txwi(txwi, txdesc);
+}
+
+
 static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 				    struct sk_buff *skb,
 				    struct txentry_desc *txdesc)
 {
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
 	__le32 *txi = (__le32 *) skb->data;
-	__le32 *txwi = (__le32 *) (skb->data + TXINFO_DESC_SIZE);
 	u32 word;
 
-	/*
-	 * Initialize TXWI descriptor
-	 */
-	rt2800_write_txwi(txwi, txdesc);
-
 	/*
 	 * Initialize TXINFO descriptor
 	 */
@@ -652,7 +655,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
 	.reset_tuner		= rt2800_reset_tuner,
 	.link_tuner		= rt2800_link_tuner,
 	.write_tx_desc		= rt2800usb_write_tx_desc,
-	.write_tx_data		= rt2x00usb_write_tx_data,
+	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
 	.get_tx_data_len	= rt2800usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,

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

@@ -550,10 +550,8 @@ struct rt2x00lib_ops {
 	void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev,
 			       struct sk_buff *skb,
 			       struct txentry_desc *txdesc);
-	int (*write_tx_data) (struct queue_entry *entry,
-			      struct txentry_desc *txdesc);
-	void (*write_tx_datadesc) (struct queue_entry *entry,
-				   struct txentry_desc *txdesc);
+	void (*write_tx_data) (struct queue_entry *entry,
+			       struct txentry_desc *txdesc);
 	void (*write_beacon) (struct queue_entry *entry,
 			      struct txentry_desc *txdesc);
 	int (*get_tx_data_len) (struct queue_entry *entry);

+ 30 - 0
drivers/net/wireless/rt2x00/rt2x00dev.c

@@ -210,6 +210,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 	unsigned int i;
 	bool success;
 
+	/*
+	 * Unmap the skb.
+	 */
+	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
+
+	/*
+	 * Remove the extra tx headroom from the skb.
+	 */
+	skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
+
+	/*
+	 * Signal that the TX descriptor is no longer in the skb.
+	 */
+	skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
+
 	/*
 	 * Remove L2 padding which was added during
 	 */
@@ -286,6 +301,21 @@ void rt2x00lib_txdone(struct queue_entry *entry,
 			rt2x00dev->low_level_stats.dot11ACKFailureCount++;
 	}
 
+	/*
+	 * Every single frame has it's own tx status, hence report
+	 * every frame as ampdu of size 1.
+	 *
+	 * TODO: if we can find out how many frames were aggregated
+	 * by the hw we could provide the real ampdu_len to mac80211
+	 * which would allow the rc algorithm to better decide on
+	 * which rates are suitable.
+	 */
+	if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
+		tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+		tx_info->status.ampdu_len = 1;
+		tx_info->status.ampdu_ack_len = success ? 1 : 0;
+	}
+
 	if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
 		if (success)
 			rt2x00dev->low_level_stats.dot11RTSSuccessCount++;

+ 4 - 4
drivers/net/wireless/rt2x00/rt2x00link.c

@@ -271,11 +271,11 @@ void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev)
 
 	/*
 	 * Link tuning should only be performed when
-	 * an active sta or master interface exists.
-	 * Single monitor mode interfaces should never have
-	 * work with link tuners.
+	 * an active sta interface exists. AP interfaces
+	 * don't need link tuning and monitor mode interfaces
+	 * should never have to work with link tuners.
 	 */
-	if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)
+	if (!rt2x00dev->intf_sta_count)
 		return;
 
 	rt2x00link_reset_tuner(rt2x00dev, false);

+ 4 - 6
drivers/net/wireless/rt2x00/rt2x00mac.c

@@ -282,7 +282,8 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
 	 * has been initialized. Otherwise the device can reset
 	 * the MAC registers.
 	 */
-	rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL);
+	rt2x00lib_config_intf(rt2x00dev, intf, vif->type,
+			      intf->mac, intf->bssid);
 
 	/*
 	 * Some filters depend on the current working mode. We can force
@@ -562,7 +563,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	int update_bssid = 0;
 
 	/*
 	 * mac80211 might be calling this function while we are trying
@@ -577,10 +577,8 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 	 * conf->bssid can be NULL if coming from the internal
 	 * beacon update routine.
 	 */
-	if (changes & BSS_CHANGED_BSSID) {
-		update_bssid = 1;
+	if (changes & BSS_CHANGED_BSSID)
 		memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN);
-	}
 
 	spin_unlock(&intf->lock);
 
@@ -592,7 +590,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
 	 */
 	if (changes & BSS_CHANGED_BSSID)
 		rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
-				      update_bssid ? bss_conf->bssid : NULL);
+				      bss_conf->bssid);
 
 	/*
 	 * Update the beacon.

+ 0 - 74
drivers/net/wireless/rt2x00/rt2x00pci.c

@@ -60,80 +60,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
 }
 EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
 
-/*
- * TX data handlers.
- */
-int rt2x00pci_write_tx_data(struct queue_entry *entry,
-			    struct txentry_desc *txdesc)
-{
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-
-	/*
-	 * This should not happen, we already checked the entry
-	 * was ours. When the hardware disagrees there has been
-	 * a queue corruption!
-	 */
-	if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) {
-		ERROR(rt2x00dev,
-		      "Corrupt queue %d, accessing entry which is not ours.\n"
-		      "Please file bug report to %s.\n",
-		      entry->queue->qid, DRV_PROJECT);
-		return -EINVAL;
-	}
-
-	/*
-	 * Add the requested extra tx headroom in front of the skb.
-	 */
-	skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
-	memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
-
-	/*
-	 * Call the driver's write_tx_datadesc function, if it exists.
-	 */
-	if (rt2x00dev->ops->lib->write_tx_datadesc)
-		rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
-
-	/*
-	 * Map the skb to DMA.
-	 */
-	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
-		rt2x00queue_map_txskb(rt2x00dev, entry->skb);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data);
-
-/*
- * TX/RX data handlers.
- */
-void rt2x00pci_txdone(struct queue_entry *entry,
-		      struct txdone_entry_desc *txdesc)
-{
-	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
-	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
-
-	/*
-	 * Unmap the skb.
-	 */
-	rt2x00queue_unmap_skb(rt2x00dev, entry->skb);
-
-	/*
-	 * Remove the extra tx headroom from the skb.
-	 */
-	skb_pull(entry->skb, rt2x00dev->ops->extra_tx_headroom);
-
-	/*
-	 * Signal that the TX descriptor is no longer in the skb.
-	 */
-	skbdesc->flags &= ~SKBDESC_DESC_IN_SKB;
-
-	/*
-	 * Pass on to rt2x00lib.
-	 */
-	rt2x00lib_txdone(entry, txdesc);
-}
-EXPORT_SYMBOL_GPL(rt2x00pci_txdone);
-
 void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
 {
 	struct data_queue *queue = rt2x00dev->rx;

+ 0 - 18
drivers/net/wireless/rt2x00/rt2x00pci.h

@@ -85,16 +85,6 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
 			   const struct rt2x00_field32 field,
 			   u32 *reg);
 
-/**
- * rt2x00pci_write_tx_data - Initialize data for TX operation
- * @entry: The entry where the frame is located
- *
- * This function will initialize the DMA and skb descriptor
- * to prepare the entry for the actual TX operation.
- */
-int rt2x00pci_write_tx_data(struct queue_entry *entry,
-			    struct txentry_desc *txdesc);
-
 /**
  * struct queue_entry_priv_pci: Per entry PCI specific information
  *
@@ -108,14 +98,6 @@ struct queue_entry_priv_pci {
 	dma_addr_t desc_dma;
 };
 
-/**
- * rt2x00pci_txdone - Handle TX done events.
- * @entry: The queue entry for which a TX done event was received.
- * @txdesc: The TX done descriptor for the entry.
- */
-void rt2x00pci_txdone(struct queue_entry *entry,
-		      struct txdone_entry_desc *txdesc);
-
 /**
  * rt2x00pci_rxdone - Handle RX done events
  * @rt2x00dev: Device pointer, see &struct rt2x00_dev.

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

@@ -404,6 +404,46 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
 	rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
 
+static int rt2x00queue_write_tx_data(struct queue_entry *entry,
+				     struct txentry_desc *txdesc)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+
+	/*
+	 * This should not happen, we already checked the entry
+	 * was ours. When the hardware disagrees there has been
+	 * a queue corruption!
+	 */
+	if (unlikely(rt2x00dev->ops->lib->get_entry_state &&
+		     rt2x00dev->ops->lib->get_entry_state(entry))) {
+		ERROR(rt2x00dev,
+		      "Corrupt queue %d, accessing entry which is not ours.\n"
+		      "Please file bug report to %s.\n",
+		      entry->queue->qid, DRV_PROJECT);
+		return -EINVAL;
+	}
+
+	/*
+	 * Add the requested extra tx headroom in front of the skb.
+	 */
+	skb_push(entry->skb, rt2x00dev->ops->extra_tx_headroom);
+	memset(entry->skb->data, 0, rt2x00dev->ops->extra_tx_headroom);
+
+	/*
+	 * Call the driver's write_tx_data function, if it exists.
+	 */
+	if (rt2x00dev->ops->lib->write_tx_data)
+		rt2x00dev->ops->lib->write_tx_data(entry, txdesc);
+
+	/*
+	 * Map the skb to DMA.
+	 */
+	if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags))
+		rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+
+	return 0;
+}
+
 static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
 					    struct txentry_desc *txdesc)
 {
@@ -515,8 +555,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb,
 	 * call failed. Since we always return NETDEV_TX_OK to mac80211,
 	 * this frame will simply be dropped.
 	 */
-	if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry,
-							       &txdesc))) {
+	if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
 		clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
 		entry->skb = NULL;
 		return -EIO;

+ 13 - 38
drivers/net/wireless/rt2x00/rt2x00usb.c

@@ -177,11 +177,6 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	    !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags))
 		return;
 
-	/*
-	 * Remove the descriptor from the front of the skb.
-	 */
-	skb_pull(entry->skb, entry->queue->desc_size);
-
 	/*
 	 * Obtain the status about this packet.
 	 * Note that when the status is 0 it does not mean the
@@ -201,48 +196,28 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb)
 	rt2x00lib_txdone(entry, &txdesc);
 }
 
-int rt2x00usb_write_tx_data(struct queue_entry *entry,
-			    struct txentry_desc *txdesc)
+static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
 {
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
 	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
 	u32 length;
 
-	/*
-	 * Add the descriptor in front of the skb.
-	 */
-	skb_push(entry->skb, entry->queue->desc_size);
-	memset(entry->skb->data, 0, entry->queue->desc_size);
-
-	/*
-	 * USB devices cannot blindly pass the skb->len as the
-	 * length of the data to usb_fill_bulk_urb. Pass the skb
-	 * to the driver to determine what the length should be.
-	 */
-	length = rt2x00dev->ops->lib->get_tx_data_len(entry);
-
-	usb_fill_bulk_urb(entry_priv->urb, usb_dev,
-			  usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
-			  entry->skb->data, length,
-			  rt2x00usb_interrupt_txdone, entry);
-
-	/*
-	 * Call the driver's write_tx_datadesc function, if it exists.
-	 */
-	if (rt2x00dev->ops->lib->write_tx_datadesc)
-		rt2x00dev->ops->lib->write_tx_datadesc(entry, txdesc);
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data);
+	if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) {
+		/*
+		 * USB devices cannot blindly pass the skb->len as the
+		 * length of the data to usb_fill_bulk_urb. Pass the skb
+		 * to the driver to determine what the length should be.
+		 */
+		length = rt2x00dev->ops->lib->get_tx_data_len(entry);
 
-static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
-{
-	struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+		usb_fill_bulk_urb(entry_priv->urb, usb_dev,
+				  usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
+				  entry->skb->data, length,
+				  rt2x00usb_interrupt_txdone, entry);
 
-	if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags))
 		usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+	}
 }
 
 void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,

+ 0 - 10
drivers/net/wireless/rt2x00/rt2x00usb.h

@@ -350,16 +350,6 @@ int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
  */
 void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev);
 
-/**
- * rt2x00usb_write_tx_data - Initialize URB for TX operation
- * @entry: The entry where the frame is located
- *
- * This function will initialize the URB and skb descriptor
- * to prepare the entry for the actual TX operation.
- */
-int rt2x00usb_write_tx_data(struct queue_entry *entry,
-			    struct txentry_desc *txdesc);
-
 /**
  * struct queue_entry_priv_usb: Per entry USB specific information
  *

+ 8 - 3
drivers/net/wireless/rt2x00/rt61pci.c

@@ -2108,7 +2108,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 			__set_bit(TXDONE_UNKNOWN, &txdesc.flags);
 			txdesc.retry = 0;
 
-			rt2x00pci_txdone(entry_done, &txdesc);
+			rt2x00lib_txdone(entry_done, &txdesc);
 			entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE);
 		}
 
@@ -2135,7 +2135,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev)
 		if (txdesc.retry)
 			__set_bit(TXDONE_FALLBACK, &txdesc.flags);
 
-		rt2x00pci_txdone(entry, &txdesc);
+		rt2x00lib_txdone(entry, &txdesc);
 	}
 }
 
@@ -2200,6 +2200,12 @@ static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
 		rt61pci_wakeup(rt2x00dev);
 
+	/*
+	 * 5 - Beacon done interrupt.
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
+		rt2x00lib_beacondone(rt2x00dev);
+
 	return IRQ_HANDLED;
 }
 
@@ -2800,7 +2806,6 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.reset_tuner		= rt61pci_reset_tuner,
 	.link_tuner		= rt61pci_link_tuner,
 	.write_tx_desc		= rt61pci_write_tx_desc,
-	.write_tx_data		= rt2x00pci_write_tx_data,
 	.write_beacon		= rt61pci_write_beacon,
 	.kick_tx_queue		= rt61pci_kick_tx_queue,
 	.kill_tx_queue		= rt61pci_kill_tx_queue,

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

@@ -2249,7 +2249,6 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
 	.reset_tuner		= rt73usb_reset_tuner,
 	.link_tuner		= rt73usb_link_tuner,
 	.write_tx_desc		= rt73usb_write_tx_desc,
-	.write_tx_data		= rt2x00usb_write_tx_data,
 	.write_beacon		= rt73usb_write_beacon,
 	.get_tx_data_len	= rt73usb_get_tx_data_len,
 	.kick_tx_queue		= rt2x00usb_kick_tx_queue,

+ 1 - 1
drivers/net/wireless/rtl818x/rtl8180_dev.c

@@ -671,7 +671,7 @@ static u64 rtl8180_get_tsf(struct ieee80211_hw *dev)
 	       (u64)(rtl818x_ioread32(priv, &priv->map->TSFT[1])) << 32;
 }
 
-void rtl8180_beacon_work(struct work_struct *work)
+static void rtl8180_beacon_work(struct work_struct *work)
 {
 	struct rtl8180_vif *vif_priv =
 		container_of(work, struct rtl8180_vif, beacon_work.work);

+ 1 - 0
include/linux/eeprom_93cx6.h

@@ -30,6 +30,7 @@
 #define PCI_EEPROM_WIDTH_93C46	6
 #define PCI_EEPROM_WIDTH_93C56	8
 #define PCI_EEPROM_WIDTH_93C66	8
+#define PCI_EEPROM_WIDTH_93C86	8
 #define PCI_EEPROM_WIDTH_OPCODE	3
 #define PCI_EEPROM_WRITE_OPCODE	0x05
 #define PCI_EEPROM_READ_OPCODE	0x06

+ 22 - 0
include/linux/nl80211.h

@@ -725,6 +725,12 @@ enum nl80211_commands {
  * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations
  *	connected to this BSS.
  *
+ * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See
+ *      &enum nl80211_tx_power_setting for possible values.
+ * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units.
+ *      This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING
+ *      for non-automatic settings.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -882,6 +888,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_AP_ISOLATE,
 
+	NL80211_ATTR_WIPHY_TX_POWER_SETTING,
+	NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -1659,4 +1668,17 @@ enum nl80211_cqm_rssi_threshold_event {
 	NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
 };
 
+
+/**
+ * enum nl80211_tx_power_setting - TX power adjustment
+ * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power
+ * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter
+ * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter
+ */
+enum nl80211_tx_power_setting {
+	NL80211_TX_POWER_AUTOMATIC,
+	NL80211_TX_POWER_LIMITED,
+	NL80211_TX_POWER_FIXED,
+};
+
 #endif /* __LINUX_NL80211_H */

+ 1 - 14
include/net/cfg80211.h

@@ -875,19 +875,6 @@ enum wiphy_params_flags {
 	WIPHY_PARAM_COVERAGE_CLASS	= 1 << 4,
 };
 
-/**
- * enum tx_power_setting - TX power adjustment
- *
- * @TX_POWER_AUTOMATIC: the dbm parameter is ignored
- * @TX_POWER_LIMITED: limit TX power by the dbm parameter
- * @TX_POWER_FIXED: fix TX power to the dbm parameter
- */
-enum tx_power_setting {
-	TX_POWER_AUTOMATIC,
-	TX_POWER_LIMITED,
-	TX_POWER_FIXED,
-};
-
 /*
  * cfg80211_bitrate_mask - masks for bitrate control
  */
@@ -1149,7 +1136,7 @@ struct cfg80211_ops {
 	int	(*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
 
 	int	(*set_tx_power)(struct wiphy *wiphy,
-				enum tx_power_setting type, int dbm);
+				enum nl80211_tx_power_setting type, int mbm);
 	int	(*get_tx_power)(struct wiphy *wiphy, int *dbm);
 
 	int	(*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,

+ 39 - 0
include/net/mac80211.h

@@ -1271,6 +1271,15 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
  * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS
  * enabled whenever user has enabled powersave.
  *
+ * Some hardware need to toggle a single shared antenna between WLAN and
+ * Bluetooth to facilitate co-existence. These types of hardware set
+ * limitations on the use of host controlled dynamic powersave whenever there
+ * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the
+ * driver may request temporarily going into full power save, in order to
+ * enable toggling the antenna between BT and WLAN. If the driver requests
+ * disabling dynamic powersave, the @dynamic_ps_timeout value will be
+ * temporarily set to zero until the driver re-enables dynamic powersave.
+ *
  * Driver informs U-APSD client support by enabling
  * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the
  * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS
@@ -2446,6 +2455,36 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
  */
 void ieee80211_connection_loss(struct ieee80211_vif *vif);
 
+/**
+ * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Some hardware require full power save to manage simultaneous BT traffic
+ * on the WLAN frequency. Full PSM is required periodically, whenever there are
+ * burst of BT traffic. The hardware gets information of BT traffic via
+ * hardware co-existence lines, and consequentially requests mac80211 to
+ * (temporarily) enter full psm.
+ * This function will only temporarily disable dynamic PS, not enable PSM if
+ * it was not already enabled.
+ * The driver must make sure to re-enable dynamic PS using
+ * ieee80211_enable_dyn_ps() if the driver has disabled it.
+ *
+ */
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif);
+
+/**
+ * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * This function restores dynamic PS after being temporarily disabled via
+ * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must
+ * be coupled with an eventual call to this function.
+ *
+ */
+void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif);
+
 /**
  * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
  *	rssi threshold triggered

+ 1 - 0
net/mac80211/Kconfig

@@ -69,6 +69,7 @@ endchoice
 
 config MAC80211_RC_DEFAULT
 	string
+	default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT
 	default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL
 	default "pid" if MAC80211_RC_DEFAULT_PID
 	default ""

+ 11 - 14
net/mac80211/cfg.c

@@ -413,9 +413,6 @@ static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
 {
 	struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
 
-	if (!local->ops->get_survey)
-		return -EOPNOTSUPP;
-
 	return drv_get_survey(local, idx, survey);
 }
 
@@ -1329,28 +1326,28 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 }
 
 static int ieee80211_set_tx_power(struct wiphy *wiphy,
-				  enum tx_power_setting type, int dbm)
+				  enum nl80211_tx_power_setting type, int mbm)
 {
 	struct ieee80211_local *local = wiphy_priv(wiphy);
 	struct ieee80211_channel *chan = local->hw.conf.channel;
 	u32 changes = 0;
 
 	switch (type) {
-	case TX_POWER_AUTOMATIC:
+	case NL80211_TX_POWER_AUTOMATIC:
 		local->user_power_level = -1;
 		break;
-	case TX_POWER_LIMITED:
-		if (dbm < 0)
-			return -EINVAL;
-		local->user_power_level = dbm;
+	case NL80211_TX_POWER_LIMITED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
+		local->user_power_level = MBM_TO_DBM(mbm);
 		break;
-	case TX_POWER_FIXED:
-		if (dbm < 0)
-			return -EINVAL;
+	case NL80211_TX_POWER_FIXED:
+		if (mbm < 0 || (mbm % 100))
+			return -EOPNOTSUPP;
 		/* TODO: move to cfg80211 when it knows the channel */
-		if (dbm > chan->max_power)
+		if (MBM_TO_DBM(mbm) > chan->max_power)
 			return -EINVAL;
-		local->user_power_level = dbm;
+		local->user_power_level = MBM_TO_DBM(mbm);
 		break;
 	}
 

+ 6 - 1
net/mac80211/driver-ops.h

@@ -375,9 +375,14 @@ static inline int drv_get_survey(struct ieee80211_local *local, int idx,
 				struct survey_info *survey)
 {
 	int ret = -EOPNOTSUPP;
+
+	trace_drv_get_survey(local, idx, survey);
+
 	if (local->ops->get_survey)
 		ret = local->ops->get_survey(&local->hw, idx, survey);
-	/* trace_drv_get_survey(local, idx, survey, ret); */
+
+	trace_drv_return_int(local, ret);
+
 	return ret;
 }
 

+ 22 - 0
net/mac80211/driver-trace.h

@@ -761,6 +761,28 @@ TRACE_EVENT(drv_ampdu_action,
 	)
 );
 
+TRACE_EVENT(drv_get_survey,
+	TP_PROTO(struct ieee80211_local *local, int idx,
+		 struct survey_info *survey),
+
+	TP_ARGS(local, idx, survey),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(int, idx)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->idx = idx;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " idx:%d",
+		LOCAL_PR_ARG, __entry->idx
+	)
+);
+
 TRACE_EVENT(drv_flush,
 	TP_PROTO(struct ieee80211_local *local, bool drop),
 

+ 2 - 0
net/mac80211/ieee80211_i.h

@@ -855,6 +855,8 @@ struct ieee80211_local {
 	 * this will override whatever chosen by mac80211 internally.
 	 */
 	int dynamic_ps_forced_timeout;
+	int dynamic_ps_user_timeout;
+	bool disable_dynamic_ps;
 
 	int user_power_level; /* in dBm */
 	int power_constr_level; /* in dBm */

+ 31 - 11
net/mac80211/mesh_plink.c

@@ -65,7 +65,6 @@ void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
 {
 	atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
 	mesh_accept_plinks_update(sdata);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 }
 
 static inline
@@ -73,7 +72,6 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
 {
 	atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
 	mesh_accept_plinks_update(sdata);
-	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 }
 
 /**
@@ -115,7 +113,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
 }
 
 /**
- * mesh_plink_deactivate - deactivate mesh peer link
+ * __mesh_plink_deactivate - deactivate mesh peer link
  *
  * @sta: mesh peer link to deactivate
  *
@@ -123,18 +121,23 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
  *
  * Locking: the caller must hold sta->lock
  */
-static void __mesh_plink_deactivate(struct sta_info *sta)
+static bool __mesh_plink_deactivate(struct sta_info *sta)
 {
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
+	bool deactivated = false;
 
-	if (sta->plink_state == PLINK_ESTAB)
+	if (sta->plink_state == PLINK_ESTAB) {
 		mesh_plink_dec_estab_count(sdata);
+		deactivated = true;
+	}
 	sta->plink_state = PLINK_BLOCKED;
 	mesh_path_flush_by_nexthop(sta);
+
+	return deactivated;
 }
 
 /**
- * __mesh_plink_deactivate - deactivate mesh peer link
+ * mesh_plink_deactivate - deactivate mesh peer link
  *
  * @sta: mesh peer link to deactivate
  *
@@ -142,9 +145,15 @@ static void __mesh_plink_deactivate(struct sta_info *sta)
  */
 void mesh_plink_deactivate(struct sta_info *sta)
 {
+	struct ieee80211_sub_if_data *sdata = sta->sdata;
+	bool deactivated;
+
 	spin_lock_bh(&sta->lock);
-	__mesh_plink_deactivate(sta);
+	deactivated = __mesh_plink_deactivate(sta);
 	spin_unlock_bh(&sta->lock);
+
+	if (deactivated)
+		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 }
 
 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
@@ -381,10 +390,16 @@ int mesh_plink_open(struct sta_info *sta)
 
 void mesh_plink_block(struct sta_info *sta)
 {
+	struct ieee80211_sub_if_data *sdata = sta->sdata;
+	bool deactivated;
+
 	spin_lock_bh(&sta->lock);
-	__mesh_plink_deactivate(sta);
+	deactivated = __mesh_plink_deactivate(sta);
 	sta->plink_state = PLINK_BLOCKED;
 	spin_unlock_bh(&sta->lock);
+
+	if (deactivated)
+		ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 }
 
 
@@ -397,6 +412,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 	enum plink_event event;
 	enum plink_frame_type ftype;
 	size_t baselen;
+	bool deactivated;
 	u8 ie_len;
 	u8 *baseaddr;
 	__le16 plid, llid, reason;
@@ -651,8 +667,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		case CNF_ACPT:
 			del_timer(&sta->plink_timer);
 			sta->plink_state = PLINK_ESTAB;
-			mesh_plink_inc_estab_count(sdata);
 			spin_unlock_bh(&sta->lock);
+			mesh_plink_inc_estab_count(sdata);
+			ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
 				sta->sta.addr);
 			break;
@@ -684,8 +701,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		case OPN_ACPT:
 			del_timer(&sta->plink_timer);
 			sta->plink_state = PLINK_ESTAB;
-			mesh_plink_inc_estab_count(sdata);
 			spin_unlock_bh(&sta->lock);
+			mesh_plink_inc_estab_count(sdata);
+			ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 			mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
 				sta->sta.addr);
 			mesh_plink_frame_tx(sdata, PLINK_CONFIRM, sta->sta.addr, llid,
@@ -702,11 +720,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
 		case CLS_ACPT:
 			reason = cpu_to_le16(MESH_CLOSE_RCVD);
 			sta->reason = reason;
-			__mesh_plink_deactivate(sta);
+			deactivated = __mesh_plink_deactivate(sta);
 			sta->plink_state = PLINK_HOLDING;
 			llid = sta->llid;
 			mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
 			spin_unlock_bh(&sta->lock);
+			if (deactivated)
+				ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
 			mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid,
 					    plid, reason);
 			break;

+ 38 - 1
net/mac80211/mlme.c

@@ -478,6 +478,39 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
 	}
 }
 
+void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_conf *conf = &local->hw.conf;
+
+	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
+		!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
+		(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
+
+	local->disable_dynamic_ps = false;
+	conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout;
+}
+EXPORT_SYMBOL(ieee80211_enable_dyn_ps);
+
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_conf *conf = &local->hw.conf;
+
+	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION ||
+		!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) ||
+		(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS));
+
+	local->disable_dynamic_ps = true;
+	conf->dynamic_ps_timeout = 0;
+	del_timer_sync(&local->dynamic_ps_timer);
+	ieee80211_queue_work(&local->hw,
+			     &local->dynamic_ps_enable_work);
+}
+EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
+
 /* powersave */
 static void ieee80211_enable_ps(struct ieee80211_local *local,
 				struct ieee80211_sub_if_data *sdata)
@@ -553,6 +586,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 	    found->u.mgd.associated->beacon_ies &&
 	    !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
 				    IEEE80211_STA_CONNECTION_POLL))) {
+		struct ieee80211_conf *conf = &local->hw.conf;
 		s32 beaconint_us;
 
 		if (latency < 0)
@@ -575,7 +609,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
 			else
 				timeout = 100;
 		}
-		local->hw.conf.dynamic_ps_timeout = timeout;
+		local->dynamic_ps_user_timeout = timeout;
+		if (!local->disable_dynamic_ps)
+			conf->dynamic_ps_timeout =
+				local->dynamic_ps_user_timeout;
 
 		if (beaconint_us > latency) {
 			local->ps_sdata = NULL;

+ 2 - 1
net/mac80211/rc80211_minstrel_ht.c

@@ -328,7 +328,8 @@ minstrel_next_sample_idx(struct minstrel_ht_sta *mi)
 }
 
 static void
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, int *idx, bool primary)
+minstrel_downgrade_rate(struct minstrel_ht_sta *mi, unsigned int *idx,
+			bool primary)
 {
 	int group, orig_group;
 

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