Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/holtmann/bluetooth-next-2.6
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index bde2fa8..a105087 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -373,8 +373,8 @@
 		pktlen = status & RDES0_STATUS_FL;
 		if (pktlen > RX_PKT_SIZE) {
 			if (net_ratelimit())
-				printk(KERN_DEBUG "%s: frame too long (%d)\n",
-				       wiphy_name(dev->wiphy), pktlen);
+				wiphy_debug(dev->wiphy, "frame too long (%d)\n",
+					    pktlen);
 			pktlen = RX_PKT_SIZE;
 		}
 
@@ -454,10 +454,10 @@
 
 static irqreturn_t adm8211_interrupt(int irq, void *dev_id)
 {
-#define ADM8211_INT(x)							   \
-do {									   \
-	if (unlikely(stsr & ADM8211_STSR_ ## x))			   \
-		printk(KERN_DEBUG "%s: " #x "\n", wiphy_name(dev->wiphy)); \
+#define ADM8211_INT(x)						\
+do {								\
+	if (unlikely(stsr & ADM8211_STSR_ ## x))		\
+		wiphy_debug(dev->wiphy, "%s\n", #x);		\
 } while (0)
 
 	struct ieee80211_hw *dev = dev_id;
@@ -570,9 +570,9 @@
 	}
 
 	if (timeout == 0) {
-		printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed"
-		       " prewrite (reg=0x%08x)\n",
-		       wiphy_name(dev->wiphy), addr, data, reg);
+		wiphy_debug(dev->wiphy,
+			    "adm8211_write_bbp(%d,%d) failed prewrite (reg=0x%08x)\n",
+			    addr, data, reg);
 		return -ETIMEDOUT;
 	}
 
@@ -605,9 +605,9 @@
 	if (timeout == 0) {
 		ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) &
 				  ~ADM8211_BBPCTL_WR);
-		printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed"
-		       " postwrite (reg=0x%08x)\n",
-		       wiphy_name(dev->wiphy), addr, data, reg);
+		wiphy_debug(dev->wiphy,
+			    "adm8211_write_bbp(%d,%d) failed postwrite (reg=0x%08x)\n",
+			    addr, data, reg);
 		return -ETIMEDOUT;
 	}
 
@@ -675,8 +675,8 @@
 		break;
 
 	default:
-		printk(KERN_DEBUG "%s: unsupported transceiver type %d\n",
-		       wiphy_name(dev->wiphy), priv->transceiver_type);
+		wiphy_debug(dev->wiphy, "unsupported transceiver type %d\n",
+			    priv->transceiver_type);
 		break;
 	}
 
@@ -732,8 +732,8 @@
 
 	/* Nothing to do for ADMtek BBP */
 	} else if (priv->bbp_type != ADM8211_TYPE_ADMTEK)
-		printk(KERN_DEBUG "%s: unsupported BBP type %d\n",
-		       wiphy_name(dev->wiphy), priv->bbp_type);
+		wiphy_debug(dev->wiphy, "unsupported bbp type %d\n",
+			    priv->bbp_type);
 
 	ADM8211_RESTORE();
 
@@ -1027,13 +1027,12 @@
 			break;
 
 		default:
-			printk(KERN_DEBUG "%s: unsupported transceiver %d\n",
-			       wiphy_name(dev->wiphy), priv->transceiver_type);
+			wiphy_debug(dev->wiphy, "unsupported transceiver %d\n",
+				    priv->transceiver_type);
 			break;
 		}
 	} else
-		printk(KERN_DEBUG "%s: unsupported BBP %d\n",
-		       wiphy_name(dev->wiphy), priv->bbp_type);
+		wiphy_debug(dev->wiphy, "unsupported bbp %d\n", priv->bbp_type);
 
 	ADM8211_CSR_WRITE(SYNRF, 0);
 
@@ -1509,15 +1508,13 @@
 	/* Power up MAC and RF chips */
 	retval = adm8211_hw_reset(dev);
 	if (retval) {
-		printk(KERN_ERR "%s: hardware reset failed\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "hardware reset failed\n");
 		goto fail;
 	}
 
 	retval = adm8211_init_rings(dev);
 	if (retval) {
-		printk(KERN_ERR "%s: failed to initialize rings\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "failed to initialize rings\n");
 		goto fail;
 	}
 
@@ -1528,8 +1525,7 @@
 	retval = request_irq(priv->pdev->irq, adm8211_interrupt,
 			     IRQF_SHARED, "adm8211", dev);
 	if (retval) {
-		printk(KERN_ERR "%s: failed to register IRQ handler\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "failed to register irq handler\n");
 		goto fail;
 	}
 
@@ -1906,9 +1902,8 @@
 		goto err_free_eeprom;
 	}
 
-	printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n",
-	       wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
-	       pdev->revision);
+	wiphy_info(dev->wiphy, "hwaddr %pm, rev 0x%02x\n",
+		   dev->wiphy->perm_addr, pdev->revision);
 
 	return 0;
 
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index cd8caea..d5140a8 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -89,22 +89,19 @@
 #define DBG_DEFAULTS		0
 
 /* Use our own dbg macro */
-#define at76_dbg(bits, format, arg...) \
-	do { \
-		if (at76_debug & (bits))				 \
-			printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \
-			       ## arg);					 \
-	} while (0)
+#define at76_dbg(bits, format, arg...)					\
+do {									\
+	if (at76_debug & (bits))					\
+		printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg);	\
+} while (0)
 
-#define at76_dbg_dump(bits, buf, len, format, arg...)	\
-	do { \
-		if (at76_debug & (bits)) { \
-			printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \
-			       ## arg);					 \
-			print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,     \
-					     buf, len);			 \
-		}							 \
-	} while (0)
+#define at76_dbg_dump(bits, buf, len, format, arg...)			\
+do {									\
+	if (at76_debug & (bits)) {					\
+		printk(KERN_DEBUG DRIVER_NAME ": " format "\n", ##arg);	\
+		print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);	\
+	}								\
+} while (0)
 
 static uint at76_debug = DBG_DEFAULTS;
 
@@ -658,8 +655,8 @@
 exit:
 	kfree(hwcfg);
 	if (ret < 0)
-		printk(KERN_ERR "%s: cannot get HW Config (error %d)\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "cannot get hw config (error %d)\n",
+			  ret);
 
 	return ret;
 }
@@ -794,8 +791,9 @@
 	do {
 		status = at76_get_cmd_status(priv->udev, cmd);
 		if (status < 0) {
-			printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n",
-			       wiphy_name(priv->hw->wiphy), status);
+			wiphy_err(priv->hw->wiphy,
+				  "at76_get_cmd_status failed: %d\n",
+				  status);
 			break;
 		}
 
@@ -810,9 +808,8 @@
 
 		schedule_timeout_interruptible(HZ / 10);	/* 100 ms */
 		if (time_after(jiffies, timeout)) {
-			printk(KERN_ERR
-			       "%s: completion timeout for command %d\n",
-			       wiphy_name(priv->hw->wiphy), cmd);
+			wiphy_err(priv->hw->wiphy,
+				  "completion timeout for command %d\n", cmd);
 			status = -ETIMEDOUT;
 			break;
 		}
@@ -833,9 +830,9 @@
 
 	ret = at76_wait_completion(priv, CMD_SET_MIB);
 	if (ret != CMD_STATUS_COMPLETE) {
-		printk(KERN_INFO
-		       "%s: set_mib: at76_wait_completion failed "
-		       "with %d\n", wiphy_name(priv->hw->wiphy), ret);
+		wiphy_info(priv->hw->wiphy,
+			   "set_mib: at76_wait_completion failed with %d\n",
+			   ret);
 		ret = -EIO;
 	}
 
@@ -855,8 +852,8 @@
 
 	ret = at76_set_card_command(priv->udev, cmd, NULL, 0);
 	if (ret < 0)
-		printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), cmd, ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_set_card_command(%d) failed: %d\n", cmd, ret);
 	else
 		ret = 1;
 
@@ -876,8 +873,8 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "set_mib (pm_mode) failed: %d\n",
+			  ret);
 
 	return ret;
 }
@@ -893,8 +890,8 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "set_mib (preamble) failed: %d\n",
+			  ret);
 
 	return ret;
 }
@@ -910,8 +907,8 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "set_mib (frag threshold) failed: %d\n", ret);
 
 	return ret;
 }
@@ -927,8 +924,7 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (rts) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "set_mib (rts) failed: %d\n", ret);
 
 	return ret;
 }
@@ -944,8 +940,8 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "set_mib (autorate fallback) failed: %d\n", ret);
 
 	return ret;
 }
@@ -963,8 +959,8 @@
 	ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m,
 			   sizeof(struct mib_mac_addr));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (mac_addr) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -992,8 +988,8 @@
 	ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m,
 			   sizeof(struct mib_mac_wep));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (mac_wep) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1029,8 +1025,8 @@
 	ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m,
 			   sizeof(struct mib_mac_mgmt));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (mac_mgmt) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1065,8 +1061,8 @@
 
 	ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (mac) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1102,8 +1098,8 @@
 
 	ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (phy) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1135,8 +1131,8 @@
 
 	ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (local) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1161,8 +1157,8 @@
 	ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m,
 			   sizeof(struct mib_mdomain));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "at76_get_mib (mdomain) failed: %d\n", ret);
 		goto exit;
 	}
 
@@ -1233,16 +1229,16 @@
 	struct sk_buff *skb = priv->rx_skb;
 
 	if (!priv->rx_urb) {
-		printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n",
-		       wiphy_name(priv->hw->wiphy), __func__);
+		wiphy_err(priv->hw->wiphy, "%s: priv->rx_urb is null\n",
+			  __func__);
 		return -EFAULT;
 	}
 
 	if (!skb) {
 		skb = dev_alloc_skb(sizeof(struct at76_rx_buffer));
 		if (!skb) {
-			printk(KERN_ERR "%s: cannot allocate rx skbuff\n",
-			       wiphy_name(priv->hw->wiphy));
+			wiphy_err(priv->hw->wiphy,
+				  "cannot allocate rx skbuff\n");
 			ret = -ENOMEM;
 			goto exit;
 		}
@@ -1261,15 +1257,14 @@
 			at76_dbg(DBG_DEVSTART,
 				 "usb_submit_urb returned -ENODEV");
 		else
-			printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n",
-			       wiphy_name(priv->hw->wiphy), ret);
+			wiphy_err(priv->hw->wiphy,
+				  "rx, usb_submit_urb failed: %d\n", ret);
 	}
 
 exit:
 	if (ret < 0 && ret != -ENODEV)
-		printk(KERN_ERR "%s: cannot submit rx urb - please unload the "
-		       "driver and/or power cycle the device\n",
-		       wiphy_name(priv->hw->wiphy));
+		wiphy_err(priv->hw->wiphy,
+			  "cannot submit rx urb - please unload the driver and/or power cycle the device\n");
 
 	return ret;
 }
@@ -1438,8 +1433,8 @@
 	ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config,
 				    sizeof(struct at76_card_config));
 	if (ret < 0) {
-		printk(KERN_ERR "%s: at76_set_card_command failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n",
+			  ret);
 		return ret;
 	}
 
@@ -1504,8 +1499,8 @@
 
 	ret = at76_set_mib(priv, &priv->mib_buf);
 	if (ret < 0)
-		printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy,
+			  "set_mib (promiscuous_mode) failed: %d\n", ret);
 
 	mutex_unlock(&priv->mtx);
 }
@@ -1668,16 +1663,16 @@
 				    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);
+		wiphy_err(priv->hw->wiphy, "at76_set_card_command failed: %d\n",
+			  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);
+		wiphy_err(priv->hw->wiphy, "at76_wait_completion failed: %d\n",
+			  ret);
 		return 0;
 	}
 
@@ -1745,8 +1740,8 @@
 	at76_dbg(DBG_MAC80211, "%s()", __func__);
 
 	if (priv->tx_urb->status == -EINPROGRESS) {
-		printk(KERN_ERR "%s: %s called while tx urb is pending\n",
-		       wiphy_name(priv->hw->wiphy), __func__);
+		wiphy_err(priv->hw->wiphy,
+			  "%s called while tx urb is pending\n", __func__);
 		return NETDEV_TX_BUSY;
 	}
 
@@ -1794,13 +1789,12 @@
 			  submit_len, at76_mac80211_tx_callback, priv);
 	ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC);
 	if (ret) {
-		printk(KERN_ERR "%s: error in tx submit urb: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "error in tx submit urb: %d\n", ret);
 		if (ret == -EINVAL)
-			printk(KERN_ERR
-			       "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n",
-			       wiphy_name(priv->hw->wiphy), priv->tx_urb,
-			       priv->tx_urb->hcpriv, priv->tx_urb->complete);
+			wiphy_err(priv->hw->wiphy,
+				  "-einval: tx urb %p hcpriv %p complete %p\n",
+				  priv->tx_urb,
+				  priv->tx_urb->hcpriv, priv->tx_urb->complete);
 	}
 
 	return 0;
@@ -1817,8 +1811,8 @@
 
 	ret = at76_submit_rx_urb(priv);
 	if (ret < 0) {
-		printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n",
-		       wiphy_name(priv->hw->wiphy), ret);
+		wiphy_err(priv->hw->wiphy, "open: submit_rx_urb failed: %d\n",
+			  ret);
 		goto error;
 	}
 
@@ -2316,14 +2310,12 @@
 
 	priv->mac80211_registered = 1;
 
-	printk(KERN_INFO "%s: USB %s, MAC %pM, firmware %d.%d.%d-%d\n",
-	       wiphy_name(priv->hw->wiphy),
-	       dev_name(&interface->dev), priv->mac_addr,
-	       priv->fw_version.major, priv->fw_version.minor,
-	       priv->fw_version.patch, priv->fw_version.build);
-	printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n",
-	       wiphy_name(priv->hw->wiphy),
-	       priv->regulatory_domain, priv->domain->name);
+	wiphy_info(priv->hw->wiphy, "usb %s, mac %pm, firmware %d.%d.%d-%d\n",
+		   dev_name(&interface->dev), priv->mac_addr,
+		   priv->fw_version.major, priv->fw_version.minor,
+		   priv->fw_version.patch, priv->fw_version.build);
+	wiphy_info(priv->hw->wiphy, "regulatory domain 0x%02x: %s\n",
+		   priv->regulatory_domain, priv->domain->name);
 
 exit:
 	return ret;
@@ -2485,7 +2477,7 @@
 	if (!priv)
 		return;
 
-	printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy));
+	wiphy_info(priv->hw->wiphy, "disconnecting\n");
 	at76_delete_device(priv);
 	dev_printk(KERN_INFO, &interface->dev, "disconnected\n");
 }
diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c
index cf6f5c4..4604de0 100644
--- a/drivers/net/wireless/ath/ar9170/cmd.c
+++ b/drivers/net/wireless/ath/ar9170/cmd.c
@@ -48,8 +48,7 @@
 
 	err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL);
 	if (err)
-		printk(KERN_DEBUG "%s: writing memory failed\n",
-		       wiphy_name(ar->hw->wiphy));
+		wiphy_debug(ar->hw->wiphy, "writing memory failed\n");
 	return err;
 }
 
@@ -67,8 +66,8 @@
 	err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf),
 			   (u8 *) buf, 0, NULL);
 	if (err)
-		printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n",
-		       wiphy_name(ar->hw->wiphy), reg, val);
+		wiphy_debug(ar->hw->wiphy, "writing reg %#x (val %#x) failed\n",
+			    reg, val);
 	return err;
 }
 
diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c
index 86c4e79..832d900 100644
--- a/drivers/net/wireless/ath/ar9170/led.c
+++ b/drivers/net/wireless/ath/ar9170/led.c
@@ -133,8 +133,8 @@
 	err = led_classdev_register(wiphy_dev(ar->hw->wiphy),
 				    &ar->leds[i].l);
 	if (err)
-		printk(KERN_ERR "%s: failed to register %s LED (%d).\n",
-		       wiphy_name(ar->hw->wiphy), ar->leds[i].name, err);
+		wiphy_err(ar->hw->wiphy, "failed to register %s LED (%d).\n",
+			  ar->leds[i].name, err);
 	else
 		ar->leds[i].registered = true;
 
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 2abc875..5e2c514 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -198,12 +198,13 @@
 	struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
 	struct ieee80211_hdr *hdr = (void *) txc->frame_data;
 
-	printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
-			  "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
-	       wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
-	       ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
-	       le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
-	       jiffies_to_msecs(arinfo->timeout - jiffies));
+	wiphy_debug(ar->hw->wiphy,
+		    "=> FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
+		    "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
+		    skb, skb_get_queue_mapping(skb),
+		    ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
+		    le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
+		    jiffies_to_msecs(arinfo->timeout - jiffies));
 }
 
 static void __ar9170_dump_txqueue(struct ar9170 *ar,
@@ -213,8 +214,8 @@
 	int i = 0;
 
 	printk(KERN_DEBUG "---[ cut here ]---\n");
-	printk(KERN_DEBUG "%s: %d entries in queue.\n",
-	       wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
+	wiphy_debug(ar->hw->wiphy, "%d entries in queue.\n",
+		    skb_queue_len(queue));
 
 	skb_queue_walk(queue, skb) {
 		printk(KERN_DEBUG "index:%d =>\n", i++);
@@ -244,15 +245,14 @@
 {
 	int i;
 
-	printk(KERN_DEBUG "%s: QoS queue stats\n",
-	       wiphy_name(ar->hw->wiphy));
+	wiphy_debug(ar->hw->wiphy, "qos queue stats\n");
 
 	for (i = 0; i < __AR9170_NUM_TXQ; i++)
-		printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
-		       " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
-		       ar->tx_stats[i].limit, ar->tx_stats[i].len,
-		       skb_queue_len(&ar->tx_status[i]),
-		       ieee80211_queue_stopped(ar->hw, i));
+		wiphy_debug(ar->hw->wiphy,
+			    "queue:%d limit:%d len:%d waitack:%d stopped:%d\n",
+			    i, ar->tx_stats[i].limit, ar->tx_stats[i].len,
+			    skb_queue_len(&ar->tx_status[i]),
+			    ieee80211_queue_stopped(ar->hw, i));
 }
 #endif /* AR9170_QUEUE_STOP_DEBUG */
 
@@ -274,9 +274,9 @@
 
 		if (time_is_before_jiffies(arinfo->timeout)) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
-			       "recycle\n", wiphy_name(ar->hw->wiphy),
-			       jiffies, arinfo->timeout);
+			wiphy_debug(ar->hw->wiphy,
+				    "[%ld > %ld] frame expired => recycle\n",
+				    jiffies, arinfo->timeout);
 			ar9170_print_txheader(ar, skb);
 #endif /* AR9170_QUEUE_DEBUG */
 			__skb_unlink(skb, queue);
@@ -317,8 +317,8 @@
 		break;
 
 	default:
-		printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
-		       wiphy_name(ar->hw->wiphy), tx_status);
+		wiphy_err(ar->hw->wiphy,
+			  "invalid tx_status response (%x)\n", tx_status);
 		break;
 	}
 
@@ -339,8 +339,7 @@
 
 	if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) {
 #ifdef AR9170_QUEUE_STOP_DEBUG
-		printk(KERN_DEBUG "%s: wake queue %d\n",
-		       wiphy_name(ar->hw->wiphy), queue);
+		wiphy_debug(ar->hw->wiphy, "wake queue %d\n", queue);
 		__ar9170_dump_txstats(ar);
 #endif /* AR9170_QUEUE_STOP_DEBUG */
 		ieee80211_wake_queue(ar->hw, queue);
@@ -387,9 +386,9 @@
 
 		if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
-			       wiphy_name(ar->hw->wiphy), mac,
-			       ieee80211_get_DA(hdr));
+			wiphy_debug(ar->hw->wiphy,
+				    "skip frame => da %pm != %pm\n",
+				    mac, ieee80211_get_DA(hdr));
 			ar9170_print_txheader(ar, skb);
 #endif /* AR9170_QUEUE_DEBUG */
 			continue;
@@ -400,8 +399,8 @@
 
 		if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
-			       wiphy_name(ar->hw->wiphy), rate, r);
+			wiphy_debug(ar->hw->wiphy,
+				    "skip frame => rate %d != %d\n", rate, r);
 			ar9170_print_txheader(ar, skb);
 #endif /* AR9170_QUEUE_DEBUG */
 			continue;
@@ -413,9 +412,9 @@
 	}
 
 #ifdef AR9170_QUEUE_DEBUG
-	printk(KERN_ERR "%s: ESS:[%pM] does not have any "
-			"outstanding frames in queue.\n",
-			wiphy_name(ar->hw->wiphy), mac);
+	wiphy_err(ar->hw->wiphy,
+		  "ESS:[%pM] does not have any outstanding frames in queue.\n",
+		  mac);
 	__ar9170_dump_txqueue(ar, queue);
 #endif /* AR9170_QUEUE_DEBUG */
 	spin_unlock_irqrestore(&queue->lock, flags);
@@ -444,8 +443,8 @@
 
 	for (i = 0; i < __AR9170_NUM_TXQ; i++) {
 #ifdef AR9170_QUEUE_DEBUG
-		printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
-		       wiphy_name(ar->hw->wiphy), i);
+		wiphy_debug(ar->hw->wiphy, "garbage collector scans queue:%d\n",
+			    i);
 		ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
 		ar9170_dump_txqueue(ar, &ar->tx_status[i]);
 #endif /* AR9170_QUEUE_DEBUG */
@@ -495,8 +494,9 @@
 		u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
 			AR9170_TX_PHY_QOS_SHIFT;
 #ifdef AR9170_QUEUE_DEBUG
-		printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
-		       wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
+		wiphy_debug(ar->hw->wiphy,
+			    "recv tx_status for %pm, p:%08x, q:%d\n",
+			    cmd->tx_status.dst, phy, q);
 #endif /* AR9170_QUEUE_DEBUG */
 
 		skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
@@ -582,7 +582,7 @@
 		break;
 
 	default:
-		printk(KERN_INFO "received unhandled event %x\n", cmd->type);
+		pr_info("received unhandled event %x\n", cmd->type);
 		print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
 		break;
 	}
@@ -675,9 +675,9 @@
 		/* TODO: update netdevice's RX dropped/errors statistics */
 
 		if (ar9170_nag_limiter(ar))
-			printk(KERN_DEBUG "%s: received frame with "
-			       "suspicious error code (%#x).\n",
-			       wiphy_name(ar->hw->wiphy), error);
+			wiphy_debug(ar->hw->wiphy,
+				    "received frame with suspicious error code (%#x).\n",
+				    error);
 
 		return -EINVAL;
 	}
@@ -704,9 +704,9 @@
 			break;
 		default:
 			if (ar9170_nag_limiter(ar))
-				printk(KERN_ERR "%s: invalid plcp cck rate "
-				       "(%x).\n", wiphy_name(ar->hw->wiphy),
-				       head->plcp[0]);
+				wiphy_err(ar->hw->wiphy,
+					  "invalid plcp cck rate (%x).\n",
+					  head->plcp[0]);
 			return -EINVAL;
 		}
 		break;
@@ -740,9 +740,9 @@
 			break;
 		default:
 			if (ar9170_nag_limiter(ar))
-				printk(KERN_ERR "%s: invalid plcp ofdm rate "
-				       "(%x).\n", wiphy_name(ar->hw->wiphy),
-				       head->plcp[0]);
+				wiphy_err(ar->hw->wiphy,
+					  "invalid plcp ofdm rate (%x).\n",
+					  head->plcp[0]);
 			return -EINVAL;
 		}
 		if (status->band == IEEE80211_BAND_2GHZ)
@@ -761,8 +761,7 @@
 
 	default:
 		if (ar9170_nag_limiter(ar))
-			printk(KERN_ERR "%s: invalid modulation\n",
-			       wiphy_name(ar->hw->wiphy));
+			wiphy_err(ar->hw->wiphy, "invalid modulation\n");
 		return -EINVAL;
 	}
 
@@ -863,8 +862,8 @@
 			ar->rx_mpdu.has_plcp = true;
 		} else {
 			if (ar9170_nag_limiter(ar))
-				printk(KERN_ERR "%s: plcp info is clipped.\n",
-				       wiphy_name(ar->hw->wiphy));
+				wiphy_err(ar->hw->wiphy,
+					  "plcp info is clipped.\n");
 			return ;
 		}
 		break;
@@ -877,8 +876,8 @@
 			phy = (void *)(buf + mpdu_len);
 		} else {
 			if (ar9170_nag_limiter(ar))
-				printk(KERN_ERR "%s: frame tail is clipped.\n",
-				       wiphy_name(ar->hw->wiphy));
+				wiphy_err(ar->hw->wiphy,
+					  "frame tail is clipped.\n");
 			return ;
 		}
 
@@ -888,9 +887,8 @@
 			if (!ar9170_nag_limiter(ar))
 				return ;
 
-			printk(KERN_ERR "%s: rx stream did not start "
-					"with a first_mpdu frame tag.\n",
-			       wiphy_name(ar->hw->wiphy));
+			wiphy_err(ar->hw->wiphy,
+				  "rx stream did not start with a first_mpdu frame tag.\n");
 
 			return ;
 		}
@@ -954,8 +952,8 @@
 			if (!ar->rx_failover_missing) {
 				/* this is no "short read". */
 				if (ar9170_nag_limiter(ar)) {
-					printk(KERN_ERR "%s: missing tag!\n",
-					       wiphy_name(ar->hw->wiphy));
+					wiphy_err(ar->hw->wiphy,
+						  "missing tag!\n");
 					goto err_telluser;
 				} else
 					goto err_silent;
@@ -963,9 +961,8 @@
 
 			if (ar->rx_failover_missing > tlen) {
 				if (ar9170_nag_limiter(ar)) {
-					printk(KERN_ERR "%s: possible multi "
-					       "stream corruption!\n",
-					       wiphy_name(ar->hw->wiphy));
+					wiphy_err(ar->hw->wiphy,
+						  "possible multi stream corruption!\n");
 					goto err_telluser;
 				} else
 					goto err_silent;
@@ -997,9 +994,8 @@
 			if (ar->rx_failover_missing) {
 				/* TODO: handle double stream corruption. */
 				if (ar9170_nag_limiter(ar)) {
-					printk(KERN_ERR "%s: double rx stream "
-					       "corruption!\n",
-						wiphy_name(ar->hw->wiphy));
+					wiphy_err(ar->hw->wiphy,
+						  "double rx stream corruption!\n");
 					goto err_telluser;
 				} else
 					goto err_silent;
@@ -1042,9 +1038,9 @@
 
 	if (tlen) {
 		if (net_ratelimit())
-			printk(KERN_ERR "%s: %d bytes of unprocessed "
-					"data left in rx stream!\n",
-			       wiphy_name(ar->hw->wiphy), tlen);
+			wiphy_err(ar->hw->wiphy,
+				  "%d bytes of unprocessed data left in rx stream!\n",
+				  tlen);
 
 		goto err_telluser;
 	}
@@ -1052,10 +1048,9 @@
 	return ;
 
 err_telluser:
-	printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
-			"data:%d, rx:%d, pending:%d ]\n",
-	       wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
-	       ar->rx_failover_missing);
+	wiphy_err(ar->hw->wiphy,
+		  "damaged RX stream data [want:%d, data:%d, rx:%d, pending:%d ]\n",
+		  clen, wlen, tlen, ar->rx_failover_missing);
 
 	if (ar->rx_failover_missing)
 		print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
@@ -1065,9 +1060,8 @@
 	print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
 			     skb->data, skb->len);
 
-	printk(KERN_ERR "%s: please check your hardware and cables, if "
-			"you see this message frequently.\n",
-	       wiphy_name(ar->hw->wiphy));
+	wiphy_err(ar->hw->wiphy,
+		  "If you see this message frequently, please check your hardware and cables.\n");
 
 err_silent:
 	if (ar->rx_failover_missing) {
@@ -1384,10 +1378,10 @@
 
 		if (remaining_space < frames) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
-			       "remaining slots:%d, needed:%d\n",
-			       wiphy_name(ar->hw->wiphy), i, remaining_space,
-			       frames);
+			wiphy_debug(ar->hw->wiphy,
+				    "tx quota reached queue:%d, "
+				    "remaining slots:%d, needed:%d\n",
+				    i, remaining_space, frames);
 #endif /* AR9170_QUEUE_DEBUG */
 			frames = remaining_space;
 		}
@@ -1396,18 +1390,14 @@
 		ar->tx_stats[i].count += frames;
 		if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: queue %d full\n",
-			       wiphy_name(ar->hw->wiphy), i);
-
-			printk(KERN_DEBUG "%s: stuck frames: ===>\n",
-			       wiphy_name(ar->hw->wiphy));
+			wiphy_debug(ar->hw->wiphy, "queue %d full\n", i);
+			wiphy_debug(ar->hw->wiphy, "stuck frames: ===>\n");
 			ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
 			ar9170_dump_txqueue(ar, &ar->tx_status[i]);
 #endif /* AR9170_QUEUE_DEBUG */
 
 #ifdef AR9170_QUEUE_STOP_DEBUG
-			printk(KERN_DEBUG "%s: stop queue %d\n",
-			       wiphy_name(ar->hw->wiphy), i);
+			wiphy_debug(ar->hw->wiphy, "stop queue %d\n", i);
 			__ar9170_dump_txstats(ar);
 #endif /* AR9170_QUEUE_STOP_DEBUG */
 			ieee80211_stop_queue(ar->hw, i);
@@ -1435,8 +1425,7 @@
 					  msecs_to_jiffies(AR9170_TX_TIMEOUT);
 
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: send frame q:%d =>\n",
-			       wiphy_name(ar->hw->wiphy), i);
+			wiphy_debug(ar->hw->wiphy, "send frame q:%d =>\n", i);
 			ar9170_print_txheader(ar, skb);
 #endif /* AR9170_QUEUE_DEBUG */
 
@@ -1453,26 +1442,25 @@
 		}
 
 #ifdef AR9170_QUEUE_DEBUG
-		printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
-		       wiphy_name(ar->hw->wiphy), i);
+		wiphy_debug(ar->hw->wiphy,
+			    "ar9170_tx report for queue %d\n", i);
 
-		printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
-		       wiphy_name(ar->hw->wiphy));
+		wiphy_debug(ar->hw->wiphy,
+			    "unprocessed pending frames left:\n");
 		ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
 #endif /* AR9170_QUEUE_DEBUG */
 
 		if (unlikely(frames_failed)) {
 #ifdef AR9170_QUEUE_DEBUG
-			printk(KERN_DEBUG "%s: frames failed %d =>\n",
-			       wiphy_name(ar->hw->wiphy), frames_failed);
+			wiphy_debug(ar->hw->wiphy,
+				    "frames failed %d =>\n", frames_failed);
 #endif /* AR9170_QUEUE_DEBUG */
 
 			spin_lock_irqsave(&ar->tx_stats_lock, flags);
 			ar->tx_stats[i].len -= frames_failed;
 			ar->tx_stats[i].count -= frames_failed;
 #ifdef AR9170_QUEUE_STOP_DEBUG
-			printk(KERN_DEBUG "%s: wake queue %d\n",
-			       wiphy_name(ar->hw->wiphy), i);
+			wiphy_debug(ar->hw->wiphy, "wake queue %d\n", i);
 			__ar9170_dump_txstats(ar);
 #endif /* AR9170_QUEUE_STOP_DEBUG */
 			ieee80211_wake_queue(ar->hw, i);
diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c
index 45a415e..0dbfcf7 100644
--- a/drivers/net/wireless/ath/ar9170/phy.c
+++ b/drivers/net/wireless/ath/ar9170/phy.c
@@ -670,8 +670,7 @@
 	ar9170_regwrite_finish();
 	err = ar9170_regwrite_result();
 	if (err)
-		printk(KERN_ERR "%s: rf init failed\n",
-		       wiphy_name(ar->hw->wiphy));
+		wiphy_err(ar->hw->wiphy, "rf init failed\n");
 	return err;
 }
 
@@ -1702,9 +1701,8 @@
 				       0x200 | ar->phy_heavy_clip);
 		if (err) {
 			if (ar9170_nag_limiter(ar))
-				printk(KERN_ERR "%s: failed to set "
-				       "heavy clip\n",
-				       wiphy_name(ar->hw->wiphy));
+				wiphy_err(ar->hw->wiphy,
+					  "failed to set heavy clip\n");
 		}
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 85fdd26..1a984b0 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -131,11 +131,8 @@
 
 	ah = sc->sc_ah;
 	ath9k_hw_name(ah, hw_name, sizeof(hw_name));
-	printk(KERN_INFO
-	       "%s: %s mem=0x%lx, irq=%d\n",
-	       wiphy_name(hw->wiphy),
-	       hw_name,
-	       (unsigned long)mem, irq);
+	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+		   hw_name, (unsigned long)mem, irq);
 
 	return 0;
 
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 257b10ba..b5b6514 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -209,11 +209,8 @@
 	}
 
 	ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
-	printk(KERN_INFO
-	       "%s: %s mem=0x%lx, irq=%d\n",
-	       wiphy_name(hw->wiphy),
-	       hw_name,
-	       (unsigned long)mem, pdev->irq);
+	wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
+		   hw_name, (unsigned long)mem, pdev->irq);
 
 	return 0;
 
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 600ee0b..e49be73 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -20,95 +20,145 @@
 #include "ath9k.h"
 
 static const struct ath_rate_table ar5416_11na_ratetable = {
-	43,
+	68,
 	8, /* MCS start */
 	{
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0, 12, 0, 0, 0, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800,  1, 18, 0, 1, 1, 1, 1 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 2, 24, 2, 2, 2, 2, 2 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 3, 36, 2, 3, 3, 3, 3 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 4, 48, 4, 4, 4, 4, 4 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 5, 72, 4, 5, 5, 5, 5 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 6, 96, 4, 6, 6, 6, 6 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 7, 108, 4, 7, 7, 7, 7 },
-		{ VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
-			6400, 0, 0, 0, 8, 25, 8, 25 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
-			12700, 1, 1, 2, 9, 26, 9, 26 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
-			18800, 2, 2, 2, 10, 27, 10, 27 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
-			25000, 3, 3, 4, 11, 28, 11, 28 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
-			36700, 4, 4, 4, 12, 29, 12, 29 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
-			48100, 5, 5, 4, 13, 30, 13, 30 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
-			53500, 6, 6, 4, 14, 31, 14, 31 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
-			59000, 7, 7, 4, 15, 32, 15, 33 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
-			12700, 8, 8, 3, 16, 34, 16, 34 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
-			24800, 9, 9, 2, 17, 35, 17, 35 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
-			36600, 10, 10, 2, 18, 36, 18, 36 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
-			48100, 11, 11, 4, 19, 37, 19, 37 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
-			69500, 12, 12, 4, 20, 38, 20, 38 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
-			89500, 13, 13, 4, 21, 39, 21, 39 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
-			98900, 14, 14, 4, 22, 40, 22, 40 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
-			108300, 15, 15, 4, 23, 41, 24, 42 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 144.4 Mb */
-			12000, 15, 15, 4, 23, 41, 24, 42 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
-			13200, 0, 0, 0, 8, 25, 25, 25 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
-			25900, 1, 1, 2, 9, 26, 26, 26 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
-			38600, 2, 2, 2, 10, 27, 27, 27 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
-			49800, 3, 3, 4, 11, 28, 28, 28 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
-			72200, 4, 4, 4, 12, 29, 29, 29 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
-			92900, 5, 5, 4, 13, 30, 30, 30 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
-			102700, 6, 6, 4, 14, 31, 31, 31 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
-			112000, 7, 7, 4, 15, 32, 33, 33 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
-			122000, 7, 7, 4, 15, 32, 33, 33 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
-			25800, 8, 8, 0, 16, 34, 34, 34 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
-			49800, 9, 9, 2, 17, 35, 35, 35 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
-			71900, 10, 10, 2, 18, 36, 36, 36 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
-			92500, 11, 11, 4, 19, 37, 37, 37 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
-			130300, 12, 12, 4, 20, 38, 38, 38 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
-			162800, 13, 13, 4, 21, 39, 39, 39 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
-			178200, 14, 14, 4, 22, 40, 40, 40 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
-			192100, 15, 15, 4, 23, 41, 42, 42 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
-			207000, 15, 15, 4, 23, 41, 42, 42 },
+		[0] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 6000,
+			5400, 0, 12, 0, 0, 0, 0 }, /* 6 Mb */
+		[1] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 9000,
+			7800,  1, 18, 0, 1, 1, 1 }, /* 9 Mb */
+		[2] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+			10000, 2, 24, 2, 2, 2, 2 }, /* 12 Mb */
+		[3] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+			13900, 3, 36, 2, 3, 3, 3 }, /* 18 Mb */
+		[4] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+			17300, 4, 48, 4, 4, 4, 4 }, /* 24 Mb */
+		[5] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+			23000, 5, 72, 4, 5, 5, 5 }, /* 36 Mb */
+		[6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+			27400, 6, 96, 4, 6, 6, 6 }, /* 48 Mb */
+		[7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+			29300, 7, 108, 4, 7, 7, 7 }, /* 54 Mb */
+		[8] = { RC_HT_SDT_2040, WLAN_RC_PHY_HT_20_SS, 6500,
+			6400, 0, 0, 0, 38, 8, 38 }, /* 6.5 Mb */
+		[9] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+			12700, 1, 1, 2, 39, 9, 39 }, /* 13 Mb */
+		[10] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+			18800, 2, 2, 2, 40, 10, 40 }, /* 19.5 Mb */
+		[11] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+			25000, 3, 3, 4, 41, 11, 41 }, /* 26 Mb */
+		[12] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+			36700, 4, 4, 4, 42, 12, 42 }, /* 39 Mb */
+		[13] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+			48100, 5, 5, 4, 43, 13, 43 }, /* 52 Mb */
+		[14] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+			53500, 6, 6, 4, 44, 14, 44 }, /* 58.5 Mb */
+		[15] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+			59000, 7, 7, 4, 45, 16, 46 }, /* 65 Mb */
+		[16] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+			65400, 7, 7, 4, 45, 16, 46 }, /* 75 Mb */
+		[17] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+			12700, 8, 8, 0, 47, 17, 47 }, /* 13 Mb */
+		[18] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+			24800, 9, 9, 2, 48, 18, 48 }, /* 26 Mb */
+		[19] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+			36600, 10, 10, 2, 49, 19, 49 }, /* 39 Mb */
+		[20] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+			48100, 11, 11, 4, 50, 20, 50 }, /* 52 Mb */
+		[21] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+			69500, 12, 12, 4, 51, 21, 51 }, /* 78 Mb */
+		[22] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+			89500, 13, 13, 4, 52, 22, 52 }, /* 104 Mb */
+		[23] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+			98900, 14, 14, 4, 53, 23, 53 }, /* 117 Mb */
+		[24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+			108300, 15, 15, 4, 54, 25, 55 }, /* 130 Mb */
+		[25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+			120000, 15, 15, 4, 54, 25, 55 }, /* 144.4 Mb */
+		[26] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+			17400, 16, 16, 0, 56, 26, 56 }, /* 19.5 Mb */
+		[27] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+			35100, 17, 17, 2, 57, 27, 57 }, /* 39 Mb */
+		[28] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+			52600, 18, 18, 2, 58, 28, 58 }, /* 58.5 Mb */
+		[29] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+			70400, 19, 19, 4, 59, 29, 59 }, /* 78 Mb */
+		[30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+			104900, 20, 20, 4, 60, 31, 61 }, /* 117 Mb */
+		[31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+			115800, 20, 20, 4, 60, 31, 61 }, /* 130 Mb*/
+		[32] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+			137200, 21, 21, 4, 62, 33, 63 }, /* 156 Mb */
+		[33] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+			151100, 21, 21, 4, 62, 33, 63 }, /* 173.3 Mb */
+		[34] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+			152800, 22, 22, 4, 64, 35, 65 }, /* 175.5 Mb */
+		[35] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+			168400, 22, 22, 4, 64, 35, 65 }, /* 195 Mb*/
+		[36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+			168400, 23, 23, 4, 66, 37, 67 }, /* 195 Mb */
+		[37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+			185000, 23, 23, 4, 66, 37, 67 }, /* 216.7 Mb */
+		[38] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+			13200, 0, 0, 0, 38, 38, 38 }, /* 13.5 Mb*/
+		[39] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+			25900, 1, 1, 2, 39, 39, 39 }, /* 27.0 Mb*/
+		[40] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+			38600, 2, 2, 2, 40, 40, 40 }, /* 40.5 Mb*/
+		[41] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+			49800, 3, 3, 4, 41, 41, 41 }, /* 54 Mb */
+		[42] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+			72200, 4, 4, 4, 42, 42, 42 }, /* 81 Mb */
+		[43] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 108000,
+			92900, 5, 5, 4, 43, 43, 43 }, /* 108 Mb */
+		[44] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+			102700, 6, 6, 4, 44, 44, 44 }, /* 121.5 Mb*/
+		[45] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+			112000, 7, 7, 4, 45, 46, 46 }, /* 135 Mb */
+		[46] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+			122000, 7, 7, 4, 45, 46, 46 }, /* 150 Mb */
+		[47] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+			25800, 8, 8, 0, 47, 47, 47 }, /* 27 Mb */
+		[48] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+			49800, 9, 9, 2, 48, 48, 48 }, /* 54 Mb */
+		[49] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+			71900, 10, 10, 2, 49, 49, 49 }, /* 81 Mb */
+		[50] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+			92500, 11, 11, 4, 50, 50, 50 }, /* 108 Mb */
+		[51] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+			130300, 12, 12, 4, 51, 51, 51 }, /* 162 Mb */
+		[52] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+			162800, 13, 13, 4, 52, 52, 52 }, /* 216 Mb */
+		[53] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+			178200, 14, 14, 4, 53, 53, 53 }, /* 243 Mb */
+		[54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+			192100, 15, 15, 4, 54, 55, 55 }, /* 270 Mb */
+		[55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+			207000, 15, 15, 4, 54, 55, 55 }, /* 300 Mb */
+		[56] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+			36100, 16, 16, 0, 56, 56, 56 }, /* 40.5 Mb */
+		[57] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+			72900, 17, 17, 2, 57, 57, 57 }, /* 81 Mb */
+		[58] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+			108300, 18, 18, 2, 58, 58, 58 }, /* 121.5 Mb */
+		[59] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+			142000, 19, 19, 4, 59, 59, 59 }, /*  162 Mb */
+		[60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+			205100, 20, 20, 4, 60, 61, 61 }, /*  243 Mb */
+		[61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+			224700, 20, 20, 4, 60, 61, 61 }, /*  270 Mb */
+		[62] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+			263100, 21, 21, 4, 62, 63, 63 }, /*  324 Mb */
+		[63] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+			288000, 21, 21, 4, 62, 63, 63 }, /*  360 Mb */
+		[64] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+			290700, 22, 22, 4, 64, 65, 65 }, /* 364.5 Mb */
+		[65] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+			317200, 22, 22, 4, 64, 65, 65 }, /* 405 Mb */
+		[66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+			317200, 23, 23, 4, 66, 67, 67 }, /* 405 Mb */
+		[67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+			346400, 23, 23, 4, 66, 67, 67 }, /* 450 Mb */
 	},
 	50,  /* probe interval */
 	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
@@ -118,103 +168,153 @@
  * for HT are the 64K max aggregate limit */
 
 static const struct ath_rate_table ar5416_11ng_ratetable = {
-	47,
+	72,
 	12, /* MCS start */
 	{
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0, 2, 0, 0, 0, 0, 0 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1900, 1, 4, 1, 1, 1, 1, 1 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4900, 2, 11, 2, 2, 2, 2, 2 },
-		{ VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			8100, 3, 22, 3, 3, 3, 3, 3 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 4, 12, 4, 4, 4, 4, 4 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 5, 18, 4, 5, 5, 5, 5 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10100, 6, 24, 6, 6, 6, 6, 6 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			14100, 7, 36, 6, 7, 7, 7, 7 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17700, 8, 48, 8, 8, 8, 8, 8 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23700, 9, 72, 8, 9, 9, 9, 9 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 10, 96, 8, 10, 10, 10, 10 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			30900, 11, 108, 8, 11, 11, 11, 11 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
-			6400, 0, 0, 4, 12, 29, 12, 29 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
-			12700, 1, 1, 6, 13, 30, 13, 30 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
-			18800, 2, 2, 6, 14, 31, 14, 31 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
-			25000, 3, 3, 8, 15, 32, 15, 32 },
-		{ VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
-			36700, 4, 4, 8, 16, 33, 16, 33 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
-			48100, 5, 5, 8, 17, 34, 17, 34 },
-		{ INVALID,  VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
-			53500, 6, 6, 8, 18, 35, 18, 35 },
-		{ INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
-			59000, 7, 7, 8, 19, 36, 19, 37 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
-			12700, 8, 8, 4, 20, 38, 20, 38 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
-			24800, 9, 9, 6, 21, 39, 21, 39 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
-			36600, 10, 10, 6, 22, 40, 22, 40 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
-			48100, 11, 11, 8, 23, 41, 23, 41 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
-			69500, 12, 12, 8, 24, 42, 24, 42 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
-			89500, 13, 13, 8, 25, 43, 25, 43 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
-			98900, 14, 14, 8, 26, 44, 26, 44 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
-			108300, 15, 15, 8, 27, 45, 28, 46 },
-		{ VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS_HGI, 144400, /* 130 Mb */
-			120000, 15, 15, 8, 27, 45, 28, 46 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
-			13200, 0, 0, 8, 12, 29, 29, 29 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
-			25900, 1, 1, 8, 13, 30, 30, 30 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
-			38600, 2, 2, 8, 14, 31, 31, 31 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
-			49800, 3, 3, 8,  15, 32, 32, 32 },
-		{ VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
-			72200, 4, 4, 8, 16, 33, 33, 33 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
-			92900, 5, 5, 8, 17, 34, 34, 34 },
-		{ INVALID,  VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
-			102700, 6, 6, 8, 18, 35, 35, 35 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
-			112000, 7, 7, 8, 19, 36, 37, 37 },
-		{ INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
-			122000, 7, 7, 8, 19, 36, 37, 37 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
-			25800, 8, 8, 8, 20, 38, 38, 38 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
-			49800, 9, 9, 8, 21, 39, 39, 39 },
-		{ INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
-			71900, 10, 10, 8, 22, 40, 40, 40 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
-			92500, 11, 11, 8, 23, 41, 41, 41 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
-			130300, 12, 12, 8, 24, 42, 42, 42 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
-			162800, 13, 13, 8, 25, 43, 43, 43 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
-			178200, 14, 14, 8, 26, 44, 44, 44 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
-			192100, 15, 15, 8, 27, 45, 46, 46 },
-		{ VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
-			207000, 15, 15, 8, 27, 45, 46, 46 },
+		[0] = { RC_ALL, WLAN_RC_PHY_CCK, 1000,
+			900, 0, 2, 0, 0, 0, 0 }, /* 1 Mb */
+		[1] = { RC_ALL, WLAN_RC_PHY_CCK, 2000,
+			1900, 1, 4, 1, 1, 1, 1 }, /* 2 Mb */
+		[2] = { RC_ALL, WLAN_RC_PHY_CCK, 5500,
+			4900, 2, 11, 2, 2, 2, 2 }, /* 5.5 Mb */
+		[3] = { RC_ALL, WLAN_RC_PHY_CCK, 11000,
+			8100, 3, 22, 3, 3, 3, 3 }, /* 11 Mb */
+		[4] = { RC_INVALID, WLAN_RC_PHY_OFDM, 6000,
+			5400, 4, 12, 4, 4, 4, 4 }, /* 6 Mb */
+		[5] = { RC_INVALID, WLAN_RC_PHY_OFDM, 9000,
+			7800, 5, 18, 4, 5, 5, 5 }, /* 9 Mb */
+		[6] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 12000,
+			10100, 6, 24, 6, 6, 6, 6 }, /* 12 Mb */
+		[7] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 18000,
+			14100, 7, 36, 6, 7, 7, 7 }, /* 18 Mb */
+		[8] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 24000,
+			17700, 8, 48, 8, 8, 8, 8 }, /* 24 Mb */
+		[9] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 36000,
+			23700, 9, 72, 8, 9, 9, 9 }, /* 36 Mb */
+		[10] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 48000,
+			27400, 10, 96, 8, 10, 10, 10 }, /* 48 Mb */
+		[11] = { RC_L_SDT, WLAN_RC_PHY_OFDM, 54000,
+			30900, 11, 108, 8, 11, 11, 11 }, /* 54 Mb */
+		[12] = { RC_INVALID, WLAN_RC_PHY_HT_20_SS, 6500,
+			6400, 0, 0, 4, 42, 12, 42 }, /* 6.5 Mb */
+		[13] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 13000,
+			12700, 1, 1, 6, 43, 13, 43 }, /* 13 Mb */
+		[14] = { RC_HT_SDT_20, WLAN_RC_PHY_HT_20_SS, 19500,
+			18800, 2, 2, 6, 44, 14, 44 }, /* 19.5 Mb*/
+		[15] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 26000,
+			25000, 3, 3, 8, 45, 15, 45 }, /* 26 Mb */
+		[16] = { RC_HT_SD_20, WLAN_RC_PHY_HT_20_SS, 39000,
+			36700, 4, 4, 8, 46, 16, 46 }, /* 39 Mb */
+		[17] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 52000,
+			48100, 5, 5, 8, 47, 17, 47 }, /* 52 Mb */
+		[18] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 58500,
+			53500, 6, 6, 8, 48, 18, 48 }, /* 58.5 Mb */
+		[19] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS, 65000,
+			59000, 7, 7, 8, 49, 20, 50 }, /* 65 Mb */
+		[20] = { RC_HT_S_20, WLAN_RC_PHY_HT_20_SS_HGI, 72200,
+			65400, 7, 7, 8, 49, 20, 50 }, /* 65 Mb*/
+		[21] = { RC_INVALID, WLAN_RC_PHY_HT_20_DS, 13000,
+			12700, 8, 8, 4, 51, 21, 51 }, /* 13 Mb */
+		[22] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 26000,
+			24800, 9, 9, 6, 52, 22, 52 }, /* 26 Mb */
+		[23] = { RC_HT_T_20, WLAN_RC_PHY_HT_20_DS, 39000,
+			36600, 10, 10, 6, 53, 23, 53 }, /* 39 Mb */
+		[24] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 52000,
+			48100, 11, 11, 8, 54, 24, 54 }, /* 52 Mb */
+		[25] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 78000,
+			69500, 12, 12, 8, 55, 25, 55 }, /* 78 Mb */
+		[26] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 104000,
+			89500, 13, 13, 8, 56, 26, 56 }, /* 104 Mb */
+		[27] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 117000,
+			98900, 14, 14, 8, 57, 27, 57 }, /* 117 Mb */
+		[28] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS, 130000,
+			108300, 15, 15, 8, 58, 29, 59 }, /* 130 Mb */
+		[29] = { RC_HT_DT_20, WLAN_RC_PHY_HT_20_DS_HGI, 144400,
+			120000, 15, 15, 8, 58, 29, 59 }, /* 144.4 Mb */
+		[30] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 19500,
+			17400, 16, 16, 4, 60, 30, 60 }, /* 19.5 Mb */
+		[31] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 39000,
+			35100, 17, 17, 6, 61, 31, 61 }, /* 39 Mb */
+		[32] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 58500,
+			52600, 18, 18, 6, 62, 32, 62 }, /* 58.5 Mb */
+		[33] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 78000,
+			70400, 19, 19, 8, 63, 33, 63 }, /* 78 Mb */
+		[34] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS, 117000,
+			104900, 20, 20, 8, 64, 35, 65 }, /* 117 Mb */
+		[35] = {  RC_INVALID, WLAN_RC_PHY_HT_20_TS_HGI, 130000,
+			115800, 20, 20, 8, 64, 35, 65 }, /* 130 Mb */
+		[36] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 156000,
+			137200, 21, 21, 8, 66, 37, 67 }, /* 156 Mb */
+		[37] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 173300,
+			151100, 21, 21, 8, 66, 37, 67 }, /* 173.3 Mb */
+		[38] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 175500,
+			152800, 22, 22, 8, 68, 39, 69 }, /* 175.5 Mb */
+		[39] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 195000,
+			168400, 22, 22, 8, 68, 39, 69 }, /* 195 Mb */
+		[40] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS, 195000,
+			168400, 23, 23, 8, 70, 41, 71 }, /* 195 Mb */
+		[41] = {  RC_HT_T_20, WLAN_RC_PHY_HT_20_TS_HGI, 216700,
+			185000, 23, 23, 8, 70, 41, 71 }, /* 216.7 Mb */
+		[42] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 13500,
+			13200, 0, 0, 8, 42, 42, 42 }, /* 13.5 Mb */
+		[43] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 27500,
+			25900, 1, 1, 8, 43, 43, 43 }, /* 27.0 Mb */
+		[44] = { RC_HT_SDT_40, WLAN_RC_PHY_HT_40_SS, 40500,
+			38600, 2, 2, 8, 44, 44, 44 }, /* 40.5 Mb */
+		[45] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 54000,
+			49800, 3, 3, 8, 45, 45, 45 }, /* 54 Mb */
+		[46] = { RC_HT_SD_40, WLAN_RC_PHY_HT_40_SS, 81500,
+			72200, 4, 4, 8, 46, 46, 46 }, /* 81 Mb */
+		[47] = { RC_HT_S_40 , WLAN_RC_PHY_HT_40_SS, 108000,
+			92900, 5, 5, 8, 47, 47, 47 }, /* 108 Mb */
+		[48] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 121500,
+			102700, 6, 6, 8, 48, 48, 48 }, /* 121.5 Mb */
+		[49] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS, 135000,
+			112000, 7, 7, 8, 49, 50, 50 }, /* 135 Mb */
+		[50] = { RC_HT_S_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000,
+			122000, 7, 7, 8, 49, 50, 50 }, /* 150 Mb */
+		[51] = { RC_INVALID, WLAN_RC_PHY_HT_40_DS, 27000,
+			25800, 8, 8, 8, 51, 51, 51 }, /* 27 Mb */
+		[52] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 54000,
+			49800, 9, 9, 8, 52, 52, 52 }, /* 54 Mb */
+		[53] = { RC_HT_T_40, WLAN_RC_PHY_HT_40_DS, 81000,
+			71900, 10, 10, 8, 53, 53, 53 }, /* 81 Mb */
+		[54] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 108000,
+			92500, 11, 11, 8, 54, 54, 54 }, /* 108 Mb */
+		[55] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 162000,
+			130300, 12, 12, 8, 55, 55, 55 }, /* 162 Mb */
+		[56] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 216000,
+			162800, 13, 13, 8, 56, 56, 56 }, /* 216 Mb */
+		[57] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 243000,
+			178200, 14, 14, 8, 57, 57, 57 }, /* 243 Mb */
+		[58] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS, 270000,
+			192100, 15, 15, 8, 58, 59, 59 }, /* 270 Mb */
+		[59] = { RC_HT_DT_40, WLAN_RC_PHY_HT_40_DS_HGI, 300000,
+			207000, 15, 15, 8, 58, 59, 59 }, /* 300 Mb */
+		[60] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 40500,
+			36100, 16, 16, 8, 60, 60, 60 }, /* 40.5 Mb */
+		[61] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 81000,
+			72900, 17, 17, 8, 61, 61, 61 }, /* 81 Mb */
+		[62] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 121500,
+			108300, 18, 18, 8, 62, 62, 62 }, /* 121.5 Mb */
+		[63] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 162000,
+			142000, 19, 19, 8, 63, 63, 63 }, /* 162 Mb */
+		[64] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS, 243000,
+			205100, 20, 20, 8, 64, 65, 65 }, /* 243 Mb */
+		[65] = {  RC_INVALID, WLAN_RC_PHY_HT_40_TS_HGI, 270000,
+			224700, 20, 20, 8, 64, 65, 65 }, /* 170 Mb */
+		[66] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 324000,
+			263100, 21, 21, 8, 66, 67, 67 }, /* 324 Mb */
+		[67] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 360000,
+			288000, 21, 21, 8, 66, 67, 67 }, /* 360 Mb */
+		[68] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 364500,
+			290700, 22, 22, 8, 68, 69, 69 }, /* 364.5 Mb */
+		[69] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 405000,
+			317200, 22, 22, 8, 68, 69, 69 }, /* 405 Mb */
+		[70] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS, 405000,
+			317200, 23, 23, 8, 70, 71, 71 }, /* 405 Mb */
+		[71] = {  RC_HT_T_40, WLAN_RC_PHY_HT_40_TS_HGI, 450000,
+			346400, 23, 23, 8, 70, 71, 71 }, /* 450 Mb */
 	},
 	50,  /* probe interval */
 	WLAN_RC_HT_FLAG,  /* Phy rates allowed initially */
@@ -224,22 +324,22 @@
 	8,
 	0,
 	{
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 0, 12, 0, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800,  1, 18, 0, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 2, 24, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 3, 36, 2, 3, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 4, 48, 4, 4, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 5, 72, 4, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 6, 96, 4, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 7, 108, 4, 7, 0 },
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 0, 12, 0},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800,  1, 18, 0},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10000, 2, 24, 2},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			13900, 3, 36, 2},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17300, 4, 48, 4},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23000, 5, 72, 4},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 6, 96, 4},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			29300, 7, 108, 4},
 	},
 	50,  /* probe interval */
 	0,   /* Phy rates allowed initially */
@@ -249,30 +349,30 @@
 	12,
 	0,
 	{
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
-			900, 0, 2, 0, 0, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
-			1900, 1, 4, 1, 1, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
-			4900, 2, 11, 2, 2, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
-			8100, 3, 22, 3, 3, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
-			5400, 4, 12, 4, 4, 0 },
-		{ INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
-			7800, 5, 18, 4, 5, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
-			10000, 6, 24, 6, 6, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
-			13900, 7, 36, 6, 7, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
-			17300, 8, 48, 8, 8, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
-			23000, 9, 72, 8, 9, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
-			27400, 10, 96, 8, 10, 0 },
-		{ VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
-			29300, 11, 108, 8, 11, 0 },
+		{ RC_L_SDT, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
+			900, 0, 2, 0},
+		{ RC_L_SDT, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
+			1900, 1, 4, 1},
+		{ RC_L_SDT, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
+			4900, 2, 11, 2},
+		{ RC_L_SDT, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
+			8100, 3, 22, 3},
+		{ RC_INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
+			5400, 4, 12, 4},
+		{ RC_INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
+			7800, 5, 18, 4},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
+			10000, 6, 24, 6},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
+			13900, 7, 36, 6},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
+			17300, 8, 48, 8},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
+			23000, 9, 72, 8},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
+			27400, 10, 96, 8},
+		{ RC_L_SDT, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
+			29300, 11, 108, 8},
 	},
 	50,  /* probe interval */
 	0,   /* Phy rates allowed initially */
@@ -342,7 +442,7 @@
 					   u8 index, int valid_tx_rate)
 {
 	BUG_ON(index > ath_rc_priv->rate_table_size);
-	ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
+	ath_rc_priv->valid_rate_index[index] = !!valid_tx_rate;
 }
 
 static inline
@@ -374,6 +474,8 @@
 		return 0;
 	if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
 		return 0;
+	if (WLAN_RC_PHY_TS(phy) && !(capflag & WLAN_RC_TS_FLAG))
+		return 0;
 	if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
 		return 0;
 	if (!ignore_cw && WLAN_RC_PHY_HT(phy))
@@ -404,13 +506,9 @@
 				 u32 capflag)
 {
 	u8 i, hi = 0;
-	u32 valid;
 
 	for (i = 0; i < rate_table->rate_cnt; i++) {
-		valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
-			 rate_table->info[i].valid_single_stream :
-			 rate_table->info[i].valid);
-		if (valid == 1) {
+		if (rate_table->info[i].rate_flags & RC_LEGACY) {
 			u32 phy = rate_table->info[i].phy;
 			u8 valid_rate_count = 0;
 
@@ -422,7 +520,7 @@
 			ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
 			ath_rc_priv->valid_phy_ratecnt[phy] += 1;
 			ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
-			hi = A_MAX(hi, i);
+			hi = i;
 		}
 	}
 
@@ -440,9 +538,7 @@
 	for (i = 0; i < rateset->rs_nrates; i++) {
 		for (j = 0; j < rate_table->rate_cnt; j++) {
 			u32 phy = rate_table->info[j].phy;
-			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
-				     rate_table->info[j].valid_single_stream :
-				     rate_table->info[j].valid);
+			u16 rate_flags = rate_table->info[i].rate_flags;
 			u8 rate = rateset->rs_rates[i];
 			u8 dot11rate = rate_table->info[j].dot11rate;
 
@@ -451,8 +547,9 @@
 			 * (VALID/VALID_20/VALID_40) flags */
 
 			if ((rate == dot11rate) &&
-			    ((valid & WLAN_RC_CAP_MODE(capflag)) ==
-			     WLAN_RC_CAP_MODE(capflag)) &&
+			    (rate_flags & WLAN_RC_CAP_MODE(capflag)) ==
+			    WLAN_RC_CAP_MODE(capflag) &&
+			    (rate_flags & WLAN_RC_CAP_STREAM(capflag)) &&
 			    !WLAN_RC_PHY_HT(phy)) {
 				u8 valid_rate_count = 0;
 
@@ -486,14 +583,13 @@
 	for (i = 0; i < rateset->rs_nrates; i++) {
 		for (j = 0; j < rate_table->rate_cnt; j++) {
 			u32 phy = rate_table->info[j].phy;
-			u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ?
-				     rate_table->info[j].valid_single_stream :
-				     rate_table->info[j].valid);
+			u16 rate_flags = rate_table->info[j].rate_flags;
 			u8 rate = rateset->rs_rates[i];
 			u8 dot11rate = rate_table->info[j].dot11rate;
 
 			if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) ||
-			    !WLAN_RC_PHY_HT_VALID(valid, capflag))
+			    !(rate_flags & WLAN_RC_CAP_STREAM(capflag)) ||
+			    !WLAN_RC_PHY_HT_VALID(rate_flags, capflag))
 				continue;
 
 			if (!ath_rc_valid_phyrate(phy, capflag, 0))
@@ -589,12 +685,15 @@
 	if (rate > (ath_rc_priv->rate_table_size - 1))
 		rate = ath_rc_priv->rate_table_size - 1;
 
-	if (rate_table->info[rate].valid &&
-	    (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
+	if (RC_TS_ONLY(rate_table->info[rate].rate_flags) &&
+	    (ath_rc_priv->ht_cap & WLAN_RC_TS_FLAG))
 		return rate;
 
-	if (rate_table->info[rate].valid_single_stream &&
-	    !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
+	if (RC_DS_OR_LATER(rate_table->info[rate].rate_flags) &&
+	    (ath_rc_priv->ht_cap & (WLAN_RC_DS_FLAG | WLAN_RC_TS_FLAG)))
+		return rate;
+
+	if (RC_SS_OR_LEGACY(rate_table->info[rate].rate_flags))
 		return rate;
 
 	/* This should not happen */
@@ -1007,12 +1106,19 @@
 static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
 				struct ieee80211_tx_rate *rate)
 {
-	int rix;
+	int rix = 0, i = 0;
+	int mcs_rix_off[] = { 7, 15, 20, 21, 22, 23 };
 
 	if (!(rate->flags & IEEE80211_TX_RC_MCS))
 		return rate->idx;
 
-	rix = rate->idx + rate_table->mcs_start;
+	while (rate->idx > mcs_rix_off[i] &&
+	      i < sizeof(mcs_rix_off)/sizeof(int)) {
+		rix++; i++;
+	}
+
+	rix += rate->idx + rate_table->mcs_start;
+
 	if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
 	    (rate->flags & IEEE80211_TX_RC_SHORT_GI))
 		rix = rate_table->info[rix].ht_index;
@@ -1020,8 +1126,6 @@
 		rix = rate_table->info[rix].sgi_index;
 	else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
 		rix = rate_table->info[rix].cw40index;
-	else
-		rix = rate_table->info[rix].base_index;
 
 	return rix;
 }
@@ -1203,13 +1307,14 @@
 
 	if (sta->ht_cap.ht_supported) {
 		caps = WLAN_RC_HT_FLAG;
-		if (sta->ht_cap.mcs.rx_mask[1])
+		if (sta->ht_cap.mcs.rx_mask[1] && sta->ht_cap.mcs.rx_mask[2])
+			caps |= WLAN_RC_TS_FLAG | WLAN_RC_DS_FLAG;
+		else if (sta->ht_cap.mcs.rx_mask[1])
 			caps |= WLAN_RC_DS_FLAG;
 		if (is_cw40)
 			caps |= WLAN_RC_40_FLAG;
 		if (is_sgi)
 			caps |= WLAN_RC_SGI_FLAG;
-
 	}
 
 	return caps;
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 3d8d40c..dc10826 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -24,32 +24,63 @@
 struct ath_softc;
 
 #define ATH_RATE_MAX     30
-#define RATE_TABLE_SIZE  64
+#define RATE_TABLE_SIZE  72
 #define MAX_TX_RATE_PHY  48
 
-/* VALID_ALL - valid for 20/40/Legacy,
- * VALID - Legacy only,
- * VALID_20 - HT 20 only,
- * VALID_40 - HT 40 only */
 
-#define INVALID    0x0
-#define VALID      0x1
-#define VALID_20   0x2
-#define VALID_40   0x4
-#define VALID_2040 (VALID_20|VALID_40)
-#define VALID_ALL  (VALID_2040|VALID)
+#define RC_INVALID	0x0000
+#define RC_LEGACY	0x0001
+#define RC_SS		0x0002
+#define RC_DS		0x0004
+#define RC_TS		0x0008
+#define RC_HT_20	0x0010
+#define RC_HT_40	0x0020
+
+#define RC_STREAM_MASK	0xe
+#define RC_DS_OR_LATER(f)	((((f) & RC_STREAM_MASK) == RC_DS) || \
+				(((f) & RC_STREAM_MASK) == (RC_DS | RC_TS)))
+#define RC_TS_ONLY(f)		(((f) & RC_STREAM_MASK) == RC_TS)
+#define RC_SS_OR_LEGACY(f)	((f) & (RC_SS | RC_LEGACY))
+
+#define RC_HT_2040		(RC_HT_20 | RC_HT_40)
+#define RC_ALL_STREAM		(RC_SS | RC_DS | RC_TS)
+#define RC_L_SD			(RC_LEGACY | RC_SS | RC_DS)
+#define RC_L_SDT		(RC_LEGACY | RC_SS | RC_DS | RC_TS)
+#define RC_HT_S_20		(RC_HT_20 | RC_SS)
+#define RC_HT_D_20		(RC_HT_20 | RC_DS)
+#define RC_HT_T_20		(RC_HT_20 | RC_TS)
+#define RC_HT_S_40		(RC_HT_40 | RC_SS)
+#define RC_HT_D_40		(RC_HT_40 | RC_DS)
+#define RC_HT_T_40		(RC_HT_40 | RC_TS)
+
+#define RC_HT_SD_20		(RC_HT_20 | RC_SS | RC_DS)
+#define RC_HT_DT_20		(RC_HT_20 | RC_DS | RC_TS)
+#define RC_HT_SD_40		(RC_HT_40 | RC_SS | RC_DS)
+#define RC_HT_DT_40		(RC_HT_40 | RC_DS | RC_TS)
+
+#define RC_HT_SD_2040		(RC_HT_2040 | RC_SS | RC_DS)
+#define RC_HT_SDT_2040		(RC_HT_2040 | RC_SS | RC_DS | RC_TS)
+
+#define RC_HT_SDT_20		(RC_HT_20 | RC_SS | RC_DS | RC_TS)
+#define RC_HT_SDT_40		(RC_HT_40 | RC_SS | RC_DS | RC_TS)
+
+#define RC_ALL			(RC_LEGACY | RC_HT_2040 | RC_ALL_STREAM)
 
 enum {
 	WLAN_RC_PHY_OFDM,
 	WLAN_RC_PHY_CCK,
 	WLAN_RC_PHY_HT_20_SS,
 	WLAN_RC_PHY_HT_20_DS,
+	WLAN_RC_PHY_HT_20_TS,
 	WLAN_RC_PHY_HT_40_SS,
 	WLAN_RC_PHY_HT_40_DS,
+	WLAN_RC_PHY_HT_40_TS,
 	WLAN_RC_PHY_HT_20_SS_HGI,
 	WLAN_RC_PHY_HT_20_DS_HGI,
+	WLAN_RC_PHY_HT_20_TS_HGI,
 	WLAN_RC_PHY_HT_40_SS_HGI,
 	WLAN_RC_PHY_HT_40_DS_HGI,
+	WLAN_RC_PHY_HT_40_TS_HGI,
 	WLAN_RC_PHY_MAX
 };
 
@@ -57,36 +88,50 @@
 				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
 				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
 				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+#define WLAN_RC_PHY_TS(_phy)   ((_phy == WLAN_RC_PHY_HT_20_TS)		\
+				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
+				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
 #define WLAN_RC_PHY_20(_phy)   ((_phy == WLAN_RC_PHY_HT_20_SS)		\
 				|| (_phy == WLAN_RC_PHY_HT_20_DS)	\
+				|| (_phy == WLAN_RC_PHY_HT_20_TS)	\
 				|| (_phy == WLAN_RC_PHY_HT_20_SS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI))
+				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)	\
+				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI))
 #define WLAN_RC_PHY_40(_phy)   ((_phy == WLAN_RC_PHY_HT_40_SS)		\
 				|| (_phy == WLAN_RC_PHY_HT_40_DS)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_TS)	\
 				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)	\
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)	\
+				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
 #define WLAN_RC_PHY_SGI(_phy)  ((_phy == WLAN_RC_PHY_HT_20_SS_HGI)      \
 				|| (_phy == WLAN_RC_PHY_HT_20_DS_HGI)   \
+				|| (_phy == WLAN_RC_PHY_HT_20_TS_HGI)   \
 				|| (_phy == WLAN_RC_PHY_HT_40_SS_HGI)   \
-				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI))
+				|| (_phy == WLAN_RC_PHY_HT_40_DS_HGI)   \
+				|| (_phy == WLAN_RC_PHY_HT_40_TS_HGI))
 
 #define WLAN_RC_PHY_HT(_phy)    (_phy >= WLAN_RC_PHY_HT_20_SS)
 
 #define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ?	\
-		(capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
+	((capflag & WLAN_RC_40_FLAG) ? RC_HT_40 : RC_HT_20) : RC_LEGACY))
+
+#define WLAN_RC_CAP_STREAM(capflag) (((capflag & WLAN_RC_TS_FLAG) ?	\
+	(RC_TS) : ((capflag & WLAN_RC_DS_FLAG) ? RC_DS : RC_SS)))
 
 /* Return TRUE if flag supports HT20 && client supports HT20 or
  * return TRUE if flag supports HT40 && client supports HT40.
  * This is used becos some rates overlap between HT20/HT40.
  */
 #define WLAN_RC_PHY_HT_VALID(flag, capflag)			\
-	(((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
-	 ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
+	(((flag & RC_HT_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+	 ((flag & RC_HT_40) && (capflag & WLAN_RC_40_FLAG)))
 
 #define WLAN_RC_DS_FLAG         (0x01)
-#define WLAN_RC_40_FLAG         (0x02)
-#define WLAN_RC_SGI_FLAG        (0x04)
-#define WLAN_RC_HT_FLAG         (0x08)
+#define WLAN_RC_TS_FLAG         (0x02)
+#define WLAN_RC_40_FLAG         (0x04)
+#define WLAN_RC_SGI_FLAG        (0x08)
+#define WLAN_RC_HT_FLAG         (0x10)
 
 /**
  * struct ath_rate_table - Rate Control table
@@ -110,15 +155,13 @@
 	int rate_cnt;
 	int mcs_start;
 	struct {
-		u8 valid;
-		u8 valid_single_stream;
+		u16 rate_flags;
 		u8 phy;
 		u32 ratekbps;
 		u32 user_ratekbps;
 		u8 ratecode;
 		u8 dot11rate;
 		u8 ctrl_rate;
-		u8 base_index;
 		u8 cw40index;
 		u8 sgi_index;
 		u8 ht_index;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 9a78189..35337b1e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -4417,19 +4419,18 @@
 {
 
 	int ret;
-	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
-	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
 
 	ret = iwlagn_rate_control_register();
 	if (ret) {
-		printk(KERN_ERR DRV_NAME
-		       "Unable to register rate control algorithm: %d\n", ret);
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
 		return ret;
 	}
 
 	ret = pci_register_driver(&iwl_driver);
 	if (ret) {
-		printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
+		pr_err("Unable to initialize PCI module\n");
 		goto error_register;
 	}
 
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index cb2d48a..8024d44 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -170,7 +170,7 @@
 	struct ieee80211_hw *hw =
 		ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops);
 	if (hw == NULL) {
-		printk(KERN_ERR "%s: Can not allocate network device\n",
+		pr_err("%s: Can not allocate network device\n",
 		       cfg->name);
 		goto out;
 	}
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 45a6845..d24eb47 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -27,6 +27,8 @@
  *
  *****************************************************************************/
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -3933,7 +3935,7 @@
 	 *   space for this driver's private structure */
 	hw = iwl_alloc_all(cfg, &iwl3945_hw_ops);
 	if (hw == NULL) {
-		printk(KERN_ERR DRV_NAME "Can not allocate network device\n");
+		pr_err("Can not allocate network device\n");
 		err = -ENOMEM;
 		goto out;
 	}
@@ -4225,19 +4227,18 @@
 {
 
 	int ret;
-	printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
-	printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
 
 	ret = iwl3945_rate_control_register();
 	if (ret) {
-		printk(KERN_ERR DRV_NAME
-		       "Unable to register rate control algorithm: %d\n", ret);
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
 		return ret;
 	}
 
 	ret = pci_register_driver(&iwl3945_driver);
 	if (ret) {
-		printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n");
+		pr_err("Unable to initialize PCI module\n");
 		goto error_register;
 	}
 
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 7e07416..25f9027 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -7,7 +7,6 @@
  */
 
 #include <linux/slab.h>
-#include <linux/if_arp.h>
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 #include <asm/unaligned.h>
@@ -1383,93 +1382,10 @@
 }
 
 
-
-/***************************************************************************
- * Monitor mode
- */
-
-/* like "struct cmd_ds_802_11_monitor_mode", but with cmd_header. Once we
- * get rid of WEXT, this should go into host.h */
-struct cmd_monitor_mode {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 mode;
-} __packed;
-
-static int lbs_enable_monitor_mode(struct lbs_private *priv, int mode)
-{
-	struct cmd_monitor_mode cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CFG80211);
-
-	/*
-	 * cmd       98 00
-	 * size      0c 00
-	 * sequence  xx xx
-	 * result    00 00
-	 * action    01 00    ACT_SET
-	 * enable    01 00
-	 */
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(CMD_ACT_SET);
-	cmd.mode = cpu_to_le16(mode);
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
-
-	if (ret == 0)
-		priv->dev->type = ARPHRD_IEEE80211_RADIOTAP;
-	else
-		priv->dev->type = ARPHRD_ETHER;
-
-	lbs_deb_leave(LBS_DEB_CFG80211);
-	return ret;
-}
-
-
-
-
-
-
 /***************************************************************************
  * Get station
  */
 
-/*
- * Returns the signal or 0 in case of an error.
- */
-
-/* like "struct cmd_ds_802_11_rssi", but with cmd_header. Once we get rid
- * of WEXT, this should go into host.h */
-struct cmd_rssi {
-	struct cmd_header hdr;
-
-	__le16 n_or_snr;
-	__le16 nf;
-	__le16 avg_snr;
-	__le16 avg_nf;
-} __packed;
-
-static int lbs_get_signal(struct lbs_private *priv, s8 *signal, s8 *noise)
-{
-	struct cmd_rssi cmd;
-	int ret;
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.n_or_snr = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
-	ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
-
-	if (ret == 0) {
-		*signal = CAL_RSSI(le16_to_cpu(cmd.n_or_snr),
-				le16_to_cpu(cmd.nf));
-		*noise  = CAL_NF(le16_to_cpu(cmd.nf));
-	}
-	return ret;
-}
-
-
 static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
 			      u8 *mac, struct station_info *sinfo)
 {
@@ -1490,7 +1406,7 @@
 	sinfo->rx_packets = priv->dev->stats.rx_packets;
 
 	/* Get current RSSI */
-	ret = lbs_get_signal(priv, &signal, &noise);
+	ret = lbs_get_rssi(priv, &signal, &noise);
 	if (ret == 0) {
 		sinfo->signal = signal;
 		sinfo->filled |= STATION_INFO_SIGNAL;
@@ -1530,7 +1446,7 @@
 	survey->channel = ieee80211_get_channel(wiphy,
 		ieee80211_channel_to_frequency(priv->channel));
 
-	ret = lbs_get_signal(priv, &signal, &noise);
+	ret = lbs_get_rssi(priv, &signal, &noise);
 	if (ret == 0) {
 		survey->filled = SURVEY_INFO_NOISE_DBM;
 		survey->noise = noise;
@@ -1558,17 +1474,17 @@
 
 	switch (type) {
 	case NL80211_IFTYPE_MONITOR:
-		ret = lbs_enable_monitor_mode(priv, 1);
+		ret = lbs_set_monitor_mode(priv, 1);
 		break;
 	case NL80211_IFTYPE_STATION:
 		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
-			ret = lbs_enable_monitor_mode(priv, 0);
+			ret = lbs_set_monitor_mode(priv, 0);
 		if (!ret)
 			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
-			ret = lbs_enable_monitor_mode(priv, 0);
+			ret = lbs_set_monitor_mode(priv, 0);
 		if (!ret)
 			ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
 		break;
@@ -2063,113 +1979,20 @@
 	return ret;
 }
 
-/**
- *  @brief This function sets DOMAIN INFO to FW
- *  @param priv       pointer to struct lbs_private
- *  @return          0; -1
-*/
-static int lbs_11d_set_domain_info(struct lbs_private *priv)
-{
-	int ret;
-
-	ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO,
-			CMD_ACT_SET,
-			CMD_OPTION_WAITFORRSP, 0, NULL);
-	if (ret)
-		lbs_deb_11d("fail to dnld domain info\n");
-
-	return ret;
-}
-
-static void lbs_send_domain_info_cmd_fw(struct wiphy *wiphy,
-					struct regulatory_request *request)
-{
-	u8   no_of_triplet = 0;
-	u8   no_of_parsed_chan = 0;
-	u8   first_channel = 0, next_chan = 0, max_pwr = 0;
-	u8   i, flag = 0;
-	enum ieee80211_band band;
-	struct ieee80211_supported_band *sband;
-	struct ieee80211_channel *ch;
-	struct lbs_private *priv = wiphy_priv(wiphy);
-	struct lbs_802_11d_domain_reg *domain_info = &priv->domain_reg;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CFG80211);
-
-	/* Set country code */
-	domain_info->country_code[0] = request->alpha2[0];
-	domain_info->country_code[1] = request->alpha2[1];
-	domain_info->country_code[2] = ' ';
-
-	for (band = 0; band < IEEE80211_NUM_BANDS ; band++) {
-
-		if (!wiphy->bands[band])
-			continue;
-
-		sband = wiphy->bands[band];
-
-		for (i = 0; i < sband->n_channels ; i++) {
-			ch = &sband->channels[i];
-			if (ch->flags & IEEE80211_CHAN_DISABLED)
-				continue;
-
-			if (!flag) {
-				flag = 1;
-				next_chan = first_channel = (u32) ch->hw_value;
-				max_pwr = ch->max_power;
-				no_of_parsed_chan = 1;
-				continue;
-			}
-
-			if (ch->hw_value == next_chan + 1 &&
-					ch->max_power == max_pwr) {
-				next_chan++;
-				no_of_parsed_chan++;
-			} else {
-				domain_info->triplet[no_of_triplet]
-					.chans.first_channel = first_channel;
-				domain_info->triplet[no_of_triplet]
-					.chans.num_channels = no_of_parsed_chan;
-				domain_info->triplet[no_of_triplet]
-					.chans.max_power = max_pwr;
-				no_of_triplet++;
-				flag = 0;
-			}
-		}
-		if (flag) {
-			domain_info->triplet[no_of_triplet]
-				.chans.first_channel = first_channel;
-			domain_info->triplet[no_of_triplet]
-				.chans.num_channels = no_of_parsed_chan;
-			domain_info->triplet[no_of_triplet]
-				.chans.max_power = max_pwr;
-			no_of_triplet++;
-		}
-	}
-
-	domain_info->no_triplet = no_of_triplet;
-
-	/* Set domain info */
-	ret = lbs_11d_set_domain_info(priv);
-	if (ret)
-		lbs_pr_err("11D: error setting domain info in FW\n");
-
-	lbs_deb_leave(LBS_DEB_CFG80211);
-}
-
 int lbs_reg_notifier(struct wiphy *wiphy,
 		struct regulatory_request *request)
 {
+	struct lbs_private *priv = wiphy_priv(wiphy);
+	int ret;
+
 	lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
 			"callback for domain %c%c\n", request->alpha2[0],
 			request->alpha2[1]);
 
-	lbs_send_domain_info_cmd_fw(wiphy, request);
+	ret = lbs_set_11d_domain_info(priv, request, wiphy->bands);
 
 	lbs_deb_leave(LBS_DEB_CFG80211);
-
-	return 0;
+	return ret;
 }
 
 void lbs_scan_deinit(struct lbs_private *priv)
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index 756fb98..4f46bb7 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -13,12 +13,6 @@
 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);
 
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 749fbde..7074592 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -6,13 +6,14 @@
 #include <linux/kfifo.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/if_arp.h>
 
 #include "decl.h"
 #include "cfg.h"
 #include "cmd.h"
 
-
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
+#define CAL_NF(nf)		((s32)(-(s32)(nf)))
+#define CAL_RSSI(snr, nf)	((s32)((s32)(snr) + CAL_NF(nf)))
 
 /**
  *  @brief Simple callback that copies response back into command
@@ -74,30 +75,6 @@
 }
 
 /**
- *  @brief This function checks if the command is allowed.
- *
- *  @param priv         A pointer to lbs_private structure
- *  @return             allowed or not allowed.
- */
-
-static int lbs_is_cmd_allowed(struct lbs_private *priv)
-{
-	int ret = 1;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (!priv->is_auto_deep_sleep_enabled) {
-		if (priv->is_deep_sleep) {
-			lbs_deb_cmd("command not allowed in deep sleep\n");
-			ret = 0;
-		}
-	}
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-/**
  *  @brief Updates the hardware details like MAC address and regulatory region
  *
  *  @param priv    	A pointer to struct lbs_private structure
@@ -227,42 +204,49 @@
 }
 EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
 
-static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
-				   u16 cmd_action)
+/**
+ *  @brief Sets the Power Save mode
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param cmd_action	The Power Save operation (PS_MODE_ACTION_ENTER_PS or
+ *                         PS_MODE_ACTION_EXIT_PS)
+ *  @param block	Whether to block on a response or not
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
 {
-	struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode;
+	struct cmd_ds_802_11_ps_mode cmd;
+	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
-	cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
-				sizeof(struct cmd_header));
-	psm->action = cpu_to_le16(cmd_action);
-	psm->multipledtim = 0;
-	switch (cmd_action) {
-	case CMD_SUBCMD_ENTER_PS:
-		lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(cmd_action);
 
-		psm->locallisteninterval = 0;
-		psm->nullpktinterval = 0;
-		psm->multipledtim =
-		    cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
-		break;
-
-	case CMD_SUBCMD_EXIT_PS:
-		lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
-		break;
-
-	case CMD_SUBCMD_SLEEP_CONFIRMED:
-		lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
-		break;
-
-	default:
-		break;
+	if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
+		lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
+		cmd.multipledtim = cpu_to_le16(1);  /* Default DTIM multiple */
+	} else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
+		lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
+	} else {
+		/* We don't handle CONFIRM_SLEEP here because it needs to
+		 * be fastpathed to the firmware.
+		 */
+		lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
+		ret = -EOPNOTSUPP;
+		goto out;
 	}
 
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
+	if (block)
+		ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
+	else
+		lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
+
+out:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
 }
 
 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
@@ -576,23 +560,35 @@
 	return ret;
 }
 
-static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
-				      u16 cmd_action, void *pdata_buf)
+/**
+ *  @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW)
+ *
+ *  @param priv        A pointer to struct lbs_private structure
+ *  @param enable      1 to enable monitor mode, 0 to disable
+ *
+ *  @return            0 on success, error on failure
+ */
+int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
 {
-	struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor;
+	struct cmd_ds_802_11_monitor_mode cmd;
+	int ret;
 
-	cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
-			     sizeof(struct cmd_header));
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_SET);
+	if (enable)
+		cmd.mode = cpu_to_le16(0x1);
 
-	monitor->action = cpu_to_le16(cmd_action);
-	if (cmd_action == CMD_ACT_SET) {
-		monitor->mode =
-		    cpu_to_le16((u16) (*(u32 *) pdata_buf));
+	lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable);
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
+	if (ret == 0) {
+		priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP :
+						ARPHRD_ETHER;
 	}
 
-	return 0;
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
 }
 
 /**
@@ -677,78 +673,242 @@
 	return ret;
 }
 
-static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
-			       u8 cmd_action, void *pdata_buf)
+/**
+ *  @brief Get current RSSI and noise floor
+ *
+ *  @param priv		A pointer to struct lbs_private structure
+ *  @param rssi		On successful return, signal level in mBm
+ *
+ *  @return 	   	The channel on success, error on failure
+ */
+int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
 {
-	struct lbs_offset_value *offval;
+	struct cmd_ds_802_11_rssi cmd;
+	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
-	offval = (struct lbs_offset_value *)pdata_buf;
+	BUG_ON(rssi == NULL);
+	BUG_ON(nf == NULL);
 
-	switch (le16_to_cpu(cmdptr->command)) {
-	case CMD_MAC_REG_ACCESS:
-		{
-			struct cmd_ds_mac_reg_access *macreg;
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	/* Average SNR over last 8 beacons */
+	cmd.n_or_snr = cpu_to_le16(8);
 
-			cmdptr->size =
-			    cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
-					+ sizeof(struct cmd_header));
-			macreg =
-			    (struct cmd_ds_mac_reg_access *)&cmdptr->params.
-			    macreg;
-
-			macreg->action = cpu_to_le16(cmd_action);
-			macreg->offset = cpu_to_le16((u16) offval->offset);
-			macreg->value = cpu_to_le32(offval->value);
-
-			break;
-		}
-
-	case CMD_BBP_REG_ACCESS:
-		{
-			struct cmd_ds_bbp_reg_access *bbpreg;
-
-			cmdptr->size =
-			    cpu_to_le16(sizeof
-					     (struct cmd_ds_bbp_reg_access)
-					     + sizeof(struct cmd_header));
-			bbpreg =
-			    (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
-			    bbpreg;
-
-			bbpreg->action = cpu_to_le16(cmd_action);
-			bbpreg->offset = cpu_to_le16((u16) offval->offset);
-			bbpreg->value = (u8) offval->value;
-
-			break;
-		}
-
-	case CMD_RF_REG_ACCESS:
-		{
-			struct cmd_ds_rf_reg_access *rfreg;
-
-			cmdptr->size =
-			    cpu_to_le16(sizeof
-					     (struct cmd_ds_rf_reg_access) +
-					     sizeof(struct cmd_header));
-			rfreg =
-			    (struct cmd_ds_rf_reg_access *)&cmdptr->params.
-			    rfreg;
-
-			rfreg->action = cpu_to_le16(cmd_action);
-			rfreg->offset = cpu_to_le16((u16) offval->offset);
-			rfreg->value = (u8) offval->value;
-
-			break;
-		}
-
-	default:
-		break;
+	ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
+	if (ret == 0) {
+		*nf = CAL_NF(le16_to_cpu(cmd.nf));
+		*rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
 	}
 
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Send regulatory and 802.11d domain information to the firmware
+ *
+ *  @param priv		pointer to struct lbs_private
+ *  @param request	cfg80211 regulatory request structure
+ *  @param bands	the device's supported bands and channels
+ *
+ *  @return		0 on success, error code on failure
+*/
+int lbs_set_11d_domain_info(struct lbs_private *priv,
+			    struct regulatory_request *request,
+			    struct ieee80211_supported_band **bands)
+{
+	struct cmd_ds_802_11d_domain_info cmd;
+	struct mrvl_ie_domain_param_set *domain = &cmd.domain;
+	struct ieee80211_country_ie_triplet *t;
+	enum ieee80211_band band;
+	struct ieee80211_channel *ch;
+	u8 num_triplet = 0;
+	u8 num_parsed_chan = 0;
+	u8 first_channel = 0, next_chan = 0, max_pwr = 0;
+	u8 i, flag = 0;
+	size_t triplet_size;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_11D);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+	lbs_deb_11d("Setting country code '%c%c'\n",
+		    request->alpha2[0], request->alpha2[1]);
+
+	domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
+
+	/* Set country code */
+	domain->country_code[0] = request->alpha2[0];
+	domain->country_code[1] = request->alpha2[1];
+	domain->country_code[2] = ' ';
+
+	/* Now set up the channel triplets; firmware is somewhat picky here
+	 * and doesn't validate channel numbers and spans; hence it would
+	 * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39.  Since
+	 * the last 3 aren't valid channels, the driver is responsible for
+	 * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20)
+	 * etc.
+	 */
+	for (band = 0;
+	     (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS);
+	     band++) {
+
+		if (!bands[band])
+			continue;
+
+		for (i = 0;
+		     (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS);
+		     i++) {
+			ch = &bands[band]->channels[i];
+			if (ch->flags & IEEE80211_CHAN_DISABLED)
+				continue;
+
+			if (!flag) {
+				flag = 1;
+				next_chan = first_channel = (u32) ch->hw_value;
+				max_pwr = ch->max_power;
+				num_parsed_chan = 1;
+				continue;
+			}
+
+			if ((ch->hw_value == next_chan + 1) &&
+					(ch->max_power == max_pwr)) {
+				/* Consolidate adjacent channels */
+				next_chan++;
+				num_parsed_chan++;
+			} else {
+				/* Add this triplet */
+				lbs_deb_11d("11D triplet (%d, %d, %d)\n",
+					first_channel, num_parsed_chan,
+					max_pwr);
+				t = &domain->triplet[num_triplet];
+				t->chans.first_channel = first_channel;
+				t->chans.num_channels = num_parsed_chan;
+				t->chans.max_power = max_pwr;
+				num_triplet++;
+				flag = 0;
+			}
+		}
+
+		if (flag) {
+			/* Add last triplet */
+			lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel,
+				num_parsed_chan, max_pwr);
+			t = &domain->triplet[num_triplet];
+			t->chans.first_channel = first_channel;
+			t->chans.num_channels = num_parsed_chan;
+			t->chans.max_power = max_pwr;
+			num_triplet++;
+		}
+	}
+
+	lbs_deb_11d("# triplets %d\n", num_triplet);
+
+	/* Set command header sizes */
+	triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet);
+	domain->header.len = cpu_to_le16(sizeof(domain->country_code) +
+					triplet_size);
+
+	lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set",
+			(u8 *) &cmd.domain.country_code,
+			le16_to_cpu(domain->header.len));
+
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) +
+				   sizeof(cmd.action) +
+				   sizeof(cmd.domain.header) +
+				   sizeof(cmd.domain.country_code) +
+				   triplet_size);
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
+
+	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Read a MAC, Baseband, or RF register
+ *
+ *  @param priv		pointer to struct lbs_private
+ *  @param cmd		register command, one of CMD_MAC_REG_ACCESS,
+ *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
+ *  @param offset       byte offset of the register to get
+ *  @param value        on success, the value of the register at 'offset'
+ *
+ *  @return		0 on success, error code on failure
+*/
+int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
+{
+	struct cmd_ds_reg_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	BUG_ON(value == NULL);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_GET);
+
+	if (reg != CMD_MAC_REG_ACCESS &&
+	    reg != CMD_BBP_REG_ACCESS &&
+	    reg != CMD_RF_REG_ACCESS) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lbs_cmd_with_response(priv, reg, &cmd);
+	if (ret) {
+		if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
+			*value = cmd.value.bbp_rf;
+		else if (reg == CMD_MAC_REG_ACCESS)
+			*value = le32_to_cpu(cmd.value.mac);
+	}
+
+out:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Write a MAC, Baseband, or RF register
+ *
+ *  @param priv		pointer to struct lbs_private
+ *  @param cmd		register command, one of CMD_MAC_REG_ACCESS,
+ *                        CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
+ *  @param offset       byte offset of the register to set
+ *  @param value        the value to write to the register at 'offset'
+ *
+ *  @return		0 on success, error code on failure
+*/
+int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
+{
+	struct cmd_ds_reg_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_SET);
+
+	if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
+		cmd.value.bbp_rf = (u8) (value & 0xFF);
+	else if (reg == CMD_MAC_REG_ACCESS)
+		cmd.value.mac = cpu_to_le32(value);
+	else {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = lbs_cmd_with_response(priv, reg, &cmd);
+
+out:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
 }
 
 static void lbs_queue_cmd(struct lbs_private *priv,
@@ -771,16 +931,15 @@
 
 	/* Exit_PS command needs to be queued in the header always. */
 	if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
-		struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
+		struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;
 
-		if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
+		if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 			if (priv->psstate != PS_STATE_FULL_POWER)
 				addtail = 0;
 		}
 	}
 
-	if (le16_to_cpu(cmdnode->cmdbuf->command) ==
-			CMD_802_11_WAKEUP_CONFIRM)
+	if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
 		addtail = 0;
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
@@ -815,7 +974,6 @@
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	priv->cur_cmd = cmdnode;
-	priv->cur_cmd_retcode = 0;
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 	cmdsize = le16_to_cpu(cmd->size);
@@ -888,9 +1046,6 @@
 void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
 			  int result)
 {
-	if (cmd == priv->cur_cmd)
-		priv->cur_cmd_retcode = result;
-
 	cmd->result = result;
 	cmd->cmdwaitqwoken = 1;
 	wake_up_interruptible(&cmd->cmdwait_q);
@@ -958,240 +1113,6 @@
 }
 
 /**
- *  @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.
- *
- *  @param priv		A pointer to struct lbs_private structure
- *  @param cmd_no	command number
- *  @param cmd_action	command action: GET or SET
- *  @param wait_option	wait option: wait response or not
- *  @param cmd_oid	cmd oid: treated as sub command
- *  @param pdata_buf	A pointer to informaion buffer
- *  @return 		0 or -1
- */
-int lbs_prepare_and_send_command(struct lbs_private *priv,
-			  u16 cmd_no,
-			  u16 cmd_action,
-			  u16 wait_option, u32 cmd_oid, void *pdata_buf)
-{
-	int ret = 0;
-	struct cmd_ctrl_node *cmdnode;
-	struct cmd_ds_command *cmdptr;
-	unsigned long flags;
-
-	lbs_deb_enter(LBS_DEB_HOST);
-
-	if (!priv) {
-		lbs_deb_host("PREP_CMD: priv is NULL\n");
-		ret = -1;
-		goto done;
-	}
-
-	if (priv->surpriseremoved) {
-		lbs_deb_host("PREP_CMD: card removed\n");
-		ret = -1;
-		goto done;
-	}
-
-	if (!lbs_is_cmd_allowed(priv)) {
-		ret = -EBUSY;
-		goto done;
-	}
-
-	cmdnode = lbs_get_cmd_ctrl_node(priv);
-
-	if (cmdnode == NULL) {
-		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
-
-		/* Wake up main thread to execute next command */
-		wake_up_interruptible(&priv->waitq);
-		ret = -1;
-		goto done;
-	}
-
-	cmdnode->callback = NULL;
-	cmdnode->callback_arg = (unsigned long)pdata_buf;
-
-	cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
-
-	lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
-
-	/* Set sequence number, command and INT option */
-	priv->seqnum++;
-	cmdptr->seqnum = cpu_to_le16(priv->seqnum);
-
-	cmdptr->command = cpu_to_le16(cmd_no);
-	cmdptr->result = 0;
-
-	switch (cmd_no) {
-	case CMD_802_11_PS_MODE:
-		ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
-		break;
-
-	case CMD_MAC_REG_ACCESS:
-	case CMD_BBP_REG_ACCESS:
-	case CMD_RF_REG_ACCESS:
-		ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
-		break;
-
-	case CMD_802_11_MONITOR_MODE:
-		ret = lbs_cmd_802_11_monitor_mode(cmdptr,
-				          cmd_action, pdata_buf);
-		break;
-
-	case CMD_802_11_RSSI:
-		ret = lbs_cmd_802_11_rssi(priv, cmdptr);
-		break;
-
-	case CMD_802_11_SET_AFC:
-	case CMD_802_11_GET_AFC:
-
-		cmdptr->command = cpu_to_le16(cmd_no);
-		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
-					   sizeof(struct cmd_header));
-
-		memmove(&cmdptr->params.afc,
-			pdata_buf, sizeof(struct cmd_ds_802_11_afc));
-
-		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 =
-		    cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
-				     sizeof(struct cmd_header));
-
-		memmove(&cmdptr->params.tpccfg,
-			pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
-
-		ret = 0;
-		break;
-
-#ifdef CONFIG_LIBERTAS_MESH
-
-	case CMD_BT_ACCESS:
-		ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
-		break;
-
-	case CMD_FWT_ACCESS:
-		ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
-		break;
-
-#endif
-
-	case CMD_802_11_BEACON_CTRL:
-		ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
-		break;
-	case CMD_802_11_DEEP_SLEEP:
-		cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
-		cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
-		break;
-	default:
-		lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
-		ret = -1;
-		break;
-	}
-
-	/* return error, since the command preparation failed */
-	if (ret != 0) {
-		lbs_deb_host("PREP_CMD: command preparation failed\n");
-		lbs_cleanup_and_insert_cmd(priv, cmdnode);
-		ret = -1;
-		goto done;
-	}
-
-	cmdnode->cmdwaitqwoken = 0;
-
-	lbs_queue_cmd(priv, cmdnode);
-	wake_up_interruptible(&priv->waitq);
-
-	if (wait_option & CMD_OPTION_WAITFORRSP) {
-		lbs_deb_host("PREP_CMD: wait for response\n");
-		might_sleep();
-		wait_event_interruptible(cmdnode->cmdwait_q,
-					 cmdnode->cmdwaitqwoken);
-	}
-
-	spin_lock_irqsave(&priv->driver_lock, flags);
-	if (priv->cur_cmd_retcode) {
-		lbs_deb_host("PREP_CMD: command failed with return code %d\n",
-		       priv->cur_cmd_retcode);
-		priv->cur_cmd_retcode = 0;
-		ret = -1;
-	}
-	spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
-	return ret;
-}
-
-/**
  *  @brief This function allocates the command buffer and link
  *  it to command free queue.
  *
@@ -1284,7 +1205,7 @@
  *  @param priv		A pointer to struct lbs_private structure
  *  @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
  */
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv)
+static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
 {
 	struct cmd_ctrl_node *tempnode;
 	unsigned long flags;
@@ -1367,10 +1288,10 @@
 			/*
 			 * 1. Non-PS command:
 			 * Queue it. set needtowakeup to TRUE if current state
-			 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS.
-			 * 2. PS command but not Exit_PS:
+			 * is SLEEP, otherwise call send EXIT_PS.
+			 * 2. PS command but not EXIT_PS:
 			 * Ignore it.
-			 * 3. PS command Exit_PS:
+			 * 3. PS command EXIT_PS:
 			 * Set needtowakeup to TRUE if current state is SLEEP,
 			 * otherwise send this command down to firmware
 			 * immediately.
@@ -1384,8 +1305,11 @@
 					/* w/ new scheme, it will not reach here.
 					   since it is blocked in main_thread. */
 					priv->needtowakeup = 1;
-				} else
-					lbs_ps_wakeup(priv, 0);
+				} else {
+					lbs_set_ps_mode(priv,
+							PS_MODE_ACTION_EXIT_PS,
+							false);
+				}
 
 				ret = 0;
 				goto done;
@@ -1400,7 +1324,7 @@
 				       "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
 				       psm->action);
 				if (psm->action !=
-				    cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
+				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
 					list_del(&cmdnode->list);
@@ -1460,13 +1384,16 @@
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
 					       " go back to PS_SLEEP");
-					lbs_ps_sleep(priv, 0);
+					lbs_set_ps_mode(priv,
+							PS_MODE_ACTION_ENTER_PS,
+							false);
 				}
 			} else {
 				lbs_deb_host(
 				       "EXEC_NEXT_CMD: cmdpendingq empty, "
 				       "go back to PS_SLEEP");
-				lbs_ps_sleep(priv, 0);
+				lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
+						false);
 			}
 		}
 #endif
@@ -1514,43 +1441,6 @@
 	lbs_deb_leave(LBS_DEB_HOST);
 }
 
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
-{
-	lbs_deb_enter(LBS_DEB_HOST);
-
-	/*
-	 * PS is currently supported only in Infrastructure mode
-	 * Remove this check if it is to be supported in IBSS mode also
-	 */
-
-	lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
-			      CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
-
-	lbs_deb_leave(LBS_DEB_HOST);
-}
-
-/**
- *  @brief This function sends Exit_PS command to firmware.
- *
- *  @param priv    	A pointer to struct lbs_private structure
- *  @param wait_option	wait response or not
- *  @return 	   	n/a
- */
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
-{
-	__le32 Localpsmode;
-
-	lbs_deb_enter(LBS_DEB_HOST);
-
-	Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
-
-	lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
-			      CMD_SUBCMD_EXIT_PS,
-			      wait_option, 0, &Localpsmode);
-
-	lbs_deb_leave(LBS_DEB_HOST);
-}
-
 /**
  *  @brief This function checks condition and prepares to
  *  send sleep confirm command to firmware if ok.
@@ -1675,12 +1565,18 @@
 		goto done;
 	}
 
-	if (!lbs_is_cmd_allowed(priv)) {
-		cmdnode = ERR_PTR(-EBUSY);
-		goto done;
+	/* No commands are allowed in Deep Sleep until we toggle the GPIO
+	 * to wake up the card and it has signaled that it's ready.
+	 */
+	if (!priv->is_auto_deep_sleep_enabled) {
+		if (priv->is_deep_sleep) {
+			lbs_deb_cmd("command not allowed in deep sleep\n");
+			cmdnode = ERR_PTR(-EBUSY);
+			goto done;
+		}
 	}
 
-	cmdnode = lbs_get_cmd_ctrl_node(priv);
+	cmdnode = lbs_get_free_cmd_node(priv);
 	if (cmdnode == NULL) {
 		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
 
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 386e565..7109d6b 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -3,6 +3,8 @@
 #ifndef _LBS_CMD_H_
 #define _LBS_CMD_H_
 
+#include <net/cfg80211.h>
+
 #include "host.h"
 #include "dev.h"
 
@@ -37,11 +39,6 @@
 #define lbs_cmd_with_response(priv, cmdnr, cmd)	\
 	lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
 
-int lbs_prepare_and_send_command(struct lbs_private *priv,
-	u16 cmd_no,
-	u16 cmd_action,
-	u16 wait_option, u32 cmd_oid, void *pdata_buf);
-
 void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
 	struct cmd_header *in_cmd, int in_cmd_size);
 
@@ -92,10 +89,6 @@
 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 				struct sleep_params *sp);
 
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
-
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-
 void lbs_ps_confirm_sleep(struct lbs_private *priv);
 
 int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
@@ -129,4 +122,18 @@
 
 int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep);
 
+int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
+
+int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
+
+int lbs_set_11d_domain_info(struct lbs_private *priv,
+			    struct regulatory_request *request,
+			    struct ieee80211_supported_band **bands);
+
+int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);
+
+int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);
+
+int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);
+
 #endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index a0d9482..5e95da9 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -49,171 +49,11 @@
 	if (priv->psstate != PS_STATE_FULL_POWER) {
 		/* make firmware to exit PS mode */
 		lbs_deb_cmd("disconnected, so exit PS mode\n");
-		lbs_ps_wakeup(priv, 0);
+		lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
 	}
 	lbs_deb_leave(LBS_DEB_ASSOC);
 }
 
-static int lbs_ret_reg_access(struct lbs_private *priv,
-			       u16 type, struct cmd_ds_command *resp)
-{
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	switch (type) {
-	case CMD_RET(CMD_MAC_REG_ACCESS):
-		{
-			struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
-
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
-			priv->offsetvalue.value = le32_to_cpu(reg->value);
-			break;
-		}
-
-	case CMD_RET(CMD_BBP_REG_ACCESS):
-		{
-			struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
-
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
-			priv->offsetvalue.value = reg->value;
-			break;
-		}
-
-	case CMD_RET(CMD_RF_REG_ACCESS):
-		{
-			struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
-
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
-			priv->offsetvalue.value = reg->value;
-			break;
-		}
-
-	default:
-		ret = -1;
-	}
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	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)
-{
-	struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
-	int ret = 0;
-	unsigned long flags;
-	uint16_t respcmd = le16_to_cpu(resp->command);
-
-	lbs_deb_enter(LBS_DEB_HOST);
-
-	switch (respcmd) {
-	case CMD_RET(CMD_MAC_REG_ACCESS):
-	case CMD_RET(CMD_BBP_REG_ACCESS):
-	case CMD_RET(CMD_RF_REG_ACCESS):
-		ret = lbs_ret_reg_access(priv, respcmd, resp);
-		break;
-
-	case CMD_RET(CMD_802_11_SET_AFC):
-	case CMD_RET(CMD_802_11_GET_AFC):
-		spin_lock_irqsave(&priv->driver_lock, flags);
-		memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
-			sizeof(struct cmd_ds_802_11_afc));
-		spin_unlock_irqrestore(&priv->driver_lock, flags);
-
-		break;
-
-	case CMD_RET(CMD_802_11_BEACON_STOP):
-		break;
-
-	case CMD_RET(CMD_802_11_RSSI):
-		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,
-			sizeof(struct cmd_ds_802_11_tpc_cfg));
-		spin_unlock_irqrestore(&priv->driver_lock, flags);
-		break;
-
-	case CMD_RET(CMD_BT_ACCESS):
-		spin_lock_irqsave(&priv->driver_lock, flags);
-		if (priv->cur_cmd->callback_arg)
-			memcpy((void *)priv->cur_cmd->callback_arg,
-			       &resp->params.bt.addr1, 2 * ETH_ALEN);
-		spin_unlock_irqrestore(&priv->driver_lock, flags);
-		break;
-	case CMD_RET(CMD_FWT_ACCESS):
-		spin_lock_irqsave(&priv->driver_lock, flags);
-		if (priv->cur_cmd->callback_arg)
-			memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
-			       sizeof(resp->params.fwt));
-		spin_unlock_irqrestore(&priv->driver_lock, flags);
-		break;
-	case CMD_RET(CMD_802_11_BEACON_CTRL):
-		ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
-		break;
-
-	default:
-		lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
-			   le16_to_cpu(resp->command));
-		break;
-	}
-	lbs_deb_leave(LBS_DEB_HOST);
-	return ret;
-}
-
 int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 {
 	uint16_t respcmd, curcmd;
@@ -272,9 +112,6 @@
 	del_timer(&priv->command_timer);
 	priv->cmd_timed_out = 0;
 
-	/* Store the response code to cur_cmd_retcode. */
-	priv->cur_cmd_retcode = result;
-
 	if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
 		struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
 		u16 action = le16_to_cpu(psmode->action);
@@ -292,9 +129,9 @@
 			 * lbs_execute_next_command().
 			 */
 			if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
-			    action == CMD_SUBCMD_ENTER_PS)
+			    action == PS_MODE_ACTION_ENTER_PS)
 				priv->psmode = LBS802_11POWERMODECAM;
-		} else if (action == CMD_SUBCMD_ENTER_PS) {
+		} else if (action == PS_MODE_ACTION_ENTER_PS) {
 			priv->needtowakeup = 0;
 			priv->psstate = PS_STATE_AWAKE;
 
@@ -309,11 +146,12 @@
 
 				spin_unlock_irqrestore(&priv->driver_lock, flags);
 				mutex_unlock(&priv->lock);
-				lbs_ps_wakeup(priv, 0);
+				lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
+						false);
 				mutex_lock(&priv->lock);
 				spin_lock_irqsave(&priv->driver_lock, flags);
 			}
-		} else if (action == CMD_SUBCMD_EXIT_PS) {
+		} else if (action == PS_MODE_ACTION_EXIT_PS) {
 			priv->needtowakeup = 0;
 			priv->psstate = PS_STATE_FULL_POWER;
 			lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
@@ -354,8 +192,7 @@
 	if (priv->cur_cmd && priv->cur_cmd->callback) {
 		ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
 				resp);
-	} else
-		ret = handle_cmd_response(priv, resp);
+	}
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 
@@ -452,7 +289,7 @@
 			 * in lbs_ps_wakeup()
 			 */
 			lbs_deb_cmd("waking up ...\n");
-			lbs_ps_wakeup(priv, 0);
+			lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
 		}
 		break;
 
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 3db621b..651a79c 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -446,30 +446,24 @@
 }
 
 
-
 static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
 				  size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	struct lbs_offset_value offval;
 	ssize_t pos = 0;
 	int ret;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
+	u32 val = 0;
+
 	if (!buf)
 		return -ENOMEM;
 
-	offval.offset = priv->mac_offset;
-	offval.value = 0;
-
-	ret = lbs_prepare_and_send_command(priv,
-				CMD_MAC_REG_ACCESS, 0,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
 	mdelay(10);
 	if (!ret) {
-		pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
-				priv->mac_offset, priv->offsetvalue.value);
-
+		pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
+				priv->mac_offset, val);
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	}
 	free_page(addr);
@@ -507,7 +501,6 @@
 	struct lbs_private *priv = file->private_data;
 	ssize_t res, buf_size;
 	u32 offset, value;
-	struct lbs_offset_value offval;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
 	if (!buf)
@@ -524,11 +517,7 @@
 		goto out_unlock;
 	}
 
-	offval.offset = offset;
-	offval.value = value;
-	res = lbs_prepare_and_send_command(priv,
-				CMD_MAC_REG_ACCESS, 1,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
 	mdelay(10);
 
 	if (!res)
@@ -542,25 +531,20 @@
 				  size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	struct lbs_offset_value offval;
 	ssize_t pos = 0;
 	int ret;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
+	u32 val;
+
 	if (!buf)
 		return -ENOMEM;
 
-	offval.offset = priv->bbp_offset;
-	offval.value = 0;
-
-	ret = lbs_prepare_and_send_command(priv,
-				CMD_BBP_REG_ACCESS, 0,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
 	mdelay(10);
 	if (!ret) {
-		pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
-				priv->bbp_offset, priv->offsetvalue.value);
-
+		pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
+				priv->bbp_offset, val);
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	}
 	free_page(addr);
@@ -599,7 +583,6 @@
 	struct lbs_private *priv = file->private_data;
 	ssize_t res, buf_size;
 	u32 offset, value;
-	struct lbs_offset_value offval;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
 	if (!buf)
@@ -616,11 +599,7 @@
 		goto out_unlock;
 	}
 
-	offval.offset = offset;
-	offval.value = value;
-	res = lbs_prepare_and_send_command(priv,
-				CMD_BBP_REG_ACCESS, 1,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
 	mdelay(10);
 
 	if (!res)
@@ -634,25 +613,20 @@
 				  size_t count, loff_t *ppos)
 {
 	struct lbs_private *priv = file->private_data;
-	struct lbs_offset_value offval;
 	ssize_t pos = 0;
 	int ret;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
+	u32 val;
+
 	if (!buf)
 		return -ENOMEM;
 
-	offval.offset = priv->rf_offset;
-	offval.value = 0;
-
-	ret = lbs_prepare_and_send_command(priv,
-				CMD_RF_REG_ACCESS, 0,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
 	mdelay(10);
 	if (!ret) {
-		pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
-				priv->rf_offset, priv->offsetvalue.value);
-
+		pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
+				priv->rf_offset, val);
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
 	}
 	free_page(addr);
@@ -691,7 +665,6 @@
 	struct lbs_private *priv = file->private_data;
 	ssize_t res, buf_size;
 	u32 offset, value;
-	struct lbs_offset_value offval;
 	unsigned long addr = get_zeroed_page(GFP_KERNEL);
 	char *buf = (char *)addr;
 	if (!buf)
@@ -708,11 +681,7 @@
 		goto out_unlock;
 	}
 
-	offval.offset = offset;
-	offval.value = value;
-	res = lbs_prepare_and_send_command(priv,
-				CMD_RF_REG_ACCESS, 1,
-				CMD_OPTION_WAITFORRSP, 0, &offval);
+	res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
 	mdelay(10);
 
 	if (!res)
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index ba5438a..1d141fe 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -53,9 +53,4 @@
 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
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index ea3f10e..d00c728 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -172,11 +172,6 @@
 #define MRVDRV_MAX_BSS_DESCRIPTS		16
 #define MRVDRV_MAX_REGION_CODE			6
 
-#define MRVDRV_IGNORE_MULTIPLE_DTIM		0xfffe
-#define MRVDRV_MIN_MULTIPLE_DTIM		1
-#define MRVDRV_MAX_MULTIPLE_DTIM		5
-#define MRVDRV_DEFAULT_MULTIPLE_DTIM		1
-
 #define MRVDRV_DEFAULT_LISTEN_INTERVAL		10
 
 #define	MRVDRV_CHANNELS_PER_SCAN		4
@@ -301,19 +296,6 @@
 #define	BAND_G			(0x02)
 #define ALL_802_11_BANDS	(BAND_B | BAND_G)
 
-/** MACRO DEFINITIONS */
-#define CAL_NF(NF)			((s32)(-(s32)(NF)))
-#define CAL_RSSI(SNR, NF) 		((s32)((s32)(SNR) + CAL_NF(NF)))
-#define SCAN_RSSI(RSSI)			(0x100 - ((u8)(RSSI)))
-
-#define DEFAULT_BCN_AVG_FACTOR		8
-#define DEFAULT_DATA_AVG_FACTOR		8
-#define AVG_SCALE			100
-#define CAL_AVG_SNR_NF(AVG, SNRNF, N)         \
-                        (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
-                        ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
-                        AVG_SCALE))  / N))
-
 #define MAX_RATES			14
 
 #define	MAX_LEDS			8
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 4536d9c..3c7e255 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -60,14 +60,10 @@
 	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;
 	u32 rf_offset;
-	struct lbs_offset_value offsetvalue;
 
 	/* Power management */
 	u16 psmode;
@@ -115,12 +111,10 @@
 	struct cmd_ctrl_node *cur_cmd;
 	struct list_head cmdfreeq;    /* free command buffers */
 	struct list_head cmdpendingq; /* pending command buffers */
-	wait_queue_head_t cmd_pending;
 	struct timer_list command_timer;
 	int cmd_timed_out;
 
 	/* Command responses sent from the hardware to the driver */
-	int cur_cmd_retcode;
 	u8 resp_idx;
 	u8 resp_buf[2][LBS_UPLD_SIZE];
 	u32 resp_len[2];
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 43d020c..5eac135 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -94,11 +94,9 @@
 #define CMD_802_11_BEACON_CTRL                  0x00b0
 
 /* For the IEEE Power Save */
-#define CMD_SUBCMD_ENTER_PS                     0x0030
-#define CMD_SUBCMD_EXIT_PS                      0x0031
-#define CMD_SUBCMD_SLEEP_CONFIRMED              0x0034
-#define CMD_SUBCMD_FULL_POWERDOWN               0x0035
-#define CMD_SUBCMD_FULL_POWERUP                 0x0036
+#define PS_MODE_ACTION_ENTER_PS                 0x0030
+#define PS_MODE_ACTION_EXIT_PS                  0x0031
+#define PS_MODE_ACTION_SLEEP_CONFIRMED          0x0034
 
 #define CMD_ENABLE_RSN                          0x0001
 #define CMD_DISABLE_RSN                         0x0000
@@ -163,11 +161,6 @@
 #define CMD_ACT_SET_TX_FIX_RATE                 0x0001
 #define CMD_ACT_GET_TX_RATE                     0x0002
 
-/* Define action or option for CMD_802_11_PS_MODE */
-#define CMD_TYPE_CAM                            0x0000
-#define CMD_TYPE_MAX_PSP                        0x0001
-#define CMD_TYPE_FAST_PSP                       0x0002
-
 /* Options for CMD_802_11_FW_WAKE_METHOD */
 #define CMD_WAKE_METHOD_UNCHANGED               0x0000
 #define CMD_WAKE_METHOD_COMMAND_INT             0x0001
@@ -389,30 +382,22 @@
 	u32 value;
 } __packed;
 
-#define MRVDRV_MAX_TRIPLET_802_11D              83
-
-#define COUNTRY_CODE_LEN                        3
+#define MAX_11D_TRIPLETS	83
 
 struct mrvl_ie_domain_param_set {
 	struct mrvl_ie_header header;
 
-	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieee80211_country_ie_triplet triplet[1];
+	u8 country_code[3];
+	struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
 } __packed;
 
 struct cmd_ds_802_11d_domain_info {
+	struct cmd_header hdr;
+
 	__le16 action;
 	struct mrvl_ie_domain_param_set domain;
 } __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];
-} __packed;
-
 /*
  * Define data structure for CMD_GET_HW_SPEC
  * This structure defines the response for the GET_HW_SPEC command
@@ -575,24 +560,15 @@
 	u8 value[128];
 } __packed;
 
-struct cmd_ds_mac_reg_access {
-	__le16 action;
-	__le16 offset;
-	__le32 value;
-} __packed;
+struct cmd_ds_reg_access {
+	struct cmd_header hdr;
 
-struct cmd_ds_bbp_reg_access {
 	__le16 action;
 	__le16 offset;
-	u8 value;
-	u8 reserved[3];
-} __packed;
-
-struct cmd_ds_rf_reg_access {
-	__le16 action;
-	__le16 offset;
-	u8 value;
-	u8 reserved[3];
+	union {
+		u8 bbp_rf;  /* for BBP and RF registers */
+		__le32 mac; /* for MAC registers */
+	} value;
 } __packed;
 
 struct cmd_ds_802_11_radio_control {
@@ -603,6 +579,8 @@
 } __packed;
 
 struct cmd_ds_802_11_beacon_control {
+	struct cmd_header hdr;
+
 	__le16 action;
 	__le16 beacon_enable;
 	__le16 beacon_period;
@@ -644,19 +622,19 @@
 } __packed;
 
 struct cmd_ds_802_11_rssi {
-	/* weighting factor */
-	__le16 N;
+	struct cmd_header hdr;
 
-	__le16 reserved_0;
-	__le16 reserved_1;
-	__le16 reserved_2;
-} __packed;
+	/* request:  number of beacons (N) to average the SNR and NF over
+	 * response: SNR of most recent beacon
+	 */
+	__le16 n_or_snr;
 
-struct cmd_ds_802_11_rssi_rsp {
-	__le16 SNR;
-	__le16 noisefloor;
-	__le16 avgSNR;
-	__le16 avgnoisefloor;
+	/* The following fields are only set in the response.
+	 * In the request these are reserved and should be set to 0.
+	 */
+	__le16 nf;       /* most recent beacon noise floor */
+	__le16 avg_snr;  /* average SNR weighted by N from request */
+	__le16 avg_nf;   /* average noise floor weighted by N from request */
 } __packed;
 
 struct cmd_ds_802_11_mac_address {
@@ -675,7 +653,10 @@
 	s8 minlevel;
 } __packed;
 
+/* MONITOR_MODE only exists in OLPC v5 firmware */
 struct cmd_ds_802_11_monitor_mode {
+	struct cmd_header hdr;
+
 	__le16 action;
 	__le16 mode;
 } __packed;
@@ -695,11 +676,35 @@
 } __packed;
 
 struct cmd_ds_802_11_ps_mode {
+	struct cmd_header hdr;
+
 	__le16 action;
+
+	/* Interval for keepalive in PS mode:
+	 * 0x0000 = don't change
+	 * 0x001E = firmware default
+	 * 0xFFFF = disable
+	 */
 	__le16 nullpktinterval;
+
+	/* Number of DTIM intervals to wake up for:
+	 * 0 = don't change
+	 * 1 = firmware default
+	 * 5 = max
+	 */
 	__le16 multipledtim;
+
 	__le16 reserved;
 	__le16 locallisteninterval;
+
+	/* AdHoc awake period (FW v9+ only):
+	 * 0 = don't change
+	 * 1 = always awake (IEEE standard behavior)
+	 * 2 - 31 = sleep for (n - 1) periods and awake for 1 period
+	 * 32 - 254 = invalid
+	 * 255 = sleep at each ATIM
+	 */
+	__le16 adhoc_awake_period;
 } __packed;
 
 struct cmd_confirm_sleep {
@@ -882,12 +887,17 @@
 
 
 struct cmd_ds_802_11_led_ctrl {
+	struct cmd_header hdr;
+
 	__le16 action;
 	__le16 numled;
 	u8 data[256];
 } __packed;
 
+/* Automatic Frequency Control */
 struct cmd_ds_802_11_afc {
+	struct cmd_header hdr;
+
 	__le16 afc_auto;
 	union {
 		struct {
@@ -910,6 +920,8 @@
 } __packed;
 
 struct cmd_ds_bt_access {
+	struct cmd_header hdr;
+
 	__le16 action;
 	__le32 id;
 	u8 addr1[ETH_ALEN];
@@ -917,6 +929,8 @@
 } __packed;
 
 struct cmd_ds_fwt_access {
+	struct cmd_header hdr;
+
 	__le16 action;
 	__le32 id;
 	u8 valid;
@@ -955,34 +969,4 @@
 
 /* Number of stats counters returned by the firmware */
 #define MESH_STATS_NUM 8
-
-struct cmd_ds_command {
-	/* command header */
-	__le16 command;
-	__le16 size;
-	__le16 seqnum;
-	__le16 result;
-
-	/* command Body */
-	union {
-		struct cmd_ds_802_11_ps_mode psmode;
-		struct cmd_ds_802_11_monitor_mode monitor;
-		struct cmd_ds_802_11_rssi rssi;
-		struct cmd_ds_802_11_rssi_rsp rssirsp;
-		struct cmd_ds_mac_reg_access macreg;
-		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;
-
-		struct cmd_ds_bt_access bt;
-		struct cmd_ds_fwt_access fwt;
-		struct cmd_ds_802_11_beacon_control bcn_ctrl;
-	} params;
-} __packed;
 #endif
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3678e53..07ece9d 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -433,7 +433,7 @@
 
 static int if_usb_reset_device(struct if_usb_card *cardp)
 {
-	struct cmd_ds_command *cmd = cardp->ep_out_buf + 4;
+	struct cmd_header *cmd = cardp->ep_out_buf + 4;
 	int ret;
 
 	lbs_deb_enter(LBS_DEB_USB);
@@ -441,7 +441,7 @@
 	*(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
 
 	cmd->command = cpu_to_le16(CMD_802_11_RESET);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_header));
+	cmd->size = cpu_to_le16(sizeof(cmd));
 	cmd->result = cpu_to_le16(0);
 	cmd->seqnum = cpu_to_le16(0x5a5a);
 	usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 2a0b590..2589671 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -157,12 +157,7 @@
 	   to kick it somehow? */
 	lbs_host_to_card_done(priv);
 
-	/* More often than not, this actually happens because the
-	   firmware has crapped itself -- rather than just a very
-	   busy medium. So send a harmless command, and if/when
-	   _that_ times out, we'll kick it in the head. */
-	lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
-				     0, 0, NULL);
+	/* FIXME: reset the card */
 
 	lbs_deb_leave(LBS_DEB_TX);
 }
@@ -507,12 +502,6 @@
 		if (!priv->dnld_sent && !priv->cur_cmd)
 			lbs_execute_next_command(priv);
 
-		/* Wake-up command waiters which can't sleep in
-		 * lbs_prepare_and_send_command
-		 */
-		if (!list_empty(&priv->cmdpendingq))
-			wake_up_all(&priv->cmd_pending);
-
 		spin_lock_irq(&priv->driver_lock);
 		if (!priv->dnld_sent && priv->tx_pending_len > 0) {
 			int ret = priv->hw_host_to_card(priv, MVMS_DAT,
@@ -538,7 +527,6 @@
 
 	del_timer(&priv->command_timer);
 	del_timer(&priv->auto_deepsleep_timer);
-	wake_up_all(&priv->cmd_pending);
 
 	lbs_deb_leave(LBS_DEB_THREAD);
 	return 0;
@@ -663,7 +651,6 @@
 static void auto_deepsleep_timer_fn(unsigned long data)
 {
 	struct lbs_private *priv = (struct lbs_private *)data;
-	int ret;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
@@ -671,14 +658,15 @@
 		priv->is_activity_detected = 0;
 	} else {
 		if (priv->is_auto_deep_sleep_enabled &&
-				(!priv->wakeup_dev_required) &&
-				(priv->connect_status != LBS_CONNECTED)) {
+		    (!priv->wakeup_dev_required) &&
+		    (priv->connect_status != LBS_CONNECTED)) {
+			struct cmd_header cmd;
+
 			lbs_deb_main("Entering auto deep sleep mode...\n");
-			ret = lbs_prepare_and_send_command(priv,
-					CMD_802_11_DEEP_SLEEP, 0,
-					0, 0, NULL);
-			if (ret)
-				lbs_pr_err("Enter Deep Sleep command failed\n");
+			memset(&cmd, 0, sizeof(cmd));
+			cmd.size = cpu_to_le16(sizeof(cmd));
+			lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd,
+					sizeof(cmd));
 		}
 	}
 	mod_timer(&priv->auto_deepsleep_timer , jiffies +
@@ -746,7 +734,6 @@
 	INIT_LIST_HEAD(&priv->cmdpendingq);
 
 	spin_lock_init(&priv->driver_lock);
-	init_waitqueue_head(&priv->cmd_pending);
 
 	/* Allocate the command buffers */
 	if (lbs_allocate_cmd_buffer(priv)) {
@@ -902,7 +889,7 @@
 
 	if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
 		priv->psmode = LBS802_11POWERMODECAM;
-		lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
+		lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true);
 	}
 
 	if (priv->is_deep_sleep) {
@@ -1065,7 +1052,7 @@
 	memset(&confirm_sleep, 0, sizeof(confirm_sleep));
 	confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
 	confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
-	confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED);
+	confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED);
 	lbs_debugfs_init();
 	lbs_deb_leave(LBS_DEB_MAIN);
 	return 0;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index bc5bc13..194762a 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -455,65 +455,189 @@
  * Mesh command handling
  */
 
-int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
+/**
+ *  @brief Add or delete Mesh Blinding Table entries
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param add  	TRUE to add the entry, FALSE to delete it
+ *  @param addr1        Destination address to blind or unblind
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
 {
-	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+	struct cmd_ds_bt_access cmd;
+	int ret = 0;
 
-	cmd->command = cpu_to_le16(CMD_BT_ACCESS);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
-		sizeof(struct cmd_header));
-	cmd->result = 0;
-	bt_access->action = cpu_to_le16(cmd_action);
+	lbs_deb_enter(LBS_DEB_CMD);
 
-	switch (cmd_action) {
-	case CMD_ACT_BT_ACCESS_ADD:
-		memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
+	BUG_ON(addr1 == NULL);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	memcpy(cmd.addr1, addr1, ETH_ALEN);
+	if (add) {
+		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
 		lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
-			bt_access->addr1, 6);
-		break;
-	case CMD_ACT_BT_ACCESS_DEL:
-		memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
+			addr1, ETH_ALEN);
+	} else {
+		cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
 		lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
-			bt_access->addr1, 6);
-		break;
-	case CMD_ACT_BT_ACCESS_LIST:
-		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
-		break;
-	case CMD_ACT_BT_ACCESS_RESET:
-		break;
-	case CMD_ACT_BT_ACCESS_SET_INVERT:
-		bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
-		break;
-	case CMD_ACT_BT_ACCESS_GET_INVERT:
-		break;
-	default:
-		break;
+			addr1, ETH_ALEN);
 	}
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
+
+	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
 }
 
-int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
+/**
+ *  @brief Reset/clear the mesh blinding table
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_mesh_bt_reset(struct lbs_private *priv)
 {
-	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
+	struct cmd_ds_bt_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
+
+	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Gets the inverted status of the mesh blinding table
+ *
+ *  Normally the firmware "blinds" or ignores traffic from mesh nodes in the
+ *  table, but an inverted table allows *only* traffic from nodes listed in
+ *  the table.
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param invert  	On success, TRUE if the blinding table is inverted,
+ *                        FALSE if it is not inverted
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
+{
+	struct cmd_ds_bt_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	BUG_ON(inverted == NULL);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
+
+	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+	if (ret == 0)
+		*inverted = !!cmd.id;
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Sets the inverted status of the mesh blinding table
+ *
+ *  Normally the firmware "blinds" or ignores traffic from mesh nodes in the
+ *  table, but an inverted table allows *only* traffic from nodes listed in
+ *  the table.
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param invert  	TRUE to invert the blinding table (only traffic from
+ *                         listed nodes allowed), FALSE to return it
+ *                         to normal state (listed nodes ignored)
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
+{
+	struct cmd_ds_bt_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
+	cmd.id = !!inverted;
+
+	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief List an entry in the mesh blinding table
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param id		The ID of the entry to list
+ *  @param addr1	MAC address associated with the table entry
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
+{
+	struct cmd_ds_bt_access cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	BUG_ON(addr1 == NULL);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
+	cmd.id = cpu_to_le32(id);
+
+	ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
+	if (ret == 0)
+		memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Access the mesh forwarding table
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param cmd_action	The forwarding table action to perform
+ *  @param cmd		The pre-filled FWT_ACCESS command
+ *
+ *  @return 	   	0 on success and 'cmd' will be filled with the
+ *                        firmware's response
+ */
+int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
+			struct cmd_ds_fwt_access *cmd)
+{
+	int ret;
+
 	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
 
-	cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
-		sizeof(struct cmd_header));
-	cmd->result = 0;
+	cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
+	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
+	cmd->hdr.result = 0;
+	cmd->action = cpu_to_le16(cmd_action);
 
-	if (pdata_buf)
-		memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
-	else
-		memset(fwt_access, 0, sizeof(*fwt_access));
+	ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
 
-	fwt_access->action = cpu_to_le16(cmd_action);
-
-	lbs_deb_leave(LBS_DEB_CMD);
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index 84ea248..afb2e8d 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -8,6 +8,7 @@
 #include <net/iw_handler.h>
 #include <net/lib80211.h>
 
+#include "host.h"
 
 #ifdef CONFIG_LIBERTAS_MESH
 
@@ -51,10 +52,15 @@
 struct cmd_ds_mesh_access;
 struct cmd_ds_mesh_config;
 
-int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
-	u16 cmd_action, void *pdata_buf);
-int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
-	u16 cmd_action, void *pdata_buf);
+int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
+int lbs_mesh_bt_reset(struct lbs_private *priv);
+int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
+int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
+int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
+
+int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
+			struct cmd_ds_fwt_access *cmd);
+
 int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
 		    struct cmd_ds_mesh_access *cmd);
 int lbs_mesh_config_send(struct lbs_private *priv,
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index e7f299d..01ad7f7 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -486,8 +486,7 @@
 	struct ieee80211_rx_status rx_status;
 
 	if (data->idle) {
-		printk(KERN_DEBUG "%s: Trying to TX when idle - reject\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_debug(hw->wiphy, "trying to tx when idle - reject\n");
 		return false;
 	}
 
@@ -576,7 +575,7 @@
 static int mac80211_hwsim_start(struct ieee80211_hw *hw)
 {
 	struct mac80211_hwsim_data *data = hw->priv;
-	printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+	wiphy_debug(hw->wiphy, "%s\n", __func__);
 	data->started = 1;
 	return 0;
 }
@@ -587,16 +586,15 @@
 	struct mac80211_hwsim_data *data = hw->priv;
 	data->started = 0;
 	del_timer(&data->beacon_timer);
-	printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+	wiphy_debug(hw->wiphy, "%s\n", __func__);
 }
 
 
 static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
 					struct ieee80211_vif *vif)
 {
-	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
-	       wiphy_name(hw->wiphy), __func__, vif->type,
-	       vif->addr);
+	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+		    __func__, vif->type, vif->addr);
 	hwsim_set_magic(vif);
 	return 0;
 }
@@ -605,9 +603,8 @@
 static void mac80211_hwsim_remove_interface(
 	struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
-	printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
-	       wiphy_name(hw->wiphy), __func__, vif->type,
-	       vif->addr);
+	wiphy_debug(hw->wiphy, "%s (type=%d mac_addr=%pM)\n",
+		    __func__, vif->type, vif->addr);
 	hwsim_check_magic(vif);
 	hwsim_clear_magic(vif);
 }
@@ -670,13 +667,14 @@
 		[IEEE80211_SMPS_DYNAMIC] = "dynamic",
 	};
 
-	printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
-	       wiphy_name(hw->wiphy), __func__,
-	       conf->channel->center_freq,
-	       hwsim_chantypes[conf->channel_type],
-	       !!(conf->flags & IEEE80211_CONF_IDLE),
-	       !!(conf->flags & IEEE80211_CONF_PS),
-	       smps_modes[conf->smps_mode]);
+	wiphy_debug(hw->wiphy,
+		    "%s (freq=%d/%s idle=%d ps=%d smps=%s)\n",
+		    __func__,
+		    conf->channel->center_freq,
+		    hwsim_chantypes[conf->channel_type],
+		    !!(conf->flags & IEEE80211_CONF_IDLE),
+		    !!(conf->flags & IEEE80211_CONF_PS),
+		    smps_modes[conf->smps_mode]);
 
 	data->idle = !!(conf->flags & IEEE80211_CONF_IDLE);
 
@@ -696,7 +694,7 @@
 {
 	struct mac80211_hwsim_data *data = hw->priv;
 
-	printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
+	wiphy_debug(hw->wiphy, "%s\n", __func__);
 
 	data->rx_filter = 0;
 	if (*total_flags & FIF_PROMISC_IN_BSS)
@@ -717,26 +715,23 @@
 
 	hwsim_check_magic(vif);
 
-	printk(KERN_DEBUG "%s:%s(changed=0x%x)\n",
-	       wiphy_name(hw->wiphy), __func__, changed);
+	wiphy_debug(hw->wiphy, "%s(changed=0x%x)\n", __func__, changed);
 
 	if (changed & BSS_CHANGED_BSSID) {
-		printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
-		       wiphy_name(hw->wiphy), __func__,
-		       info->bssid);
+		wiphy_debug(hw->wiphy, "%s: BSSID changed: %pM\n",
+			    __func__, info->bssid);
 		memcpy(vp->bssid, info->bssid, ETH_ALEN);
 	}
 
 	if (changed & BSS_CHANGED_ASSOC) {
-		printk(KERN_DEBUG "  %s: ASSOC: assoc=%d aid=%d\n",
-		       wiphy_name(hw->wiphy), info->assoc, info->aid);
+		wiphy_debug(hw->wiphy, "  ASSOC: assoc=%d aid=%d\n",
+			    info->assoc, info->aid);
 		vp->assoc = info->assoc;
 		vp->aid = info->aid;
 	}
 
 	if (changed & BSS_CHANGED_BEACON_INT) {
-		printk(KERN_DEBUG "  %s: BCNINT: %d\n",
-		       wiphy_name(hw->wiphy), info->beacon_int);
+		wiphy_debug(hw->wiphy, "  BCNINT: %d\n", info->beacon_int);
 		data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
 		if (WARN_ON(!data->beacon_int))
 			data->beacon_int = 1;
@@ -746,31 +741,28 @@
 	}
 
 	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		printk(KERN_DEBUG "  %s: ERP_CTS_PROT: %d\n",
-		       wiphy_name(hw->wiphy), info->use_cts_prot);
+		wiphy_debug(hw->wiphy, "  ERP_CTS_PROT: %d\n",
+			    info->use_cts_prot);
 	}
 
 	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		printk(KERN_DEBUG "  %s: ERP_PREAMBLE: %d\n",
-		       wiphy_name(hw->wiphy), info->use_short_preamble);
+		wiphy_debug(hw->wiphy, "  ERP_PREAMBLE: %d\n",
+			    info->use_short_preamble);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
-		printk(KERN_DEBUG "  %s: ERP_SLOT: %d\n",
-		       wiphy_name(hw->wiphy), info->use_short_slot);
+		wiphy_debug(hw->wiphy, "  ERP_SLOT: %d\n", info->use_short_slot);
 	}
 
 	if (changed & BSS_CHANGED_HT) {
-		printk(KERN_DEBUG "  %s: HT: op_mode=0x%x, chantype=%s\n",
-		       wiphy_name(hw->wiphy),
-		       info->ht_operation_mode,
-		       hwsim_chantypes[info->channel_type]);
+		wiphy_debug(hw->wiphy, "  HT: op_mode=0x%x, chantype=%s\n",
+			    info->ht_operation_mode,
+			    hwsim_chantypes[info->channel_type]);
 	}
 
 	if (changed & BSS_CHANGED_BASIC_RATES) {
-		printk(KERN_DEBUG "  %s: BASIC_RATES: 0x%llx\n",
-		       wiphy_name(hw->wiphy),
-		       (unsigned long long) info->basic_rates);
+		wiphy_debug(hw->wiphy, "  BASIC_RATES: 0x%llx\n",
+			    (unsigned long long) info->basic_rates);
 	}
 }
 
@@ -824,10 +816,11 @@
 	struct ieee80211_hw *hw, u16 queue,
 	const struct ieee80211_tx_queue_params *params)
 {
-	printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d "
-	       "aifs=%d)\n",
-	       wiphy_name(hw->wiphy), __func__, queue,
-	       params->txop, params->cw_min, params->cw_max, params->aifs);
+	wiphy_debug(hw->wiphy,
+		    "%s (queue=%d txop=%d cw_min=%d cw_max=%d aifs=%d)\n",
+		    __func__, queue,
+		    params->txop, params->cw_min,
+		    params->cw_max, params->aifs);
 	return 0;
 }
 
@@ -837,8 +830,7 @@
 {
 	struct ieee80211_conf *conf = &hw->conf;
 
-	printk(KERN_DEBUG "%s:%s (idx=%d)\n",
-	       wiphy_name(hw->wiphy), __func__, idx);
+	wiphy_debug(hw->wiphy, "%s (idx=%d)\n", __func__, idx);
 
 	if (idx != 0)
 		return -ENOENT;
@@ -1108,8 +1100,9 @@
 	if (!vp->assoc)
 		return;
 
-	printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n",
-	       wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid);
+	wiphy_debug(data->hw->wiphy,
+		    "%s: send PS-Poll to %pM for aid %d\n",
+		    __func__, vp->bssid, vp->aid);
 
 	skb = dev_alloc_skb(sizeof(*pspoll));
 	if (!skb)
@@ -1137,8 +1130,9 @@
 	if (!vp->assoc)
 		return;
 
-	printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n",
-	       wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps);
+	wiphy_debug(data->hw->wiphy,
+		    "%s: send data::nullfunc to %pM ps=%d\n",
+		    __func__, vp->bssid, ps);
 
 	skb = dev_alloc_skb(sizeof(*hdr));
 	if (!skb)
@@ -1473,9 +1467,8 @@
 			break;
 		}
 
-		printk(KERN_DEBUG "%s: hwaddr %pM registered\n",
-		       wiphy_name(hw->wiphy),
-		       hw->wiphy->perm_addr);
+		wiphy_debug(hw->wiphy, "hwaddr %pm registered\n",
+			    hw->wiphy->perm_addr);
 
 		data->debugfs = debugfs_create_dir("hwsim",
 						   hw->wiphy->debugfsdir);
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index 0e34260..28beeaf 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -905,16 +905,14 @@
 
 	rxq->rxd = pci_alloc_consistent(priv->pdev, size, &rxq->rxd_dma);
 	if (rxq->rxd == NULL) {
-		printk(KERN_ERR "%s: failed to alloc RX descriptors\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to alloc rx descriptors\n");
 		return -ENOMEM;
 	}
 	memset(rxq->rxd, 0, size);
 
 	rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
 	if (rxq->buf == NULL) {
-		printk(KERN_ERR "%s: failed to alloc RX skbuff list\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to alloc rx skbuff list\n");
 		pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
 		return -ENOMEM;
 	}
@@ -1141,16 +1139,14 @@
 
 	txq->txd = pci_alloc_consistent(priv->pdev, size, &txq->txd_dma);
 	if (txq->txd == NULL) {
-		printk(KERN_ERR "%s: failed to alloc TX descriptors\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to alloc tx descriptors\n");
 		return -ENOMEM;
 	}
 	memset(txq->txd, 0, size);
 
 	txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
-		printk(KERN_ERR "%s: failed to alloc TX skbuff list\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to alloc tx skbuff list\n");
 		pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
 		return -ENOMEM;
 	}
@@ -1206,11 +1202,12 @@
 				unused++;
 		}
 
-		printk(KERN_ERR "%s: txq[%d] len=%d head=%d tail=%d "
-		       "fw_owned=%d drv_owned=%d unused=%d\n",
-		       wiphy_name(hw->wiphy), i,
-		       txq->len, txq->head, txq->tail,
-		       fw_owned, drv_owned, unused);
+		wiphy_err(hw->wiphy,
+			  "txq[%d] len=%d head=%d tail=%d "
+			  "fw_owned=%d drv_owned=%d unused=%d\n",
+			  i,
+			  txq->len, txq->head, txq->tail,
+			  fw_owned, drv_owned, unused);
 	}
 }
 
@@ -1254,25 +1251,23 @@
 		if (timeout) {
 			WARN_ON(priv->pending_tx_pkts);
 			if (retry) {
-				printk(KERN_NOTICE "%s: tx rings drained\n",
-				       wiphy_name(hw->wiphy));
+				wiphy_notice(hw->wiphy, "tx rings drained\n");
 			}
 			break;
 		}
 
 		if (priv->pending_tx_pkts < oldcount) {
-			printk(KERN_NOTICE "%s: waiting for tx rings "
-			       "to drain (%d -> %d pkts)\n",
-			       wiphy_name(hw->wiphy), oldcount,
-			       priv->pending_tx_pkts);
+			wiphy_notice(hw->wiphy,
+				     "waiting for tx rings to drain (%d -> %d pkts)\n",
+				     oldcount, priv->pending_tx_pkts);
 			retry = 1;
 			continue;
 		}
 
 		priv->tx_wait = NULL;
 
-		printk(KERN_ERR "%s: tx rings stuck for %d ms\n",
-		       wiphy_name(hw->wiphy), MWL8K_TX_WAIT_TIMEOUT_MS);
+		wiphy_err(hw->wiphy, "tx rings stuck for %d ms\n",
+			  MWL8K_TX_WAIT_TIMEOUT_MS);
 		mwl8k_dump_tx_rings(hw);
 
 		rc = -ETIMEDOUT;
@@ -1423,8 +1418,8 @@
 				skb->len, PCI_DMA_TODEVICE);
 
 	if (pci_dma_mapping_error(priv->pdev, dma)) {
-		printk(KERN_DEBUG "%s: failed to dma map skb, "
-		       "dropping TX frame.\n", wiphy_name(hw->wiphy));
+		wiphy_debug(hw->wiphy,
+			    "failed to dma map skb, dropping TX frame.\n");
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -1572,10 +1567,9 @@
 					PCI_DMA_BIDIRECTIONAL);
 
 	if (!timeout) {
-		printk(KERN_ERR "%s: Command %s timeout after %u ms\n",
-		       wiphy_name(hw->wiphy),
-		       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
-		       MWL8K_CMD_TIMEOUT_MS);
+		wiphy_err(hw->wiphy, "command %s timeout after %u ms\n",
+			  mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
+			  MWL8K_CMD_TIMEOUT_MS);
 		rc = -ETIMEDOUT;
 	} else {
 		int ms;
@@ -1584,15 +1578,14 @@
 
 		rc = cmd->result ? -EINVAL : 0;
 		if (rc)
-			printk(KERN_ERR "%s: Command %s error 0x%x\n",
-			       wiphy_name(hw->wiphy),
-			       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
-			       le16_to_cpu(cmd->result));
+			wiphy_err(hw->wiphy, "command %s error 0x%x\n",
+				  mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
+				  le16_to_cpu(cmd->result));
 		else if (ms > 2000)
-			printk(KERN_NOTICE "%s: Command %s took %d ms\n",
-			       wiphy_name(hw->wiphy),
-			       mwl8k_cmd_name(cmd->code, buf, sizeof(buf)),
-			       ms);
+			wiphy_notice(hw->wiphy, "command %s took %d ms\n",
+				     mwl8k_cmd_name(cmd->code,
+						    buf, sizeof(buf)),
+				     ms);
 	}
 
 	return rc;
@@ -3192,8 +3185,8 @@
 	int rc;
 
 	if (!priv->radio_on) {
-		printk(KERN_DEBUG "%s: dropped TX frame since radio "
-		       "disabled\n", wiphy_name(hw->wiphy));
+		wiphy_debug(hw->wiphy,
+			    "dropped TX frame since radio disabled\n");
 		dev_kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -3211,8 +3204,7 @@
 	rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
 			 IRQF_SHARED, MWL8K_NAME, hw);
 	if (rc) {
-		printk(KERN_ERR "%s: failed to register IRQ handler\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to register irq handler\n");
 		return -EIO;
 	}
 
@@ -3299,9 +3291,8 @@
 	 * mode.  (Sniffer mode is only used on STA firmware.)
 	 */
 	if (priv->sniffer_enabled) {
-		printk(KERN_INFO "%s: unable to create STA "
-		       "interface due to sniffer mode being enabled\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_info(hw->wiphy,
+			   "unable to create STA interface because sniffer mode is enabled\n");
 		return -EINVAL;
 	}
 
@@ -3583,9 +3574,8 @@
 	 */
 	if (!list_empty(&priv->vif_list)) {
 		if (net_ratelimit())
-			printk(KERN_INFO "%s: not enabling sniffer "
-			       "mode because STA interface is active\n",
-			       wiphy_name(hw->wiphy));
+			wiphy_info(hw->wiphy,
+				   "not enabling sniffer mode because STA interface is active\n");
 		return 0;
 	}
 
@@ -3913,8 +3903,7 @@
 
 	priv->sram = pci_iomap(pdev, 0, 0x10000);
 	if (priv->sram == NULL) {
-		printk(KERN_ERR "%s: Cannot map device SRAM\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot map device sram\n");
 		goto err_iounmap;
 	}
 
@@ -3926,8 +3915,7 @@
 	if (priv->regs == NULL) {
 		priv->regs = pci_iomap(pdev, 2, 0x10000);
 		if (priv->regs == NULL) {
-			printk(KERN_ERR "%s: Cannot map device registers\n",
-			       wiphy_name(hw->wiphy));
+			wiphy_err(hw->wiphy, "cannot map device registers\n");
 			goto err_iounmap;
 		}
 	}
@@ -3939,16 +3927,14 @@
 	/* Ask userland hotplug daemon for the device firmware */
 	rc = mwl8k_request_firmware(priv);
 	if (rc) {
-		printk(KERN_ERR "%s: Firmware files not found\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "firmware files not found\n");
 		goto err_stop_firmware;
 	}
 
 	/* Load firmware into hardware */
 	rc = mwl8k_load_firmware(hw);
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot start firmware\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot start firmware\n");
 		goto err_stop_firmware;
 	}
 
@@ -3959,9 +3945,8 @@
 	if (priv->ap_fw) {
 		priv->rxd_ops = priv->device_info->ap_rxd_ops;
 		if (priv->rxd_ops == NULL) {
-			printk(KERN_ERR "%s: Driver does not have AP "
-			       "firmware image support for this hardware\n",
-			       wiphy_name(hw->wiphy));
+			wiphy_err(hw->wiphy,
+				  "Driver does not have AP firmware image support for this hardware\n");
 			goto err_stop_firmware;
 		}
 	} else {
@@ -4039,8 +4024,7 @@
 	rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
 			 IRQF_SHARED, MWL8K_NAME, hw);
 	if (rc) {
-		printk(KERN_ERR "%s: failed to register IRQ handler\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "failed to register irq handler\n");
 		goto err_free_queues;
 	}
 
@@ -4060,8 +4044,7 @@
 		rc = mwl8k_cmd_get_hw_spec_sta(hw);
 	}
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot initialise firmware\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot initialise firmware\n");
 		goto err_free_irq;
 	}
 
@@ -4075,15 +4058,14 @@
 	/* Turn radio off */
 	rc = mwl8k_cmd_radio_disable(hw);
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot disable\n");
 		goto err_free_irq;
 	}
 
 	/* Clear MAC address */
 	rc = mwl8k_cmd_set_mac_addr(hw, NULL, "\x00\x00\x00\x00\x00\x00");
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot clear MAC address\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot clear mac address\n");
 		goto err_free_irq;
 	}
 
@@ -4093,17 +4075,16 @@
 
 	rc = ieee80211_register_hw(hw);
 	if (rc) {
-		printk(KERN_ERR "%s: Cannot register device\n",
-		       wiphy_name(hw->wiphy));
+		wiphy_err(hw->wiphy, "cannot register device\n");
 		goto err_free_queues;
 	}
 
-	printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n",
-	       wiphy_name(hw->wiphy), priv->device_info->part_name,
-	       priv->hw_rev, hw->wiphy->perm_addr,
-	       priv->ap_fw ? "AP" : "STA",
-	       (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
-	       (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
+	wiphy_info(hw->wiphy, "%s v%d, %pm, %s firmware %u.%u.%u.%u\n",
+		   priv->device_info->part_name,
+		   priv->hw_rev, hw->wiphy->perm_addr,
+		   priv->ap_fw ? "AP" : "STA",
+		   (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff,
+		   (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff);
 
 	return 0;
 
diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c
index 8c4169c..09fae2f 100644
--- a/drivers/net/wireless/orinoco/cfg.c
+++ b/drivers/net/wireless/orinoco/cfg.c
@@ -117,9 +117,8 @@
 
 	case NL80211_IFTYPE_MONITOR:
 		if (priv->broken_monitor && !force_monitor) {
-			printk(KERN_WARNING "%s: Monitor mode support is "
-			       "buggy in this firmware, not enabling\n",
-			       wiphy_name(wiphy));
+			wiphy_warn(wiphy,
+				   "Monitor mode support is buggy in this firmware, not enabling\n");
 			err = -EINVAL;
 		}
 		break;
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c
index e51650e..d687cb7 100644
--- a/drivers/net/wireless/p54/eeprom.c
+++ b/drivers/net/wireless/p54/eeprom.c
@@ -149,16 +149,15 @@
 			continue;
 
 		if (list->channels[i].data != CHAN_HAS_ALL) {
-			printk(KERN_ERR "%s:%s%s%s is/are missing for "
-					"channel:%d [%d MHz].\n",
-			       wiphy_name(dev->wiphy),
-			       (list->channels[i].data & CHAN_HAS_CAL ? "" :
-				" [iqauto calibration data]"),
-			       (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
-				" [output power limits]"),
-			       (list->channels[i].data & CHAN_HAS_CURVE ? "" :
-				" [curve data]"),
-			       list->channels[i].index, list->channels[i].freq);
+			wiphy_err(dev->wiphy,
+				  "%s%s%s is/are missing for channel:%d [%d MHz].\n",
+				  (list->channels[i].data & CHAN_HAS_CAL ? "" :
+				   " [iqauto calibration data]"),
+				  (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
+				   " [output power limits]"),
+				  (list->channels[i].data & CHAN_HAS_CURVE ? "" :
+				   " [curve data]"),
+				  list->channels[i].index, list->channels[i].freq);
 			continue;
 		}
 
@@ -168,9 +167,8 @@
 	}
 
 	if (j == 0) {
-		printk(KERN_ERR "%s: Disabling totally damaged %s band.\n",
-		       wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ?
-		       "2 GHz" : "5 GHz");
+		wiphy_err(dev->wiphy, "disabling totally damaged %d GHz band\n",
+			  (band == IEEE80211_BAND_2GHZ) ? 2 : 5);
 
 		ret = -ENODATA;
 		goto err_out;
@@ -244,9 +242,9 @@
 
 	if ((priv->iq_autocal_len != priv->curve_data->entries) ||
 	    (priv->iq_autocal_len != priv->output_limit->entries))
-		printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. "
-				"You may not be able to use all channels.\n",
-				wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy,
+			  "Unsupported or damaged EEPROM detected. "
+			  "You may not be able to use all channels.\n");
 
 	max_channel_num = max_t(unsigned int, priv->output_limit->entries,
 				priv->iq_autocal_len);
@@ -419,15 +417,14 @@
 	int i;
 
 	if (len != (entry_size * num_entries)) {
-		printk(KERN_ERR "%s: unknown rssi calibration data packing "
-				 " type:(%x) len:%d.\n",
-		       wiphy_name(dev->wiphy), type, len);
+		wiphy_err(dev->wiphy,
+			  "unknown rssi calibration data packing type:(%x) len:%d.\n",
+			  type, len);
 
 		print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
 				     data, len);
 
-		printk(KERN_ERR "%s: please report this issue.\n",
-			wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "please report this issue.\n");
 		return;
 	}
 
@@ -445,15 +442,14 @@
 	struct pda_country *country;
 
 	if (len != sizeof(*country)) {
-		printk(KERN_ERR "%s: found possible invalid default country "
-				"eeprom entry. (entry size: %d)\n",
-		       wiphy_name(dev->wiphy), len);
+		wiphy_err(dev->wiphy,
+			  "found possible invalid default country eeprom entry. (entry size: %d)\n",
+			  len);
 
 		print_hex_dump_bytes("country:", DUMP_PREFIX_NONE,
 				     data, len);
 
-		printk(KERN_ERR "%s: please report this issue.\n",
-			wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "please report this issue.\n");
 		return;
 	}
 
@@ -478,8 +474,8 @@
 		return -EINVAL;
 
 	if (data[0] != 0) {
-		printk(KERN_ERR "%s: unknown output power db revision:%x\n",
-		       wiphy_name(dev->wiphy), data[0]);
+		wiphy_err(dev->wiphy, "unknown output power db revision:%x\n",
+			  data[0]);
 		return -EINVAL;
 	}
 
@@ -587,10 +583,9 @@
 				err = p54_convert_rev1(dev, curve_data);
 				break;
 			default:
-				printk(KERN_ERR "%s: unknown curve data "
-						"revision %d\n",
-						wiphy_name(dev->wiphy),
-						curve_data->cal_method_rev);
+				wiphy_err(dev->wiphy,
+					  "unknown curve data revision %d\n",
+					  curve_data->cal_method_rev);
 				err = -ENODEV;
 				break;
 			}
@@ -672,8 +667,8 @@
 
 	if (!synth || !priv->iq_autocal || !priv->output_limit ||
 	    !priv->curve_data) {
-		printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
-			wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy,
+			  "not all required entries found in eeprom!\n");
 		err = -EINVAL;
 		goto err;
 	}
@@ -699,15 +694,15 @@
 	if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
 		u8 perm_addr[ETH_ALEN];
 
-		printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n",
-			wiphy_name(dev->wiphy));
+		wiphy_warn(dev->wiphy,
+			   "invalid hwaddr! using randomly generated mac addr\n");
 		random_ether_addr(perm_addr);
 		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 	}
 
-	printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
-		wiphy_name(dev->wiphy),	dev->wiphy->perm_addr, priv->version,
-		p54_rf_chips[priv->rxhw]);
+	wiphy_info(dev->wiphy, "hwaddr %pm, mac:isl38%02x rf:%s\n",
+		   dev->wiphy->perm_addr, priv->version,
+		   p54_rf_chips[priv->rxhw]);
 
 	return 0;
 
@@ -719,8 +714,7 @@
 	priv->output_limit = NULL;
 	priv->curve_data = NULL;
 
-	printk(KERN_ERR "%s: eeprom parse failed!\n",
-		wiphy_name(dev->wiphy));
+	wiphy_err(dev->wiphy, "eeprom parse failed!\n");
 	return err;
 }
 EXPORT_SYMBOL_GPL(p54_parse_eeprom);
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c
index c43a5d4..47006bc 100644
--- a/drivers/net/wireless/p54/fwio.c
+++ b/drivers/net/wireless/p54/fwio.c
@@ -62,16 +62,15 @@
 			case FW_LM20:
 			case FW_LM87: {
 				char *iftype = (char *)bootrec->data;
-				printk(KERN_INFO "%s: p54 detected a LM%c%c "
-						 "firmware\n",
-					wiphy_name(priv->hw->wiphy),
-					iftype[2], iftype[3]);
+				wiphy_info(priv->hw->wiphy,
+					   "p54 detected a LM%c%c firmware\n",
+					   iftype[2], iftype[3]);
 				break;
 				}
 			case FW_FMAC:
 			default:
-				printk(KERN_ERR "%s: unsupported firmware\n",
-					wiphy_name(priv->hw->wiphy));
+				wiphy_err(priv->hw->wiphy,
+					  "unsupported firmware\n");
 				return -ENODEV;
 			}
 			break;
@@ -125,15 +124,15 @@
 	}
 
 	if (fw_version)
-		printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
-			wiphy_name(priv->hw->wiphy), fw_version,
-			priv->fw_var >> 8, priv->fw_var & 0xff);
+		wiphy_info(priv->hw->wiphy,
+			   "fw rev %s - softmac protocol %x.%x\n",
+			   fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
 
 	if (priv->fw_var < 0x500)
-		printk(KERN_INFO "%s: you are using an obsolete firmware. "
-		       "visit http://wireless.kernel.org/en/users/Drivers/p54 "
-		       "and grab one for \"kernel >= 2.6.28\"!\n",
-			wiphy_name(priv->hw->wiphy));
+		wiphy_info(priv->hw->wiphy,
+			   "you are using an obsolete firmware. "
+			   "visit http://wireless.kernel.org/en/users/Drivers/p54 "
+			   "and grab one for \"kernel >= 2.6.28\"!\n");
 
 	if (priv->fw_var >= 0x300) {
 		/* Firmware supports QoS, use it! */
@@ -152,13 +151,14 @@
 		priv->hw->queues = P54_QUEUE_AC_NUM;
 	}
 
-	printk(KERN_INFO "%s: cryptographic accelerator "
-	       "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy),
-		(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
-		"no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
-		BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
-		(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
-		"YES" : "no");
+	wiphy_info(priv->hw->wiphy,
+		   "cryptographic accelerator WEP:%s, TKIP:%s, CCMP:%s\n",
+		   (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : "no",
+		   (priv->privacy_caps &
+		    (BR_DESC_PRIV_CAP_TKIP | BR_DESC_PRIV_CAP_MICHAEL))
+		   ? "YES" : "no",
+		   (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)
+		   ? "YES" : "no");
 
 	if (priv->rx_keycache_size) {
 		/*
@@ -247,8 +247,7 @@
 
 	if (!wait_for_completion_interruptible_timeout(
 	     &priv->eeprom_comp, HZ)) {
-		printk(KERN_ERR "%s: device does not respond!\n",
-		       wiphy_name(priv->hw->wiphy));
+		wiphy_err(priv->hw->wiphy, "device does not respond!\n");
 		ret = -EBUSY;
 	}
 	priv->eeprom = NULL;
@@ -523,9 +522,9 @@
 	return 0;
 
 err:
-	printk(KERN_ERR "%s: frequency change to channel %d failed.\n",
-	       wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel(
-	       priv->hw->conf.channel->center_freq));
+	wiphy_err(priv->hw->wiphy, "frequency change to channel %d failed.\n",
+		  ieee80211_frequency_to_channel(
+			  priv->hw->conf.channel->center_freq));
 
 	dev_kfree_skb_any(skb);
 	return -EINVAL;
@@ -676,8 +675,8 @@
 		break;
 
 	default:
-		printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n",
-		       wiphy_name(priv->hw->wiphy), algo);
+		wiphy_err(priv->hw->wiphy,
+			  "invalid cryptographic algorithm: %d\n", algo);
 		dev_kfree_skb(skb);
 		return -EINVAL;
 	}
diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c
index 9575ac0..ea91f5c 100644
--- a/drivers/net/wireless/p54/led.c
+++ b/drivers/net/wireless/p54/led.c
@@ -57,8 +57,8 @@
 
 	err = p54_set_leds(priv);
 	if (err && net_ratelimit())
-		printk(KERN_ERR "%s: failed to update LEDs (%d).\n",
-			wiphy_name(priv->hw->wiphy), err);
+		wiphy_err(priv->hw->wiphy,
+			  "failed to update leds (%d).\n", err);
 
 	if (rerun)
 		ieee80211_queue_delayed_work(priv->hw, &priv->led_work,
@@ -102,8 +102,8 @@
 
 	err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev);
 	if (err)
-		printk(KERN_ERR "%s: Failed to register %s LED.\n",
-			wiphy_name(priv->hw->wiphy), name);
+		wiphy_err(priv->hw->wiphy,
+			  "failed to register %s led.\n", name);
 	else
 		led->registered = 1;
 
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c
index c072f41..47db439 100644
--- a/drivers/net/wireless/p54/main.c
+++ b/drivers/net/wireless/p54/main.c
@@ -507,6 +507,22 @@
 	return ret;
 }
 
+static int p54_get_survey(struct ieee80211_hw *dev, int idx,
+				struct survey_info *survey)
+{
+	struct p54_common *priv = dev->priv;
+	struct ieee80211_conf *conf = &dev->conf;
+
+	if (idx != 0)
+		return -ENOENT;
+
+	survey->channel = conf->channel;
+	survey->filled = SURVEY_INFO_NOISE_DBM;
+	survey->noise = clamp_t(s8, priv->noise, -128, 127);
+
+	return 0;
+}
+
 static const struct ieee80211_ops p54_ops = {
 	.tx			= p54_tx_80211,
 	.start			= p54_start,
@@ -523,6 +539,7 @@
 	.configure_filter	= p54_configure_filter,
 	.conf_tx		= p54_conf_tx,
 	.get_stats		= p54_get_stats,
+	.get_survey		= p54_get_survey,
 };
 
 struct ieee80211_hw *p54_init_common(size_t priv_data_len)
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index a5ea89c..822f8dc 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -466,8 +466,7 @@
 	P54P_READ(dev_int);
 
 	if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) {
-		printk(KERN_ERR "%s: Cannot boot firmware!\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "cannot boot firmware!\n");
 		p54p_stop(dev);
 		return -ETIMEDOUT;
 	}
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c
index 4e68910..427b46f 100644
--- a/drivers/net/wireless/p54/txrx.c
+++ b/drivers/net/wireless/p54/txrx.c
@@ -38,8 +38,8 @@
 	u32 largest_hole = 0, free;
 
 	spin_lock_irqsave(&priv->tx_queue.lock, flags);
-	printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) ---\n",
-	       wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue));
+	wiphy_debug(priv->hw->wiphy, "/ --- tx queue dump (%d entries) ---\n",
+		    skb_queue_len(&priv->tx_queue));
 
 	prev_addr = priv->rx_start;
 	skb_queue_walk(&priv->tx_queue, skb) {
@@ -48,21 +48,23 @@
 		hdr = (void *) skb->data;
 
 		free = range->start_addr - prev_addr;
-		printk(KERN_DEBUG "%s: | [%02d] => [skb:%p skb_len:0x%04x "
-		       "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} "
-		       "mem:{start:%04x end:%04x, free:%d}]\n",
-		       wiphy_name(priv->hw->wiphy), i++, skb, skb->len,
-		       le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len),
-		       le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type),
-		       range->start_addr, range->end_addr, free);
+		wiphy_debug(priv->hw->wiphy,
+			    "| [%02d] => [skb:%p skb_len:0x%04x "
+			    "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} "
+			    "mem:{start:%04x end:%04x, free:%d}]\n",
+			    i++, skb, skb->len,
+			    le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len),
+			    le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type),
+			    range->start_addr, range->end_addr, free);
 
 		prev_addr = range->end_addr;
 		largest_hole = max(largest_hole, free);
 	}
 	free = priv->rx_end - prev_addr;
 	largest_hole = max(largest_hole, free);
-	printk(KERN_DEBUG "%s: \\ --- [free: %d], largest free block: %d ---\n",
-	       wiphy_name(priv->hw->wiphy), free, largest_hole);
+	wiphy_debug(priv->hw->wiphy,
+		    "\\ --- [free: %d], largest free block: %d ---\n",
+		    free, largest_hole);
 	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
 }
 #endif /* P54_MM_DEBUG */
@@ -538,8 +540,7 @@
 	case P54_TRAP_BEACON_TX:
 		break;
 	case P54_TRAP_RADAR:
-		printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
-			wiphy_name(priv->hw->wiphy), freq);
+		wiphy_info(priv->hw->wiphy, "radar (freq:%d mhz)\n", freq);
 		break;
 	case P54_TRAP_NO_BEACON:
 		if (priv->vif)
@@ -558,8 +559,8 @@
 		wiphy_rfkill_set_hw_state(priv->hw->wiphy, false);
 		break;
 	default:
-		printk(KERN_INFO "%s: received event:%x freq:%d\n",
-		       wiphy_name(priv->hw->wiphy), event, freq);
+		wiphy_info(priv->hw->wiphy, "received event:%x freq:%d\n",
+			   event, freq);
 		break;
 	}
 }
@@ -584,8 +585,9 @@
 		p54_rx_eeprom_readback(priv, skb);
 		break;
 	default:
-		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
-		       wiphy_name(priv->hw->wiphy), le16_to_cpu(hdr->type));
+		wiphy_debug(priv->hw->wiphy,
+			    "not handling 0x%02x type control frame\n",
+			    le16_to_cpu(hdr->type));
 		break;
 	}
 	return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 242d595..cdaf93f 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -351,6 +351,14 @@
 
 	if (crypto->cmd == SET_KEY) {
 		/*
+		 * Disallow to set WEP key other than with index 0,
+		 * it is known that not work at least on some hardware.
+		 * SW crypto will be used in that case.
+		 */
+		if (key->alg == ALG_WEP && key->keyidx != 0)
+			return -EOPNOTSUPP;
+
+		/*
 		 * Pairwise key will always be entry 0, but this
 		 * could collide with a shared key on the same
 		 * position...
@@ -376,7 +384,7 @@
 		if (key->hw_key_idx > 0 && crypto->cipher != curr_cipher)
 			return -EOPNOTSUPP;
 
-		rt2500usb_register_multiwrite(rt2x00dev, reg,
+		rt2500usb_register_multiwrite(rt2x00dev, KEY_ENTRY(key->hw_key_idx),
 					      crypto->key, sizeof(crypto->key));
 
 		/*
@@ -817,6 +825,7 @@
 	rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg);
 
 	rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+	rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, CIPHER_NONE);
 	rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
 	rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
 	rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index d8b186a..1d81785 100644
--- a/drivers/net/wireless/rtl818x/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -361,7 +361,7 @@
 
 	/* check success of reset */
 	if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) {
-		printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "reset timeout!\n");
 		return -ETIMEDOUT;
 	}
 
@@ -445,8 +445,7 @@
 					     &priv->rx_ring_dma);
 
 	if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) {
-		printk(KERN_ERR "%s: Cannot allocate RX ring\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "cannot allocate rx ring\n");
 		return -ENOMEM;
 	}
 
@@ -503,8 +502,8 @@
 
 	ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma);
 	if (!ring || (unsigned long)ring & 0xFF) {
-		printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n",
-		       wiphy_name(dev->wiphy), prio);
+		wiphy_err(dev->wiphy, "cannot allocate tx ring (prio = %d)\n",
+			  prio);
 		return -ENOMEM;
 	}
 
@@ -569,8 +568,7 @@
 	ret = request_irq(priv->pdev->irq, rtl8180_interrupt,
 			  IRQF_SHARED, KBUILD_MODNAME, dev);
 	if (ret) {
-		printk(KERN_ERR "%s: failed to register IRQ handler\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "failed to register irq handler\n");
 		goto err_free_rings;
 	}
 
@@ -1107,9 +1105,8 @@
 		goto err_iounmap;
 	}
 
-	printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n",
-	       wiphy_name(dev->wiphy), mac_addr,
-	       chip_name, priv->rf->name);
+	wiphy_info(dev->wiphy, "hwaddr %pm, %s + %s\n",
+		   mac_addr, chip_name, priv->rf->name);
 
 	return 0;
 
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 891b849..5738a55 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -573,7 +573,7 @@
 	} while (--i);
 
 	if (!i) {
-		printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "reset timeout!\n");
 		return -ETIMEDOUT;
 	}
 
@@ -589,8 +589,7 @@
 	} while (--i);
 
 	if (!i) {
-		printk(KERN_ERR "%s: eeprom reset timeout!\n",
-		       wiphy_name(dev->wiphy));
+		wiphy_err(dev->wiphy, "eeprom reset timeout!\n");
 		return -ETIMEDOUT;
 	}
 
@@ -1527,9 +1526,9 @@
 	mutex_init(&priv->conf_mutex);
 	skb_queue_head_init(&priv->b_tx_status.queue);
 
-	printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n",
-	       wiphy_name(dev->wiphy), mac_addr,
-	       chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask);
+	wiphy_info(dev->wiphy, "hwaddr %pm, %s v%d + %s, rfkill mask %d\n",
+		   mac_addr, chip_name, priv->asic_rev, priv->rf->name,
+		   priv->rfkill_mask);
 
 #ifdef CONFIG_RTL8187_LEDS
 	eeprom_93cx6_read(&eeprom, 0x3F, &reg);
diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
index a098193..fd96f91 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -366,8 +366,8 @@
 		rtl8225_write(dev, 0x02, 0x044d);
 		msleep(100);
 		if (!(rtl8225_read(dev, 6) & (1 << 7)))
-			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
-			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+			wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+				   rtl8225_read(dev, 6));
 	}
 
 	rtl8225_write(dev, 0x0, 0x127);
@@ -735,8 +735,8 @@
 		rtl8225_write(dev, 0x02, 0x044D);
 		msleep(100);
 		if (!(rtl8225_read(dev, 6) & (1 << 7)))
-			printk(KERN_WARNING "%s: RF Calibration Failed! %x\n",
-			       wiphy_name(dev->wiphy), rtl8225_read(dev, 6));
+			wiphy_warn(dev->wiphy, "rf calibration failed! %x\n",
+				   rtl8225_read(dev, 6));
 	}
 
 	msleep(200);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 4d1f19d..ae80f8f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1416,7 +1416,7 @@
  *
  * @wiphy: The wiphy whose name to return
  */
-static inline const char *wiphy_name(struct wiphy *wiphy)
+static inline const char *wiphy_name(const struct wiphy *wiphy)
 {
 	return dev_name(&wiphy->dev);
 }
@@ -2420,4 +2420,67 @@
 			      enum nl80211_cqm_rssi_threshold_event rssi_event,
 			      gfp_t gfp);
 
+#ifdef __KERNEL__
+
+/* Logging, debugging and troubleshooting/diagnostic helpers. */
+
+/* wiphy_printk helpers, similar to dev_printk */
+
+#define wiphy_printk(level, wiphy, format, args...)		\
+	printk(level "%s: " format, wiphy_name(wiphy), ##args)
+#define wiphy_emerg(wiphy, format, args...)			\
+	wiphy_printk(KERN_EMERG, wiphy, format, ##args)
+#define wiphy_alert(wiphy, format, args...)			\
+	wiphy_printk(KERN_ALERT, wiphy, format, ##args)
+#define wiphy_crit(wiphy, format, args...)			\
+	wiphy_printk(KERN_CRIT, wiphy, format, ##args)
+#define wiphy_err(wiphy, format, args...)			\
+	wiphy_printk(KERN_ERR, wiphy, format, ##args)
+#define wiphy_warn(wiphy, format, args...)			\
+	wiphy_printk(KERN_WARNING, wiphy, format, ##args)
+#define wiphy_notice(wiphy, format, args...)			\
+	wiphy_printk(KERN_NOTICE, wiphy, format, ##args)
+#define wiphy_info(wiphy, format, args...)			\
+	wiphy_printk(KERN_INFO, wiphy, format, ##args)
+
+int wiphy_debug(const struct wiphy *wiphy, const char *format, ...)
+	__attribute__ ((format (printf, 2, 3)));
+
+#if defined(DEBUG)
+#define wiphy_dbg(wiphy, format, args...)			\
+	wiphy_printk(KERN_DEBUG, wiphy, format, ##args)
+#elif defined(CONFIG_DYNAMIC_DEBUG)
+#define wiphy_dbg(wiphy, format, args...)			\
+	dynamic_pr_debug("%s: " format,	wiphy_name(dev), ##args)
+#else
+#define wiphy_dbg(wiphy, format, args...)				\
+({									\
+	if (0)								\
+		wiphy_printk(KERN_DEBUG, wiphy, format, ##args);	\
+	0;								\
+})
+#endif
+
+#if defined(VERBOSE_DEBUG)
+#define wiphy_vdbg	wiphy_dbg
+#else
+
+#define wiphy_vdbg(wiphy, format, args...)				\
+({									\
+	if (0)								\
+		wiphy_printk(KERN_DEBUG, wiphy, format, ##args);	\
+		0;							\
+})
+#endif
+
+/*
+ * wiphy_WARN() acts like wiphy_printk(), but with the key difference
+ * of using a WARN/WARN_ON to get the message out, including the
+ * file/line information and a backtrace.
+ */
+#define wiphy_WARN(wiphy, format, args...)			\
+	WARN(1, "wiphy: %s\n" format, wiphy_name(wiphy), ##args);
+
+#endif
+
 #endif /* __NET_CFG80211_H */
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b769567..dab6b8e 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -158,7 +158,7 @@
 	if (mac_addr) {
 		sta = sta_info_get_bss(sdata, mac_addr);
 		if (!sta) {
-			ieee80211_key_free(key);
+			ieee80211_key_free(sdata->local, key);
 			err = -ENOENT;
 			goto out_unlock;
 		}
@@ -192,7 +192,7 @@
 			goto out_unlock;
 
 		if (sta->key) {
-			ieee80211_key_free(sta->key);
+			ieee80211_key_free(sdata->local, sta->key);
 			WARN_ON(sta->key);
 			ret = 0;
 		}
@@ -205,7 +205,7 @@
 		goto out_unlock;
 	}
 
-	ieee80211_key_free(sdata->keys[key_idx]);
+	ieee80211_key_free(sdata->local, sdata->keys[key_idx]);
 	WARN_ON(sdata->keys[key_idx]);
 
 	ret = 0;
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 50d1cff..1b9d87e 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -323,13 +323,15 @@
 	if (!key)
 		return;
 
-	ieee80211_key_disable_hw_accel(key);
+	if (key->local)
+		ieee80211_key_disable_hw_accel(key);
 
 	if (key->conf.alg == ALG_CCMP)
 		ieee80211_aes_key_free(key->u.ccmp.tfm);
 	if (key->conf.alg == ALG_AES_CMAC)
 		ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
-	ieee80211_debugfs_key_remove(key);
+	if (key->local)
+		ieee80211_debugfs_key_remove(key);
 
 	kfree(key);
 }
@@ -410,15 +412,12 @@
 	__ieee80211_key_destroy(key);
 }
 
-void ieee80211_key_free(struct ieee80211_key *key)
+void ieee80211_key_free(struct ieee80211_local *local,
+			struct ieee80211_key *key)
 {
-	struct ieee80211_local *local;
-
 	if (!key)
 		return;
 
-	local = key->sdata->local;
-
 	mutex_lock(&local->key_mtx);
 	__ieee80211_key_free(key);
 	mutex_unlock(&local->key_mtx);
diff --git a/net/mac80211/key.h b/net/mac80211/key.h
index a3849fa..b665bbb 100644
--- a/net/mac80211/key.h
+++ b/net/mac80211/key.h
@@ -135,7 +135,8 @@
 void ieee80211_key_link(struct ieee80211_key *key,
 			struct ieee80211_sub_if_data *sdata,
 			struct sta_info *sta);
-void ieee80211_key_free(struct ieee80211_key *key);
+void ieee80211_key_free(struct ieee80211_local *local,
+			struct ieee80211_key *key);
 void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx);
 void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
 				    int idx);
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 67656cb..6d86f0c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -647,7 +647,7 @@
 		return ret;
 
 	if (sta->key) {
-		ieee80211_key_free(sta->key);
+		ieee80211_key_free(local, sta->key);
 		WARN_ON(sta->key);
 	}
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index f65c649..541e2ff 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -907,3 +907,52 @@
 	destroy_workqueue(cfg80211_wq);
 }
 module_exit(cfg80211_exit);
+
+static int ___wiphy_printk(const char *level, const struct wiphy *wiphy,
+			   struct va_format *vaf)
+{
+	if (!wiphy)
+		return printk("%s(NULL wiphy *): %pV", level, vaf);
+
+	return printk("%s%s: %pV", level, wiphy_name(wiphy), vaf);
+}
+
+int __wiphy_printk(const char *level, const struct wiphy *wiphy,
+		   const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+	int r;
+
+	va_start(args, fmt);
+
+	vaf.fmt = fmt;
+	vaf.va = &args;
+
+	r = ___wiphy_printk(level, wiphy, &vaf);
+	va_end(args);
+
+	return r;
+}
+EXPORT_SYMBOL(__wiphy_printk);
+
+#define define_wiphy_printk_level(func, kern_level)		\
+int func(const struct wiphy *wiphy, const char *fmt, ...)	\
+{								\
+	struct va_format vaf;					\
+	va_list args;						\
+	int r;							\
+								\
+	va_start(args, fmt);					\
+								\
+	vaf.fmt = fmt;						\
+	vaf.va = &args;						\
+								\
+	r = ___wiphy_printk(kern_level, wiphy, &vaf);		\
+	va_end(args);						\
+								\
+	return r;						\
+}								\
+EXPORT_SYMBOL(func);
+
+define_wiphy_printk_level(wiphy_debug, KERN_DEBUG);