summary refs log tree commit diff
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/11d.c696
-rw-r--r--drivers/net/wireless/libertas/11d.h105
-rw-r--r--drivers/net/wireless/libertas/Kconfig39
-rw-r--r--drivers/net/wireless/libertas/Makefile14
-rw-r--r--drivers/net/wireless/libertas/README26
-rw-r--r--drivers/net/wireless/libertas/assoc.c445
-rw-r--r--drivers/net/wireless/libertas/assoc.h141
-rw-r--r--drivers/net/wireless/libertas/cfg.c198
-rw-r--r--drivers/net/wireless/libertas/cfg.h16
-rw-r--r--drivers/net/wireless/libertas/cmd.c695
-rw-r--r--drivers/net/wireless/libertas/cmd.h127
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c116
-rw-r--r--drivers/net/wireless/libertas/debugfs.c27
-rw-r--r--drivers/net/wireless/libertas/decl.h65
-rw-r--r--drivers/net/wireless/libertas/defs.h3
-rw-r--r--drivers/net/wireless/libertas/dev.h431
-rw-r--r--drivers/net/wireless/libertas/ethtool.c84
-rw-r--r--drivers/net/wireless/libertas/host.h959
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h800
-rw-r--r--drivers/net/wireless/libertas/if_cs.c4
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c62
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h3
-rw-r--r--drivers/net/wireless/libertas/if_spi.c143
-rw-r--r--drivers/net/wireless/libertas/if_usb.c5
-rw-r--r--drivers/net/wireless/libertas/main.c720
-rw-r--r--drivers/net/wireless/libertas/mesh.c1141
-rw-r--r--drivers/net/wireless/libertas/mesh.h78
-rw-r--r--drivers/net/wireless/libertas/persistcfg.c453
-rw-r--r--drivers/net/wireless/libertas/rx.c13
-rw-r--r--drivers/net/wireless/libertas/scan.c250
-rw-r--r--drivers/net/wireless/libertas/scan.h30
-rw-r--r--drivers/net/wireless/libertas/tx.c9
-rw-r--r--drivers/net/wireless/libertas/types.h4
-rw-r--r--drivers/net/wireless/libertas/wext.c196
-rw-r--r--drivers/net/wireless/libertas/wext.h9
35 files changed, 3858 insertions, 4249 deletions
diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
deleted file mode 100644
index 5c6968101f0d..000000000000
--- a/drivers/net/wireless/libertas/11d.c
+++ /dev/null
@@ -1,696 +0,0 @@
-/**
-  * This file contains functions for 802.11D.
-  */
-#include <linux/ctype.h>
-#include <linux/kernel.h>
-#include <linux/wireless.h>
-
-#include "host.h"
-#include "decl.h"
-#include "11d.h"
-#include "dev.h"
-#include "wext.h"
-
-#define TX_PWR_DEFAULT	10
-
-static struct region_code_mapping region_code_mapping[] = {
-	{"US ", 0x10},		/* US FCC      */
-	{"CA ", 0x10},		/* IC Canada   */
-	{"SG ", 0x10},		/* Singapore   */
-	{"EU ", 0x30},		/* ETSI        */
-	{"AU ", 0x30},		/* Australia   */
-	{"KR ", 0x30},		/* Republic Of Korea */
-	{"ES ", 0x31},		/* Spain       */
-	{"FR ", 0x32},		/* France      */
-	{"JP ", 0x40},		/* Japan       */
-};
-
-/* Following 2 structure defines the supported channels */
-static struct chan_freq_power channel_freq_power_UN_BG[] = {
-	{1, 2412, TX_PWR_DEFAULT},
-	{2, 2417, TX_PWR_DEFAULT},
-	{3, 2422, TX_PWR_DEFAULT},
-	{4, 2427, TX_PWR_DEFAULT},
-	{5, 2432, TX_PWR_DEFAULT},
-	{6, 2437, TX_PWR_DEFAULT},
-	{7, 2442, TX_PWR_DEFAULT},
-	{8, 2447, TX_PWR_DEFAULT},
-	{9, 2452, TX_PWR_DEFAULT},
-	{10, 2457, TX_PWR_DEFAULT},
-	{11, 2462, TX_PWR_DEFAULT},
-	{12, 2467, TX_PWR_DEFAULT},
-	{13, 2472, TX_PWR_DEFAULT},
-	{14, 2484, TX_PWR_DEFAULT}
-};
-
-static u8 lbs_region_2_code(u8 *region)
-{
-	u8 i;
-
-	for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++)
-		region[i] = toupper(region[i]);
-
-	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
-		if (!memcmp(region, region_code_mapping[i].region,
-			    COUNTRY_CODE_LEN))
-			return (region_code_mapping[i].code);
-	}
-
-	/* default is US */
-	return (region_code_mapping[0].code);
-}
-
-static u8 *lbs_code_2_region(u8 code)
-{
-	u8 i;
-
-	for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) {
-		if (region_code_mapping[i].code == code)
-			return (region_code_mapping[i].region);
-	}
-	/* default is US */
-	return (region_code_mapping[0].region);
-}
-
-/**
- *  @brief This function finds the nrchan-th chan after the firstchan
- *  @param band       band
- *  @param firstchan  first channel number
- *  @param nrchan   number of channels
- *  @return 	      the nrchan-th chan number
-*/
-static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan)
-/*find the nrchan-th chan after the firstchan*/
-{
-	u8 i;
-	struct chan_freq_power *cfp;
-	u8 cfp_no;
-
-	cfp = channel_freq_power_UN_BG;
-	cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG);
-
-	for (i = 0; i < cfp_no; i++) {
-		if ((cfp + i)->channel == firstchan) {
-			lbs_deb_11d("firstchan found\n");
-			break;
-		}
-	}
-
-	if (i < cfp_no) {
-		/*if beyond the boundary */
-		if (i + nrchan < cfp_no) {
-			*chan = (cfp + i + nrchan)->channel;
-			return 1;
-		}
-	}
-
-	return 0;
-}
-
-/**
- *  @brief This function Checks if chan txpwr is learned from AP/IBSS
- *  @param chan                 chan number
- *  @param parsed_region_chan   pointer to parsed_region_chan_11d
- *  @return 	                TRUE; FALSE
-*/
-static u8 lbs_channel_known_11d(u8 chan,
-			  struct parsed_region_chan_11d * parsed_region_chan)
-{
-	struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr;
-	u8 nr_chan = parsed_region_chan->nr_chan;
-	u8 i = 0;
-
-	lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr,
-		sizeof(struct chan_power_11d) * nr_chan);
-
-	for (i = 0; i < nr_chan; i++) {
-		if (chan == chanpwr[i].chan) {
-			lbs_deb_11d("found chan %d\n", chan);
-			return 1;
-		}
-	}
-
-	lbs_deb_11d("chan %d not found\n", chan);
-	return 0;
-}
-
-u32 lbs_chan_2_freq(u8 chan)
-{
-	struct chan_freq_power *cf;
-	u16 i;
-	u32 freq = 0;
-
-	cf = channel_freq_power_UN_BG;
-
-	for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) {
-		if (chan == cf[i].channel)
-			freq = cf[i].freq;
-	}
-
-	return freq;
-}
-
-static int generate_domain_info_11d(struct parsed_region_chan_11d
-				  *parsed_region_chan,
-				  struct lbs_802_11d_domain_reg *domaininfo)
-{
-	u8 nr_subband = 0;
-
-	u8 nr_chan = parsed_region_chan->nr_chan;
-	u8 nr_parsedchan = 0;
-
-	u8 firstchan = 0, nextchan = 0, maxpwr = 0;
-
-	u8 i, flag = 0;
-
-	memcpy(domaininfo->countrycode, parsed_region_chan->countrycode,
-	       COUNTRY_CODE_LEN);
-
-	lbs_deb_11d("nrchan %d\n", nr_chan);
-	lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan,
-		sizeof(struct parsed_region_chan_11d));
-
-	for (i = 0; i < nr_chan; i++) {
-		if (!flag) {
-			flag = 1;
-			nextchan = firstchan =
-			    parsed_region_chan->chanpwr[i].chan;
-			maxpwr = parsed_region_chan->chanpwr[i].pwr;
-			nr_parsedchan = 1;
-			continue;
-		}
-
-		if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 &&
-		    parsed_region_chan->chanpwr[i].pwr == maxpwr) {
-			nextchan++;
-			nr_parsedchan++;
-		} else {
-			domaininfo->subband[nr_subband].firstchan = firstchan;
-			domaininfo->subband[nr_subband].nrchan =
-			    nr_parsedchan;
-			domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
-			nr_subband++;
-			nextchan = firstchan =
-			    parsed_region_chan->chanpwr[i].chan;
-			maxpwr = parsed_region_chan->chanpwr[i].pwr;
-		}
-	}
-
-	if (flag) {
-		domaininfo->subband[nr_subband].firstchan = firstchan;
-		domaininfo->subband[nr_subband].nrchan = nr_parsedchan;
-		domaininfo->subband[nr_subband].maxtxpwr = maxpwr;
-		nr_subband++;
-	}
-	domaininfo->nr_subband = nr_subband;
-
-	lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband);
-	lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo,
-		COUNTRY_CODE_LEN + 1 +
-		sizeof(struct ieee_subbandset) * nr_subband);
-	return 0;
-}
-
-/**
- *  @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
- *  @param region_chan          pointer to struct region_channel
- *  @param *parsed_region_chan  pointer to parsed_region_chan_11d
- *  @return 	                N/A
-*/
-static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan,
-					  struct parsed_region_chan_11d *
-					  parsed_region_chan)
-{
-	u8 i;
-	struct chan_freq_power *cfp;
-
-	if (region_chan == NULL) {
-		lbs_deb_11d("region_chan is NULL\n");
-		return;
-	}
-
-	cfp = region_chan->CFP;
-	if (cfp == NULL) {
-		lbs_deb_11d("cfp is NULL \n");
-		return;
-	}
-
-	parsed_region_chan->band = region_chan->band;
-	parsed_region_chan->region = region_chan->region;
-	memcpy(parsed_region_chan->countrycode,
-	       lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN);
-
-	lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region,
-	       parsed_region_chan->band);
-
-	for (i = 0; i < region_chan->nrcfp; i++, cfp++) {
-		parsed_region_chan->chanpwr[i].chan = cfp->channel;
-		parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower;
-		lbs_deb_11d("chan %d, pwr %d\n",
-		       parsed_region_chan->chanpwr[i].chan,
-		       parsed_region_chan->chanpwr[i].pwr);
-	}
-	parsed_region_chan->nr_chan = region_chan->nrcfp;
-
-	lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan);
-
-	return;
-}
-
-/**
- *  @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
- *  @param region               region ID
- *  @param band                 band
- *  @param chan                 chan
- *  @return 	                TRUE;FALSE
-*/
-static u8 lbs_region_chan_supported_11d(u8 region, u8 chan)
-{
-	struct chan_freq_power *cfp;
-	int cfp_no;
-	u8 idx;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_11D);
-
-	cfp = lbs_get_region_cfp_table(region, &cfp_no);
-	if (cfp == NULL)
-		return 0;
-
-	for (idx = 0; idx < cfp_no; idx++) {
-		if (chan == (cfp + idx)->channel) {
-			/* If Mrvl Chip Supported? */
-			if ((cfp + idx)->unsupported) {
-				ret = 0;
-			} else {
-				ret = 1;
-			}
-			goto done;
-		}
-	}
-
-	/*chan is not in the region table */
-
-done:
-	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief This function checks if chan txpwr is learned from AP/IBSS
- *  @param chan                 chan number
- *  @param parsed_region_chan   pointer to parsed_region_chan_11d
- *  @return 	                0
-*/
-static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo,
-				 u8 band,
-				 struct parsed_region_chan_11d *parsed_region_chan)
-{
-	u8 nr_subband, nrchan;
-	u8 lastchan, firstchan;
-	u8 region;
-	u8 curchan = 0;
-
-	u8 idx = 0;		/*chan index in parsed_region_chan */
-
-	u8 j, i;
-
-	lbs_deb_enter(LBS_DEB_11D);
-
-	/*validation Rules:
-	   1. valid region Code
-	   2. First Chan increment
-	   3. channel range no overlap
-	   4. channel is valid?
-	   5. channel is supported by region?
-	   6. Others
-	 */
-
-	lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30);
-
-	if ((*(countryinfo->countrycode)) == 0
-	    || (countryinfo->header.len <= COUNTRY_CODE_LEN)) {
-		/* No region Info or Wrong region info: treat as No 11D info */
-		goto done;
-	}
-
-	/*Step1: check region_code */
-	parsed_region_chan->region = region =
-	    lbs_region_2_code(countryinfo->countrycode);
-
-	lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region);
-	lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode,
-		COUNTRY_CODE_LEN);
-
-	parsed_region_chan->band = band;
-
-	memcpy(parsed_region_chan->countrycode, countryinfo->countrycode,
-	       COUNTRY_CODE_LEN);
-
-	nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) /
-	    sizeof(struct ieee_subbandset);
-
-	for (j = 0, lastchan = 0; j < nr_subband; j++) {
-
-		if (countryinfo->subband[j].firstchan <= lastchan) {
-			/*Step2&3. Check First Chan Num increment and no overlap */
-			lbs_deb_11d("chan %d>%d, overlap\n",
-			       countryinfo->subband[j].firstchan, lastchan);
-			continue;
-		}
-
-		firstchan = countryinfo->subband[j].firstchan;
-		nrchan = countryinfo->subband[j].nrchan;
-
-		for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) {
-			/*step4: channel is supported? */
-
-			if (!lbs_get_chan_11d(firstchan, i, &curchan)) {
-				/* Chan is not found in UN table */
-				lbs_deb_11d("chan is not supported: %d \n", i);
-				break;
-			}
-
-			lastchan = curchan;
-
-			if (lbs_region_chan_supported_11d(region, curchan)) {
-				/*step5: Check if curchan is supported by mrvl in region */
-				parsed_region_chan->chanpwr[idx].chan = curchan;
-				parsed_region_chan->chanpwr[idx].pwr =
-				    countryinfo->subband[j].maxtxpwr;
-				idx++;
-			} else {
-				/*not supported and ignore the chan */
-				lbs_deb_11d(
-				       "i %d, chan %d unsupported in region %x, band %d\n",
-				       i, curchan, region, band);
-			}
-		}
-
-		/*Step6: Add other checking if any */
-
-	}
-
-	parsed_region_chan->nr_chan = idx;
-
-	lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan);
-	lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan,
-		2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
-
-done:
-	lbs_deb_enter(LBS_DEB_11D);
-	return 0;
-}
-
-/**
- *  @brief This function calculates the scan type for channels
- *  @param chan                 chan number
- *  @param parsed_region_chan   pointer to parsed_region_chan_11d
- *  @return 	                PASSIVE if chan is unknown; ACTIVE if chan is known
-*/
-u8 lbs_get_scan_type_11d(u8 chan,
-			  struct parsed_region_chan_11d * parsed_region_chan)
-{
-	u8 scan_type = CMD_SCAN_TYPE_PASSIVE;
-
-	lbs_deb_enter(LBS_DEB_11D);
-
-	if (lbs_channel_known_11d(chan, parsed_region_chan)) {
-		lbs_deb_11d("found, do active scan\n");
-		scan_type = CMD_SCAN_TYPE_ACTIVE;
-	} else {
-		lbs_deb_11d("not found, do passive scan\n");
-	}
-
-	lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type);
-	return scan_type;
-
-}
-
-void lbs_init_11d(struct lbs_private *priv)
-{
-	priv->enable11d = 0;
-	memset(&(priv->parsed_region_chan), 0,
-	       sizeof(struct parsed_region_chan_11d));
-	return;
-}
-
-/**
- *  @brief This function sets DOMAIN INFO to FW
- *  @param priv       pointer to struct lbs_private
- *  @return 	      0; -1
-*/
-static int set_domain_info_11d(struct lbs_private *priv)
-{
-	int ret;
-
-	if (!priv->enable11d) {
-		lbs_deb_11d("dnld domain Info with 11d disabled\n");
-		return 0;
-	}
-
-	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;
-}
-
-/**
- *  @brief This function setups scan channels
- *  @param priv       pointer to struct lbs_private
- *  @param band       band
- *  @return 	      0
-*/
-int lbs_set_universaltable(struct lbs_private *priv, u8 band)
-{
-	u16 size = sizeof(struct chan_freq_power);
-	u16 i = 0;
-
-	memset(priv->universal_channel, 0,
-	       sizeof(priv->universal_channel));
-
-	priv->universal_channel[i].nrcfp =
-	    sizeof(channel_freq_power_UN_BG) / size;
-	lbs_deb_11d("BG-band nrcfp %d\n",
-	       priv->universal_channel[i].nrcfp);
-
-	priv->universal_channel[i].CFP = channel_freq_power_UN_BG;
-	priv->universal_channel[i].valid = 1;
-	priv->universal_channel[i].region = UNIVERSAL_REGION_CODE;
-	priv->universal_channel[i].band = band;
-	i++;
-
-	return 0;
-}
-
-/**
- *  @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 cmdno,
-				 u16 cmdoption)
-{
-	struct cmd_ds_802_11d_domain_info *pdomaininfo =
-	    &cmd->params.domaininfo;
-	struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain;
-	u8 nr_subband = priv->domainreg.nr_subband;
-
-	lbs_deb_enter(LBS_DEB_11D);
-
-	lbs_deb_11d("nr_subband=%x\n", nr_subband);
-
-	cmd->command = cpu_to_le16(cmdno);
-	pdomaininfo->action = cpu_to_le16(cmdoption);
-	if (cmdoption == CMD_ACT_GET) {
-		cmd->size =
-		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
-		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->domainreg.countrycode,
-	       sizeof(domain->countrycode));
-
-	domain->header.len =
-	    cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) +
-			     sizeof(domain->countrycode));
-
-	if (nr_subband) {
-		memcpy(domain->subband, priv->domainreg.subband,
-		       nr_subband * sizeof(struct ieee_subbandset));
-
-		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
-					     le16_to_cpu(domain->header.len) +
-					     sizeof(struct mrvl_ie_header) +
-					     S_DS_GEN);
-	} else {
-		cmd->size =
-		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
-	}
-
-	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 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
- */
-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_subband = 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_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
-		      sizeof(struct ieee_subbandset);
-
-	lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
-
-	if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) {
-		lbs_deb_11d("Invalid Numrer of Subband 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;
-}
-
-/**
- *  @brief This function parses countryinfo from AP and download country info to FW
- *  @param priv    pointer to struct lbs_private
- *  @return 	   0; -1
- */
-int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
-                                        struct bss_descriptor * bss)
-{
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_11D);
-	if (priv->enable11d) {
-		memset(&priv->parsed_region_chan, 0,
-		       sizeof(struct parsed_region_chan_11d));
-		ret = parse_domain_info_11d(&bss->countryinfo, 0,
-					       &priv->parsed_region_chan);
-
-		if (ret == -1) {
-			lbs_deb_11d("error parsing domain_info from AP\n");
-			goto done;
-		}
-
-		memset(&priv->domainreg, 0,
-		       sizeof(struct lbs_802_11d_domain_reg));
-		generate_domain_info_11d(&priv->parsed_region_chan,
-				      &priv->domainreg);
-
-		ret = set_domain_info_11d(priv);
-
-		if (ret) {
-			lbs_deb_11d("error setting domain info\n");
-			goto done;
-		}
-	}
-	ret = 0;
-
-done:
-	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
-	return ret;
-}
-
-/**
- *  @brief This function generates 11D info from user specified regioncode and download to FW
- *  @param priv    pointer to struct lbs_private
- *  @return 	   0; -1
- */
-int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv)
-{
-	int ret;
-	struct region_channel *region_chan;
-	u8 j;
-
-	lbs_deb_enter(LBS_DEB_11D);
-	lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band);
-
-	if (priv->enable11d) {
-		/* update parsed_region_chan_11; dnld domaininf to FW */
-
-		for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) {
-			region_chan = &priv->region_channel[j];
-
-			lbs_deb_11d("%d region_chan->band %d\n", j,
-			       region_chan->band);
-
-			if (!region_chan || !region_chan->valid
-			    || !region_chan->CFP)
-				continue;
-			if (region_chan->band != priv->curbssparams.band)
-				continue;
-			break;
-		}
-
-		if (j >= ARRAY_SIZE(priv->region_channel)) {
-			lbs_deb_11d("region_chan not found, band %d\n",
-			       priv->curbssparams.band);
-			ret = -1;
-			goto done;
-		}
-
-		memset(&priv->parsed_region_chan, 0,
-		       sizeof(struct parsed_region_chan_11d));
-		lbs_generate_parsed_region_chan_11d(region_chan,
-						     &priv->
-						     parsed_region_chan);
-
-		memset(&priv->domainreg, 0,
-		       sizeof(struct lbs_802_11d_domain_reg));
-		generate_domain_info_11d(&priv->parsed_region_chan,
-					 &priv->domainreg);
-
-		ret = set_domain_info_11d(priv);
-
-		if (ret) {
-			lbs_deb_11d("error setting domain info\n");
-			goto done;
-		}
-
-	}
-	ret = 0;
-
-done:
-	lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
-	return ret;
-}
diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h
deleted file mode 100644
index fb75d3e321a0..000000000000
--- a/drivers/net/wireless/libertas/11d.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/**
-  * This header file contains data structures and
-  * function declarations of 802.11d
-  */
-#ifndef _LBS_11D_
-#define _LBS_11D_
-
-#include "types.h"
-#include "defs.h"
-
-#define UNIVERSAL_REGION_CODE			0xff
-
-/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr)
- */
-#define MRVDRV_MAX_SUBBAND_802_11D		83
-
-#define COUNTRY_CODE_LEN			3
-#define MAX_NO_OF_CHAN 				40
-
-struct cmd_ds_command;
-
-/** Data structure for Country IE*/
-struct ieee_subbandset {
-	u8 firstchan;
-	u8 nrchan;
-	u8 maxtxpwr;
-} __attribute__ ((packed));
-
-struct ieee_ie_country_info_set {
-	struct ieee_ie_header header;
-
-	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieee_subbandset subband[1];
-};
-
-struct ieee_ie_country_info_full_set {
-	struct ieee_ie_header header;
-
-	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
-} __attribute__ ((packed));
-
-struct mrvl_ie_domain_param_set {
-	struct mrvl_ie_header header;
-
-	u8 countrycode[COUNTRY_CODE_LEN];
-	struct ieee_subbandset subband[1];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11d_domain_info {
-	__le16 action;
-	struct mrvl_ie_domain_param_set domain;
-} __attribute__ ((packed));
-
-/** domain regulatory information */
-struct lbs_802_11d_domain_reg {
-	/** country Code*/
-	u8 countrycode[COUNTRY_CODE_LEN];
-	/** No. of subband*/
-	u8 nr_subband;
-	struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D];
-};
-
-struct chan_power_11d {
-	u8 chan;
-	u8 pwr;
-} __attribute__ ((packed));
-
-struct parsed_region_chan_11d {
-	u8 band;
-	u8 region;
-	s8 countrycode[COUNTRY_CODE_LEN];
-	struct chan_power_11d chanpwr[MAX_NO_OF_CHAN];
-	u8 nr_chan;
-} __attribute__ ((packed));
-
-struct region_code_mapping {
-	u8 region[COUNTRY_CODE_LEN];
-	u8 code;
-};
-
-struct lbs_private;
-
-u8 lbs_get_scan_type_11d(u8 chan,
-			  struct parsed_region_chan_11d *parsed_region_chan);
-
-u32 lbs_chan_2_freq(u8 chan);
-
-void lbs_init_11d(struct lbs_private *priv);
-
-int lbs_set_universaltable(struct lbs_private *priv, u8 band);
-
-int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
-				 struct cmd_ds_command *cmd, u16 cmdno,
-				 u16 cmdOption);
-
-int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp);
-
-struct bss_descriptor;
-int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv,
-                                        struct bss_descriptor * bss);
-
-int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv);
-
-#endif
diff --git a/drivers/net/wireless/libertas/Kconfig b/drivers/net/wireless/libertas/Kconfig
new file mode 100644
index 000000000000..30aa9d48d67e
--- /dev/null
+++ b/drivers/net/wireless/libertas/Kconfig
@@ -0,0 +1,39 @@
+config LIBERTAS
+	tristate "Marvell 8xxx Libertas WLAN driver support"
+	depends on CFG80211
+	select WIRELESS_EXT
+	select WEXT_SPY
+	select LIB80211
+	select FW_LOADER
+	---help---
+	  A library for Marvell Libertas 8xxx devices.
+
+config LIBERTAS_USB
+	tristate "Marvell Libertas 8388 USB 802.11b/g cards"
+	depends on LIBERTAS && USB
+	---help---
+	  A driver for Marvell Libertas 8388 USB devices.
+
+config LIBERTAS_CS
+	tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards"
+	depends on LIBERTAS && PCMCIA
+	---help---
+	  A driver for Marvell Libertas 8385 CompactFlash devices.
+
+config LIBERTAS_SDIO
+	tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards"
+	depends on LIBERTAS && MMC
+	---help---
+	  A driver for Marvell Libertas 8385/8686/8688 SDIO devices.
+
+config LIBERTAS_SPI
+	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
+	depends on LIBERTAS && SPI
+	---help---
+	  A driver for Marvell Libertas 8686 SPI devices.
+
+config LIBERTAS_DEBUG
+	bool "Enable full debugging output in the Libertas module."
+	depends on LIBERTAS
+	---help---
+	  Debugging support.
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 0b6918584503..b188cd97a053 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,5 +1,15 @@
-libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
-		 debugfs.o persistcfg.o ethtool.o assoc.o
+libertas-y += assoc.o
+libertas-y += cfg.o
+libertas-y += cmd.o
+libertas-y += cmdresp.o
+libertas-y += debugfs.o
+libertas-y += ethtool.o
+libertas-y += main.o
+libertas-y += mesh.o
+libertas-y += rx.o
+libertas-y += scan.o
+libertas-y += tx.o
+libertas-y += wext.o
 
 usb8xxx-objs += if_usb.o
 libertas_cs-objs += if_cs.o
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index ab6a2d518af0..2726c044430f 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -1,5 +1,5 @@
 ================================================================================
-			README for USB8388
+			README for Libertas
 
  (c) Copyright © 2003-2006, Marvell International Ltd.
  All Rights Reserved
@@ -226,4 +226,28 @@ setuserscan
     All entries in the scan table (not just the new scan data when keep=1)
     will be displayed upon completion by use of the getscantable ioctl.
 
+========================
+IWCONFIG COMMANDS
+========================
+power period
+
+	This command is used to configure the station in deep sleep mode /
+	auto deep sleep mode.
+
+	The timer is implemented to monitor the activities (command, event,
+	etc.). When an activity is detected station will exit from deep
+	sleep mode automatically and restart the timer. At timer expiry
+	(no activity for defined time period) the deep sleep mode is entered
+	automatically.
+
+	Note: this command is for SDIO interface only.
+
+	Usage:
+	To enable deep sleep mode do:
+		iwconfig wlan0 power period 0
+	To enable auto deep sleep mode with idle time period 5 seconds do:
+		iwconfig wlan0 power period 5
+	To disable deep sleep/auto deep sleep mode do:
+		iwconfig wlan0 power period -1
+
 ==============================================================================
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index dd8732611ba9..751067369ba8 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -23,6 +23,13 @@ static const u8 bssid_off[ETH_ALEN]  __attribute__ ((aligned (2))) =
  */
 #define CAPINFO_MASK	(~(0xda00))
 
+/**
+ * 802.11b/g supported bitrates (in 500Kb/s units)
+ */
+u8 lbs_bg_rates[MAX_RATES] =
+    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
+0x00, 0x00 };
+
 
 /**
  *  @brief This function finds common rates between rates and card rates.
@@ -147,6 +154,397 @@ static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth
 }
 
 
+int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+			   struct assoc_request *assoc)
+{
+	struct cmd_ds_802_11_set_wep cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+	cmd.action = cpu_to_le16(cmd_action);
+
+	if (cmd_action == CMD_ACT_ADD) {
+		int i;
+
+		/* default tx key index */
+		cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
+					   CMD_WEP_KEY_INDEX_MASK);
+
+		/* Copy key types and material to host command structure */
+		for (i = 0; i < 4; i++) {
+			struct enc_key *pkey = &assoc->wep_keys[i];
+
+			switch (pkey->len) {
+			case KEY_LEN_WEP_40:
+				cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
+				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
+				lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
+				break;
+			case KEY_LEN_WEP_104:
+				cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
+				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
+				lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
+				break;
+			case 0:
+				break;
+			default:
+				lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
+					    i, pkey->len);
+				ret = -1;
+				goto done;
+				break;
+			}
+		}
+	} else if (cmd_action == CMD_ACT_REMOVE) {
+		/* ACT_REMOVE clears _all_ WEP keys */
+
+		/* default tx key index */
+		cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
+					   CMD_WEP_KEY_INDEX_MASK);
+		lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
+	}
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
+done:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+			      uint16_t *enable)
+{
+	struct cmd_ds_802_11_enable_rsn cmd;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+	cmd.action = cpu_to_le16(cmd_action);
+
+	if (cmd_action == CMD_ACT_GET)
+		cmd.enable = 0;
+	else {
+		if (*enable)
+			cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
+		else
+			cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
+		lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
+	}
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
+	if (!ret && cmd_action == CMD_ACT_GET)
+		*enable = le16_to_cpu(cmd.enable);
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
+		struct enc_key *key)
+{
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	if (key->flags & KEY_INFO_WPA_ENABLED)
+		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
+	if (key->flags & KEY_INFO_WPA_UNICAST)
+		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
+	if (key->flags & KEY_INFO_WPA_MCAST)
+		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
+
+	keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+	keyparam->keytypeid = cpu_to_le16(key->type);
+	keyparam->keylen = cpu_to_le16(key->len);
+	memcpy(keyparam->key, key->key, key->len);
+
+	/* Length field doesn't include the {type,length} header */
+	keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
+	lbs_deb_leave(LBS_DEB_CMD);
+}
+
+int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
+				struct assoc_request *assoc)
+{
+	struct cmd_ds_802_11_key_material cmd;
+	int ret = 0;
+	int index = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	cmd.action = cpu_to_le16(cmd_action);
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+	if (cmd_action == CMD_ACT_GET) {
+		cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
+	} else {
+		memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
+
+		if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
+			set_one_wpa_key(&cmd.keyParamSet[index],
+					&assoc->wpa_unicast_key);
+			index++;
+		}
+
+		if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
+			set_one_wpa_key(&cmd.keyParamSet[index],
+					&assoc->wpa_mcast_key);
+			index++;
+		}
+
+		/* The common header and as many keys as we included */
+		cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
+						    keyParamSet[index]));
+	}
+	ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
+	/* Copy the returned key to driver private data */
+	if (!ret && cmd_action == CMD_ACT_GET) {
+		void *buf_ptr = cmd.keyParamSet;
+		void *resp_end = &(&cmd)[1];
+
+		while (buf_ptr < resp_end) {
+			struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
+			struct enc_key *key;
+			uint16_t param_set_len = le16_to_cpu(keyparam->length);
+			uint16_t key_len = le16_to_cpu(keyparam->keylen);
+			uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
+			uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
+			void *end;
+
+			end = (void *)keyparam + sizeof(keyparam->type)
+				+ sizeof(keyparam->length) + param_set_len;
+
+			/* Make sure we don't access past the end of the IEs */
+			if (end > resp_end)
+				break;
+
+			if (key_flags & KEY_INFO_WPA_UNICAST)
+				key = &priv->wpa_unicast_key;
+			else if (key_flags & KEY_INFO_WPA_MCAST)
+				key = &priv->wpa_mcast_key;
+			else
+				break;
+
+			/* Copy returned key into driver */
+			memset(key, 0, sizeof(struct enc_key));
+			if (key_len > sizeof(key->key))
+				break;
+			key->type = key_type;
+			key->flags = key_flags;
+			key->len = key_len;
+			memcpy(key->key, keyparam->key, key->len);
+
+			buf_ptr = end + 1;
+		}
+	}
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
+{
+/*		Bit  	Rate
+*		15:13 Reserved
+*		12    54 Mbps
+*		11    48 Mbps
+*		10    36 Mbps
+*		9     24 Mbps
+*		8     18 Mbps
+*		7     12 Mbps
+*		6     9 Mbps
+*		5     6 Mbps
+*		4     Reserved
+*		3     11 Mbps
+*		2     5.5 Mbps
+*		1     2 Mbps
+*		0     1 Mbps
+**/
+
+	uint16_t ratemask;
+	int i = lbs_data_rate_to_fw_index(rate);
+	if (lower_rates_ok)
+		ratemask = (0x1fef >> (12 - i));
+	else
+		ratemask = (1 << i);
+	return cpu_to_le16(ratemask);
+}
+
+int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
+				      uint16_t cmd_action)
+{
+	struct cmd_ds_802_11_rate_adapt_rateset cmd;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	if (!priv->cur_rate && !priv->enablehwauto)
+		return -EINVAL;
+
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+	cmd.action = cpu_to_le16(cmd_action);
+	cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
+	cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
+	ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
+	if (!ret && cmd_action == CMD_ACT_GET) {
+		priv->ratebitmap = le16_to_cpu(cmd.bitmap);
+		priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
+	}
+
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+/**
+ *  @brief Set the data rate
+ *
+ *  @param priv    	A pointer to struct lbs_private structure
+ *  @param rate  	The desired data rate, or 0 to clear a locked rate
+ *
+ *  @return 	   	0 on success, error on failure
+ */
+int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
+{
+	struct cmd_ds_802_11_data_rate cmd;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+
+	if (rate > 0) {
+		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
+		cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
+		if (cmd.rates[0] == 0) {
+			lbs_deb_cmd("DATA_RATE: invalid requested rate of"
+				" 0x%02X\n", rate);
+			ret = 0;
+			goto out;
+		}
+		lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
+	} else {
+		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
+		lbs_deb_cmd("DATA_RATE: setting auto\n");
+	}
+
+	ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
+	if (ret)
+		goto out;
+
+	lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
+
+	/* FIXME: get actual rates FW can do if this command actually returns
+	 * all data rates supported.
+	 */
+	priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
+	lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
+
+out:
+	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
+	return ret;
+}
+
+
+int lbs_cmd_802_11_rssi(struct lbs_private *priv,
+				struct cmd_ds_command *cmd)
+{
+
+	lbs_deb_enter(LBS_DEB_CMD);
+	cmd->command = cpu_to_le16(CMD_802_11_RSSI);
+	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
+		sizeof(struct cmd_header));
+	cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
+
+	/* reset Beacon SNR/NF/RSSI values */
+	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
+	priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
+	priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
+	priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
+	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
+	priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_ret_802_11_rssi(struct lbs_private *priv,
+				struct cmd_ds_command *resp)
+{
+	struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	/* store the non average value */
+	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
+	priv->NF[TYPE_BEACON][TYPE_NOAVG] =
+		get_unaligned_le16(&rssirsp->noisefloor);
+
+	priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
+	priv->NF[TYPE_BEACON][TYPE_AVG] =
+		get_unaligned_le16(&rssirsp->avgnoisefloor);
+
+	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
+	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
+		     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
+
+	priv->RSSI[TYPE_BEACON][TYPE_AVG] =
+	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
+		     priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
+
+	lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
+	       priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
+	       priv->RSSI[TYPE_BEACON][TYPE_AVG]);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+
+int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
+				struct cmd_ds_command *cmd,
+				u16 cmd_action)
+{
+	struct cmd_ds_802_11_beacon_control
+		*bcn_ctrl = &cmd->params.bcn_ctrl;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+	cmd->size =
+	    cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
+			     + sizeof(struct cmd_header));
+	cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
+
+	bcn_ctrl->action = cpu_to_le16(cmd_action);
+	bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
+	bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
+					struct cmd_ds_command *resp)
+{
+	struct cmd_ds_802_11_beacon_control *bcn_ctrl =
+	    &resp->params.bcn_ctrl;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	if (bcn_ctrl->action == CMD_ACT_GET) {
+		priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
+		priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
+	}
+
+	lbs_deb_enter(LBS_DEB_CMD);
+	return 0;
+}
+
+
+
 static int lbs_assoc_post(struct lbs_private *priv,
 			  struct cmd_ds_802_11_associate_response *resp)
 {
@@ -226,7 +624,7 @@ static int lbs_assoc_post(struct lbs_private *priv,
 	priv->connect_status = LBS_CONNECTED;
 
 	/* Update current SSID and BSSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
 	priv->curbssparams.ssid_len = bss->ssid_len;
 	memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
@@ -369,12 +767,7 @@ static int lbs_associate(struct lbs_private *priv,
 				   (u16)(pos - (u8 *) &cmd.iebuf));
 
 	/* update curbssparams */
-	priv->curbssparams.channel = bss->phy.ds.channel;
-
-	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-		ret = -1;
-		goto done;
-	}
+	priv->channel = bss->phy.ds.channel;
 
 	ret = lbs_cmd_with_response(priv, command, &cmd);
 	if (ret == 0) {
@@ -472,7 +865,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
 	memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
 
 	/* Set the new SSID to current SSID */
-	memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE);
+	memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
 	priv->curbssparams.ssid_len = bss->ssid_len;
 
 	netif_carrier_on(priv->dev);
@@ -487,7 +880,7 @@ static int lbs_adhoc_post(struct lbs_private *priv,
 	lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
 		     print_ssid(ssid, bss->ssid, bss->ssid_len),
 		     priv->curbssparams.bssid,
-		     priv->curbssparams.channel);
+		     priv->channel);
 
 done:
 	lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
@@ -560,7 +953,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
 	lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
 
 	priv->adhoccreate = 0;
-	priv->curbssparams.channel = bss->channel;
+	priv->channel = bss->channel;
 
 	/* Build the join command */
 	memset(&cmd, 0, sizeof(cmd));
@@ -633,11 +1026,6 @@ static int lbs_adhoc_join(struct lbs_private *priv,
 		}
 	}
 
-	if (lbs_parse_dnld_countryinfo_11d(priv, bss)) {
-		ret = -1;
-		goto out;
-	}
-
 	ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
 	if (ret == 0) {
 		ret = lbs_adhoc_post(priv,
@@ -737,12 +1125,6 @@ static int lbs_adhoc_start(struct lbs_private *priv,
 	lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
 	       cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
 
-	if (lbs_create_dnld_countryinfo_11d(priv)) {
-		lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n");
-		ret = -1;
-		goto out;
-	}
-
 	lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
 		     assoc_req->channel, assoc_req->band);
 
@@ -1099,7 +1481,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
 			/* else send START command */
 			lbs_deb_assoc("SSID not found, creating adhoc network\n");
 			memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
-				IW_ESSID_MAX_SIZE);
+				IEEE80211_MAX_SSID_LEN);
 			assoc_req->bss.ssid_len = assoc_req->ssid_len;
 			lbs_adhoc_start(priv, assoc_req);
 		}
@@ -1185,7 +1567,8 @@ static int assoc_helper_mode(struct lbs_private *priv,
 	}
 
 	priv->mode = assoc_req->mode;
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode);
+	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
+		assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
 
 done:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1205,7 +1588,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
 		goto done;
 	}
 
-	if (assoc_req->channel == priv->curbssparams.channel)
+	if (assoc_req->channel == priv->channel)
 		goto done;
 
 	if (priv->mesh_dev) {
@@ -1217,7 +1600,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
 	}
 
 	lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
-		      priv->curbssparams.channel, assoc_req->channel);
+		      priv->channel, assoc_req->channel);
 
 	ret = lbs_set_channel(priv, assoc_req->channel);
 	if (ret < 0)
@@ -1232,7 +1615,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
 		goto done;
 	}
 
-	if (assoc_req->channel != priv->curbssparams.channel) {
+	if (assoc_req->channel != priv->channel) {
 		lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
 		              assoc_req->channel);
 		goto restore_mesh;
@@ -1253,7 +1636,7 @@ static int assoc_helper_channel(struct lbs_private *priv,
  restore_mesh:
 	if (priv->mesh_dev)
 		lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				priv->curbssparams.channel);
+				priv->channel);
 
  done:
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -1475,7 +1858,7 @@ static int should_stop_adhoc(struct lbs_private *priv,
 	}
 
 	if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
-		if (assoc_req->channel != priv->curbssparams.channel)
+		if (assoc_req->channel != priv->channel)
 			return 1;
 	}
 
@@ -1557,7 +1940,7 @@ static int lbs_find_best_network_ssid(struct lbs_private *priv,
 
 	found = lbs_find_best_ssid_in_list(priv, preferred_mode);
 	if (found && (found->ssid_len > 0)) {
-		memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE);
+		memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
 		*out_ssid_len = found->ssid_len;
 		*out_mode = found->mode;
 		ret = 0;
@@ -1775,12 +2158,12 @@ struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
 	assoc_req = priv->pending_assoc_req;
 	if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
 		memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
-		       IW_ESSID_MAX_SIZE);
+		       IEEE80211_MAX_SSID_LEN);
 		assoc_req->ssid_len = priv->curbssparams.ssid_len;
 	}
 
 	if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
-		assoc_req->channel = priv->curbssparams.channel;
+		assoc_req->channel = priv->channel;
 
 	if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
 		assoc_req->band = priv->curbssparams.band;
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
index 6e765e9f91a3..40621b789fc5 100644
--- a/drivers/net/wireless/libertas/assoc.h
+++ b/drivers/net/wireless/libertas/assoc.h
@@ -3,7 +3,126 @@
 #ifndef _LBS_ASSOC_H_
 #define _LBS_ASSOC_H_
 
-#include "dev.h"
+
+#include "defs.h"
+#include "host.h"
+
+
+struct lbs_private;
+
+/*
+ * In theory, the IE is limited to the IE length, 255,
+ * but in practice 64 bytes are enough.
+ */
+#define MAX_WPA_IE_LEN 64
+
+
+
+struct lbs_802_11_security {
+	u8 WPAenabled;
+	u8 WPA2enabled;
+	u8 wep_enabled;
+	u8 auth_mode;
+	u32 key_mgmt;
+};
+
+/** Current Basic Service Set State Structure */
+struct current_bss_params {
+	/** bssid */
+	u8 bssid[ETH_ALEN];
+	/** ssid */
+	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
+	u8 ssid_len;
+
+	/** band */
+	u8 band;
+	/** channel is directly in priv->channel */
+	/** zero-terminated array of supported data rates */
+	u8 rates[MAX_RATES + 1];
+};
+
+/**
+ *  @brief Structure used to store information for each beacon/probe response
+ */
+struct bss_descriptor {
+	u8 bssid[ETH_ALEN];
+
+	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
+	u8 ssid_len;
+
+	u16 capability;
+	u32 rssi;
+	u32 channel;
+	u16 beaconperiod;
+	__le16 atimwindow;
+
+	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
+	u8 mode;
+
+	/* zero-terminated array of supported data rates */
+	u8 rates[MAX_RATES + 1];
+
+	unsigned long last_scanned;
+
+	union ieee_phy_param_set phy;
+	union ieee_ss_param_set ss;
+
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	size_t wpa_ie_len;
+	u8 rsn_ie[MAX_WPA_IE_LEN];
+	size_t rsn_ie_len;
+
+	u8 mesh;
+
+	struct list_head list;
+};
+
+/** Association request
+ *
+ * Encapsulates all the options that describe a specific assocation request
+ * or configuration of the wireless card's radio, mode, and security settings.
+ */
+struct assoc_request {
+#define ASSOC_FLAG_SSID			1
+#define ASSOC_FLAG_CHANNEL		2
+#define ASSOC_FLAG_BAND			3
+#define ASSOC_FLAG_MODE			4
+#define ASSOC_FLAG_BSSID		5
+#define ASSOC_FLAG_WEP_KEYS		6
+#define ASSOC_FLAG_WEP_TX_KEYIDX	7
+#define ASSOC_FLAG_WPA_MCAST_KEY	8
+#define ASSOC_FLAG_WPA_UCAST_KEY	9
+#define ASSOC_FLAG_SECINFO		10
+#define ASSOC_FLAG_WPA_IE		11
+	unsigned long flags;
+
+	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
+	u8 ssid_len;
+	u8 channel;
+	u8 band;
+	u8 mode;
+	u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
+
+	/** WEP keys */
+	struct enc_key wep_keys[4];
+	u16 wep_tx_keyidx;
+
+	/** WPA keys */
+	struct enc_key wpa_mcast_key;
+	struct enc_key wpa_unicast_key;
+
+	struct lbs_802_11_security secinfo;
+
+	/** WPA Information Elements*/
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	u8 wpa_ie_len;
+
+	/* BSS to associate with for infrastructure of Ad-Hoc join */
+	struct bss_descriptor bss;
+};
+
+
+extern u8 lbs_bg_rates[MAX_RATES];
 
 void lbs_association_worker(struct work_struct *work);
 struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
@@ -13,4 +132,24 @@ int lbs_adhoc_stop(struct lbs_private *priv);
 int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
 				 u8 bssid[ETH_ALEN], u16 reason);
 
+int lbs_cmd_802_11_rssi(struct lbs_private *priv,
+				struct cmd_ds_command *cmd);
+int lbs_ret_802_11_rssi(struct lbs_private *priv,
+				struct cmd_ds_command *resp);
+
+int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
+				struct cmd_ds_command *cmd,
+				u16 cmd_action);
+int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
+					struct cmd_ds_command *resp);
+
+int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
+			   struct assoc_request *assoc);
+
+int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
+			      uint16_t *enable);
+
+int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
+				struct assoc_request *assoc);
+
 #endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
new file mode 100644
index 000000000000..4396dccd12ac
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -0,0 +1,198 @@
+/*
+ * Implement cfg80211 ("iw") support.
+ *
+ * Copyright (C) 2009 M&N Solutions GmbH, 61191 Rosbach, Germany
+ * Holger Schurig <hs4233@mail.mn-solutions.de>
+ *
+ */
+
+#include <net/cfg80211.h>
+
+#include "cfg.h"
+#include "cmd.h"
+
+
+#define CHAN2G(_channel, _freq, _flags) {        \
+	.band             = IEEE80211_BAND_2GHZ, \
+	.center_freq      = (_freq),             \
+	.hw_value         = (_channel),          \
+	.flags            = (_flags),            \
+	.max_antenna_gain = 0,                   \
+	.max_power        = 30,                  \
+}
+
+static struct ieee80211_channel lbs_2ghz_channels[] = {
+	CHAN2G(1,  2412, 0),
+	CHAN2G(2,  2417, 0),
+	CHAN2G(3,  2422, 0),
+	CHAN2G(4,  2427, 0),
+	CHAN2G(5,  2432, 0),
+	CHAN2G(6,  2437, 0),
+	CHAN2G(7,  2442, 0),
+	CHAN2G(8,  2447, 0),
+	CHAN2G(9,  2452, 0),
+	CHAN2G(10, 2457, 0),
+	CHAN2G(11, 2462, 0),
+	CHAN2G(12, 2467, 0),
+	CHAN2G(13, 2472, 0),
+	CHAN2G(14, 2484, 0),
+};
+
+#define RATETAB_ENT(_rate, _rateid, _flags) { \
+	.bitrate  = (_rate),                  \
+	.hw_value = (_rateid),                \
+	.flags    = (_flags),                 \
+}
+
+
+static struct ieee80211_rate lbs_rates[] = {
+	RATETAB_ENT(10,  0x1,   0),
+	RATETAB_ENT(20,  0x2,   0),
+	RATETAB_ENT(55,  0x4,   0),
+	RATETAB_ENT(110, 0x8,   0),
+	RATETAB_ENT(60,  0x10,  0),
+	RATETAB_ENT(90,  0x20,  0),
+	RATETAB_ENT(120, 0x40,  0),
+	RATETAB_ENT(180, 0x80,  0),
+	RATETAB_ENT(240, 0x100, 0),
+	RATETAB_ENT(360, 0x200, 0),
+	RATETAB_ENT(480, 0x400, 0),
+	RATETAB_ENT(540, 0x800, 0),
+};
+
+static struct ieee80211_supported_band lbs_band_2ghz = {
+	.channels = lbs_2ghz_channels,
+	.n_channels = ARRAY_SIZE(lbs_2ghz_channels),
+	.bitrates = lbs_rates,
+	.n_bitrates = ARRAY_SIZE(lbs_rates),
+};
+
+
+static const u32 cipher_suites[] = {
+	WLAN_CIPHER_SUITE_WEP40,
+	WLAN_CIPHER_SUITE_WEP104,
+	WLAN_CIPHER_SUITE_TKIP,
+	WLAN_CIPHER_SUITE_CCMP,
+};
+
+
+
+static int lbs_cfg_set_channel(struct wiphy *wiphy,
+	struct ieee80211_channel *chan,
+	enum nl80211_channel_type channel_type)
+{
+	struct lbs_private *priv = wiphy_priv(wiphy);
+	int ret = -ENOTSUPP;
+
+	lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type);
+
+	if (channel_type != NL80211_CHAN_NO_HT)
+		goto out;
+
+	ret = lbs_set_channel(priv, chan->hw_value);
+
+ out:
+	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+	return ret;
+}
+
+
+
+
+static struct cfg80211_ops lbs_cfg80211_ops = {
+	.set_channel = lbs_cfg_set_channel,
+};
+
+
+/*
+ * At this time lbs_private *priv doesn't even exist, so we just allocate
+ * memory and don't initialize the wiphy further. This is postponed until we
+ * can talk to the firmware and happens at registration time in
+ * lbs_cfg_wiphy_register().
+ */
+struct wireless_dev *lbs_cfg_alloc(struct device *dev)
+{
+	int ret = 0;
+	struct wireless_dev *wdev;
+
+	lbs_deb_enter(LBS_DEB_CFG80211);
+
+	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+	if (!wdev) {
+		dev_err(dev, "cannot allocate wireless device\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	wdev->wiphy = wiphy_new(&lbs_cfg80211_ops, sizeof(struct lbs_private));
+	if (!wdev->wiphy) {
+		dev_err(dev, "cannot allocate wiphy\n");
+		ret = -ENOMEM;
+		goto err_wiphy_new;
+	}
+
+	lbs_deb_leave(LBS_DEB_CFG80211);
+	return wdev;
+
+ err_wiphy_new:
+	kfree(wdev);
+	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+	return ERR_PTR(ret);
+}
+
+
+/*
+ * This function get's called after lbs_setup_firmware() determined the
+ * firmware capabities. So we can setup the wiphy according to our
+ * hardware/firmware.
+ */
+int lbs_cfg_register(struct lbs_private *priv)
+{
+	struct wireless_dev *wdev = priv->wdev;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_CFG80211);
+
+	wdev->wiphy->max_scan_ssids = 1;
+	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	/* TODO: BIT(NL80211_IFTYPE_ADHOC); */
+	wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+
+	/* TODO: honor priv->regioncode */
+	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
+
+	/*
+	 * We could check priv->fwcapinfo && FW_CAPINFO_WPA, but I have
+	 * never seen a firmware without WPA
+	 */
+	wdev->wiphy->cipher_suites = cipher_suites;
+	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
+	ret = wiphy_register(wdev->wiphy);
+	if (ret < 0)
+		lbs_pr_err("cannot register wiphy device\n");
+
+	ret = register_netdev(priv->dev);
+	if (ret)
+		lbs_pr_err("cannot register network device\n");
+
+	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
+	return ret;
+}
+
+
+void lbs_cfg_free(struct lbs_private *priv)
+{
+	struct wireless_dev *wdev = priv->wdev;
+
+	lbs_deb_enter(LBS_DEB_CFG80211);
+
+	if (!wdev)
+		return;
+
+	if (wdev->wiphy) {
+		wiphy_unregister(wdev->wiphy);
+		wiphy_free(wdev->wiphy);
+	}
+	kfree(wdev);
+}
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
new file mode 100644
index 000000000000..e09a193a34d6
--- /dev/null
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -0,0 +1,16 @@
+#ifndef __LBS_CFG80211_H__
+#define __LBS_CFG80211_H__
+
+#include "dev.h"
+
+struct wireless_dev *lbs_cfg_alloc(struct device *dev);
+int lbs_cfg_register(struct lbs_private *priv);
+void lbs_cfg_free(struct lbs_private *priv);
+
+int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
+	u8 ssid_len);
+int lbs_scan_networks(struct lbs_private *priv, int full_scan);
+void lbs_cfg_scan_worker(struct work_struct *work);
+
+
+#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 0a324dcd264c..b9b371bfa30f 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,21 +3,20 @@
   * It prepares command and sends it to firmware when it is ready.
   */
 
-#include <net/iw_handler.h>
-#include <net/lib80211.h>
 #include <linux/kfifo.h>
 #include <linux/sched.h>
+
 #include "host.h"
-#include "hostcmd.h"
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
 #include "assoc.h"
 #include "wext.h"
+#include "scan.h"
 #include "cmd.h"
 
-static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
 
+static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv);
 
 /**
  *  @brief Simple callback that copies response back into command
@@ -77,6 +76,30 @@ static u8 is_command_allowed_in_ps(u16 cmd)
 }
 
 /**
+ *  @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
@@ -169,11 +192,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
 		goto out;
 	}
 
-	if (lbs_set_universaltable(priv, 0)) {
-		ret = -1;
-		goto out;
-	}
-
 out:
 	lbs_deb_leave(LBS_DEB_CMD);
 	return ret;
@@ -222,7 +240,7 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
 
 	cmd->command = cpu_to_le16(CMD_802_11_PS_MODE);
 	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) +
-				S_DS_GEN);
+				sizeof(struct cmd_header));
 	psm->action = cpu_to_le16(cmd_action);
 	psm->multipledtim = 0;
 	switch (cmd_action) {
@@ -251,33 +269,6 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd,
 	return 0;
 }
 
-int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
-				      uint16_t cmd_action, uint16_t *timeout)
-{
-	struct cmd_ds_802_11_inactivity_timeout cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT);
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.action = cpu_to_le16(cmd_action);
-
-	if (cmd_action == CMD_ACT_SET)
-		cmd.timeout = cpu_to_le16(*timeout);
-	else
-		cmd.timeout = 0;
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
-
-	if (!ret)
-		*timeout = le16_to_cpu(cmd.timeout);
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return 0;
-}
-
 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 				struct sleep_params *sp)
 {
@@ -320,190 +311,53 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 	return 0;
 }
 
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
-			   struct assoc_request *assoc)
+static int lbs_wait_for_ds_awake(struct lbs_private *priv)
 {
-	struct cmd_ds_802_11_set_wep cmd;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.action = cpu_to_le16(cmd_action);
-
-	if (cmd_action == CMD_ACT_ADD) {
-		int i;
-
-		/* default tx key index */
-		cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
-					   CMD_WEP_KEY_INDEX_MASK);
-
-		/* Copy key types and material to host command structure */
-		for (i = 0; i < 4; i++) {
-			struct enc_key *pkey = &assoc->wep_keys[i];
-
-			switch (pkey->len) {
-			case KEY_LEN_WEP_40:
-				cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
-				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
-				lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
-				break;
-			case KEY_LEN_WEP_104:
-				cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
-				memmove(cmd.keymaterial[i], pkey->key, pkey->len);
-				lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
-				break;
-			case 0:
-				break;
-			default:
-				lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
-					    i, pkey->len);
-				ret = -1;
-				goto done;
-				break;
-			}
+	if (priv->is_deep_sleep) {
+		if (!wait_event_interruptible_timeout(priv->ds_awake_q,
+					!priv->is_deep_sleep, (10 * HZ))) {
+			lbs_pr_err("ds_awake_q: timer expired\n");
+			ret = -1;
 		}
-	} else if (cmd_action == CMD_ACT_REMOVE) {
-		/* ACT_REMOVE clears _all_ WEP keys */
-
-		/* default tx key index */
-		cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
-					   CMD_WEP_KEY_INDEX_MASK);
-		lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
-done:
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
-			      uint16_t *enable)
-{
-	struct cmd_ds_802_11_enable_rsn cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-	cmd.action = cpu_to_le16(cmd_action);
-
-	if (cmd_action == CMD_ACT_GET)
-		cmd.enable = 0;
-	else {
-		if (*enable)
-			cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
-		else
-			cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
-		lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
 	}
 
-	ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
-	if (!ret && cmd_action == CMD_ACT_GET)
-		*enable = le16_to_cpu(cmd.enable);
-
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
-static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
-                            struct enc_key *key)
+int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
 {
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (key->flags & KEY_INFO_WPA_ENABLED)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
-	if (key->flags & KEY_INFO_WPA_UNICAST)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
-	if (key->flags & KEY_INFO_WPA_MCAST)
-		keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
-
-	keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
-	keyparam->keytypeid = cpu_to_le16(key->type);
-	keyparam->keylen = cpu_to_le16(key->len);
-	memcpy(keyparam->key, key->key, key->len);
-
-	/* Length field doesn't include the {type,length} header */
-	keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
-	lbs_deb_leave(LBS_DEB_CMD);
-}
-
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-				struct assoc_request *assoc)
-{
-	struct cmd_ds_802_11_key_material cmd;
-	int ret = 0;
-	int index = 0;
+	int ret =  0;
 
 	lbs_deb_enter(LBS_DEB_CMD);
 
-	cmd.action = cpu_to_le16(cmd_action);
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	if (cmd_action == CMD_ACT_GET) {
-		cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2);
-	} else {
-		memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
-
-		if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
-			set_one_wpa_key(&cmd.keyParamSet[index],
-					&assoc->wpa_unicast_key);
-			index++;
-		}
-
-		if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
-			set_one_wpa_key(&cmd.keyParamSet[index],
-					&assoc->wpa_mcast_key);
-			index++;
+	if (deep_sleep) {
+		if (priv->is_deep_sleep != 1) {
+			lbs_deb_cmd("deep sleep: sleep\n");
+			BUG_ON(!priv->enter_deep_sleep);
+			ret = priv->enter_deep_sleep(priv);
+			if (!ret) {
+				netif_stop_queue(priv->dev);
+				netif_carrier_off(priv->dev);
+			}
+		} else {
+			lbs_pr_err("deep sleep: already enabled\n");
 		}
-
-		/* The common header and as many keys as we included */
-		cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
-						    keyParamSet[index]));
-	}
-	ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
-	/* Copy the returned key to driver private data */
-	if (!ret && cmd_action == CMD_ACT_GET) {
-		void *buf_ptr = cmd.keyParamSet;
-		void *resp_end = &(&cmd)[1];
-
-		while (buf_ptr < resp_end) {
-			struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
-			struct enc_key *key;
-			uint16_t param_set_len = le16_to_cpu(keyparam->length);
-			uint16_t key_len = le16_to_cpu(keyparam->keylen);
-			uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
-			uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
-			void *end;
-
-			end = (void *)keyparam + sizeof(keyparam->type)
-				+ sizeof(keyparam->length) + param_set_len;
-
-			/* Make sure we don't access past the end of the IEs */
-			if (end > resp_end)
-				break;
-
-			if (key_flags & KEY_INFO_WPA_UNICAST)
-				key = &priv->wpa_unicast_key;
-			else if (key_flags & KEY_INFO_WPA_MCAST)
-				key = &priv->wpa_mcast_key;
-			else
-				break;
-
-			/* Copy returned key into driver */
-			memset(key, 0, sizeof(struct enc_key));
-			if (key_len > sizeof(key->key))
-				break;
-			key->type = key_type;
-			key->flags = key_flags;
-			key->len = key_len;
-			memcpy(key->key, keyparam->key, key->len);
-
-			buf_ptr = end + 1;
+	} else {
+		if (priv->is_deep_sleep) {
+			lbs_deb_cmd("deep sleep: wakeup\n");
+			BUG_ON(!priv->exit_deep_sleep);
+			ret = priv->exit_deep_sleep(priv);
+			if (!ret) {
+				ret = lbs_wait_for_ds_awake(priv);
+				if (ret)
+					lbs_pr_err("deep sleep: wakeup"
+							"failed\n");
+			}
 		}
 	}
 
@@ -535,7 +389,7 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
 	switch (oid) {
 	case SNMP_MIB_OID_BSS_TYPE:
 		cmd.bufsize = cpu_to_le16(sizeof(u8));
-		cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1;
+		cmd.value[0] = val;
 		break;
 	case SNMP_MIB_OID_11D_ENABLE:
 	case SNMP_MIB_OID_FRAG_THRESHOLD:
@@ -588,13 +442,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
 
 	switch (le16_to_cpu(cmd.bufsize)) {
 	case sizeof(u8):
-		if (oid == SNMP_MIB_OID_BSS_TYPE) {
-			if (cmd.value[0] == 2)
-				*out_val = IW_MODE_ADHOC;
-			else
-				*out_val = IW_MODE_INFRA;
-		} else
-			*out_val = cmd.value[0];
+		*out_val = cmd.value[0];
 		break;
 	case sizeof(u16):
 		*out_val = le16_to_cpu(*((__le16 *)(&cmd.value)));
@@ -681,7 +529,7 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
 	cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE);
 	cmd->size =
 	    cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
-			     S_DS_GEN);
+			     sizeof(struct cmd_header));
 
 	monitor->action = cpu_to_le16(cmd_action);
 	if (cmd_action == CMD_ACT_SET) {
@@ -692,111 +540,6 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd,
 	return 0;
 }
 
-static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
-{
-/*		Bit  	Rate
-*		15:13 Reserved
-*		12    54 Mbps
-*		11    48 Mbps
-*		10    36 Mbps
-*		9     24 Mbps
-*		8     18 Mbps
-*		7     12 Mbps
-*		6     9 Mbps
-*		5     6 Mbps
-*		4     Reserved
-*		3     11 Mbps
-*		2     5.5 Mbps
-*		1     2 Mbps
-*		0     1 Mbps
-**/
-
-	uint16_t ratemask;
-	int i = lbs_data_rate_to_fw_index(rate);
-	if (lower_rates_ok)
-		ratemask = (0x1fef >> (12 - i));
-	else
-		ratemask = (1 << i);
-	return cpu_to_le16(ratemask);
-}
-
-int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
-				      uint16_t cmd_action)
-{
-	struct cmd_ds_802_11_rate_adapt_rateset cmd;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (!priv->cur_rate && !priv->enablehwauto)
-		return -EINVAL;
-
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	cmd.action = cpu_to_le16(cmd_action);
-	cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
-	cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
-	ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
-	if (!ret && cmd_action == CMD_ACT_GET) {
-		priv->ratebitmap = le16_to_cpu(cmd.bitmap);
-		priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
-	}
-
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset);
-
-/**
- *  @brief Set the data rate
- *
- *  @param priv    	A pointer to struct lbs_private structure
- *  @param rate  	The desired data rate, or 0 to clear a locked rate
- *
- *  @return 	   	0 on success, error on failure
- */
-int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
-{
-	struct cmd_ds_802_11_data_rate cmd;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.hdr.size = cpu_to_le16(sizeof(cmd));
-
-	if (rate > 0) {
-		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
-		cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
-		if (cmd.rates[0] == 0) {
-			lbs_deb_cmd("DATA_RATE: invalid requested rate of"
-			            " 0x%02X\n", rate);
-			ret = 0;
-			goto out;
-		}
-		lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
-	} else {
-		cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
-		lbs_deb_cmd("DATA_RATE: setting auto\n");
-	}
-
-	ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
-	if (ret)
-		goto out;
-
-	lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd));
-
-	/* FIXME: get actual rates FW can do if this command actually returns
-	 * all data rates supported.
-	 */
-	priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
-	lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
-
-out:
-	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
-	return ret;
-}
-
 /**
  *  @brief Get the radio channel
  *
@@ -804,7 +547,7 @@ out:
  *
  *  @return 	   	The channel on success, error on failure
  */
-int lbs_get_channel(struct lbs_private *priv)
+static int lbs_get_channel(struct lbs_private *priv)
 {
 	struct cmd_ds_802_11_rf_channel cmd;
 	int ret = 0;
@@ -836,7 +579,7 @@ int lbs_update_channel(struct lbs_private *priv)
 
 	ret = lbs_get_channel(priv);
 	if (ret > 0) {
-		priv->curbssparams.channel = ret;
+		priv->channel = ret;
 		ret = 0;
 	}
 	lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
@@ -855,7 +598,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
 {
 	struct cmd_ds_802_11_rf_channel cmd;
 #ifdef DEBUG
-	u8 old_channel = priv->curbssparams.channel;
+	u8 old_channel = priv->channel;
 #endif
 	int ret = 0;
 
@@ -870,36 +613,15 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
 	if (ret)
 		goto out;
 
-	priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
+	priv->channel = (uint8_t) le16_to_cpu(cmd.channel);
 	lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
-		priv->curbssparams.channel);
+		priv->channel);
 
 out:
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
 }
 
-static int lbs_cmd_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *cmd)
-{
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	cmd->command = cpu_to_le16(CMD_802_11_RSSI);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN);
-	cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
-
-	/* reset Beacon SNR/NF/RSSI values */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
-	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
-	priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
 static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 			       u8 cmd_action, void *pdata_buf)
 {
@@ -916,7 +638,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 
 			cmdptr->size =
 			    cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access)
-					+ S_DS_GEN);
+					+ sizeof(struct cmd_header));
 			macreg =
 			    (struct cmd_ds_mac_reg_access *)&cmdptr->params.
 			    macreg;
@@ -935,7 +657,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 			cmdptr->size =
 			    cpu_to_le16(sizeof
 					     (struct cmd_ds_bbp_reg_access)
-					     + S_DS_GEN);
+					     + sizeof(struct cmd_header));
 			bbpreg =
 			    (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
 			    bbpreg;
@@ -954,7 +676,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 			cmdptr->size =
 			    cpu_to_le16(sizeof
 					     (struct cmd_ds_rf_reg_access) +
-					     S_DS_GEN);
+					     sizeof(struct cmd_header));
 			rfreg =
 			    (struct cmd_ds_rf_reg_access *)&cmdptr->params.
 			    rfreg;
@@ -974,192 +696,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 	return 0;
 }
 
-static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
-{
-	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->command = cpu_to_le16(CMD_BT_ACCESS);
-	cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN);
-	cmd->result = 0;
-	bt_access->action = cpu_to_le16(cmd_action);
-
-	switch (cmd_action) {
-	case CMD_ACT_BT_ACCESS_ADD:
-		memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
-		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);
-		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;
-	}
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
-			       u16 cmd_action, void *pdata_buf)
-{
-	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
-	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) + S_DS_GEN);
-	cmd->result = 0;
-
-	if (pdata_buf)
-		memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
-	else
-		memset(fwt_access, 0, sizeof(*fwt_access));
-
-	fwt_access->action = cpu_to_le16(cmd_action);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
-		    struct cmd_ds_mesh_access *cmd)
-{
-	int ret;
-
-	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
-
-	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
-	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
-	cmd->hdr.result = 0;
-
-	cmd->action = cpu_to_le16(cmd_action);
-
-	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-static int __lbs_mesh_config_send(struct lbs_private *priv,
-				  struct cmd_ds_mesh_config *cmd,
-				  uint16_t action, uint16_t type)
-{
-	int ret;
-	u16 command = CMD_MESH_CONFIG_OLD;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	/*
-	 * Command id is 0xac for v10 FW along with mesh interface
-	 * id in bits 14-13-12.
-	 */
-	if (priv->mesh_fw_ver == MESH_FW_NEW)
-		command = CMD_MESH_CONFIG |
-			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
-
-	cmd->hdr.command = cpu_to_le16(command);
-	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
-	cmd->hdr.result = 0;
-
-	cmd->type = cpu_to_le16(type);
-	cmd->action = cpu_to_le16(action);
-
-	ret = lbs_cmd_with_response(priv, command, cmd);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return ret;
-}
-
-int lbs_mesh_config_send(struct lbs_private *priv,
-			 struct cmd_ds_mesh_config *cmd,
-			 uint16_t action, uint16_t type)
-{
-	int ret;
-
-	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
-		return -EOPNOTSUPP;
-
-	ret = __lbs_mesh_config_send(priv, cmd, action, type);
-	return ret;
-}
-
-/* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
- * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
- * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
- * lbs_mesh_config_send.
- */
-int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_meshie *ie;
-	DECLARE_SSID_BUF(ssid);
-
-	memset(&cmd, 0, sizeof(cmd));
-	cmd.channel = cpu_to_le16(chan);
-	ie = (struct mrvl_meshie *)cmd.data;
-
-	switch (action) {
-	case CMD_ACT_MESH_CONFIG_START:
-		ie->id = WLAN_EID_GENERIC;
-		ie->val.oui[0] = 0x00;
-		ie->val.oui[1] = 0x50;
-		ie->val.oui[2] = 0x43;
-		ie->val.type = MARVELL_MESH_IE_TYPE;
-		ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
-		ie->val.version = MARVELL_MESH_IE_VERSION;
-		ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
-		ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
-		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
-		ie->val.mesh_id_len = priv->mesh_ssid_len;
-		memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
-		ie->len = sizeof(struct mrvl_meshie_val) -
-			IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
-		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
-		break;
-	case CMD_ACT_MESH_CONFIG_STOP:
-		break;
-	default:
-		return -1;
-	}
-	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
-		    action, priv->mesh_tlv, chan,
-		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
-
-	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
-}
-
-static int lbs_cmd_bcn_ctrl(struct lbs_private * priv,
-				struct cmd_ds_command *cmd,
-				u16 cmd_action)
-{
-	struct cmd_ds_802_11_beacon_control
-		*bcn_ctrl = &cmd->params.bcn_ctrl;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	cmd->size =
-	    cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
-			     + S_DS_GEN);
-	cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
-
-	bcn_ctrl->action = cpu_to_le16(cmd_action);
-	bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
-	bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
 static void lbs_queue_cmd(struct lbs_private *priv,
 			  struct cmd_ctrl_node *cmdnode)
 {
@@ -1243,8 +779,17 @@ static void lbs_submit_command(struct lbs_private *priv,
 		timeo = HZ/4;
 	}
 
-	/* Setup the timer after transmit command */
-	mod_timer(&priv->command_timer, jiffies + timeo);
+	if (command == CMD_802_11_DEEP_SLEEP) {
+		if (priv->is_auto_deep_sleep_enabled) {
+			priv->wakeup_dev_required = 1;
+			priv->dnld_sent = 0;
+		}
+		priv->is_deep_sleep = 1;
+		lbs_complete_command(priv, cmdnode, 0);
+	} else {
+		/* Setup the timer after transmit command */
+		mod_timer(&priv->command_timer, jiffies + timeo);
+	}
 
 	lbs_deb_leave(LBS_DEB_HOST);
 }
@@ -1391,6 +936,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 		goto done;
 	}
 
+	if (!lbs_is_cmd_allowed(priv)) {
+		ret = -EBUSY;
+		goto done;
+	}
+
 	cmdnode = lbs_get_cmd_ctrl_node(priv);
 
 	if (cmdnode == NULL) {
@@ -1441,7 +991,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 
 		cmdptr->command = cpu_to_le16(cmd_no);
 		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
-					   S_DS_GEN);
+					   sizeof(struct cmd_header));
 
 		memmove(&cmdptr->params.afc,
 			pdata_buf, sizeof(struct cmd_ds_802_11_afc));
@@ -1449,45 +999,17 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 		ret = 0;
 		goto done;
 
-	case CMD_802_11D_DOMAIN_INFO:
-		ret = lbs_cmd_802_11d_domain_info(priv, cmdptr,
-						   cmd_no, 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) +
-				     S_DS_GEN);
+				     sizeof(struct cmd_header));
 
 		memmove(&cmdptr->params.tpccfg,
 			pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
 
 		ret = 0;
 		break;
-	case CMD_802_11_LED_GPIO_CTRL:
-		{
-			struct mrvl_ie_ledgpio *gpio =
-			    (struct mrvl_ie_ledgpio*)
-			    cmdptr->params.ledgpio.data;
-
-			memmove(&cmdptr->params.ledgpio,
-				pdata_buf,
-				sizeof(struct cmd_ds_802_11_led_ctrl));
-
-			cmdptr->command =
-			    cpu_to_le16(CMD_802_11_LED_GPIO_CTRL);
-
-#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
-			cmdptr->size =
-			    cpu_to_le16(le16_to_cpu(gpio->header.len)
-				+ S_DS_GEN
-				+ ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
-			gpio->header.len = gpio->header.len;
-
-			ret = 0;
-			break;
-		}
 
 	case CMD_BT_ACCESS:
 		ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
@@ -1497,15 +1019,13 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 		ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
 		break;
 
-	case CMD_GET_TSF:
-		cmdptr->command = cpu_to_le16(CMD_GET_TSF);
-		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
-					   S_DS_GEN);
-		ret = 0;
-		break;
 	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;
@@ -1823,30 +1343,6 @@ done:
 	return ret;
 }
 
-void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
-{
-	union iwreq_data iwrq;
-	u8 buf[50];
-
-	lbs_deb_enter(LBS_DEB_WEXT);
-
-	memset(&iwrq, 0, sizeof(union iwreq_data));
-	memset(buf, 0, sizeof(buf));
-
-	snprintf(buf, sizeof(buf) - 1, "%s", str);
-
-	iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
-
-	/* Send Event to upper layer */
-	lbs_deb_wext("event indication string %s\n", (char *)buf);
-	lbs_deb_wext("event indication length %d\n", iwrq.data.length);
-	lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
-
-	wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
-
-	lbs_deb_leave(LBS_DEB_WEXT);
-}
-
 static void lbs_send_confirmsleep(struct lbs_private *priv)
 {
 	unsigned long flags;
@@ -2024,7 +1520,7 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
 }
 
 
-static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
+struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
 	uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
 	int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
 	unsigned long callback_arg)
@@ -2039,6 +1535,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
 		goto done;
 	}
 
+	if (!lbs_is_cmd_allowed(priv)) {
+		cmdnode = ERR_PTR(-EBUSY);
+		goto done;
+	}
+
 	cmdnode = lbs_get_cmd_ctrl_node(priv);
 	if (cmdnode == NULL) {
 		lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
@@ -2117,5 +1618,3 @@ done:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(__lbs_cmd);
-
-
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 392e578ca095..2862748aef70 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -3,11 +3,30 @@
 #ifndef _LBS_CMD_H_
 #define _LBS_CMD_H_
 
-#include "hostcmd.h"
+#include "host.h"
 #include "dev.h"
 
+
+/* Command & response transfer between host and card */
+
+struct cmd_ctrl_node {
+	struct list_head list;
+	int result;
+	/* command response */
+	int (*callback)(struct lbs_private *,
+			unsigned long,
+			struct cmd_header *);
+	unsigned long callback_arg;
+	/* command data */
+	struct cmd_header *cmdbuf;
+	/* wait queue */
+	u16 cmdwaitqwoken;
+	wait_queue_head_t cmdwait_q;
+};
+
+
 /* lbs_cmd() infers the size of the buffer to copy data back into, from
-   the size of the target of the pointer. Since the command to be sent 
+   the size of the target of the pointer. Since the command to be sent
    may often be smaller, that size is set in cmd->size by the caller.*/
 #define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg)	({		\
 	uint16_t __sz = le16_to_cpu((cmd)->hdr.size);		\
@@ -18,6 +37,11 @@
 #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);
 
@@ -26,62 +50,93 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
 	      int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
 	      unsigned long callback_arg);
 
-int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
-		int8_t p1, int8_t p2);
+struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
+	uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
+	int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
+	unsigned long callback_arg);
 
-int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
-		int8_t p2, int usesnr);
+int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
+		     struct cmd_header *resp);
 
-int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
-		int8_t p1, int8_t p2);
+int lbs_allocate_cmd_buffer(struct lbs_private *priv);
+int lbs_free_cmd_buffer(struct lbs_private *priv);
 
-int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
-		int8_t p2, int usesnr);
+int lbs_execute_next_command(struct lbs_private *priv);
+void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
+			  int result);
+int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
 
-int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
-		     struct cmd_header *resp);
 
-int lbs_update_hw_spec(struct lbs_private *priv);
+/* From cmdresp.c */
 
-int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
-		    struct cmd_ds_mesh_access *cmd);
+void lbs_mac_event_disconnected(struct lbs_private *priv);
 
-int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
 
-int lbs_get_channel(struct lbs_private *priv);
+
+/* Events */
+
+int lbs_process_event(struct lbs_private *priv, u32 event);
+
+
+/* Actual commands */
+
+int lbs_update_hw_spec(struct lbs_private *priv);
+
 int lbs_set_channel(struct lbs_private *priv, u8 channel);
 
-int lbs_mesh_config_send(struct lbs_private *priv,
-			 struct cmd_ds_mesh_config *cmd,
-			 uint16_t action, uint16_t type);
-int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
+int lbs_update_channel(struct lbs_private *priv);
 
 int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
 		struct wol_config *p_wol_config);
-int lbs_suspend(struct lbs_private *priv);
-void lbs_resume(struct lbs_private *priv);
 
-int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
-				      uint16_t cmd_action);
-int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
-				      uint16_t cmd_action, uint16_t *timeout);
 int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 				struct sleep_params *sp);
-int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
-			   struct assoc_request *assoc);
-int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
-			      uint16_t *enable);
-int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
-				struct assoc_request *assoc);
 
-int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
-		     s16 *maxlevel);
-int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
+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);
 
+void lbs_set_mac_control(struct lbs_private *priv);
+
+int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
+		     s16 *maxlevel);
+
 int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val);
 
 int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val);
 
+
+/* Mesh related */
+
+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,
+			 struct cmd_ds_mesh_config *cmd,
+			 uint16_t action, uint16_t type);
+
+int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
+
+
+/* Commands only used in wext.c, assoc. and scan.c */
+
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+		int8_t p1, int8_t p2);
+
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+		int8_t p2, int usesnr);
+
+int lbs_set_data_rate(struct lbs_private *priv, u8 rate);
+
+int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
+				      uint16_t cmd_action);
+
+int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
+
+int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
+
 #endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 23f684337fdd..21d57690c20a 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -11,6 +11,7 @@
 
 #include "host.h"
 #include "decl.h"
+#include "cmd.h"
 #include "defs.h"
 #include "dev.h"
 #include "assoc.h"
@@ -26,23 +27,17 @@
  */
 void lbs_mac_event_disconnected(struct lbs_private *priv)
 {
-	union iwreq_data wrqu;
-
 	if (priv->connect_status != LBS_CONNECTED)
 		return;
 
 	lbs_deb_enter(LBS_DEB_ASSOC);
 
-	memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-
 	/*
 	 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
 	 * It causes problem in the Supplicant
 	 */
-
 	msleep_interruptible(1000);
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+	lbs_send_disconnect_notification(priv);
 
 	/* report disconnect to upper layer */
 	netif_stop_queue(priv->dev);
@@ -67,7 +62,7 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
 	 * no longer valid.
 	 */
 	memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
-	memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE);
+	memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
 	priv->curbssparams.ssid_len = 0;
 
 	if (priv->psstate != PS_STATE_FULL_POWER) {
@@ -78,32 +73,6 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
 	lbs_deb_leave(LBS_DEB_ASSOC);
 }
 
-/**
- *  @brief This function handles MIC failure event.
- *
- *  @param priv    A pointer to struct lbs_private structure
- *  @para  event   the event id
- *  @return 	   n/a
- */
-static void handle_mic_failureevent(struct lbs_private *priv, u32 event)
-{
-	char buf[50];
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	memset(buf, 0, sizeof(buf));
-
-	sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
-
-	if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
-		strcat(buf, "unicast ");
-	} else {
-		strcat(buf, "multicast ");
-	}
-
-	lbs_send_iwevcustom_event(priv, buf);
-	lbs_deb_leave(LBS_DEB_CMD);
-}
-
 static int lbs_ret_reg_access(struct lbs_private *priv,
 			       u16 type, struct cmd_ds_command *resp)
 {
@@ -147,53 +116,6 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
 	return ret;
 }
 
-static int lbs_ret_802_11_rssi(struct lbs_private *priv,
-				struct cmd_ds_command *resp)
-{
-	struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	/* store the non average value */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor);
-
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
-	priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor);
-
-	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
-	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
-		     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-
-	priv->RSSI[TYPE_BEACON][TYPE_AVG] =
-	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
-		     priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
-
-	lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
-	       priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
-	       priv->RSSI[TYPE_BEACON][TYPE_AVG]);
-
-	lbs_deb_leave(LBS_DEB_CMD);
-	return 0;
-}
-
-static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
-					struct cmd_ds_command *resp)
-{
-	struct cmd_ds_802_11_beacon_control *bcn_ctrl =
-	    &resp->params.bcn_ctrl;
-
-	lbs_deb_enter(LBS_DEB_CMD);
-
-	if (bcn_ctrl->action == CMD_ACT_GET) {
-		priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
-		priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
-	}
-
-	lbs_deb_enter(LBS_DEB_CMD);
-	return 0;
-}
-
 static inline int handle_cmd_response(struct lbs_private *priv,
 				      struct cmd_header *cmd_response)
 {
@@ -227,29 +149,13 @@ static inline int handle_cmd_response(struct lbs_private *priv,
 		ret = lbs_ret_802_11_rssi(priv, resp);
 		break;
 
-	case CMD_RET(CMD_802_11D_DOMAIN_INFO):
-		ret = lbs_ret_802_11d_domain_info(resp);
-		break;
-
 	case CMD_RET(CMD_802_11_TPC_CFG):
 		spin_lock_irqsave(&priv->driver_lock, flags);
 		memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
 			sizeof(struct cmd_ds_802_11_tpc_cfg));
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		break;
-	case CMD_RET(CMD_802_11_LED_GPIO_CTRL):
-		spin_lock_irqsave(&priv->driver_lock, flags);
-		memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio,
-			sizeof(struct cmd_ds_802_11_led_ctrl));
-		spin_unlock_irqrestore(&priv->driver_lock, flags);
-		break;
 
-	case CMD_RET(CMD_GET_TSF):
-		spin_lock_irqsave(&priv->driver_lock, flags);
-		memcpy((void *)priv->cur_cmd->callback_arg,
-		       &resp->params.gettsf.tsfvalue, sizeof(u64));
-		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)
@@ -505,9 +411,21 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
 
 	case MACREG_INT_CODE_HOST_AWAKE:
 		lbs_deb_cmd("EVENT: host awake\n");
+		if (priv->reset_deep_sleep_wakeup)
+			priv->reset_deep_sleep_wakeup(priv);
+		priv->is_deep_sleep = 0;
 		lbs_send_confirmwake(priv);
 		break;
 
+	case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
+		if (priv->reset_deep_sleep_wakeup)
+			priv->reset_deep_sleep_wakeup(priv);
+		lbs_deb_cmd("EVENT: ds awake\n");
+		priv->is_deep_sleep = 0;
+		priv->wakeup_dev_required = 0;
+		wake_up_interruptible(&priv->ds_awake_q);
+		break;
+
 	case MACREG_INT_CODE_PS_AWAKE:
 		lbs_deb_cmd("EVENT: ps awake\n");
 		/* handle unexpected PS AWAKE event */
@@ -533,12 +451,12 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
 
 	case MACREG_INT_CODE_MIC_ERR_UNICAST:
 		lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n");
-		handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
+		lbs_send_mic_failureevent(priv, event);
 		break;
 
 	case MACREG_INT_CODE_MIC_ERR_MULTICAST:
 		lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n");
-		handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
+		lbs_send_mic_failureevent(priv, event);
 		break;
 
 	case MACREG_INT_CODE_MIB_CHANGED:
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 893a55ca344a..587b0cb0088d 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -451,10 +451,12 @@ static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
 				CMD_MAC_REG_ACCESS, 0,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
-	pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
+	if (!ret) {
+		pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n",
 				priv->mac_offset, priv->offsetvalue.value);
 
-	ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	}
 	free_page(addr);
 	return ret;
 }
@@ -514,7 +516,8 @@ static ssize_t lbs_wrmac_write(struct file *file,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
 
-	res = count;
+	if (!res)
+		res = count;
 out_unlock:
 	free_page(addr);
 	return res;
@@ -539,10 +542,12 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
 				CMD_BBP_REG_ACCESS, 0,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
-	pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
+	if (!ret) {
+		pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n",
 				priv->bbp_offset, priv->offsetvalue.value);
 
-	ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	}
 	free_page(addr);
 
 	return ret;
@@ -603,7 +608,8 @@ static ssize_t lbs_wrbbp_write(struct file *file,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
 
-	res = count;
+	if (!res)
+		res = count;
 out_unlock:
 	free_page(addr);
 	return res;
@@ -628,10 +634,12 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
 				CMD_RF_REG_ACCESS, 0,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
-	pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
+	if (!ret) {
+		pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n",
 				priv->rf_offset, priv->offsetvalue.value);
 
-	ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+		ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+	}
 	free_page(addr);
 
 	return ret;
@@ -692,7 +700,8 @@ static ssize_t lbs_wrrf_write(struct file *file,
 				CMD_OPTION_WAITFORRSP, 0, &offval);
 	mdelay(10);
 
-	res = count;
+	if (!res)
+		res = count;
 out_unlock:
 	free_page(addr);
 	return res;
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 8b15380ae6e1..709ffcad22ad 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -8,71 +8,46 @@
 
 #include <linux/netdevice.h>
 
-#include "defs.h"
 
-/** Function Prototype Declaration */
 struct lbs_private;
 struct sk_buff;
 struct net_device;
-struct cmd_ctrl_node;
-struct cmd_ds_command;
 
-void lbs_set_mac_control(struct lbs_private *priv);
 
-void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
-
-int lbs_free_cmd_buffer(struct lbs_private *priv);
-
-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);
+/* ethtool.c */
+extern const struct ethtool_ops lbs_ethtool_ops;
 
-int lbs_allocate_cmd_buffer(struct lbs_private *priv);
-int lbs_execute_next_command(struct lbs_private *priv);
-int lbs_process_event(struct lbs_private *priv, u32 event);
-void lbs_queue_event(struct lbs_private *priv, u32 event);
-void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
 
-u32 lbs_fw_index_to_data_rate(u8 index);
-u8 lbs_data_rate_to_fw_index(u32 rate);
-
-/** The proc fs interface */
-int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len);
-void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
-			  int result);
+/* tx.c */
+void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count);
 netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
 				struct net_device *dev);
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
 
+/* rx.c */
 int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
 
-void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
-void lbs_ps_confirm_sleep(struct lbs_private *priv);
-void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
-
-struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
-	struct lbs_private *priv,
-	u8 band,
-	u16 channel);
-
-void lbs_mac_event_disconnected(struct lbs_private *priv);
-
-void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str);
-
-/* persistcfg.c */
-void lbs_persist_config_init(struct net_device *net);
-void lbs_persist_config_remove(struct net_device *net);
 
 /* main.c */
-struct chan_freq_power *lbs_get_region_cfp_table(u8 region,
-	int *cfp_no);
 struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
 void lbs_remove_card(struct lbs_private *priv);
 int lbs_start_card(struct lbs_private *priv);
 void lbs_stop_card(struct lbs_private *priv);
 void lbs_host_to_card_done(struct lbs_private *priv);
 
-int lbs_update_channel(struct lbs_private *priv);
+int lbs_set_mac_address(struct net_device *dev, void *addr);
+void lbs_set_multicast_list(struct net_device *dev);
+
+int lbs_suspend(struct lbs_private *priv);
+void lbs_resume(struct lbs_private *priv);
+
+void lbs_queue_event(struct lbs_private *priv, u32 event);
+void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
+
+int lbs_enter_auto_deep_sleep(struct lbs_private *priv);
+int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
+
+u32 lbs_fw_index_to_data_rate(u8 index);
+u8 lbs_data_rate_to_fw_index(u32 rate);
+
 
 #endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 72f3479a4d70..6b6ea9f7bf5b 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -42,6 +42,7 @@
 #define LBS_DEB_SDIO	0x00400000
 #define LBS_DEB_SYSFS	0x00800000
 #define LBS_DEB_SPI	0x01000000
+#define LBS_DEB_CFG80211 0x02000000
 
 extern unsigned int lbs_debug;
 
@@ -86,6 +87,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
 #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
 #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
 #define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
+#define lbs_deb_cfg80211(fmt, args...)  LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
 
 #define lbs_pr_info(format, args...) \
 	printk(KERN_INFO DRV_NAME": " format, ## args)
@@ -320,7 +322,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
 extern const char lbs_driver_version[];
 extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE];
 
-extern u8 lbs_bg_rates[MAX_RATES];
 
 /** ENUM definition*/
 /** SNRNF_TYPE */
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index d3b69a4b4b5e..6a8d2b291d8c 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,75 +6,11 @@
 #ifndef _LBS_DEV_H_
 #define _LBS_DEV_H_
 
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/ethtool.h>
-#include <linux/debugfs.h>
+#include "mesh.h"
+#include "scan.h"
+#include "assoc.h"
 
-#include "defs.h"
-#include "hostcmd.h"
 
-extern const struct ethtool_ops lbs_ethtool_ops;
-
-#define	MAX_BSSID_PER_CHANNEL		16
-
-#define NR_TX_QUEUE			3
-
-/* For the extended Scan */
-#define MAX_EXTENDED_SCAN_BSSID_LIST    MAX_BSSID_PER_CHANNEL * \
-						MRVDRV_MAX_CHANNEL_SIZE + 1
-
-#define	MAX_REGION_CHANNEL_NUM	2
-
-/** Chan-freq-TxPower mapping table*/
-struct chan_freq_power {
-	/** channel Number		*/
-	u16 channel;
-	/** frequency of this channel	*/
-	u32 freq;
-	/** Max allowed Tx power level	*/
-	u16 maxtxpower;
-	/** TRUE:channel unsupported;  FLASE:supported*/
-	u8 unsupported;
-};
-
-/** region-band mapping table*/
-struct region_channel {
-	/** TRUE if this entry is valid		     */
-	u8 valid;
-	/** region code for US, Japan ...	     */
-	u8 region;
-	/** band B/G/A, used for BAND_CONFIG cmd	     */
-	u8 band;
-	/** Actual No. of elements in the array below */
-	u8 nrcfp;
-	/** chan-freq-txpower mapping table*/
-	struct chan_freq_power *CFP;
-};
-
-struct lbs_802_11_security {
-	u8 WPAenabled;
-	u8 WPA2enabled;
-	u8 wep_enabled;
-	u8 auth_mode;
-	u32 key_mgmt;
-};
-
-/** Current Basic Service Set State Structure */
-struct current_bss_params {
-	/** bssid */
-	u8 bssid[ETH_ALEN];
-	/** ssid */
-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 ssid_len;
-
-	/** band */
-	u8 band;
-	/** channel */
-	u8 channel;
-	/** zero-terminated array of supported data rates */
-	u8 rates[MAX_RATES + 1];
-};
 
 /** sleep_params */
 struct sleep_params {
@@ -86,109 +22,99 @@ struct sleep_params {
 	uint16_t sp_reserved;
 };
 
-/* Mesh statistics */
-struct lbs_mesh_stats {
-	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
-	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
-	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
-	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
-	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
-	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
-	u32	drop_blind;		/* Rx:  Dropped by blinding table */
-	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
-};
 
 /** Private structure for the MV device */
 struct lbs_private {
-	int mesh_open;
-	int mesh_fw_ver;
-	int infra_open;
-	int mesh_autostart_enabled;
 
-	char name[DEV_NAME_LEN];
-
-	void *card;
+	/* Basic networking */
 	struct net_device *dev;
+	u32 connect_status;
+	int infra_open;
+	struct work_struct mcast_work;
+	u32 nr_of_multicastmacaddr;
+	u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+
+	/* CFG80211 */
+	struct wireless_dev *wdev;
 
+	/* Mesh */
 	struct net_device *mesh_dev; /* Virtual device */
+	u32 mesh_connect_status;
+	struct lbs_mesh_stats mstats;
+	int mesh_open;
+	int mesh_fw_ver;
+	int mesh_autostart_enabled;
+	uint16_t mesh_tlv;
+	u8 mesh_ssid[IEEE80211_MAX_SSID_LEN + 1];
+	u8 mesh_ssid_len;
+	struct work_struct sync_channel;
+
+	/* Monitor mode */
 	struct net_device *rtap_net_dev;
+	u32 monitormode;
 
-	struct iw_statistics wstats;
-	struct lbs_mesh_stats mstats;
+	/* Debugfs */
 	struct dentry *debugfs_dir;
 	struct dentry *debugfs_debug;
 	struct dentry *debugfs_files[6];
-
 	struct dentry *events_dir;
 	struct dentry *debugfs_events_files[6];
-
 	struct dentry *regs_dir;
 	struct dentry *debugfs_regs_files[6];
 
+	/* Hardware debugging */
 	u32 mac_offset;
 	u32 bbp_offset;
 	u32 rf_offset;
+	struct lbs_offset_value offsetvalue;
 
-	/* Download sent:
-	   bit0 1/0=data_sent/data_tx_done,
-	   bit1 1/0=cmd_sent/cmd_tx_done,
-	   all other bits reserved 0 */
-	u8 dnld_sent;
-
-	/** thread to service interrupts */
-	struct task_struct *main_thread;
-	wait_queue_head_t waitq;
-	struct workqueue_struct *work_thread;
-
-	struct work_struct mcast_work;
+	/* Power management */
+	u16 psmode;
+	u32 psstate;
+	u8 needtowakeup;
 
-	/** Scanning */
-	struct delayed_work scan_work;
-	struct delayed_work assoc_work;
-	struct work_struct sync_channel;
-	/* remember which channel was scanned last, != 0 if currently scanning */
-	int scan_channel;
-	u8 scan_ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 scan_ssid_len;
+	/* Deep sleep */
+	int is_deep_sleep;
+	int is_auto_deep_sleep_enabled;
+	int wakeup_dev_required;
+	int is_activity_detected;
+	int auto_deep_sleep_timeout; /* in ms */
+	wait_queue_head_t ds_awake_q;
+	struct timer_list auto_deepsleep_timer;
 
-	/** Hardware access */
+	/* Hardware access */
+	void *card;
+	u8 fw_ready;
+	u8 surpriseremoved;
 	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
 	void (*reset_card) (struct lbs_private *priv);
+	int (*enter_deep_sleep) (struct lbs_private *priv);
+	int (*exit_deep_sleep) (struct lbs_private *priv);
+	int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
 
-	/* Wake On LAN */
-	uint32_t wol_criteria;
-	uint8_t wol_gpio;
-	uint8_t wol_gap;
-
-	/** Wlan adapter data structure*/
-	/** STATUS variables */
+	/* Adapter info (from EEPROM) */
 	u32 fwrelease;
 	u32 fwcapinfo;
+	u16 regioncode;
+	u8 current_addr[ETH_ALEN];
 
-	struct mutex lock;
-
-	/* TX packet ready to be sent... */
-	int tx_pending_len;		/* -1 while building packet */
-
-	u8 tx_pending_buf[LBS_UPLD_SIZE];
-	/* protected by hard_start_xmit serialization */
-
-	/** command-related variables */
+	/* Command download */
+	u8 dnld_sent;
+	/* bit0 1/0=data_sent/data_tx_done,
+	   bit1 1/0=cmd_sent/cmd_tx_done,
+	   all other bits reserved 0 */
 	u16 seqnum;
-
 	struct cmd_ctrl_node *cmd_array;
-	/** Current command */
 	struct cmd_ctrl_node *cur_cmd;
-	int cur_cmd_retcode;
-	/** command Queues */
-	/** Free command buffers */
-	struct list_head cmdfreeq;
-	/** Pending command buffers */
-	struct list_head cmdpendingq;
-
+	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 nr_retries;
+	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];
@@ -196,95 +122,76 @@ struct lbs_private {
 	/* Events sent from hardware to driver */
 	struct kfifo *event_fifo;
 
-	/* nickname */
-	u8 nodename[16];
-
-	/** spin locks */
-	spinlock_t driver_lock;
-
-	/** Timers */
-	struct timer_list command_timer;
-	int nr_retries;
-	int cmd_timed_out;
-
-	/** current ssid/bssid related parameters*/
-	struct current_bss_params curbssparams;
-
-	uint16_t mesh_tlv;
-	u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 mesh_ssid_len;
-
-	/* IW_MODE_* */
-	u8 mode;
-
-	/* Scan results list */
-	struct list_head network_list;
-	struct list_head network_free_list;
-	struct bss_descriptor *networks;
-
-	u16 beacon_period;
-	u8 beacon_enable;
-	u8 adhoccreate;
-
-	/** capability Info used in Association, start, join */
-	u16 capability;
-
-	/** MAC address information */
-	u8 current_addr[ETH_ALEN];
-	u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
-	u32 nr_of_multicastmacaddr;
+	/** thread to service interrupts */
+	struct task_struct *main_thread;
+	wait_queue_head_t waitq;
+	struct workqueue_struct *work_thread;
 
-	/** 802.11 statistics */
-//	struct cmd_DS_802_11_GET_STAT wlan802_11Stat;
+	/** Encryption stuff */
+	struct lbs_802_11_security secinfo;
+	struct enc_key wpa_mcast_key;
+	struct enc_key wpa_unicast_key;
+	u8 wpa_ie[MAX_WPA_IE_LEN];
+	u8 wpa_ie_len;
+	u16 wep_tx_keyidx;
+	struct enc_key wep_keys[4];
 
-	uint16_t enablehwauto;
-	uint16_t ratebitmap;
+	/* Wake On LAN */
+	uint32_t wol_criteria;
+	uint8_t wol_gpio;
+	uint8_t wol_gap;
 
+	/* Transmitting */
+	int tx_pending_len;		/* -1 while building packet */
+	u8 tx_pending_buf[LBS_UPLD_SIZE];
+	/* protected by hard_start_xmit serialization */
 	u8 txretrycount;
-
-	/** Tx-related variables (for single packet tx) */
 	struct sk_buff *currenttxskb;
 
-	/** NIC Operation characteristics */
+	/* Locks */
+	struct mutex lock;
+	spinlock_t driver_lock;
+
+	/* NIC/link operation characteristics */
 	u16 mac_control;
-	u32 connect_status;
-	u32 mesh_connect_status;
-	u16 regioncode;
+	u8 radio_on;
+	u8 channel;
 	s16 txpower_cur;
 	s16 txpower_min;
 	s16 txpower_max;
 
-	/** POWER MANAGEMENT AND PnP SUPPORT */
-	u8 surpriseremoved;
-
-	u16 psmode;		/* Wlan802_11PowermodeCAM=disable
-				   Wlan802_11PowermodeMAX_PSP=enable */
-	u32 psstate;
-	u8 needtowakeup;
+	/** Scanning */
+	struct delayed_work scan_work;
+	int scan_channel;
+	/* remember which channel was scanned last, != 0 if currently scanning */
+	u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
+	u8 scan_ssid_len;
 
+	/* Associating */
+	struct delayed_work assoc_work;
+	struct current_bss_params curbssparams;
+	u8 mode;
+	struct list_head network_list;
+	struct list_head network_free_list;
+	struct bss_descriptor *networks;
 	struct assoc_request * pending_assoc_req;
 	struct assoc_request * in_progress_assoc_req;
+	u16 capability;
+	uint16_t enablehwauto;
+	uint16_t ratebitmap;
 
-	/** Encryption parameter */
-	struct lbs_802_11_security secinfo;
-
-	/** WEP keys */
-	struct enc_key wep_keys[4];
-	u16 wep_tx_keyidx;
-
-	/** WPA keys */
-	struct enc_key wpa_mcast_key;
-	struct enc_key wpa_unicast_key;
-
-/*
- * In theory, the IE is limited to the IE length, 255,
- * but in practice 64 bytes are enough.
- */
-#define MAX_WPA_IE_LEN 64
+	/* ADHOC */
+	u16 beacon_period;
+	u8 beacon_enable;
+	u8 adhoccreate;
 
-	/** WPA Information Elements*/
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	u8 wpa_ie_len;
+	/* WEXT */
+	char name[DEV_NAME_LEN];
+	u8 nodename[16];
+	struct iw_statistics wstats;
+	u8 cur_rate;
+#define	MAX_REGION_CHANNEL_NUM	2
+	struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
 
 	/** Requested Signal Strength*/
 	u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
@@ -294,116 +201,8 @@ struct lbs_private {
 	u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
 	u16 nextSNRNF;
 	u16 numSNRNF;
-
-	u8 radio_on;
-
-	/** data rate stuff */
-	u8 cur_rate;
-
-	/** RF calibration data */
-
-#define	MAX_REGION_CHANNEL_NUM	2
-	/** region channel data */
-	struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
-
-	struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
-
-	/** 11D and Domain Regulatory Data */
-	struct lbs_802_11d_domain_reg domainreg;
-	struct parsed_region_chan_11d parsed_region_chan;
-
-	/** FSM variable for 11d support */
-	u32 enable11d;
-
-	/**	MISCELLANEOUS */
-	struct lbs_offset_value offsetvalue;
-
-	u32 monitormode;
-	u8 fw_ready;
 };
 
 extern struct cmd_confirm_sleep confirm_sleep;
 
-/**
- *  @brief Structure used to store information for each beacon/probe response
- */
-struct bss_descriptor {
-	u8 bssid[ETH_ALEN];
-
-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 ssid_len;
-
-	u16 capability;
-	u32 rssi;
-	u32 channel;
-	u16 beaconperiod;
-	__le16 atimwindow;
-
-	/* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
-	u8 mode;
-
-	/* zero-terminated array of supported data rates */
-	u8 rates[MAX_RATES + 1];
-
-	unsigned long last_scanned;
-
-	union ieee_phy_param_set phy;
-	union ieee_ss_param_set ss;
-
-	struct ieee_ie_country_info_full_set countryinfo;
-
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	size_t wpa_ie_len;
-	u8 rsn_ie[MAX_WPA_IE_LEN];
-	size_t rsn_ie_len;
-
-	u8 mesh;
-
-	struct list_head list;
-};
-
-/** Association request
- *
- * Encapsulates all the options that describe a specific assocation request
- * or configuration of the wireless card's radio, mode, and security settings.
- */
-struct assoc_request {
-#define ASSOC_FLAG_SSID			1
-#define ASSOC_FLAG_CHANNEL		2
-#define ASSOC_FLAG_BAND			3
-#define ASSOC_FLAG_MODE			4
-#define ASSOC_FLAG_BSSID		5
-#define ASSOC_FLAG_WEP_KEYS		6
-#define ASSOC_FLAG_WEP_TX_KEYIDX	7
-#define ASSOC_FLAG_WPA_MCAST_KEY	8
-#define ASSOC_FLAG_WPA_UCAST_KEY	9
-#define ASSOC_FLAG_SECINFO		10
-#define ASSOC_FLAG_WPA_IE		11
-	unsigned long flags;
-
-	u8 ssid[IW_ESSID_MAX_SIZE + 1];
-	u8 ssid_len;
-	u8 channel;
-	u8 band;
-	u8 mode;
-	u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
-
-	/** WEP keys */
-	struct enc_key wep_keys[4];
-	u16 wep_tx_keyidx;
-
-	/** WPA keys */
-	struct enc_key wpa_mcast_key;
-	struct enc_key wpa_unicast_key;
-
-	struct lbs_802_11_security secinfo;
-
-	/** WPA Information Elements*/
-	u8 wpa_ie[MAX_WPA_IE_LEN];
-	u8 wpa_ie_len;
-
-	/* BSS to associate with for infrastructure of Ad-Hoc join */
-	struct bss_descriptor bss;
-};
-
 #endif
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 53d56ab83c03..63d020374c2b 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -8,17 +8,8 @@
 #include "dev.h"
 #include "wext.h"
 #include "cmd.h"
+#include "mesh.h"
 
-static const char * mesh_stat_strings[]= {
-			"drop_duplicate_bcast",
-			"drop_ttl_zero",
-			"drop_no_fwd_route",
-			"drop_no_buffers",
-			"fwded_unicast_cnt",
-			"fwded_bcast_cnt",
-			"drop_blind_table",
-			"tx_failed_cnt"
-};
 
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,
 					 struct ethtool_drvinfo *info)
@@ -73,73 +64,6 @@ out:
         return ret;
 }
 
-static void lbs_ethtool_get_stats(struct net_device *dev,
-				  struct ethtool_stats *stats, uint64_t *data)
-{
-	struct lbs_private *priv = dev->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-
-	/* Get Mesh Statistics */
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
-
-	if (ret) {
-		memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
-		return;
-	}
-
-	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
-	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
-	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
-	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
-	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
-	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
-	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
-	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
-
-	data[0] = priv->mstats.fwd_drop_rbt;
-	data[1] = priv->mstats.fwd_drop_ttl;
-	data[2] = priv->mstats.fwd_drop_noroute;
-	data[3] = priv->mstats.fwd_drop_nobuf;
-	data[4] = priv->mstats.fwd_unicast_cnt;
-	data[5] = priv->mstats.fwd_bcast_cnt;
-	data[6] = priv->mstats.drop_blind;
-	data[7] = priv->mstats.tx_failed_cnt;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
-static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
-		return MESH_STATS_NUM;
-
-	return -EOPNOTSUPP;
-}
-
-static void lbs_ethtool_get_strings(struct net_device *dev,
-				    uint32_t stringset, uint8_t *s)
-{
-	int i;
-
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-
-	switch (stringset) {
-        case ETH_SS_STATS:
-		for (i=0; i < MESH_STATS_NUM; i++) {
-			memcpy(s + i * ETH_GSTRING_LEN,
-					mesh_stat_strings[i],
-					ETH_GSTRING_LEN);
-		}
-		break;
-        }
-	lbs_deb_enter(LBS_DEB_ETHTOOL);
-}
-
 static void lbs_ethtool_get_wol(struct net_device *dev,
 				struct ethtool_wolinfo *wol)
 {
@@ -190,9 +114,9 @@ const struct ethtool_ops lbs_ethtool_ops = {
 	.get_drvinfo = lbs_ethtool_get_drvinfo,
 	.get_eeprom =  lbs_ethtool_get_eeprom,
 	.get_eeprom_len = lbs_ethtool_get_eeprom_len,
-	.get_sset_count = lbs_ethtool_get_sset_count,
-	.get_ethtool_stats = lbs_ethtool_get_stats,
-	.get_strings = lbs_ethtool_get_strings,
+	.get_sset_count = lbs_mesh_ethtool_get_sset_count,
+	.get_ethtool_stats = lbs_mesh_ethtool_get_stats,
+	.get_strings = lbs_mesh_ethtool_get_strings,
 	.get_wol = lbs_ethtool_get_wol,
 	.set_wol = lbs_ethtool_set_wol,
 };
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index fe8f0cb737bc..3809c0b49464 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -1,201 +1,190 @@
 /**
-  * This file contains definitions of WLAN commands.
+  * This file function prototypes, data structure
+  * and  definitions for all the host/station commands
   */
 
 #ifndef _LBS_HOST_H_
 #define _LBS_HOST_H_
 
-/** PUBLIC DEFINITIONS */
-#define DEFAULT_AD_HOC_CHANNEL			6
-#define	DEFAULT_AD_HOC_CHANNEL_A		36
+#include "types.h"
+#include "defs.h"
 
-#define CMD_OPTION_WAITFORRSP			0x0002
+#define DEFAULT_AD_HOC_CHANNEL                  6
+
+#define CMD_OPTION_WAITFORRSP                   0x0002
 
 /** Host command IDs */
 
 /* Return command are almost always the same as the host command, but with
  * bit 15 set high.  There are a few exceptions, though...
  */
-#define CMD_RET(cmd)			(0x8000 | cmd)
+#define CMD_RET(cmd)                            (0x8000 | cmd)
 
 /* Return command convention exceptions: */
-#define CMD_RET_802_11_ASSOCIATE		0x8012
+#define CMD_RET_802_11_ASSOCIATE                0x8012
 
 /* Command codes */
-#define CMD_GET_HW_SPEC				0x0003
-#define	CMD_EEPROM_UPDATE			0x0004
-#define CMD_802_11_RESET			0x0005
-#define	CMD_802_11_SCAN				0x0006
-#define CMD_802_11_GET_LOG			0x000b
-#define CMD_MAC_MULTICAST_ADR			0x0010
-#define CMD_802_11_AUTHENTICATE			0x0011
-#define CMD_802_11_EEPROM_ACCESS		0x0059
-#define CMD_802_11_ASSOCIATE			0x0050
-#define CMD_802_11_SET_WEP			0x0013
-#define CMD_802_11_GET_STAT			0x0014
-#define CMD_802_3_GET_STAT			0x0015
-#define CMD_802_11_SNMP_MIB			0x0016
-#define CMD_MAC_REG_MAP				0x0017
-#define CMD_BBP_REG_MAP				0x0018
-#define CMD_MAC_REG_ACCESS			0x0019
-#define CMD_BBP_REG_ACCESS			0x001a
-#define CMD_RF_REG_ACCESS			0x001b
-#define CMD_802_11_RADIO_CONTROL		0x001c
-#define CMD_802_11_RF_CHANNEL			0x001d
-#define CMD_802_11_RF_TX_POWER			0x001e
-#define CMD_802_11_RSSI				0x001f
-#define CMD_802_11_RF_ANTENNA			0x0020
-#define CMD_802_11_PS_MODE			0x0021
-#define CMD_802_11_DATA_RATE			0x0022
-#define CMD_RF_REG_MAP				0x0023
-#define CMD_802_11_DEAUTHENTICATE		0x0024
-#define CMD_802_11_REASSOCIATE			0x0025
-#define CMD_MAC_CONTROL				0x0028
-#define CMD_802_11_AD_HOC_START			0x002b
-#define CMD_802_11_AD_HOC_JOIN			0x002c
-#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS	0x002e
-#define CMD_802_11_ENABLE_RSN			0x002f
-#define CMD_802_11_SET_AFC			0x003c
-#define CMD_802_11_GET_AFC			0x003d
-#define CMD_802_11_AD_HOC_STOP			0x0040
-#define CMD_802_11_HOST_SLEEP_CFG		0x0043
-#define CMD_802_11_WAKEUP_CONFIRM		0x0044
-#define CMD_802_11_HOST_SLEEP_ACTIVATE		0x0045
-#define CMD_802_11_BEACON_STOP			0x0049
-#define CMD_802_11_MAC_ADDRESS			0x004d
-#define CMD_802_11_LED_GPIO_CTRL		0x004e
-#define CMD_802_11_EEPROM_ACCESS		0x0059
-#define CMD_802_11_BAND_CONFIG			0x0058
-#define CMD_GSPI_BUS_CONFIG			0x005a
-#define CMD_802_11D_DOMAIN_INFO			0x005b
-#define CMD_802_11_KEY_MATERIAL			0x005e
-#define CMD_802_11_SLEEP_PARAMS			0x0066
-#define CMD_802_11_INACTIVITY_TIMEOUT		0x0067
-#define CMD_802_11_SLEEP_PERIOD			0x0068
-#define CMD_802_11_TPC_CFG			0x0072
-#define CMD_802_11_PA_CFG			0x0073
-#define CMD_802_11_FW_WAKE_METHOD		0x0074
-#define CMD_802_11_SUBSCRIBE_EVENT		0x0075
-#define CMD_802_11_RATE_ADAPT_RATESET		0x0076
-#define CMD_802_11_TX_RATE_QUERY		0x007f
-#define	CMD_GET_TSF				0x0080
-#define CMD_BT_ACCESS				0x0087
-#define CMD_FWT_ACCESS				0x0095
-#define CMD_802_11_MONITOR_MODE			0x0098
-#define CMD_MESH_ACCESS				0x009b
-#define CMD_MESH_CONFIG_OLD			0x00a3
-#define CMD_MESH_CONFIG				0x00ac
-#define	CMD_SET_BOOT2_VER			0x00a5
-#define	CMD_FUNC_INIT				0x00a9
-#define	CMD_FUNC_SHUTDOWN			0x00aa
-#define CMD_802_11_BEACON_CTRL			0x00b0
+#define CMD_GET_HW_SPEC                         0x0003
+#define CMD_EEPROM_UPDATE                       0x0004
+#define CMD_802_11_RESET                        0x0005
+#define CMD_802_11_SCAN                         0x0006
+#define CMD_802_11_GET_LOG                      0x000b
+#define CMD_MAC_MULTICAST_ADR                   0x0010
+#define CMD_802_11_AUTHENTICATE                 0x0011
+#define CMD_802_11_EEPROM_ACCESS                0x0059
+#define CMD_802_11_ASSOCIATE                    0x0050
+#define CMD_802_11_SET_WEP                      0x0013
+#define CMD_802_11_GET_STAT                     0x0014
+#define CMD_802_3_GET_STAT                      0x0015
+#define CMD_802_11_SNMP_MIB                     0x0016
+#define CMD_MAC_REG_MAP                         0x0017
+#define CMD_BBP_REG_MAP                         0x0018
+#define CMD_MAC_REG_ACCESS                      0x0019
+#define CMD_BBP_REG_ACCESS                      0x001a
+#define CMD_RF_REG_ACCESS                       0x001b
+#define CMD_802_11_RADIO_CONTROL                0x001c
+#define CMD_802_11_RF_CHANNEL                   0x001d
+#define CMD_802_11_RF_TX_POWER                  0x001e
+#define CMD_802_11_RSSI                         0x001f
+#define CMD_802_11_RF_ANTENNA                   0x0020
+#define CMD_802_11_PS_MODE                      0x0021
+#define CMD_802_11_DATA_RATE                    0x0022
+#define CMD_RF_REG_MAP                          0x0023
+#define CMD_802_11_DEAUTHENTICATE               0x0024
+#define CMD_802_11_REASSOCIATE                  0x0025
+#define CMD_MAC_CONTROL                         0x0028
+#define CMD_802_11_AD_HOC_START                 0x002b
+#define CMD_802_11_AD_HOC_JOIN                  0x002c
+#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS       0x002e
+#define CMD_802_11_ENABLE_RSN                   0x002f
+#define CMD_802_11_SET_AFC                      0x003c
+#define CMD_802_11_GET_AFC                      0x003d
+#define CMD_802_11_DEEP_SLEEP                   0x003e
+#define CMD_802_11_AD_HOC_STOP                  0x0040
+#define CMD_802_11_HOST_SLEEP_CFG               0x0043
+#define CMD_802_11_WAKEUP_CONFIRM               0x0044
+#define CMD_802_11_HOST_SLEEP_ACTIVATE          0x0045
+#define CMD_802_11_BEACON_STOP                  0x0049
+#define CMD_802_11_MAC_ADDRESS                  0x004d
+#define CMD_802_11_LED_GPIO_CTRL                0x004e
+#define CMD_802_11_EEPROM_ACCESS                0x0059
+#define CMD_802_11_BAND_CONFIG                  0x0058
+#define CMD_GSPI_BUS_CONFIG                     0x005a
+#define CMD_802_11D_DOMAIN_INFO                 0x005b
+#define CMD_802_11_KEY_MATERIAL                 0x005e
+#define CMD_802_11_SLEEP_PARAMS                 0x0066
+#define CMD_802_11_INACTIVITY_TIMEOUT           0x0067
+#define CMD_802_11_SLEEP_PERIOD                 0x0068
+#define CMD_802_11_TPC_CFG                      0x0072
+#define CMD_802_11_PA_CFG                       0x0073
+#define CMD_802_11_FW_WAKE_METHOD               0x0074
+#define CMD_802_11_SUBSCRIBE_EVENT              0x0075
+#define CMD_802_11_RATE_ADAPT_RATESET           0x0076
+#define CMD_802_11_TX_RATE_QUERY                0x007f
+#define CMD_GET_TSF                             0x0080
+#define CMD_BT_ACCESS                           0x0087
+#define CMD_FWT_ACCESS                          0x0095
+#define CMD_802_11_MONITOR_MODE                 0x0098
+#define CMD_MESH_ACCESS                         0x009b
+#define CMD_MESH_CONFIG_OLD                     0x00a3
+#define CMD_MESH_CONFIG                         0x00ac
+#define CMD_SET_BOOT2_VER                       0x00a5
+#define CMD_FUNC_INIT                           0x00a9
+#define CMD_FUNC_SHUTDOWN                       0x00aa
+#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 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 CMD_ENABLE_RSN			0x0001
-#define CMD_DISABLE_RSN			0x0000
+#define CMD_ENABLE_RSN                          0x0001
+#define CMD_DISABLE_RSN                         0x0000
 
-#define CMD_ACT_GET			0x0000
-#define CMD_ACT_SET			0x0001
-#define CMD_ACT_GET_AES			0x0002
-#define CMD_ACT_SET_AES			0x0003
-#define CMD_ACT_REMOVE_AES		0x0004
+#define CMD_ACT_GET                             0x0000
+#define CMD_ACT_SET                             0x0001
 
 /* Define action or option for CMD_802_11_SET_WEP */
-#define CMD_ACT_ADD			0x0002
-#define CMD_ACT_REMOVE			0x0004
-#define CMD_ACT_USE_DEFAULT		0x0008
-
-#define CMD_TYPE_WEP_40_BIT		0x01
-#define CMD_TYPE_WEP_104_BIT		0x02
+#define CMD_ACT_ADD                             0x0002
+#define CMD_ACT_REMOVE                          0x0004
 
-#define CMD_NUM_OF_WEP_KEYS		4
+#define CMD_TYPE_WEP_40_BIT                     0x01
+#define CMD_TYPE_WEP_104_BIT                    0x02
 
-#define CMD_WEP_KEY_INDEX_MASK		0x3fff
+#define CMD_NUM_OF_WEP_KEYS                     4
 
-/* Define action or option for CMD_802_11_RESET */
-#define CMD_ACT_HALT			0x0003
+#define CMD_WEP_KEY_INDEX_MASK                  0x3fff
 
 /* Define action or option for CMD_802_11_SCAN */
-#define CMD_BSS_TYPE_BSS		0x0001
-#define CMD_BSS_TYPE_IBSS		0x0002
-#define CMD_BSS_TYPE_ANY		0x0003
+#define CMD_BSS_TYPE_BSS                        0x0001
+#define CMD_BSS_TYPE_IBSS                       0x0002
+#define CMD_BSS_TYPE_ANY                        0x0003
 
 /* Define action or option for CMD_802_11_SCAN */
-#define CMD_SCAN_TYPE_ACTIVE		0x0000
-#define CMD_SCAN_TYPE_PASSIVE		0x0001
+#define CMD_SCAN_TYPE_ACTIVE                    0x0000
+#define CMD_SCAN_TYPE_PASSIVE                   0x0001
 
-#define CMD_SCAN_RADIO_TYPE_BG		0
+#define CMD_SCAN_RADIO_TYPE_BG                  0
 
-#define	CMD_SCAN_PROBE_DELAY_TIME	0
+#define CMD_SCAN_PROBE_DELAY_TIME               0
 
 /* Define action or option for CMD_MAC_CONTROL */
-#define CMD_ACT_MAC_RX_ON			0x0001
-#define CMD_ACT_MAC_TX_ON			0x0002
-#define CMD_ACT_MAC_LOOPBACK_ON			0x0004
-#define CMD_ACT_MAC_WEP_ENABLE			0x0008
-#define CMD_ACT_MAC_INT_ENABLE			0x0010
-#define CMD_ACT_MAC_MULTICAST_ENABLE		0x0020
-#define CMD_ACT_MAC_BROADCAST_ENABLE		0x0040
-#define CMD_ACT_MAC_PROMISCUOUS_ENABLE		0x0080
-#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE	0x0100
-#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE	0x0400
+#define CMD_ACT_MAC_RX_ON                       0x0001
+#define CMD_ACT_MAC_TX_ON                       0x0002
+#define CMD_ACT_MAC_LOOPBACK_ON                 0x0004
+#define CMD_ACT_MAC_WEP_ENABLE                  0x0008
+#define CMD_ACT_MAC_INT_ENABLE                  0x0010
+#define CMD_ACT_MAC_MULTICAST_ENABLE            0x0020
+#define CMD_ACT_MAC_BROADCAST_ENABLE            0x0040
+#define CMD_ACT_MAC_PROMISCUOUS_ENABLE          0x0080
+#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE        0x0100
+#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE    0x0400
 
 /* Event flags for CMD_802_11_SUBSCRIBE_EVENT */
-#define CMD_SUBSCRIBE_RSSI_LOW		0x0001
-#define CMD_SUBSCRIBE_SNR_LOW		0x0002
-#define CMD_SUBSCRIBE_FAILCOUNT		0x0004
-#define CMD_SUBSCRIBE_BCNMISS		0x0008
-#define CMD_SUBSCRIBE_RSSI_HIGH		0x0010
-#define CMD_SUBSCRIBE_SNR_HIGH		0x0020
+#define CMD_SUBSCRIBE_RSSI_LOW                  0x0001
+#define CMD_SUBSCRIBE_SNR_LOW                   0x0002
+#define CMD_SUBSCRIBE_FAILCOUNT                 0x0004
+#define CMD_SUBSCRIBE_BCNMISS                   0x0008
+#define CMD_SUBSCRIBE_RSSI_HIGH                 0x0010
+#define CMD_SUBSCRIBE_SNR_HIGH                  0x0020
 
-#define RADIO_PREAMBLE_LONG	0x00
-#define RADIO_PREAMBLE_SHORT	0x02
-#define RADIO_PREAMBLE_AUTO	0x04
+#define RADIO_PREAMBLE_LONG                     0x00
+#define RADIO_PREAMBLE_SHORT                    0x02
+#define RADIO_PREAMBLE_AUTO                     0x04
 
 /* Define action or option for CMD_802_11_RF_CHANNEL */
-#define CMD_OPT_802_11_RF_CHANNEL_GET	0x00
-#define CMD_OPT_802_11_RF_CHANNEL_SET	0x01
+#define CMD_OPT_802_11_RF_CHANNEL_GET           0x00
+#define CMD_OPT_802_11_RF_CHANNEL_SET           0x01
 
 /* Define action or option for CMD_802_11_DATA_RATE */
-#define CMD_ACT_SET_TX_AUTO		0x0000
-#define CMD_ACT_SET_TX_FIX_RATE		0x0001
-#define CMD_ACT_GET_TX_RATE		0x0002
-
-#define CMD_ACT_SET_RX			0x0001
-#define	CMD_ACT_SET_TX			0x0002
-#define CMD_ACT_SET_BOTH		0x0003
-#define	CMD_ACT_GET_RX			0x0004
-#define CMD_ACT_GET_TX			0x0008
-#define	CMD_ACT_GET_BOTH		0x000c
+#define CMD_ACT_SET_TX_AUTO                     0x0000
+#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
+#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
-#define CMD_WAKE_METHOD_GPIO		0x0002
+#define CMD_WAKE_METHOD_UNCHANGED               0x0000
+#define CMD_WAKE_METHOD_COMMAND_INT             0x0001
+#define CMD_WAKE_METHOD_GPIO                    0x0002
 
 /* Object IDs for CMD_802_11_SNMP_MIB */
-#define SNMP_MIB_OID_BSS_TYPE		0x0000
-#define SNMP_MIB_OID_OP_RATE_SET	0x0001
-#define SNMP_MIB_OID_BEACON_PERIOD	0x0002  /* Reserved on v9+ */
-#define SNMP_MIB_OID_DTIM_PERIOD	0x0003  /* Reserved on v9+ */
-#define SNMP_MIB_OID_ASSOC_TIMEOUT	0x0004  /* Reserved on v9+ */
-#define SNMP_MIB_OID_RTS_THRESHOLD	0x0005
-#define SNMP_MIB_OID_SHORT_RETRY_LIMIT	0x0006
-#define SNMP_MIB_OID_LONG_RETRY_LIMIT	0x0007
-#define SNMP_MIB_OID_FRAG_THRESHOLD	0x0008
-#define SNMP_MIB_OID_11D_ENABLE		0x0009
-#define SNMP_MIB_OID_11H_ENABLE		0x000A
+#define SNMP_MIB_OID_BSS_TYPE                   0x0000
+#define SNMP_MIB_OID_OP_RATE_SET                0x0001
+#define SNMP_MIB_OID_BEACON_PERIOD              0x0002  /* Reserved on v9+ */
+#define SNMP_MIB_OID_DTIM_PERIOD                0x0003  /* Reserved on v9+ */
+#define SNMP_MIB_OID_ASSOC_TIMEOUT              0x0004  /* Reserved on v9+ */
+#define SNMP_MIB_OID_RTS_THRESHOLD              0x0005
+#define SNMP_MIB_OID_SHORT_RETRY_LIMIT          0x0006
+#define SNMP_MIB_OID_LONG_RETRY_LIMIT           0x0007
+#define SNMP_MIB_OID_FRAG_THRESHOLD             0x0008
+#define SNMP_MIB_OID_11D_ENABLE                 0x0009
+#define SNMP_MIB_OID_11H_ENABLE                 0x000A
 
 /* Define action or option for CMD_BT_ACCESS */
 enum cmd_bt_access_opts {
@@ -302,4 +291,672 @@ enum cmd_mesh_config_types {
 #define MACREG_INT_CODE_MESH_AUTO_STARTED	35
 #define MACREG_INT_CODE_FIRMWARE_READY		48
 
+
+/* 802.11-related definitions */
+
+/* TxPD descriptor */
+struct txpd {
+	/* union to cope up with later FW revisions */
+	union {
+		/* Current Tx packet status */
+		__le32 tx_status;
+		struct {
+			/* BSS type: client, AP, etc. */
+			u8 bss_type;
+			/* BSS number */
+			u8 bss_num;
+			/* Reserved */
+			__le16 reserved;
+		} bss;
+	} u;
+	/* Tx control */
+	__le32 tx_control;
+	__le32 tx_packet_location;
+	/* Tx packet length */
+	__le16 tx_packet_length;
+	/* First 2 byte of destination MAC address */
+	u8 tx_dest_addr_high[2];
+	/* Last 4 byte of destination MAC address */
+	u8 tx_dest_addr_low[4];
+	/* Pkt Priority */
+	u8 priority;
+	/* Pkt Trasnit Power control */
+	u8 powermgmt;
+	/* Amount of time the packet has been queued (units = 2ms) */
+	u8 pktdelay_2ms;
+	/* reserved */
+	u8 reserved1;
+} __attribute__ ((packed));
+
+/* RxPD Descriptor */
+struct rxpd {
+	/* union to cope up with later FW revisions */
+	union {
+		/* Current Rx packet status */
+		__le16 status;
+		struct {
+			/* BSS type: client, AP, etc. */
+			u8 bss_type;
+			/* BSS number */
+			u8 bss_num;
+		} __attribute__ ((packed)) bss;
+	} __attribute__ ((packed)) u;
+
+	/* SNR */
+	u8 snr;
+
+	/* Tx control */
+	u8 rx_control;
+
+	/* Pkt length */
+	__le16 pkt_len;
+
+	/* Noise Floor */
+	u8 nf;
+
+	/* Rx Packet Rate */
+	u8 rx_rate;
+
+	/* Pkt addr */
+	__le32 pkt_ptr;
+
+	/* Next Rx RxPD addr */
+	__le32 next_rxpd_ptr;
+
+	/* Pkt Priority */
+	u8 priority;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+struct cmd_header {
+	__le16 command;
+	__le16 size;
+	__le16 seqnum;
+	__le16 result;
+} __attribute__ ((packed));
+
+/* Generic structure to hold all key types. */
+struct enc_key {
+	u16 len;
+	u16 flags;  /* KEY_INFO_* from defs.h */
+	u16 type; /* KEY_TYPE_* from defs.h */
+	u8 key[32];
+};
+
+/* lbs_offset_value */
+struct lbs_offset_value {
+	u32 offset;
+	u32 value;
+} __attribute__ ((packed));
+
+/*
+ * Define data structure for CMD_GET_HW_SPEC
+ * This structure defines the response for the GET_HW_SPEC command
+ */
+struct cmd_ds_get_hw_spec {
+	struct cmd_header hdr;
+
+	/* HW Interface version number */
+	__le16 hwifversion;
+	/* HW version number */
+	__le16 version;
+	/* Max number of TxPD FW can handle */
+	__le16 nr_txpd;
+	/* Max no of Multicast address */
+	__le16 nr_mcast_adr;
+	/* MAC address */
+	u8 permanentaddr[6];
+
+	/* region Code */
+	__le16 regioncode;
+
+	/* Number of antenna used */
+	__le16 nr_antenna;
+
+	/* FW release number, example 0x01030304 = 2.3.4p1 */
+	__le32 fwrelease;
+
+	/* Base Address of TxPD queue */
+	__le32 wcb_base;
+	/* Read Pointer of RxPd queue */
+	__le32 rxpd_rdptr;
+
+	/* Write Pointer of RxPd queue */
+	__le32 rxpd_wrptr;
+
+	/*FW/HW capability */
+	__le32 fwcapinfo;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_subscribe_event {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 events;
+
+	/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
+	 * number of TLVs. From the v5.1 manual, those TLVs would add up to
+	 * 40 bytes. However, future firmware might add additional TLVs, so I
+	 * bump this up a bit.
+	 */
+	uint8_t tlv[128];
+} __attribute__ ((packed));
+
+/*
+ * This scan handle Country Information IE(802.11d compliant)
+ * Define data structure for CMD_802_11_SCAN
+ */
+struct cmd_ds_802_11_scan {
+	struct cmd_header hdr;
+
+	uint8_t bsstype;
+	uint8_t bssid[ETH_ALEN];
+	uint8_t tlvbuffer[0];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_scan_rsp {
+	struct cmd_header hdr;
+
+	__le16 bssdescriptsize;
+	uint8_t nr_sets;
+	uint8_t bssdesc_and_tlvbuffer[0];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_get_log {
+	struct cmd_header hdr;
+
+	__le32 mcasttxframe;
+	__le32 failed;
+	__le32 retry;
+	__le32 multiretry;
+	__le32 framedup;
+	__le32 rtssuccess;
+	__le32 rtsfailure;
+	__le32 ackfailure;
+	__le32 rxfrag;
+	__le32 mcastrxframe;
+	__le32 fcserror;
+	__le32 txframe;
+	__le32 wepundecryptable;
+} __attribute__ ((packed));
+
+struct cmd_ds_mac_control {
+	struct cmd_header hdr;
+	__le16 action;
+	u16 reserved;
+} __attribute__ ((packed));
+
+struct cmd_ds_mac_multicast_adr {
+	struct cmd_header hdr;
+	__le16 action;
+	__le16 nr_of_adrs;
+	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_authenticate {
+	struct cmd_header hdr;
+
+	u8 bssid[ETH_ALEN];
+	u8 authtype;
+	u8 reserved[10];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_deauthenticate {
+	struct cmd_header hdr;
+
+	u8 macaddr[ETH_ALEN];
+	__le16 reasoncode;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_associate {
+	struct cmd_header hdr;
+
+	u8 bssid[6];
+	__le16 capability;
+	__le16 listeninterval;
+	__le16 bcnperiod;
+	u8 dtimperiod;
+	u8 iebuf[512];    /* Enough for required and most optional IEs */
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_associate_response {
+	struct cmd_header hdr;
+
+	__le16 capability;
+	__le16 statuscode;
+	__le16 aid;
+	u8 iebuf[512];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_set_wep {
+	struct cmd_header hdr;
+
+	/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
+	__le16 action;
+
+	/* key Index selected for Tx */
+	__le16 keyindex;
+
+	/* 40, 128bit or TXWEP */
+	uint8_t keytype[4];
+	uint8_t keymaterial[4][16];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_snmp_mib {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 oid;
+	__le16 bufsize;
+	u8 value[128];
+} __attribute__ ((packed));
+
+struct cmd_ds_mac_reg_access {
+	__le16 action;
+	__le16 offset;
+	__le32 value;
+} __attribute__ ((packed));
+
+struct cmd_ds_bbp_reg_access {
+	__le16 action;
+	__le16 offset;
+	u8 value;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+struct cmd_ds_rf_reg_access {
+	__le16 action;
+	__le16 offset;
+	u8 value;
+	u8 reserved[3];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_radio_control {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 control;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_beacon_control {
+	__le16 action;
+	__le16 beacon_enable;
+	__le16 beacon_period;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_sleep_params {
+	struct cmd_header hdr;
+
+	/* ACT_GET/ACT_SET */
+	__le16 action;
+
+	/* Sleep clock error in ppm */
+	__le16 error;
+
+	/* Wakeup offset in usec */
+	__le16 offset;
+
+	/* Clock stabilization time in usec */
+	__le16 stabletime;
+
+	/* control periodic calibration */
+	uint8_t calcontrol;
+
+	/* control the use of external sleep clock */
+	uint8_t externalsleepclk;
+
+	/* reserved field, should be set to zero */
+	__le16 reserved;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_rf_channel {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 channel;
+	__le16 rftype;      /* unused */
+	__le16 reserved;    /* unused */
+	u8 channellist[32]; /* unused */
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_rssi {
+	/* weighting factor */
+	__le16 N;
+
+	__le16 reserved_0;
+	__le16 reserved_1;
+	__le16 reserved_2;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_rssi_rsp {
+	__le16 SNR;
+	__le16 noisefloor;
+	__le16 avgSNR;
+	__le16 avgnoisefloor;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_mac_address {
+	struct cmd_header hdr;
+
+	__le16 action;
+	u8 macadd[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_rf_tx_power {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 curlevel;
+	s8 maxlevel;
+	s8 minlevel;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_monitor_mode {
+	__le16 action;
+	__le16 mode;
+} __attribute__ ((packed));
+
+struct cmd_ds_set_boot2_ver {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 version;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_fw_wake_method {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 method;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_ps_mode {
+	__le16 action;
+	__le16 nullpktinterval;
+	__le16 multipledtim;
+	__le16 reserved;
+	__le16 locallisteninterval;
+} __attribute__ ((packed));
+
+struct cmd_confirm_sleep {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 nullpktinterval;
+	__le16 multipledtim;
+	__le16 reserved;
+	__le16 locallisteninterval;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_data_rate {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 reserved;
+	u8 rates[MAX_RATES];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_rate_adapt_rateset {
+	struct cmd_header hdr;
+	__le16 action;
+	__le16 enablehwauto;
+	__le16 bitmap;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_ad_hoc_start {
+	struct cmd_header hdr;
+
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	u8 bsstype;
+	__le16 beaconperiod;
+	u8 dtimperiod;   /* Reserved on v9 and later */
+	struct ieee_ie_ibss_param_set ibss;
+	u8 reserved1[4];
+	struct ieee_ie_ds_param_set ds;
+	u8 reserved2[4];
+	__le16 probedelay;  /* Reserved on v9 and later */
+	__le16 capability;
+	u8 rates[MAX_RATES];
+	u8 tlv_memory_size_pad[100];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_ad_hoc_result {
+	struct cmd_header hdr;
+
+	u8 pad[3];
+	u8 bssid[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct adhoc_bssdesc {
+	u8 bssid[ETH_ALEN];
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
+	u8 type;
+	__le16 beaconperiod;
+	u8 dtimperiod;
+	__le64 timestamp;
+	__le64 localtime;
+	struct ieee_ie_ds_param_set ds;
+	u8 reserved1[4];
+	struct ieee_ie_ibss_param_set ibss;
+	u8 reserved2[4];
+	__le16 capability;
+	u8 rates[MAX_RATES];
+
+	/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
+	 * Adhoc join command and will cause a binary layout mismatch with
+	 * the firmware
+	 */
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_ad_hoc_join {
+	struct cmd_header hdr;
+
+	struct adhoc_bssdesc bss;
+	__le16 failtimeout;   /* Reserved on v9 and later */
+	__le16 probedelay;    /* Reserved on v9 and later */
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_ad_hoc_stop {
+	struct cmd_header hdr;
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_enable_rsn {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 enable;
+} __attribute__ ((packed));
+
+struct MrvlIEtype_keyParamSet {
+	/* type ID */
+	__le16 type;
+
+	/* length of Payload */
+	__le16 length;
+
+	/* type of key: WEP=0, TKIP=1, AES=2 */
+	__le16 keytypeid;
+
+	/* key control Info specific to a keytypeid */
+	__le16 keyinfo;
+
+	/* length of key */
+	__le16 keylen;
+
+	/* key material of size keylen */
+	u8 key[32];
+} __attribute__ ((packed));
+
+#define MAX_WOL_RULES 		16
+
+struct host_wol_rule {
+	uint8_t rule_no;
+	uint8_t rule_ops;
+	__le16 sig_offset;
+	__le16 sig_length;
+	__le16 reserve;
+	__be32 sig_mask;
+	__be32 signature;
+} __attribute__ ((packed));
+
+struct wol_config {
+	uint8_t action;
+	uint8_t pattern;
+	uint8_t no_rules_in_cmd;
+	uint8_t result;
+	struct host_wol_rule rule[MAX_WOL_RULES];
+} __attribute__ ((packed));
+
+struct cmd_ds_host_sleep {
+	struct cmd_header hdr;
+	__le32 criteria;
+	uint8_t gpio;
+	uint16_t gap;
+	struct wol_config wol_conf;
+} __attribute__ ((packed));
+
+
+
+struct cmd_ds_802_11_key_material {
+	struct cmd_header hdr;
+
+	__le16 action;
+	struct MrvlIEtype_keyParamSet keyParamSet[2];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_eeprom_access {
+	struct cmd_header hdr;
+	__le16 action;
+	__le16 offset;
+	__le16 len;
+	/* firmware says it returns a maximum of 20 bytes */
+#define LBS_EEPROM_READ_LEN 20
+	u8 value[LBS_EEPROM_READ_LEN];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_tpc_cfg {
+	struct cmd_header hdr;
+
+	__le16 action;
+	uint8_t enable;
+	int8_t P0;
+	int8_t P1;
+	int8_t P2;
+	uint8_t usesnr;
+} __attribute__ ((packed));
+
+
+struct cmd_ds_802_11_pa_cfg {
+	struct cmd_header hdr;
+
+	__le16 action;
+	uint8_t enable;
+	int8_t P0;
+	int8_t P1;
+	int8_t P2;
+} __attribute__ ((packed));
+
+
+struct cmd_ds_802_11_led_ctrl {
+	__le16 action;
+	__le16 numled;
+	u8 data[256];
+} __attribute__ ((packed));
+
+struct cmd_ds_802_11_afc {
+	__le16 afc_auto;
+	union {
+		struct {
+			__le16 threshold;
+			__le16 period;
+		};
+		struct {
+			__le16 timing_offset; /* signed */
+			__le16 carrier_offset; /* signed */
+		};
+	};
+} __attribute__ ((packed));
+
+struct cmd_tx_rate_query {
+	__le16 txrate;
+} __attribute__ ((packed));
+
+struct cmd_ds_get_tsf {
+	__le64 tsfvalue;
+} __attribute__ ((packed));
+
+struct cmd_ds_bt_access {
+	__le16 action;
+	__le32 id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct cmd_ds_fwt_access {
+	__le16 action;
+	__le32 id;
+	u8 valid;
+	u8 da[ETH_ALEN];
+	u8 dir;
+	u8 ra[ETH_ALEN];
+	__le32 ssn;
+	__le32 dsn;
+	__le32 metric;
+	u8 rate;
+	u8 hopcount;
+	u8 ttl;
+	__le32 expiration;
+	u8 sleepmode;
+	__le32 snr;
+	__le32 references;
+	u8 prec[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct cmd_ds_mesh_config {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le16 channel;
+	__le16 type;
+	__le16 length;
+	u8 data[128];	/* last position reserved */
+} __attribute__ ((packed));
+
+struct cmd_ds_mesh_access {
+	struct cmd_header hdr;
+
+	__le16 action;
+	__le32 data[32];	/* last position reserved */
+} __attribute__ ((packed));
+
+/* 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_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;
+} __attribute__ ((packed));
+
 #endif
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
deleted file mode 100644
index c8a1998d4744..000000000000
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * This file contains the function prototypes, data structure
- * and defines for all the host/station commands
- */
-#ifndef _LBS_HOSTCMD_H
-#define _LBS_HOSTCMD_H
-
-#include <linux/wireless.h>
-#include "11d.h"
-#include "types.h"
-
-/* 802.11-related definitions */
-
-/* TxPD descriptor */
-struct txpd {
-	/* union to cope up with later FW revisions */
-	union {
-		/* Current Tx packet status */
-		__le32 tx_status;
-		struct {
-			/* BSS type: client, AP, etc. */
-			u8 bss_type;
-			/* BSS number */
-			u8 bss_num;
-			/* Reserved */
-			__le16 reserved;
-		} bss;
-	} u;
-	/* Tx control */
-	__le32 tx_control;
-	__le32 tx_packet_location;
-	/* Tx packet length */
-	__le16 tx_packet_length;
-	/* First 2 byte of destination MAC address */
-	u8 tx_dest_addr_high[2];
-	/* Last 4 byte of destination MAC address */
-	u8 tx_dest_addr_low[4];
-	/* Pkt Priority */
-	u8 priority;
-	/* Pkt Trasnit Power control */
-	u8 powermgmt;
-	/* Amount of time the packet has been queued in the driver (units = 2ms) */
-	u8 pktdelay_2ms;
-	/* reserved */
-	u8 reserved1;
-} __attribute__ ((packed));
-
-/* RxPD Descriptor */
-struct rxpd {
-	/* union to cope up with later FW revisions */
-	union {
-		/* Current Rx packet status */
-		__le16 status;
-		struct {
-			/* BSS type: client, AP, etc. */
-			u8 bss_type;
-			/* BSS number */
-			u8 bss_num;
-		} __attribute__ ((packed)) bss;
-	} __attribute__ ((packed)) u;
-
-	/* SNR */
-	u8 snr;
-
-	/* Tx control */
-	u8 rx_control;
-
-	/* Pkt length */
-	__le16 pkt_len;
-
-	/* Noise Floor */
-	u8 nf;
-
-	/* Rx Packet Rate */
-	u8 rx_rate;
-
-	/* Pkt addr */
-	__le32 pkt_ptr;
-
-	/* Next Rx RxPD addr */
-	__le32 next_rxpd_ptr;
-
-	/* Pkt Priority */
-	u8 priority;
-	u8 reserved[3];
-} __attribute__ ((packed));
-
-struct cmd_header {
-	__le16 command;
-	__le16 size;
-	__le16 seqnum;
-	__le16 result;
-} __attribute__ ((packed));
-
-struct cmd_ctrl_node {
-	struct list_head list;
-	int result;
-	/* command response */
-	int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *);
-	unsigned long callback_arg;
-	/* command data */
-	struct cmd_header *cmdbuf;
-	/* wait queue */
-	u16 cmdwaitqwoken;
-	wait_queue_head_t cmdwait_q;
-};
-
-/* Generic structure to hold all key types. */
-struct enc_key {
-	u16 len;
-	u16 flags;  /* KEY_INFO_* from defs.h */
-	u16 type; /* KEY_TYPE_* from defs.h */
-	u8 key[32];
-};
-
-/* lbs_offset_value */
-struct lbs_offset_value {
-	u32 offset;
-	u32 value;
-} __attribute__ ((packed));
-
-/* Define general data structure */
-/* cmd_DS_GEN */
-struct cmd_ds_gen {
-	__le16 command;
-	__le16 size;
-	__le16 seqnum;
-	__le16 result;
-	void *cmdresp[0];
-} __attribute__ ((packed));
-
-#define S_DS_GEN sizeof(struct cmd_ds_gen)
-
-
-/*
- * Define data structure for CMD_GET_HW_SPEC
- * This structure defines the response for the GET_HW_SPEC command
- */
-struct cmd_ds_get_hw_spec {
-	struct cmd_header hdr;
-
-	/* HW Interface version number */
-	__le16 hwifversion;
-	/* HW version number */
-	__le16 version;
-	/* Max number of TxPD FW can handle */
-	__le16 nr_txpd;
-	/* Max no of Multicast address */
-	__le16 nr_mcast_adr;
-	/* MAC address */
-	u8 permanentaddr[6];
-
-	/* region Code */
-	__le16 regioncode;
-
-	/* Number of antenna used */
-	__le16 nr_antenna;
-
-	/* FW release number, example 0x01030304 = 2.3.4p1 */
-	__le32 fwrelease;
-
-	/* Base Address of TxPD queue */
-	__le32 wcb_base;
-	/* Read Pointer of RxPd queue */
-	__le32 rxpd_rdptr;
-
-	/* Write Pointer of RxPd queue */
-	__le32 rxpd_wrptr;
-
-	/*FW/HW capability */
-	__le32 fwcapinfo;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_subscribe_event {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 events;
-
-	/* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a
-	 * number of TLVs. From the v5.1 manual, those TLVs would add up to
-	 * 40 bytes. However, future firmware might add additional TLVs, so I
-	 * bump this up a bit.
-	 */
-	uint8_t tlv[128];
-} __attribute__ ((packed));
-
-/*
- * This scan handle Country Information IE(802.11d compliant)
- * Define data structure for CMD_802_11_SCAN
- */
-struct cmd_ds_802_11_scan {
-	struct cmd_header hdr;
-
-	uint8_t bsstype;
-	uint8_t bssid[ETH_ALEN];
-	uint8_t tlvbuffer[0];
-#if 0
-	mrvlietypes_ssidparamset_t ssidParamSet;
-	mrvlietypes_chanlistparamset_t ChanListParamSet;
-	mrvlietypes_ratesparamset_t OpRateSet;
-#endif
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_scan_rsp {
-	struct cmd_header hdr;
-
-	__le16 bssdescriptsize;
-	uint8_t nr_sets;
-	uint8_t bssdesc_and_tlvbuffer[0];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_get_log {
-	struct cmd_header hdr;
-
-	__le32 mcasttxframe;
-	__le32 failed;
-	__le32 retry;
-	__le32 multiretry;
-	__le32 framedup;
-	__le32 rtssuccess;
-	__le32 rtsfailure;
-	__le32 ackfailure;
-	__le32 rxfrag;
-	__le32 mcastrxframe;
-	__le32 fcserror;
-	__le32 txframe;
-	__le32 wepundecryptable;
-} __attribute__ ((packed));
-
-struct cmd_ds_mac_control {
-	struct cmd_header hdr;
-	__le16 action;
-	u16 reserved;
-} __attribute__ ((packed));
-
-struct cmd_ds_mac_multicast_adr {
-	struct cmd_header hdr;
-	__le16 action;
-	__le16 nr_of_adrs;
-	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-} __attribute__ ((packed));
-
-struct cmd_ds_gspi_bus_config {
-	struct cmd_header hdr;
-	__le16 action;
-	__le16 bus_delay_mode;
-	__le16 host_time_delay_to_read_port;
-	__le16 host_time_delay_to_read_register;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_authenticate {
-	struct cmd_header hdr;
-
-	u8 bssid[ETH_ALEN];
-	u8 authtype;
-	u8 reserved[10];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_deauthenticate {
-	struct cmd_header hdr;
-
-	u8 macaddr[ETH_ALEN];
-	__le16 reasoncode;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_associate {
-	struct cmd_header hdr;
-
-	u8 bssid[6];
-	__le16 capability;
-	__le16 listeninterval;
-	__le16 bcnperiod;
-	u8 dtimperiod;
-	u8 iebuf[512];    /* Enough for required and most optional IEs */
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_associate_response {
-	struct cmd_header hdr;
-
-	__le16 capability;
-	__le16 statuscode;
-	__le16 aid;
-	u8 iebuf[512];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_set_wep {
-	struct cmd_header hdr;
-
-	/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
-	__le16 action;
-
-	/* key Index selected for Tx */
-	__le16 keyindex;
-
-	/* 40, 128bit or TXWEP */
-	uint8_t keytype[4];
-	uint8_t keymaterial[4][16];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_3_get_stat {
-	__le32 xmitok;
-	__le32 rcvok;
-	__le32 xmiterror;
-	__le32 rcverror;
-	__le32 rcvnobuffer;
-	__le32 rcvcrcerror;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_get_stat {
-	__le32 txfragmentcnt;
-	__le32 mcasttxframecnt;
-	__le32 failedcnt;
-	__le32 retrycnt;
-	__le32 Multipleretrycnt;
-	__le32 rtssuccesscnt;
-	__le32 rtsfailurecnt;
-	__le32 ackfailurecnt;
-	__le32 frameduplicatecnt;
-	__le32 rxfragmentcnt;
-	__le32 mcastrxframecnt;
-	__le32 fcserrorcnt;
-	__le32 bcasttxframecnt;
-	__le32 bcastrxframecnt;
-	__le32 txbeacon;
-	__le32 rxbeacon;
-	__le32 wepundecryptable;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_snmp_mib {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 oid;
-	__le16 bufsize;
-	u8 value[128];
-} __attribute__ ((packed));
-
-struct cmd_ds_mac_reg_map {
-	__le16 buffersize;
-	u8 regmap[128];
-	__le16 reserved;
-} __attribute__ ((packed));
-
-struct cmd_ds_bbp_reg_map {
-	__le16 buffersize;
-	u8 regmap[128];
-	__le16 reserved;
-} __attribute__ ((packed));
-
-struct cmd_ds_rf_reg_map {
-	__le16 buffersize;
-	u8 regmap[64];
-	__le16 reserved;
-} __attribute__ ((packed));
-
-struct cmd_ds_mac_reg_access {
-	__le16 action;
-	__le16 offset;
-	__le32 value;
-} __attribute__ ((packed));
-
-struct cmd_ds_bbp_reg_access {
-	__le16 action;
-	__le16 offset;
-	u8 value;
-	u8 reserved[3];
-} __attribute__ ((packed));
-
-struct cmd_ds_rf_reg_access {
-	__le16 action;
-	__le16 offset;
-	u8 value;
-	u8 reserved[3];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_radio_control {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 control;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_beacon_control {
-	__le16 action;
-	__le16 beacon_enable;
-	__le16 beacon_period;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_sleep_params {
-	struct cmd_header hdr;
-
-	/* ACT_GET/ACT_SET */
-	__le16 action;
-
-	/* Sleep clock error in ppm */
-	__le16 error;
-
-	/* Wakeup offset in usec */
-	__le16 offset;
-
-	/* Clock stabilization time in usec */
-	__le16 stabletime;
-
-	/* control periodic calibration */
-	uint8_t calcontrol;
-
-	/* control the use of external sleep clock */
-	uint8_t externalsleepclk;
-
-	/* reserved field, should be set to zero */
-	__le16 reserved;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_inactivity_timeout {
-	struct cmd_header hdr;
-
-	/* ACT_GET/ACT_SET */
-	__le16 action;
-
-	/* Inactivity timeout in msec */
-	__le16 timeout;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rf_channel {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 channel;
-	__le16 rftype;      /* unused */
-	__le16 reserved;    /* unused */
-	u8 channellist[32]; /* unused */
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rssi {
-	/* weighting factor */
-	__le16 N;
-
-	__le16 reserved_0;
-	__le16 reserved_1;
-	__le16 reserved_2;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rssi_rsp {
-	__le16 SNR;
-	__le16 noisefloor;
-	__le16 avgSNR;
-	__le16 avgnoisefloor;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_mac_address {
-	struct cmd_header hdr;
-
-	__le16 action;
-	u8 macadd[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rf_tx_power {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 curlevel;
-	s8 maxlevel;
-	s8 minlevel;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rf_antenna {
-	__le16 action;
-
-	/* Number of antennas or 0xffff(diversity) */
-	__le16 antennamode;
-
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_monitor_mode {
-	__le16 action;
-	__le16 mode;
-} __attribute__ ((packed));
-
-struct cmd_ds_set_boot2_ver {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 version;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_fw_wake_method {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 method;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_sleep_period {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 period;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ps_mode {
-	__le16 action;
-	__le16 nullpktinterval;
-	__le16 multipledtim;
-	__le16 reserved;
-	__le16 locallisteninterval;
-} __attribute__ ((packed));
-
-struct cmd_confirm_sleep {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 nullpktinterval;
-	__le16 multipledtim;
-	__le16 reserved;
-	__le16 locallisteninterval;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_data_rate {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 reserved;
-	u8 rates[MAX_RATES];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_rate_adapt_rateset {
-	struct cmd_header hdr;
-	__le16 action;
-	__le16 enablehwauto;
-	__le16 bitmap;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ad_hoc_start {
-	struct cmd_header hdr;
-
-	u8 ssid[IW_ESSID_MAX_SIZE];
-	u8 bsstype;
-	__le16 beaconperiod;
-	u8 dtimperiod;   /* Reserved on v9 and later */
-	struct ieee_ie_ibss_param_set ibss;
-	u8 reserved1[4];
-	struct ieee_ie_ds_param_set ds;
-	u8 reserved2[4];
-	__le16 probedelay;  /* Reserved on v9 and later */
-	__le16 capability;
-	u8 rates[MAX_RATES];
-	u8 tlv_memory_size_pad[100];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ad_hoc_result {
-	struct cmd_header hdr;
-
-	u8 pad[3];
-	u8 bssid[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct adhoc_bssdesc {
-	u8 bssid[ETH_ALEN];
-	u8 ssid[IW_ESSID_MAX_SIZE];
-	u8 type;
-	__le16 beaconperiod;
-	u8 dtimperiod;
-	__le64 timestamp;
-	__le64 localtime;
-	struct ieee_ie_ds_param_set ds;
-	u8 reserved1[4];
-	struct ieee_ie_ibss_param_set ibss;
-	u8 reserved2[4];
-	__le16 capability;
-	u8 rates[MAX_RATES];
-
-	/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
-	 * Adhoc join command and will cause a binary layout mismatch with
-	 * the firmware
-	 */
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ad_hoc_join {
-	struct cmd_header hdr;
-
-	struct adhoc_bssdesc bss;
-	__le16 failtimeout;   /* Reserved on v9 and later */
-	__le16 probedelay;    /* Reserved on v9 and later */
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_ad_hoc_stop {
-	struct cmd_header hdr;
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_enable_rsn {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le16 enable;
-} __attribute__ ((packed));
-
-struct MrvlIEtype_keyParamSet {
-	/* type ID */
-	__le16 type;
-
-	/* length of Payload */
-	__le16 length;
-
-	/* type of key: WEP=0, TKIP=1, AES=2 */
-	__le16 keytypeid;
-
-	/* key control Info specific to a keytypeid */
-	__le16 keyinfo;
-
-	/* length of key */
-	__le16 keylen;
-
-	/* key material of size keylen */
-	u8 key[32];
-} __attribute__ ((packed));
-
-#define MAX_WOL_RULES 		16
-
-struct host_wol_rule {
-	uint8_t rule_no;
-	uint8_t rule_ops;
-	__le16 sig_offset;
-	__le16 sig_length;
-	__le16 reserve;
-	__be32 sig_mask;
-	__be32 signature;
-} __attribute__ ((packed));
-
-struct wol_config {
-	uint8_t action;
-	uint8_t pattern;
-	uint8_t no_rules_in_cmd;
-	uint8_t result;
-	struct host_wol_rule rule[MAX_WOL_RULES];
-} __attribute__ ((packed));
-
-struct cmd_ds_host_sleep {
-	struct cmd_header hdr;
-	__le32 criteria;
-	uint8_t gpio;
-	uint16_t gap;
-	struct wol_config wol_conf;
-} __attribute__ ((packed));
-
-
-
-struct cmd_ds_802_11_key_material {
-	struct cmd_header hdr;
-
-	__le16 action;
-	struct MrvlIEtype_keyParamSet keyParamSet[2];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_eeprom_access {
-	struct cmd_header hdr;
-	__le16 action;
-	__le16 offset;
-	__le16 len;
-	/* firmware says it returns a maximum of 20 bytes */
-#define LBS_EEPROM_READ_LEN 20
-	u8 value[LBS_EEPROM_READ_LEN];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_tpc_cfg {
-	struct cmd_header hdr;
-
-	__le16 action;
-	uint8_t enable;
-	int8_t P0;
-	int8_t P1;
-	int8_t P2;
-	uint8_t usesnr;
-} __attribute__ ((packed));
-
-
-struct cmd_ds_802_11_pa_cfg {
-	struct cmd_header hdr;
-
-	__le16 action;
-	uint8_t enable;
-	int8_t P0;
-	int8_t P1;
-	int8_t P2;
-} __attribute__ ((packed));
-
-
-struct cmd_ds_802_11_led_ctrl {
-	__le16 action;
-	__le16 numled;
-	u8 data[256];
-} __attribute__ ((packed));
-
-struct cmd_ds_802_11_afc {
-	__le16 afc_auto;
-	union {
-		struct {
-			__le16 threshold;
-			__le16 period;
-		};
-		struct {
-			__le16 timing_offset; /* signed */
-			__le16 carrier_offset; /* signed */
-		};
-	};
-} __attribute__ ((packed));
-
-struct cmd_tx_rate_query {
-	__le16 txrate;
-} __attribute__ ((packed));
-
-struct cmd_ds_get_tsf {
-	__le64 tsfvalue;
-} __attribute__ ((packed));
-
-struct cmd_ds_bt_access {
-	__le16 action;
-	__le32 id;
-	u8 addr1[ETH_ALEN];
-	u8 addr2[ETH_ALEN];
-} __attribute__ ((packed));
-
-struct cmd_ds_fwt_access {
-	__le16 action;
-	__le32 id;
-	u8 valid;
-	u8 da[ETH_ALEN];
-	u8 dir;
-	u8 ra[ETH_ALEN];
-	__le32 ssn;
-	__le32 dsn;
-	__le32 metric;
-	u8 rate;
-	u8 hopcount;
-	u8 ttl;
-	__le32 expiration;
-	u8 sleepmode;
-	__le32 snr;
-	__le32 references;
-	u8 prec[ETH_ALEN];
-} __attribute__ ((packed));
-
-
-struct cmd_ds_mesh_config {
-	struct cmd_header hdr;
-
-        __le16 action;
-        __le16 channel;
-        __le16 type;
-        __le16 length;
-        u8 data[128];   /* last position reserved */
-} __attribute__ ((packed));
-
-
-struct cmd_ds_mesh_access {
-	struct cmd_header hdr;
-
-	__le16 action;
-	__le32 data[32];	/* last position reserved */
-} __attribute__ ((packed));
-
-/* 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_get_stat gstat;
-		struct cmd_ds_802_3_get_stat gstat_8023;
-		struct cmd_ds_802_11_rf_antenna rant;
-		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_tx_rate_query txrate;
-		struct cmd_ds_bt_access bt;
-		struct cmd_ds_fwt_access fwt;
-		struct cmd_ds_get_tsf gettsf;
-		struct cmd_ds_802_11_beacon_control bcn_ctrl;
-	} params;
-} __attribute__ ((packed));
-
-#endif
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index b1d84592b959..1f6cb58dd66c 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -48,6 +48,7 @@
 MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>");
 MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("libertas_cs_helper.fw");
 
 
 
@@ -932,6 +933,9 @@ static int if_cs_probe(struct pcmcia_device *p_dev)
 	card->priv = priv;
 	priv->card = card;
 	priv->hw_host_to_card = if_cs_host_to_card;
+	priv->enter_deep_sleep = NULL;
+	priv->exit_deep_sleep = NULL;
+	priv->reset_deep_sleep_wakeup = NULL;
 	priv->fw_ready = 1;
 
 	/* Now actually get the IRQ */
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 485a8d406525..09fcfad742e7 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -99,6 +99,12 @@ static struct if_sdio_model if_sdio_models[] = {
 		.firmware = "sd8688.bin",
 	},
 };
+MODULE_FIRMWARE("sd8385_helper.bin");
+MODULE_FIRMWARE("sd8385.bin");
+MODULE_FIRMWARE("sd8686_helper.bin");
+MODULE_FIRMWARE("sd8686.bin");
+MODULE_FIRMWARE("sd8688_helper.bin");
+MODULE_FIRMWARE("sd8688.bin");
 
 struct if_sdio_packet {
 	struct if_sdio_packet	*next;
@@ -831,6 +837,58 @@ out:
 	return ret;
 }
 
+static int if_sdio_enter_deep_sleep(struct lbs_private *priv)
+{
+	int ret = -1;
+	struct cmd_header cmd;
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	lbs_deb_sdio("send DEEP_SLEEP command\n");
+	ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd),
+			lbs_cmd_copyback, (unsigned long) &cmd);
+	if (ret)
+		lbs_pr_err("DEEP_SLEEP cmd failed\n");
+
+	mdelay(200);
+	return ret;
+}
+
+static int if_sdio_exit_deep_sleep(struct lbs_private *priv)
+{
+	struct if_sdio_card *card = priv->card;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_SDIO);
+	sdio_claim_host(card->func);
+
+	sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret);
+	if (ret)
+		lbs_pr_err("sdio_writeb failed!\n");
+
+	sdio_release_host(card->func);
+	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+	return ret;
+}
+
+static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv)
+{
+	struct if_sdio_card *card = priv->card;
+	int ret = -1;
+
+	lbs_deb_enter(LBS_DEB_SDIO);
+	sdio_claim_host(card->func);
+
+	sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret);
+	if (ret)
+		lbs_pr_err("sdio_writeb failed!\n");
+
+	sdio_release_host(card->func);
+	lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
+	return ret;
+
+}
+
 /*******************************************************************/
 /* SDIO callbacks                                                  */
 /*******************************************************************/
@@ -859,6 +917,7 @@ static void if_sdio_interrupt(struct sdio_func *func)
 	 * Ignore the define name, this really means the card has
 	 * successfully received the command.
 	 */
+	card->priv->is_activity_detected = 1;
 	if (cause & IF_SDIO_H_INT_DNLD)
 		lbs_host_to_card_done(card->priv);
 
@@ -998,6 +1057,9 @@ static int if_sdio_probe(struct sdio_func *func,
 
 	priv->card = card;
 	priv->hw_host_to_card = if_sdio_host_to_card;
+	priv->enter_deep_sleep = if_sdio_enter_deep_sleep;
+	priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
+	priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
 
 	priv->fw_ready = 1;
 
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 60c9b2fcef03..12179c1dc9c9 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -51,5 +51,6 @@
 #define IF_SDIO_EVENT           0x80fc
 
 #define IF_SDIO_BLOCK_SIZE	256
-
+#define CONFIGURATION_REG               0x03
+#define HOST_POWER_UP                   (0x1U << 1)
 #endif
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 5b3672c4d0cc..bf4bfbae6227 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -32,12 +32,6 @@
 #include "dev.h"
 #include "if_spi.h"
 
-struct if_spi_packet {
-	struct list_head		list;
-	u16				blen;
-	u8				buffer[0] __attribute__((aligned(4)));
-};
-
 struct if_spi_card {
 	struct spi_device		*spi;
 	struct lbs_private		*priv;
@@ -66,33 +60,10 @@ struct if_spi_card {
 	struct semaphore		spi_thread_terminated;
 
 	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
-
-	/* A buffer of incoming packets from libertas core.
-	 * Since we can't sleep in hw_host_to_card, we have to buffer
-	 * them. */
-	struct list_head		cmd_packet_list;
-	struct list_head		data_packet_list;
-
-	/* Protects cmd_packet_list and data_packet_list */
-	spinlock_t			buffer_lock;
 };
 
 static void free_if_spi_card(struct if_spi_card *card)
 {
-	struct list_head *cursor, *next;
-	struct if_spi_packet *packet;
-
-	BUG_ON(card->run_thread);
-	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
-		packet = container_of(cursor, struct if_spi_packet, list);
-		list_del(&packet->list);
-		kfree(packet);
-	}
-	list_for_each_safe(cursor, next, &card->data_packet_list) {
-		packet = container_of(cursor, struct if_spi_packet, list);
-		list_del(&packet->list);
-		kfree(packet);
-	}
 	spi_set_drvdata(card->spi, NULL);
 	kfree(card);
 }
@@ -774,40 +745,6 @@ out:
 	return err;
 }
 
-/* Move data or a command from the host to the card. */
-static void if_spi_h2c(struct if_spi_card *card,
-			struct if_spi_packet *packet, int type)
-{
-	int err = 0;
-	u16 int_type, port_reg;
-
-	switch (type) {
-	case MVMS_DAT:
-		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
-		port_reg = IF_SPI_DATA_RDWRPORT_REG;
-		break;
-	case MVMS_CMD:
-		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
-		port_reg = IF_SPI_CMD_RDWRPORT_REG;
-		break;
-	default:
-		lbs_pr_err("can't transfer buffer of type %d\n", type);
-		err = -EINVAL;
-		goto out;
-	}
-
-	/* Write the data to the card */
-	err = spu_write(card, port_reg, packet->buffer, packet->blen);
-	if (err)
-		goto out;
-
-out:
-	kfree(packet);
-
-	if (err)
-		lbs_pr_err("%s: error %d\n", __func__, err);
-}
-
 /* Inform the host about a card event */
 static void if_spi_e2h(struct if_spi_card *card)
 {
@@ -837,8 +774,6 @@ static int lbs_spi_thread(void *data)
 	int err;
 	struct if_spi_card *card = data;
 	u16 hiStatus;
-	unsigned long flags;
-	struct if_spi_packet *packet;
 
 	while (1) {
 		/* Wait to be woken up by one of two things.  First, our ISR
@@ -877,43 +812,9 @@ static int lbs_spi_thread(void *data)
 		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY ||
 		   (card->priv->psstate != PS_STATE_FULL_POWER &&
 		    (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) {
-			/* This means two things. First of all,
-			 * if there was a previous command sent, the card has
-			 * successfully received it.
-			 * Secondly, it is now ready to download another
-			 * command.
-			 */
 			lbs_host_to_card_done(card->priv);
-
-			/* Do we have any command packets from the host to
-			 * send? */
-			packet = NULL;
-			spin_lock_irqsave(&card->buffer_lock, flags);
-			if (!list_empty(&card->cmd_packet_list)) {
-				packet = (struct if_spi_packet *)(card->
-						cmd_packet_list.next);
-				list_del(&packet->list);
-			}
-			spin_unlock_irqrestore(&card->buffer_lock, flags);
-
-			if (packet)
-				if_spi_h2c(card, packet, MVMS_CMD);
 		}
-		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
-			/* Do we have any data packets from the host to
-			 * send? */
-			packet = NULL;
-			spin_lock_irqsave(&card->buffer_lock, flags);
-			if (!list_empty(&card->data_packet_list)) {
-				packet = (struct if_spi_packet *)(card->
-						data_packet_list.next);
-				list_del(&packet->list);
-			}
-			spin_unlock_irqrestore(&card->buffer_lock, flags);
 
-			if (packet)
-				if_spi_h2c(card, packet, MVMS_DAT);
-		}
 		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
 			if_spi_e2h(card);
 
@@ -942,40 +843,18 @@ static int if_spi_host_to_card(struct lbs_private *priv,
 				u8 type, u8 *buf, u16 nb)
 {
 	int err = 0;
-	unsigned long flags;
 	struct if_spi_card *card = priv->card;
-	struct if_spi_packet *packet;
-	u16 blen;
 
 	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
 
-	if (nb == 0) {
-		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
-		err = -EINVAL;
-		goto out;
-	}
-	blen = ALIGN(nb, 4);
-	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
-	if (!packet) {
-		err = -ENOMEM;
-		goto out;
-	}
-	packet->blen = blen;
-	memcpy(packet->buffer, buf, nb);
-	memset(packet->buffer + nb, 0, blen - nb);
+	nb = ALIGN(nb, 4);
 
 	switch (type) {
 	case MVMS_CMD:
-		priv->dnld_sent = DNLD_CMD_SENT;
-		spin_lock_irqsave(&card->buffer_lock, flags);
-		list_add_tail(&packet->list, &card->cmd_packet_list);
-		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
 		break;
 	case MVMS_DAT:
-		priv->dnld_sent = DNLD_DATA_SENT;
-		spin_lock_irqsave(&card->buffer_lock, flags);
-		list_add_tail(&packet->list, &card->data_packet_list);
-		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb);
 		break;
 	default:
 		lbs_pr_err("can't transfer buffer of type %d", type);
@@ -983,9 +862,6 @@ static int if_spi_host_to_card(struct lbs_private *priv,
 		break;
 	}
 
-	/* Wake up the spi thread */
-	up(&card->spi_ready);
-out:
 	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
 	return err;
 }
@@ -1026,6 +902,10 @@ static int if_spi_calculate_fw_names(u16 card_id,
 		 chip_id_to_device_name[i].name);
 	return 0;
 }
+MODULE_FIRMWARE("libertas/gspi8385_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8385.bin");
+MODULE_FIRMWARE("libertas/gspi8686_hlp.bin");
+MODULE_FIRMWARE("libertas/gspi8686.bin");
 
 static int __devinit if_spi_probe(struct spi_device *spi)
 {
@@ -1062,9 +942,6 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 
 	sema_init(&card->spi_ready, 0);
 	sema_init(&card->spi_thread_terminated, 0);
-	INIT_LIST_HEAD(&card->cmd_packet_list);
-	INIT_LIST_HEAD(&card->data_packet_list);
-	spin_lock_init(&card->buffer_lock);
 
 	/* Initialize the SPI Interface Unit */
 	err = spu_init(card, pdata->use_dummy_writes);
@@ -1117,6 +994,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 	card->priv = priv;
 	priv->card = card;
 	priv->hw_host_to_card = if_spi_host_to_card;
+	priv->enter_deep_sleep = NULL;
+	priv->exit_deep_sleep = NULL;
+	priv->reset_deep_sleep_wakeup = NULL;
 	priv->fw_ready = 1;
 
 	/* Initialize interrupt handling stuff. */
@@ -1138,6 +1018,9 @@ static int __devinit if_spi_probe(struct spi_device *spi)
 		goto terminate_thread;
 	}
 
+	/* poke the IRQ handler so that we don't miss the first interrupt */
+	up(&card->spi_ready);
+
 	/* Start the card.
 	 * This will call register_netdev, and we'll start
 	 * getting interrupts... */
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 3fac4efa5ac8..65e174595d12 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -28,6 +28,8 @@
 static char *lbs_fw_name = "usb8388.bin";
 module_param_named(fw_name, lbs_fw_name, charp, 0644);
 
+MODULE_FIRMWARE("usb8388.bin");
+
 static struct usb_device_id if_usb_table[] = {
 	/* Enter the device signature inside */
 	{ USB_DEVICE(0x1286, 0x2001) },
@@ -300,6 +302,9 @@ static int if_usb_probe(struct usb_interface *intf,
 	cardp->priv->fw_ready = 1;
 
 	priv->hw_host_to_card = if_usb_host_to_card;
+	priv->enter_deep_sleep = NULL;
+	priv->exit_deep_sleep = NULL;
+	priv->reset_deep_sleep_wakeup = NULL;
 #ifdef CONFIG_OLPC
 	if (machine_is_olpc())
 		priv->reset_card = if_usb_reset_olpc_card;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 87b4e497faa2..db38a5a719fa 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -14,11 +14,13 @@
 #include <linux/stddef.h>
 #include <linux/ieee80211.h>
 #include <net/iw_handler.h>
+#include <net/cfg80211.h>
 
 #include "host.h"
 #include "decl.h"
 #include "dev.h"
 #include "wext.h"
+#include "cfg.h"
 #include "debugfs.h"
 #include "scan.h"
 #include "assoc.h"
@@ -43,119 +45,6 @@ module_param_named(libertas_debug, lbs_debug, int, 0644);
 struct cmd_confirm_sleep confirm_sleep;
 
 
-#define LBS_TX_PWR_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_US_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_JP_DEFAULT		16	/*50mW */
-#define LBS_TX_PWR_FR_DEFAULT		20	/*100mW */
-#define LBS_TX_PWR_EMEA_DEFAULT	20	/*100mW */
-
-/* Format { channel, frequency (MHz), maxtxpower } */
-/* band: 'B/G', region: USA FCC/Canada IC */
-static struct chan_freq_power channel_freq_power_US_BG[] = {
-	{1, 2412, LBS_TX_PWR_US_DEFAULT},
-	{2, 2417, LBS_TX_PWR_US_DEFAULT},
-	{3, 2422, LBS_TX_PWR_US_DEFAULT},
-	{4, 2427, LBS_TX_PWR_US_DEFAULT},
-	{5, 2432, LBS_TX_PWR_US_DEFAULT},
-	{6, 2437, LBS_TX_PWR_US_DEFAULT},
-	{7, 2442, LBS_TX_PWR_US_DEFAULT},
-	{8, 2447, LBS_TX_PWR_US_DEFAULT},
-	{9, 2452, LBS_TX_PWR_US_DEFAULT},
-	{10, 2457, LBS_TX_PWR_US_DEFAULT},
-	{11, 2462, LBS_TX_PWR_US_DEFAULT}
-};
-
-/* band: 'B/G', region: Europe ETSI */
-static struct chan_freq_power channel_freq_power_EU_BG[] = {
-	{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
-	{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
-	{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
-	{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
-	{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
-	{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
-	{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
-	{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
-	{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
-	{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
-	{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
-	{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
-	{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
-};
-
-/* band: 'B/G', region: Spain */
-static struct chan_freq_power channel_freq_power_SPN_BG[] = {
-	{10, 2457, LBS_TX_PWR_DEFAULT},
-	{11, 2462, LBS_TX_PWR_DEFAULT}
-};
-
-/* band: 'B/G', region: France */
-static struct chan_freq_power channel_freq_power_FR_BG[] = {
-	{10, 2457, LBS_TX_PWR_FR_DEFAULT},
-	{11, 2462, LBS_TX_PWR_FR_DEFAULT},
-	{12, 2467, LBS_TX_PWR_FR_DEFAULT},
-	{13, 2472, LBS_TX_PWR_FR_DEFAULT}
-};
-
-/* band: 'B/G', region: Japan */
-static struct chan_freq_power channel_freq_power_JPN_BG[] = {
-	{1, 2412, LBS_TX_PWR_JP_DEFAULT},
-	{2, 2417, LBS_TX_PWR_JP_DEFAULT},
-	{3, 2422, LBS_TX_PWR_JP_DEFAULT},
-	{4, 2427, LBS_TX_PWR_JP_DEFAULT},
-	{5, 2432, LBS_TX_PWR_JP_DEFAULT},
-	{6, 2437, LBS_TX_PWR_JP_DEFAULT},
-	{7, 2442, LBS_TX_PWR_JP_DEFAULT},
-	{8, 2447, LBS_TX_PWR_JP_DEFAULT},
-	{9, 2452, LBS_TX_PWR_JP_DEFAULT},
-	{10, 2457, LBS_TX_PWR_JP_DEFAULT},
-	{11, 2462, LBS_TX_PWR_JP_DEFAULT},
-	{12, 2467, LBS_TX_PWR_JP_DEFAULT},
-	{13, 2472, LBS_TX_PWR_JP_DEFAULT},
-	{14, 2484, LBS_TX_PWR_JP_DEFAULT}
-};
-
-/**
- * the structure for channel, frequency and power
- */
-struct region_cfp_table {
-	u8 region;
-	struct chan_freq_power *cfp_BG;
-	int cfp_no_BG;
-};
-
-/**
- * the structure for the mapping between region and CFP
- */
-static struct region_cfp_table region_cfp_table[] = {
-	{0x10,			/*US FCC */
-	 channel_freq_power_US_BG,
-	 ARRAY_SIZE(channel_freq_power_US_BG),
-	 }
-	,
-	{0x20,			/*CANADA IC */
-	 channel_freq_power_US_BG,
-	 ARRAY_SIZE(channel_freq_power_US_BG),
-	 }
-	,
-	{0x30, /*EU*/ channel_freq_power_EU_BG,
-	 ARRAY_SIZE(channel_freq_power_EU_BG),
-	 }
-	,
-	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
-	 ARRAY_SIZE(channel_freq_power_SPN_BG),
-	 }
-	,
-	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
-	 ARRAY_SIZE(channel_freq_power_FR_BG),
-	 }
-	,
-	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
-	 ARRAY_SIZE(channel_freq_power_JPN_BG),
-	 }
-	,
-/*Add new region here */
-};
-
 /**
  * the table to keep region code
  */
@@ -163,13 +52,6 @@ u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
     { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
 
 /**
- * 802.11b/g supported bitrates (in 500Kb/s units)
- */
-u8 lbs_bg_rates[MAX_RATES] =
-    { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
-0x00, 0x00 };
-
-/**
  * FW rate table.  FW refers to rates by their index in this table, not by the
  * rate value itself.  Values of 0x00 are
  * reserved positions.
@@ -212,107 +94,9 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
 	return 0;
 }
 
-/**
- * Attributes exported through sysfs
- */
-
-/**
- * @brief Get function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
-}
-
-/**
- * @brief Set function for sysfs attribute anycast_mask
- */
-static ssize_t lbs_anycast_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	uint32_t datum;
-	int ret;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	sscanf(buf, "%x", &datum);
-	mesh_access.data[0] = cpu_to_le32(datum);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	u32 retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	retry_limit = le32_to_cpu(mesh_access.data[1]);
-	return snprintf(buf, 10, "%d\n", retry_limit);
-}
-
-/**
- * @brief Set function for sysfs attribute prb_rsp_limit
- */
-static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_access mesh_access;
-	int ret;
-	unsigned long retry_limit;
-
-	memset(&mesh_access, 0, sizeof(mesh_access));
-	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
-
-	if (!strict_strtoul(buf, 10, &retry_limit))
-		return -ENOTSUPP;
-	if (retry_limit > 15)
-		return -ENOTSUPP;
-
-	mesh_access.data[1] = cpu_to_le32(retry_limit);
-
-	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
-			&mesh_access);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
 
 static int lbs_add_rtap(struct lbs_private *priv);
 static void lbs_remove_rtap(struct lbs_private *priv);
-static int lbs_add_mesh(struct lbs_private *priv);
-static void lbs_remove_mesh(struct lbs_private *priv);
 
 
 /**
@@ -378,74 +162,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
 static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
 
 /**
- * Get function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_get(struct device *dev,
-		struct device_attribute *attr, char * buf)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
-}
-
-/**
- *  Set function for sysfs attribute mesh
- */
-static ssize_t lbs_mesh_set(struct device *dev,
-		struct device_attribute *attr, const char * buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	int enable;
-	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
-
-	sscanf(buf, "%x", &enable);
-	enable = !!enable;
-	if (enable == !!priv->mesh_dev)
-		return count;
-	if (enable)
-		action = CMD_ACT_MESH_CONFIG_START;
-	ret = lbs_mesh_config(priv, action, priv->curbssparams.channel);
-	if (ret)
-		return ret;
-
-	if (enable)
-		lbs_add_mesh(priv);
-	else
-		lbs_remove_mesh(priv);
-
-	return count;
-}
-
-/**
- * lbs_mesh attribute to be exported per ethX interface
- * through sysfs (/sys/class/net/ethX/lbs_mesh)
- */
-static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
-
-/**
- * anycast_mask attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/anycast_mask)
- */
-static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
-
-/**
- * prb_rsp_limit attribute to be exported per mshX interface
- * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
- */
-static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
-		lbs_prb_rsp_limit_set);
-
-static struct attribute *lbs_mesh_sysfs_entries[] = {
-	&dev_attr_anycast_mask.attr,
-	&dev_attr_prb_rsp_limit.attr,
-	NULL,
-};
-
-static struct attribute_group lbs_mesh_attr_group = {
-	.attrs = lbs_mesh_sysfs_entries,
-};
-
-/**
- *  @brief This function opens the ethX or mshX interface
+ *  @brief This function opens the ethX interface
  *
  *  @param dev     A pointer to net_device structure
  *  @return 	   0 or -EBUSY if monitor mode active
@@ -464,18 +181,12 @@ static int lbs_dev_open(struct net_device *dev)
 		goto out;
 	}
 
-	if (dev == priv->mesh_dev) {
-		priv->mesh_open = 1;
-		priv->mesh_connect_status = LBS_CONNECTED;
-		netif_carrier_on(dev);
-	} else {
-		priv->infra_open = 1;
+	priv->infra_open = 1;
 
-		if (priv->connect_status == LBS_CONNECTED)
-			netif_carrier_on(dev);
-		else
-			netif_carrier_off(dev);
-	}
+	if (priv->connect_status == LBS_CONNECTED)
+		netif_carrier_on(dev);
+	else
+		netif_carrier_off(dev);
 
 	if (!priv->tx_pending_len)
 		netif_wake_queue(dev);
@@ -487,33 +198,6 @@ static int lbs_dev_open(struct net_device *dev)
 }
 
 /**
- *  @brief This function closes the mshX interface
- *
- *  @param dev     A pointer to net_device structure
- *  @return 	   0
- */
-static int lbs_mesh_stop(struct net_device *dev)
-{
-	struct lbs_private *priv = dev->ml_priv;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	spin_lock_irq(&priv->driver_lock);
-
-	priv->mesh_open = 0;
-	priv->mesh_connect_status = LBS_DISCONNECTED;
-
-	netif_stop_queue(dev);
-	netif_carrier_off(dev);
-
-	spin_unlock_irq(&priv->driver_lock);
-
-	schedule_work(&priv->mcast_work);
-
-	lbs_deb_leave(LBS_DEB_MESH);
-	return 0;
-}
-
-/**
  *  @brief This function closes the ethX interface
  *
  *  @param dev     A pointer to net_device structure
@@ -574,15 +258,17 @@ void lbs_host_to_card_done(struct lbs_private *priv)
 	priv->dnld_sent = DNLD_RES_RECEIVED;
 
 	/* Wake main thread if commands are pending */
-	if (!priv->cur_cmd || priv->tx_pending_len > 0)
-		wake_up_interruptible(&priv->waitq);
+	if (!priv->cur_cmd || priv->tx_pending_len > 0) {
+		if (!priv->wakeup_dev_required)
+			wake_up_interruptible(&priv->waitq);
+	}
 
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 	lbs_deb_leave(LBS_DEB_THREAD);
 }
 EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
 
-static int lbs_set_mac_address(struct net_device *dev, void *addr)
+int lbs_set_mac_address(struct net_device *dev, void *addr)
 {
 	int ret = 0;
 	struct lbs_private *priv = dev->ml_priv;
@@ -716,7 +402,7 @@ static void lbs_set_mcast_worker(struct work_struct *work)
 	lbs_deb_leave(LBS_DEB_NET);
 }
 
-static void lbs_set_multicast_list(struct net_device *dev)
+void lbs_set_multicast_list(struct net_device *dev)
 {
 	struct lbs_private *priv = dev->ml_priv;
 
@@ -770,7 +456,8 @@ static int lbs_thread(void *data)
 			shouldsleep = 0;	/* We have a command response */
 		else if (priv->cur_cmd)
 			shouldsleep = 1;	/* Can't send a command; one already running */
-		else if (!list_empty(&priv->cmdpendingq))
+		else if (!list_empty(&priv->cmdpendingq) &&
+					!(priv->wakeup_dev_required))
 			shouldsleep = 0;	/* We have a command to send */
 		else if (__kfifo_len(priv->event_fifo))
 			shouldsleep = 0;	/* We have an event to process */
@@ -822,6 +509,26 @@ static int lbs_thread(void *data)
 		}
 		spin_unlock_irq(&priv->driver_lock);
 
+		/* Process hardware events, e.g. card removed, link lost */
+		spin_lock_irq(&priv->driver_lock);
+		while (__kfifo_len(priv->event_fifo)) {
+			u32 event;
+			__kfifo_get(priv->event_fifo, (unsigned char *) &event,
+				sizeof(event));
+			spin_unlock_irq(&priv->driver_lock);
+			lbs_process_event(priv, event);
+			spin_lock_irq(&priv->driver_lock);
+		}
+		spin_unlock_irq(&priv->driver_lock);
+
+		if (priv->wakeup_dev_required) {
+			lbs_deb_thread("Waking up device...\n");
+			/* Wake up device */
+			if (priv->exit_deep_sleep(priv))
+				lbs_deb_thread("Wakeup device failed\n");
+			continue;
+		}
+
 		/* command timeout stuff */
 		if (priv->cmd_timed_out && priv->cur_cmd) {
 			struct cmd_ctrl_node *cmdnode = priv->cur_cmd;
@@ -849,18 +556,7 @@ static int lbs_thread(void *data)
 		}
 		priv->cmd_timed_out = 0;
 
-		/* Process hardware events, e.g. card removed, link lost */
-		spin_lock_irq(&priv->driver_lock);
-		while (__kfifo_len(priv->event_fifo)) {
-			u32 event;
 
-			__kfifo_get(priv->event_fifo, (unsigned char *) &event,
-				sizeof(event));
-			spin_unlock_irq(&priv->driver_lock);
-			lbs_process_event(priv, event);
-			spin_lock_irq(&priv->driver_lock);
-		}
-		spin_unlock_irq(&priv->driver_lock);
 
 		if (!priv->fw_ready)
 			continue;
@@ -894,6 +590,9 @@ static int lbs_thread(void *data)
 		    (priv->psstate == PS_STATE_PRE_SLEEP))
 			continue;
 
+		if (priv->is_deep_sleep)
+			continue;
+
 		/* Execute the next command */
 		if (!priv->dnld_sent && !priv->cur_cmd)
 			lbs_execute_next_command(priv);
@@ -928,6 +627,7 @@ static int lbs_thread(void *data)
 	}
 
 	del_timer(&priv->command_timer);
+	del_timer(&priv->auto_deepsleep_timer);
 	wake_up_all(&priv->cmd_pending);
 
 	lbs_deb_leave(LBS_DEB_THREAD);
@@ -1050,6 +750,62 @@ out:
 	lbs_deb_leave(LBS_DEB_CMD);
 }
 
+/**
+ *  This function put the device back to deep sleep mode when timer expires
+ *  and no activity (command, event, data etc.) is detected.
+ */
+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);
+
+	if (priv->is_activity_detected) {
+		priv->is_activity_detected = 0;
+	} else {
+		if (priv->is_auto_deep_sleep_enabled &&
+				(!priv->wakeup_dev_required) &&
+				(priv->connect_status != LBS_CONNECTED)) {
+			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");
+		}
+	}
+	mod_timer(&priv->auto_deepsleep_timer , jiffies +
+				(priv->auto_deep_sleep_timeout * HZ)/1000);
+	lbs_deb_leave(LBS_DEB_CMD);
+}
+
+int lbs_enter_auto_deep_sleep(struct lbs_private *priv)
+{
+	lbs_deb_enter(LBS_DEB_SDIO);
+
+	priv->is_auto_deep_sleep_enabled = 1;
+	if (priv->is_deep_sleep)
+		priv->wakeup_dev_required = 1;
+	mod_timer(&priv->auto_deepsleep_timer ,
+			jiffies + (priv->auto_deep_sleep_timeout * HZ)/1000);
+
+	lbs_deb_leave(LBS_DEB_SDIO);
+	return 0;
+}
+
+int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
+{
+	lbs_deb_enter(LBS_DEB_SDIO);
+
+	priv->is_auto_deep_sleep_enabled = 0;
+	priv->auto_deep_sleep_timeout = 0;
+	del_timer(&priv->auto_deepsleep_timer);
+
+	lbs_deb_leave(LBS_DEB_SDIO);
+	return 0;
+}
+
 static void lbs_sync_channel_worker(struct work_struct *work)
 {
 	struct lbs_private *priv = container_of(work, struct lbs_private,
@@ -1092,18 +848,24 @@ static int lbs_init_adapter(struct lbs_private *priv)
 	priv->mesh_connect_status = LBS_DISCONNECTED;
 	priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
 	priv->mode = IW_MODE_INFRA;
-	priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL;
+	priv->channel = DEFAULT_AD_HOC_CHANNEL;
 	priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
 	priv->radio_on = 1;
 	priv->enablehwauto = 1;
 	priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE;
 	priv->psmode = LBS802_11POWERMODECAM;
 	priv->psstate = PS_STATE_FULL_POWER;
+	priv->is_deep_sleep = 0;
+	priv->is_auto_deep_sleep_enabled = 0;
+	priv->wakeup_dev_required = 0;
+	init_waitqueue_head(&priv->ds_awake_q);
 
 	mutex_init(&priv->lock);
 
 	setup_timer(&priv->command_timer, command_timer_fn,
 		(unsigned long)priv);
+	setup_timer(&priv->auto_deepsleep_timer, auto_deepsleep_timer_fn,
+			(unsigned long)priv);
 
 	INIT_LIST_HEAD(&priv->cmdfreeq);
 	INIT_LIST_HEAD(&priv->cmdpendingq);
@@ -1142,6 +904,7 @@ static void lbs_free_adapter(struct lbs_private *priv)
 	if (priv->event_fifo)
 		kfifo_free(priv->event_fifo);
 	del_timer(&priv->command_timer);
+	del_timer(&priv->auto_deepsleep_timer);
 	kfree(priv->networks);
 	priv->networks = NULL;
 
@@ -1168,31 +931,41 @@ static const struct net_device_ops lbs_netdev_ops = {
  */
 struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 {
-	struct net_device *dev = NULL;
+	struct net_device *dev;
+	struct wireless_dev *wdev;
 	struct lbs_private *priv = NULL;
 
 	lbs_deb_enter(LBS_DEB_MAIN);
 
 	/* Allocate an Ethernet device and register it */
-	dev = alloc_etherdev(sizeof(struct lbs_private));
-	if (!dev) {
-		lbs_pr_err("init wlanX device failed\n");
+	wdev = lbs_cfg_alloc(dmdev);
+	if (IS_ERR(wdev)) {
+		lbs_pr_err("cfg80211 init failed\n");
 		goto done;
 	}
-	priv = netdev_priv(dev);
-	dev->ml_priv = priv;
+	/* TODO? */
+	wdev->iftype = NL80211_IFTYPE_STATION;
+	priv = wdev_priv(wdev);
+	priv->wdev = wdev;
 
 	if (lbs_init_adapter(priv)) {
 		lbs_pr_err("failed to initialize adapter structure.\n");
-		goto err_init_adapter;
+		goto err_wdev;
 	}
 
+	//TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
+	dev = alloc_netdev(0, "wlan%d", ether_setup);
+	if (!dev) {
+		dev_err(dmdev, "no memory for network device instance\n");
+		goto err_adapter;
+	}
+
+	dev->ieee80211_ptr = wdev;
+	dev->ml_priv = priv;
+	SET_NETDEV_DEV(dev, dmdev);
+	wdev->netdev = dev;
 	priv->dev = dev;
-	priv->card = card;
-	priv->mesh_open = 0;
-	priv->infra_open = 0;
 
-	/* Setup the OS Interface to our functions */
  	dev->netdev_ops = &lbs_netdev_ops;
 	dev->watchdog_timeo = 5 * HZ;
 	dev->ethtool_ops = &lbs_ethtool_ops;
@@ -1201,7 +974,13 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 #endif
 	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
 
-	SET_NETDEV_DEV(dev, dmdev);
+
+	// TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
+
+
+	priv->card = card;
+	priv->infra_open = 0;
+
 
 	priv->rtap_net_dev = NULL;
 	strcpy(dev->name, "wlan%d");
@@ -1211,7 +990,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 	priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main");
 	if (IS_ERR(priv->main_thread)) {
 		lbs_deb_thread("Error creating main thread.\n");
-		goto err_init_adapter;
+		goto err_ndev;
 	}
 
 	priv->work_thread = create_singlethread_workqueue("lbs_worker");
@@ -1220,6 +999,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 	INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
 	INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
 
+	priv->mesh_open = 0;
 	sprintf(priv->mesh_ssid, "mesh");
 	priv->mesh_ssid_len = 4;
 
@@ -1228,9 +1008,15 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
 
 	goto done;
 
-err_init_adapter:
-	lbs_free_adapter(priv);
+ err_ndev:
 	free_netdev(dev);
+
+ err_adapter:
+	lbs_free_adapter(priv);
+
+ err_wdev:
+	lbs_cfg_free(priv);
+
 	priv = NULL;
 
 done:
@@ -1243,7 +1029,6 @@ EXPORT_SYMBOL_GPL(lbs_add_card);
 void lbs_remove_card(struct lbs_private *priv)
 {
 	struct net_device *dev = priv->dev;
-	union iwreq_data wrqu;
 
 	lbs_deb_enter(LBS_DEB_MAIN);
 
@@ -1268,15 +1053,19 @@ void lbs_remove_card(struct lbs_private *priv)
 		lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
 	}
 
-	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
-	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
-	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+	lbs_send_disconnect_notification(priv);
+
+	if (priv->is_deep_sleep) {
+		priv->is_deep_sleep = 0;
+		wake_up_interruptible(&priv->ds_awake_q);
+	}
 
 	/* Stop the thread servicing the interrupts */
 	priv->surpriseremoved = 1;
 	kthread_stop(priv->main_thread);
 
 	lbs_free_adapter(priv);
+	lbs_cfg_free(priv);
 
 	priv->dev = NULL;
 	free_netdev(dev);
@@ -1298,60 +1087,19 @@ int lbs_start_card(struct lbs_private *priv)
 	if (ret)
 		goto done;
 
-	/* init 802.11d */
-	lbs_init_11d(priv);
-
-	if (register_netdev(dev)) {
-		lbs_pr_err("cannot register ethX device\n");
+	if (lbs_cfg_register(priv)) {
+		lbs_pr_err("cannot register device\n");
 		goto done;
 	}
 
 	lbs_update_channel(priv);
 
-	/* Check mesh FW version and appropriately send the mesh start
-	 * command
+	/*
+	 * While rtap isn't related to mesh, only mesh-enabled
+	 * firmware implements the rtap functionality via
+	 * CMD_802_11_MONITOR_MODE.
 	 */
-	if (priv->mesh_fw_ver == MESH_FW_OLD) {
-		/* Enable mesh, if supported, and work out which TLV it uses.
-		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
-		   0x100 + 37 is the official value used in 5.110.21.pXX
-		   but we check them in that order because 20.pXX doesn't
-		   give an error -- it just silently fails. */
-
-		/* 5.110.20.pXX firmware will fail the command if the channel
-		   doesn't match the existing channel. But only if the TLV
-		   is correct. If the channel is wrong, _BOTH_ versions will
-		   give an error to 0x100+291, and allow 0x100+37 to succeed.
-		   It's just that 5.110.20.pXX will not have done anything
-		   useful */
-
-		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->curbssparams.channel)) {
-			priv->mesh_tlv = TLV_TYPE_MESH_ID;
-			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-					    priv->curbssparams.channel))
-				priv->mesh_tlv = 0;
-		}
-	} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
-		/* 10.0.0.pXX new firmwares should succeed with TLV
-		 * 0x100+37; Do not invoke command with old TLV.
-		 */
-		priv->mesh_tlv = TLV_TYPE_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->curbssparams.channel))
-			priv->mesh_tlv = 0;
-	}
-	if (priv->mesh_tlv) {
-		lbs_add_mesh(priv);
-
-		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
-			lbs_pr_err("cannot register lbs_mesh attribute\n");
-
-		/* While rtap isn't related to mesh, only mesh-enabled
-		 * firmware implements the rtap functionality via
-		 * CMD_802_11_MONITOR_MODE.
-		 */
+	if (lbs_init_mesh(priv)) {
 		if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
 			lbs_pr_err("cannot register lbs_rtap attribute\n");
 	}
@@ -1385,13 +1133,12 @@ void lbs_stop_card(struct lbs_private *priv)
 	netif_carrier_off(dev);
 
 	lbs_debugfs_remove_one(priv);
-	if (priv->mesh_tlv) {
-		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+	if (lbs_deinit_mesh(priv))
 		device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
-	}
 
 	/* Delete the timeout of the currently processing command */
 	del_timer_sync(&priv->command_timer);
+	del_timer_sync(&priv->auto_deepsleep_timer);
 
 	/* Flush pending command nodes */
 	spin_lock_irqsave(&priv->driver_lock, flags);
@@ -1420,157 +1167,6 @@ out:
 EXPORT_SYMBOL_GPL(lbs_stop_card);
 
 
-static const struct net_device_ops mesh_netdev_ops = {
-	.ndo_open		= lbs_dev_open,
-	.ndo_stop 		= lbs_mesh_stop,
-	.ndo_start_xmit		= lbs_hard_start_xmit,
-	.ndo_set_mac_address	= lbs_set_mac_address,
-	.ndo_set_multicast_list = lbs_set_multicast_list,
-};
-
-/**
- * @brief This function adds mshX interface
- *
- *  @param priv    A pointer to the struct lbs_private structure
- *  @return 	   0 if successful, -X otherwise
- */
-static int lbs_add_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev = NULL;
-	int ret = 0;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-
-	/* Allocate a virtual mesh device */
-	if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
-		lbs_deb_mesh("init mshX device failed\n");
-		ret = -ENOMEM;
-		goto done;
-	}
-	mesh_dev->ml_priv = priv;
-	priv->mesh_dev = mesh_dev;
-
-	mesh_dev->netdev_ops = &mesh_netdev_ops;
-	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
-	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
-			sizeof(priv->dev->dev_addr));
-
-	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
-
-#ifdef	WIRELESS_EXT
-	mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
-#endif
-	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
-	/* Register virtual mesh interface */
-	ret = register_netdev(mesh_dev);
-	if (ret) {
-		lbs_pr_err("cannot register mshX virtual interface\n");
-		goto err_free;
-	}
-
-	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	if (ret)
-		goto err_unregister;
-
-	lbs_persist_config_init(mesh_dev);
-
-	/* Everything successful */
-	ret = 0;
-	goto done;
-
-err_unregister:
-	unregister_netdev(mesh_dev);
-
-err_free:
-	free_netdev(mesh_dev);
-
-done:
-	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
-	return ret;
-}
-
-static void lbs_remove_mesh(struct lbs_private *priv)
-{
-	struct net_device *mesh_dev;
-
-
-	mesh_dev = priv->mesh_dev;
-	if (!mesh_dev)
-		return;
-
-	lbs_deb_enter(LBS_DEB_MESH);
-	netif_stop_queue(mesh_dev);
-	netif_carrier_off(mesh_dev);
-	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-	lbs_persist_config_remove(mesh_dev);
-	unregister_netdev(mesh_dev);
-	priv->mesh_dev = NULL;
-	free_netdev(mesh_dev);
-	lbs_deb_leave(LBS_DEB_MESH);
-}
-
-/**
- *  @brief This function finds the CFP in
- *  region_cfp_table based on region and band parameter.
- *
- *  @param region  The region code
- *  @param band	   The band
- *  @param cfp_no  A pointer to CFP number
- *  @return 	   A pointer to CFP
- */
-struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
-{
-	int i, end;
-
-	lbs_deb_enter(LBS_DEB_MAIN);
-
-	end = ARRAY_SIZE(region_cfp_table);
-
-	for (i = 0; i < end ; i++) {
-		lbs_deb_main("region_cfp_table[i].region=%d\n",
-			region_cfp_table[i].region);
-		if (region_cfp_table[i].region == region) {
-			*cfp_no = region_cfp_table[i].cfp_no_BG;
-			lbs_deb_leave(LBS_DEB_MAIN);
-			return region_cfp_table[i].cfp_BG;
-		}
-	}
-
-	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
-	return NULL;
-}
-
-int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
-{
-	int ret = 0;
-	int i = 0;
-
-	struct chan_freq_power *cfp;
-	int cfp_no;
-
-	lbs_deb_enter(LBS_DEB_MAIN);
-
-	memset(priv->region_channel, 0, sizeof(priv->region_channel));
-
-	cfp = lbs_get_region_cfp_table(region, &cfp_no);
-	if (cfp != NULL) {
-		priv->region_channel[i].nrcfp = cfp_no;
-		priv->region_channel[i].CFP = cfp;
-	} else {
-		lbs_deb_main("wrong region code %#x in band B/G\n",
-		       region);
-		ret = -1;
-		goto out;
-	}
-	priv->region_channel[i].valid = 1;
-	priv->region_channel[i].region = region;
-	priv->region_channel[i].band = band;
-	i++;
-out:
-	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
-	return ret;
-}
-
 void lbs_queue_event(struct lbs_private *priv, u32 event)
 {
 	unsigned long flags;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
new file mode 100644
index 000000000000..2f91c9b808af
--- /dev/null
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -0,0 +1,1141 @@
+#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/kthread.h>
+#include <linux/kfifo.h>
+
+#include "mesh.h"
+#include "decl.h"
+#include "cmd.h"
+
+
+/***************************************************************************
+ * Mesh sysfs support
+ */
+
+/**
+ * Attributes exported through sysfs
+ */
+
+/**
+ * @brief Get function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
+}
+
+/**
+ * @brief Set function for sysfs attribute anycast_mask
+ */
+static ssize_t lbs_anycast_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	uint32_t datum;
+	int ret;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	sscanf(buf, "%x", &datum);
+	mesh_access.data[0] = cpu_to_le32(datum);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	u32 retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	retry_limit = le32_to_cpu(mesh_access.data[1]);
+	return snprintf(buf, 10, "%d\n", retry_limit);
+}
+
+/**
+ * @brief Set function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+	unsigned long retry_limit;
+
+	memset(&mesh_access, 0, sizeof(mesh_access));
+	mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
+
+	if (!strict_strtoul(buf, 10, &retry_limit))
+		return -ENOTSUPP;
+	if (retry_limit > 15)
+		return -ENOTSUPP;
+
+	mesh_access.data[1] = cpu_to_le32(retry_limit);
+
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+			&mesh_access);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * Get function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_get(struct device *dev,
+		struct device_attribute *attr, char * buf)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
+}
+
+/**
+ *  Set function for sysfs attribute mesh
+ */
+static ssize_t lbs_mesh_set(struct device *dev,
+		struct device_attribute *attr, const char * buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	int enable;
+	int ret, action = CMD_ACT_MESH_CONFIG_STOP;
+
+	sscanf(buf, "%x", &enable);
+	enable = !!enable;
+	if (enable == !!priv->mesh_dev)
+		return count;
+	if (enable)
+		action = CMD_ACT_MESH_CONFIG_START;
+	ret = lbs_mesh_config(priv, action, priv->channel);
+	if (ret)
+		return ret;
+
+	if (enable)
+		lbs_add_mesh(priv);
+	else
+		lbs_remove_mesh(priv);
+
+	return count;
+}
+
+/**
+ * lbs_mesh attribute to be exported per ethX interface
+ * through sysfs (/sys/class/net/ethX/lbs_mesh)
+ */
+static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
+
+/**
+ * anycast_mask attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/anycast_mask)
+ */
+static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
+
+/**
+ * prb_rsp_limit attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
+ */
+static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
+		lbs_prb_rsp_limit_set);
+
+static struct attribute *lbs_mesh_sysfs_entries[] = {
+	&dev_attr_anycast_mask.attr,
+	&dev_attr_prb_rsp_limit.attr,
+	NULL,
+};
+
+static struct attribute_group lbs_mesh_attr_group = {
+	.attrs = lbs_mesh_sysfs_entries,
+};
+
+
+
+/***************************************************************************
+ * Initializing and starting, stopping mesh
+ */
+
+/*
+ * Check mesh FW version and appropriately send the mesh start
+ * command
+ */
+int lbs_init_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	if (priv->mesh_fw_ver == MESH_FW_OLD) {
+		/* Enable mesh, if supported, and work out which TLV it uses.
+		   0x100 + 291 is an unofficial value used in 5.110.20.pXX
+		   0x100 + 37 is the official value used in 5.110.21.pXX
+		   but we check them in that order because 20.pXX doesn't
+		   give an error -- it just silently fails. */
+
+		/* 5.110.20.pXX firmware will fail the command if the channel
+		   doesn't match the existing channel. But only if the TLV
+		   is correct. If the channel is wrong, _BOTH_ versions will
+		   give an error to 0x100+291, and allow 0x100+37 to succeed.
+		   It's just that 5.110.20.pXX will not have done anything
+		   useful */
+
+		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel)) {
+			priv->mesh_tlv = TLV_TYPE_MESH_ID;
+			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+					    priv->channel))
+				priv->mesh_tlv = 0;
+		}
+	} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+		/* 10.0.0.pXX new firmwares should succeed with TLV
+		 * 0x100+37; Do not invoke command with old TLV.
+		 */
+		priv->mesh_tlv = TLV_TYPE_MESH_ID;
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+				    priv->channel))
+			priv->mesh_tlv = 0;
+	}
+	if (priv->mesh_tlv) {
+		lbs_add_mesh(priv);
+
+		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
+			lbs_pr_err("cannot register lbs_mesh attribute\n");
+
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+int lbs_deinit_mesh(struct lbs_private *priv)
+{
+	struct net_device *dev = priv->dev;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	if (priv->mesh_tlv) {
+		device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
+		ret = 1;
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+
+/**
+ *  @brief This function closes the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0
+ */
+static int lbs_mesh_stop(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	spin_lock_irq(&priv->driver_lock);
+
+	priv->mesh_open = 0;
+	priv->mesh_connect_status = LBS_DISCONNECTED;
+
+	netif_stop_queue(dev);
+	netif_carrier_off(dev);
+
+	spin_unlock_irq(&priv->driver_lock);
+
+	schedule_work(&priv->mcast_work);
+
+	lbs_deb_leave(LBS_DEB_MESH);
+	return 0;
+}
+
+/**
+ *  @brief This function opens the mshX interface
+ *
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   0 or -EBUSY if monitor mode active
+ */
+static int lbs_mesh_dev_open(struct net_device *dev)
+{
+	struct lbs_private *priv = dev->ml_priv;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_NET);
+
+	spin_lock_irq(&priv->driver_lock);
+
+	if (priv->monitormode) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	priv->mesh_open = 1;
+	priv->mesh_connect_status = LBS_CONNECTED;
+	netif_carrier_on(dev);
+
+	if (!priv->tx_pending_len)
+		netif_wake_queue(dev);
+ out:
+
+	spin_unlock_irq(&priv->driver_lock);
+	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
+	return ret;
+}
+
+static const struct net_device_ops mesh_netdev_ops = {
+	.ndo_open		= lbs_mesh_dev_open,
+	.ndo_stop 		= lbs_mesh_stop,
+	.ndo_start_xmit		= lbs_hard_start_xmit,
+	.ndo_set_mac_address	= lbs_set_mac_address,
+	.ndo_set_multicast_list = lbs_set_multicast_list,
+};
+
+/**
+ * @brief This function adds mshX interface
+ *
+ *  @param priv    A pointer to the struct lbs_private structure
+ *  @return 	   0 if successful, -X otherwise
+ */
+int lbs_add_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev = NULL;
+	int ret = 0;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+
+	/* Allocate a virtual mesh device */
+	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
+	if (!mesh_dev) {
+		lbs_deb_mesh("init mshX device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+	mesh_dev->ml_priv = priv;
+	priv->mesh_dev = mesh_dev;
+
+	mesh_dev->netdev_ops = &mesh_netdev_ops;
+	mesh_dev->ethtool_ops = &lbs_ethtool_ops;
+	memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
+			sizeof(priv->dev->dev_addr));
+
+	SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
+
+#ifdef	WIRELESS_EXT
+	mesh_dev->wireless_handlers = &mesh_handler_def;
+#endif
+	mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	/* Register virtual mesh interface */
+	ret = register_netdev(mesh_dev);
+	if (ret) {
+		lbs_pr_err("cannot register mshX virtual interface\n");
+		goto err_free;
+	}
+
+	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	if (ret)
+		goto err_unregister;
+
+	lbs_persist_config_init(mesh_dev);
+
+	/* Everything successful */
+	ret = 0;
+	goto done;
+
+err_unregister:
+	unregister_netdev(mesh_dev);
+
+err_free:
+	free_netdev(mesh_dev);
+
+done:
+	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
+	return ret;
+}
+
+void lbs_remove_mesh(struct lbs_private *priv)
+{
+	struct net_device *mesh_dev;
+
+	mesh_dev = priv->mesh_dev;
+	if (!mesh_dev)
+		return;
+
+	lbs_deb_enter(LBS_DEB_MESH);
+	netif_stop_queue(mesh_dev);
+	netif_carrier_off(mesh_dev);
+	sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
+	lbs_persist_config_remove(mesh_dev);
+	unregister_netdev(mesh_dev);
+	priv->mesh_dev = NULL;
+	free_netdev(mesh_dev);
+	lbs_deb_leave(LBS_DEB_MESH);
+}
+
+
+
+/***************************************************************************
+ * Sending and receiving
+ */
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd)
+{
+	if (priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD) {
+			if (rxpd->rx_control & RxPD_MESH_FRAME)
+				dev = priv->mesh_dev;
+		} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
+			if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
+				dev = priv->mesh_dev;
+		}
+	}
+	return dev;
+}
+
+
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd)
+{
+	if (dev == priv->mesh_dev) {
+		if (priv->mesh_fw_ver == MESH_FW_OLD)
+			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
+		else if (priv->mesh_fw_ver == MESH_FW_NEW)
+			txpd->u.bss.bss_num = MESH_IFACE_ID;
+	}
+}
+
+
+/***************************************************************************
+ * Mesh command handling
+ */
+
+int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
+			       u16 cmd_action, void *pdata_buf)
+{
+	struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	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);
+
+	switch (cmd_action) {
+	case CMD_ACT_BT_ACCESS_ADD:
+		memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
+		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);
+		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;
+	}
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
+			       u16 cmd_action, void *pdata_buf)
+{
+	struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
+	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;
+
+	if (pdata_buf)
+		memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
+	else
+		memset(fwt_access, 0, sizeof(*fwt_access));
+
+	fwt_access->action = cpu_to_le16(cmd_action);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
+		    struct cmd_ds_mesh_access *cmd)
+{
+	int ret;
+
+	lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
+
+	cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
+	cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
+	cmd->hdr.result = 0;
+
+	cmd->action = cpu_to_le16(cmd_action);
+
+	ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+static int __lbs_mesh_config_send(struct lbs_private *priv,
+				  struct cmd_ds_mesh_config *cmd,
+				  uint16_t action, uint16_t type)
+{
+	int ret;
+	u16 command = CMD_MESH_CONFIG_OLD;
+
+	lbs_deb_enter(LBS_DEB_CMD);
+
+	/*
+	 * Command id is 0xac for v10 FW along with mesh interface
+	 * id in bits 14-13-12.
+	 */
+	if (priv->mesh_fw_ver == MESH_FW_NEW)
+		command = CMD_MESH_CONFIG |
+			  (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
+
+	cmd->hdr.command = cpu_to_le16(command);
+	cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
+	cmd->hdr.result = 0;
+
+	cmd->type = cpu_to_le16(type);
+	cmd->action = cpu_to_le16(action);
+
+	ret = lbs_cmd_with_response(priv, command, cmd);
+
+	lbs_deb_leave(LBS_DEB_CMD);
+	return ret;
+}
+
+int lbs_mesh_config_send(struct lbs_private *priv,
+			 struct cmd_ds_mesh_config *cmd,
+			 uint16_t action, uint16_t type)
+{
+	int ret;
+
+	if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
+		return -EOPNOTSUPP;
+
+	ret = __lbs_mesh_config_send(priv, cmd, action, type);
+	return ret;
+}
+
+/* This function is the CMD_MESH_CONFIG legacy function.  It only handles the
+ * START and STOP actions.  The extended actions supported by CMD_MESH_CONFIG
+ * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
+ * lbs_mesh_config_send.
+ */
+int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_meshie *ie;
+	DECLARE_SSID_BUF(ssid);
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.channel = cpu_to_le16(chan);
+	ie = (struct mrvl_meshie *)cmd.data;
+
+	switch (action) {
+	case CMD_ACT_MESH_CONFIG_START:
+		ie->id = WLAN_EID_GENERIC;
+		ie->val.oui[0] = 0x00;
+		ie->val.oui[1] = 0x50;
+		ie->val.oui[2] = 0x43;
+		ie->val.type = MARVELL_MESH_IE_TYPE;
+		ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
+		ie->val.version = MARVELL_MESH_IE_VERSION;
+		ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
+		ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
+		ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
+		ie->val.mesh_id_len = priv->mesh_ssid_len;
+		memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
+		ie->len = sizeof(struct mrvl_meshie_val) -
+			IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
+		cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
+		break;
+	case CMD_ACT_MESH_CONFIG_STOP:
+		break;
+	default:
+		return -1;
+	}
+	lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
+		    action, priv->mesh_tlv, chan,
+		    print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
+
+	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
+}
+
+
+
+/***************************************************************************
+ * Persistent configuration support
+ */
+
+static int mesh_get_default_parameters(struct device *dev,
+				       struct mrvl_mesh_defaults *defs)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	int ret;
+
+	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
+				   CMD_TYPE_MESH_GET_DEFAULTS);
+
+	if (ret)
+		return -EOPNOTSUPP;
+
+	memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
+
+	return 0;
+}
+
+/**
+ * @brief Get function for sysfs attribute bootflag
+ */
+static ssize_t bootflag_get(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
+}
+
+/**
+ * @brief Set function for sysfs attribute bootflag
+ */
+static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 1))
+		return -EINVAL;
+
+	*((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
+	cmd.length = cpu_to_le16(sizeof(uint32_t));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_BOOTFLAG);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute boottime
+ */
+static ssize_t boottime_get(struct device *dev,
+			    struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "%d\n", defs.boottime);
+}
+
+/**
+ * @brief Set function for sysfs attribute boottime
+ */
+static ssize_t boottime_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* A too small boot time will result in the device booting into
+	 * standalone (no-host) mode before the host can take control of it,
+	 * so the change will be hard to revert.  This may be a desired
+	 * feature (e.g to configure a very fast boot time for devices that
+	 * will not be attached to a host), but dangerous.  So I'm enforcing a
+	 * lower limit of 20 seconds:  remove and recompile the driver if this
+	 * does not work for you.
+	 */
+	datum = (datum < 20) ? 20 : datum;
+	cmd.data[0] = datum;
+	cmd.length = cpu_to_le16(sizeof(uint8_t));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_BOOTTIME);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute channel
+ */
+static ssize_t channel_get(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
+}
+
+/**
+ * @brief Set function for sysfs attribute channel
+ */
+static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	struct cmd_ds_mesh_config cmd;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if (ret != 1 || datum < 1 || datum > 11)
+		return -EINVAL;
+
+	*((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
+	cmd.length = cpu_to_le16(sizeof(uint16_t));
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_DEF_CHANNEL);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute mesh_id
+ */
+static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int maxlen;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) {
+		lbs_pr_err("inconsistent mesh ID length");
+		defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
+	}
+
+	/* SSID not null terminated: reserve room for \0 + \n */
+	maxlen = defs.meshie.val.mesh_id_len + 2;
+	maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
+
+	defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
+
+	return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
+}
+
+/**
+ * @brief Set function for sysfs attribute mesh_id
+ */
+static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	int len;
+	int ret;
+
+	if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1)
+		return -EINVAL;
+
+	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+
+	len = count - 1;
+	memcpy(ie->val.mesh_id, buf, len);
+	/* SSID len */
+	ie->val.mesh_id_len = len;
+	/* IE len */
+	ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute protocol_id
+ */
+static ssize_t protocol_id_get(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
+}
+
+/**
+ * @brief Set function for sysfs attribute protocol_id
+ */
+static ssize_t protocol_id_set(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+	/* update protocol id */
+	ie->val.active_protocol_id = datum;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute metric_id
+ */
+static ssize_t metric_id_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
+}
+
+/**
+ * @brief Set function for sysfs attribute metric_id
+ */
+static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+	/* update metric id */
+	ie->val.active_metric_id = datum;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+/**
+ * @brief Get function for sysfs attribute capability
+ */
+static ssize_t capability_get(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct mrvl_mesh_defaults defs;
+	int ret;
+
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	if (ret)
+		return ret;
+
+	return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
+}
+
+/**
+ * @brief Set function for sysfs attribute capability
+ */
+static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct cmd_ds_mesh_config cmd;
+	struct mrvl_mesh_defaults defs;
+	struct mrvl_meshie *ie;
+	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
+	uint32_t datum;
+	int ret;
+
+	memset(&cmd, 0, sizeof(cmd));
+	ret = sscanf(buf, "%d", &datum);
+	if ((ret != 1) || (datum > 255))
+		return -EINVAL;
+
+	/* fetch all other Information Element parameters */
+	ret = mesh_get_default_parameters(dev, &defs);
+
+	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
+
+	/* transfer IE elements */
+	ie = (struct mrvl_meshie *) &cmd.data[0];
+	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
+	/* update value */
+	ie->val.mesh_capability = datum;
+
+	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
+				   CMD_TYPE_MESH_SET_MESH_IE);
+	if (ret)
+		return ret;
+
+	return strlen(buf);
+}
+
+
+static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
+static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
+static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
+static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
+static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
+static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
+static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
+
+static struct attribute *boot_opts_attrs[] = {
+	&dev_attr_bootflag.attr,
+	&dev_attr_boottime.attr,
+	&dev_attr_channel.attr,
+	NULL
+};
+
+static struct attribute_group boot_opts_group = {
+	.name = "boot_options",
+	.attrs = boot_opts_attrs,
+};
+
+static struct attribute *mesh_ie_attrs[] = {
+	&dev_attr_mesh_id.attr,
+	&dev_attr_protocol_id.attr,
+	&dev_attr_metric_id.attr,
+	&dev_attr_capability.attr,
+	NULL
+};
+
+static struct attribute_group mesh_ie_group = {
+	.name = "mesh_ie",
+	.attrs = mesh_ie_attrs,
+};
+
+void lbs_persist_config_init(struct net_device *dev)
+{
+	int ret;
+	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
+	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
+}
+
+void lbs_persist_config_remove(struct net_device *dev)
+{
+	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
+	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
+}
+
+
+
+/***************************************************************************
+ * Ethtool related
+ */
+
+static const char *mesh_stat_strings[] = {
+			"drop_duplicate_bcast",
+			"drop_ttl_zero",
+			"drop_no_fwd_route",
+			"drop_no_buffers",
+			"fwded_unicast_cnt",
+			"fwded_bcast_cnt",
+			"drop_blind_table",
+			"tx_failed_cnt"
+};
+
+void lbs_mesh_ethtool_get_stats(struct net_device *dev,
+	struct ethtool_stats *stats, uint64_t *data)
+{
+	struct lbs_private *priv = dev->ml_priv;
+	struct cmd_ds_mesh_access mesh_access;
+	int ret;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
+	/* Get Mesh Statistics */
+	ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
+
+	if (ret) {
+		memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
+		return;
+	}
+
+	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
+	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
+	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
+	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
+	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
+	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
+	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
+	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
+
+	data[0] = priv->mstats.fwd_drop_rbt;
+	data[1] = priv->mstats.fwd_drop_ttl;
+	data[2] = priv->mstats.fwd_drop_noroute;
+	data[3] = priv->mstats.fwd_drop_nobuf;
+	data[4] = priv->mstats.fwd_unicast_cnt;
+	data[5] = priv->mstats.fwd_bcast_cnt;
+	data[6] = priv->mstats.drop_blind;
+	data[7] = priv->mstats.tx_failed_cnt;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+}
+
+int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
+{
+	struct lbs_private *priv = dev->ml_priv;
+
+	if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
+		return MESH_STATS_NUM;
+
+	return -EOPNOTSUPP;
+}
+
+void lbs_mesh_ethtool_get_strings(struct net_device *dev,
+	uint32_t stringset, uint8_t *s)
+{
+	int i;
+
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < MESH_STATS_NUM; i++) {
+			memcpy(s + i * ETH_GSTRING_LEN,
+					mesh_stat_strings[i],
+					ETH_GSTRING_LEN);
+		}
+		break;
+	}
+	lbs_deb_enter(LBS_DEB_ETHTOOL);
+}
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
new file mode 100644
index 000000000000..fea9b5d005fc
--- /dev/null
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -0,0 +1,78 @@
+/**
+  * Contains all definitions needed for the Libertas' MESH implementation.
+  */
+#ifndef _LBS_MESH_H_
+#define _LBS_MESH_H_
+
+
+#include <net/iw_handler.h>
+#include <net/lib80211.h>
+
+
+/* Mesh statistics */
+struct lbs_mesh_stats {
+	u32	fwd_bcast_cnt;		/* Fwd: Broadcast counter */
+	u32	fwd_unicast_cnt;	/* Fwd: Unicast counter */
+	u32	fwd_drop_ttl;		/* Fwd: TTL zero */
+	u32	fwd_drop_rbt;		/* Fwd: Recently Broadcasted */
+	u32	fwd_drop_noroute; 	/* Fwd: No route to Destination */
+	u32	fwd_drop_nobuf;		/* Fwd: Run out of internal buffers */
+	u32	drop_blind;		/* Rx:  Dropped by blinding table */
+	u32	tx_failed_cnt;		/* Tx:  Failed transmissions */
+};
+
+
+struct net_device;
+struct lbs_private;
+
+int lbs_init_mesh(struct lbs_private *priv);
+int lbs_deinit_mesh(struct lbs_private *priv);
+
+int lbs_add_mesh(struct lbs_private *priv);
+void lbs_remove_mesh(struct lbs_private *priv);
+
+
+/* Sending / Receiving */
+
+struct rxpd;
+struct txpd;
+
+struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
+	struct net_device *dev, struct rxpd *rxpd);
+void lbs_mesh_set_txpd(struct lbs_private *priv,
+	struct net_device *dev, struct txpd *txpd);
+
+
+/* Command handling */
+
+struct cmd_ds_command;
+
+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);
+
+
+/* Persistent configuration */
+
+void lbs_persist_config_init(struct net_device *net);
+void lbs_persist_config_remove(struct net_device *net);
+
+
+/* WEXT handler */
+
+extern struct iw_handler_def mesh_handler_def;
+
+
+/* Ethtool statistics */
+
+struct ethtool_stats;
+
+void lbs_mesh_ethtool_get_stats(struct net_device *dev,
+	struct ethtool_stats *stats, uint64_t *data);
+int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
+void lbs_mesh_ethtool_get_strings(struct net_device *dev,
+	uint32_t stringset, uint8_t *s);
+
+
+#endif
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c
deleted file mode 100644
index 18fe29faf99b..000000000000
--- a/drivers/net/wireless/libertas/persistcfg.c
+++ /dev/null
@@ -1,453 +0,0 @@
-#include <linux/moduleparam.h>
-#include <linux/delay.h>
-#include <linux/etherdevice.h>
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/kthread.h>
-#include <linux/kfifo.h>
-
-#include "host.h"
-#include "decl.h"
-#include "dev.h"
-#include "wext.h"
-#include "debugfs.h"
-#include "scan.h"
-#include "assoc.h"
-#include "cmd.h"
-
-static int mesh_get_default_parameters(struct device *dev,
-				       struct mrvl_mesh_defaults *defs)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	int ret;
-
-	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
-				   CMD_TYPE_MESH_GET_DEFAULTS);
-
-	if (ret)
-		return -EOPNOTSUPP;
-
-	memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
-
-	return 0;
-}
-
-/**
- * @brief Get function for sysfs attribute bootflag
- */
-static ssize_t bootflag_get(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
-}
-
-/**
- * @brief Set function for sysfs attribute bootflag
- */
-static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
-			    const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 1))
-		return -EINVAL;
-
-	*((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
-	cmd.length = cpu_to_le16(sizeof(uint32_t));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_BOOTFLAG);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute boottime
- */
-static ssize_t boottime_get(struct device *dev,
-			    struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "%d\n", defs.boottime);
-}
-
-/**
- * @brief Set function for sysfs attribute boottime
- */
-static ssize_t boottime_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
-
-	/* A too small boot time will result in the device booting into
-	 * standalone (no-host) mode before the host can take control of it,
-	 * so the change will be hard to revert.  This may be a desired
-	 * feature (e.g to configure a very fast boot time for devices that
-	 * will not be attached to a host), but dangerous.  So I'm enforcing a
-	 * lower limit of 20 seconds:  remove and recompile the driver if this
-	 * does not work for you.
-	 */
-	datum = (datum < 20) ? 20 : datum;
-	cmd.data[0] = datum;
-	cmd.length = cpu_to_le16(sizeof(uint8_t));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_BOOTTIME);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute channel
- */
-static ssize_t channel_get(struct device *dev,
-			   struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
-}
-
-/**
- * @brief Set function for sysfs attribute channel
- */
-static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	struct cmd_ds_mesh_config cmd;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if (ret != 1 || datum < 1 || datum > 11)
-		return -EINVAL;
-
-	*((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
-	cmd.length = cpu_to_le16(sizeof(uint16_t));
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_DEF_CHANNEL);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute mesh_id
- */
-static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
-			   char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int maxlen;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) {
-		lbs_pr_err("inconsistent mesh ID length");
-		defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE;
-	}
-
-	/* SSID not null terminated: reserve room for \0 + \n */
-	maxlen = defs.meshie.val.mesh_id_len + 2;
-	maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
-
-	defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
-
-	return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
-}
-
-/**
- * @brief Set function for sysfs attribute mesh_id
- */
-static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	int len;
-	int ret;
-
-	if (count < 2 || count > IW_ESSID_MAX_SIZE + 1)
-		return -EINVAL;
-
-	memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
-
-	/* transfer IE elements */
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-
-	len = count - 1;
-	memcpy(ie->val.mesh_id, buf, len);
-	/* SSID len */
-	ie->val.mesh_id_len = len;
-	/* IE len */
-	ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
-
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute protocol_id
- */
-static ssize_t protocol_id_get(struct device *dev,
-			       struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
-}
-
-/**
- * @brief Set function for sysfs attribute protocol_id
- */
-static ssize_t protocol_id_set(struct device *dev,
-		struct device_attribute *attr, const char *buf, size_t count)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
-
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
-
-	/* transfer IE elements */
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-	/* update protocol id */
-	ie->val.active_protocol_id = datum;
-
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute metric_id
- */
-static ssize_t metric_id_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
-}
-
-/**
- * @brief Set function for sysfs attribute metric_id
- */
-static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
-
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
-
-	/* transfer IE elements */
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-	/* update metric id */
-	ie->val.active_metric_id = datum;
-
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-/**
- * @brief Get function for sysfs attribute capability
- */
-static ssize_t capability_get(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	struct mrvl_mesh_defaults defs;
-	int ret;
-
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	if (ret)
-		return ret;
-
-	return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
-}
-
-/**
- * @brief Set function for sysfs attribute capability
- */
-static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct cmd_ds_mesh_config cmd;
-	struct mrvl_mesh_defaults defs;
-	struct mrvl_meshie *ie;
-	struct lbs_private *priv = to_net_dev(dev)->ml_priv;
-	uint32_t datum;
-	int ret;
-
-	memset(&cmd, 0, sizeof(cmd));
-	ret = sscanf(buf, "%d", &datum);
-	if ((ret != 1) || (datum > 255))
-		return -EINVAL;
-
-	/* fetch all other Information Element parameters */
-	ret = mesh_get_default_parameters(dev, &defs);
-
-	cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
-
-	/* transfer IE elements */
-	ie = (struct mrvl_meshie *) &cmd.data[0];
-	memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
-	/* update value */
-	ie->val.mesh_capability = datum;
-
-	ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
-				   CMD_TYPE_MESH_SET_MESH_IE);
-	if (ret)
-		return ret;
-
-	return strlen(buf);
-}
-
-
-static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
-static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
-static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
-static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
-static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
-static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
-static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
-
-static struct attribute *boot_opts_attrs[] = {
-	&dev_attr_bootflag.attr,
-	&dev_attr_boottime.attr,
-	&dev_attr_channel.attr,
-	NULL
-};
-
-static struct attribute_group boot_opts_group = {
-	.name = "boot_options",
-	.attrs = boot_opts_attrs,
-};
-
-static struct attribute *mesh_ie_attrs[] = {
-	&dev_attr_mesh_id.attr,
-	&dev_attr_protocol_id.attr,
-	&dev_attr_metric_id.attr,
-	&dev_attr_capability.attr,
-	NULL
-};
-
-static struct attribute_group mesh_ie_group = {
-	.name = "mesh_ie",
-	.attrs = mesh_ie_attrs,
-};
-
-void lbs_persist_config_init(struct net_device *dev)
-{
-	int ret;
-	ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
-	ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
-}
-
-void lbs_persist_config_remove(struct net_device *dev)
-{
-	sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
-	sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
-}
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 65f02cc6752f..2daf8ffdb7e1 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -4,7 +4,7 @@
 #include <linux/etherdevice.h>
 #include <linux/types.h>
 
-#include "hostcmd.h"
+#include "host.h"
 #include "radiotap.h"
 #include "decl.h"
 #include "dev.h"
@@ -160,15 +160,8 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
 	p_rx_pd = (struct rxpd *) skb->data;
 	p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
 		le32_to_cpu(p_rx_pd->pkt_ptr));
-	if (priv->mesh_dev) {
-		if (priv->mesh_fw_ver == MESH_FW_OLD) {
-			if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
-				dev = priv->mesh_dev;
-		} else if (priv->mesh_fw_ver == MESH_FW_NEW) {
-			if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID)
-				dev = priv->mesh_dev;
-		}
-	}
+
+	dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
 
 	lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
 		 min_t(unsigned int, skb->len, 100));
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 6c95af3023cc..c6a6c042b82f 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -12,18 +12,19 @@
 #include <net/lib80211.h>
 
 #include "host.h"
-#include "decl.h"
 #include "dev.h"
 #include "scan.h"
+#include "assoc.h"
+#include "wext.h"
 #include "cmd.h"
 
 //! Approximate amount of data needed to pass a scan result back to iwlist
 #define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \
-                             + IW_ESSID_MAX_SIZE        \
+                             + IEEE80211_MAX_SSID_LEN   \
                              + IW_EV_UINT_LEN           \
                              + IW_EV_FREQ_LEN           \
                              + IW_EV_QUAL_LEN           \
-                             + IW_ESSID_MAX_SIZE        \
+                             + IEEE80211_MAX_SSID_LEN   \
                              + IW_EV_PARAM_LEN          \
                              + 40)	/* 40 for WPAIE */
 
@@ -121,6 +122,189 @@ static inline int is_same_network(struct bss_descriptor *src,
 
 
 
+/*********************************************************************/
+/*                                                                   */
+/* Region channel support                                            */
+/*                                                                   */
+/*********************************************************************/
+
+#define LBS_TX_PWR_DEFAULT		20	/*100mW */
+#define LBS_TX_PWR_US_DEFAULT		20	/*100mW */
+#define LBS_TX_PWR_JP_DEFAULT		16	/*50mW */
+#define LBS_TX_PWR_FR_DEFAULT		20	/*100mW */
+#define LBS_TX_PWR_EMEA_DEFAULT	20	/*100mW */
+
+/* Format { channel, frequency (MHz), maxtxpower } */
+/* band: 'B/G', region: USA FCC/Canada IC */
+static struct chan_freq_power channel_freq_power_US_BG[] = {
+	{1, 2412, LBS_TX_PWR_US_DEFAULT},
+	{2, 2417, LBS_TX_PWR_US_DEFAULT},
+	{3, 2422, LBS_TX_PWR_US_DEFAULT},
+	{4, 2427, LBS_TX_PWR_US_DEFAULT},
+	{5, 2432, LBS_TX_PWR_US_DEFAULT},
+	{6, 2437, LBS_TX_PWR_US_DEFAULT},
+	{7, 2442, LBS_TX_PWR_US_DEFAULT},
+	{8, 2447, LBS_TX_PWR_US_DEFAULT},
+	{9, 2452, LBS_TX_PWR_US_DEFAULT},
+	{10, 2457, LBS_TX_PWR_US_DEFAULT},
+	{11, 2462, LBS_TX_PWR_US_DEFAULT}
+};
+
+/* band: 'B/G', region: Europe ETSI */
+static struct chan_freq_power channel_freq_power_EU_BG[] = {
+	{1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
+	{2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
+	{3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
+	{4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
+	{5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
+	{6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
+	{7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
+	{8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
+	{9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
+	{10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
+	{11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
+	{12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
+	{13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
+};
+
+/* band: 'B/G', region: Spain */
+static struct chan_freq_power channel_freq_power_SPN_BG[] = {
+	{10, 2457, LBS_TX_PWR_DEFAULT},
+	{11, 2462, LBS_TX_PWR_DEFAULT}
+};
+
+/* band: 'B/G', region: France */
+static struct chan_freq_power channel_freq_power_FR_BG[] = {
+	{10, 2457, LBS_TX_PWR_FR_DEFAULT},
+	{11, 2462, LBS_TX_PWR_FR_DEFAULT},
+	{12, 2467, LBS_TX_PWR_FR_DEFAULT},
+	{13, 2472, LBS_TX_PWR_FR_DEFAULT}
+};
+
+/* band: 'B/G', region: Japan */
+static struct chan_freq_power channel_freq_power_JPN_BG[] = {
+	{1, 2412, LBS_TX_PWR_JP_DEFAULT},
+	{2, 2417, LBS_TX_PWR_JP_DEFAULT},
+	{3, 2422, LBS_TX_PWR_JP_DEFAULT},
+	{4, 2427, LBS_TX_PWR_JP_DEFAULT},
+	{5, 2432, LBS_TX_PWR_JP_DEFAULT},
+	{6, 2437, LBS_TX_PWR_JP_DEFAULT},
+	{7, 2442, LBS_TX_PWR_JP_DEFAULT},
+	{8, 2447, LBS_TX_PWR_JP_DEFAULT},
+	{9, 2452, LBS_TX_PWR_JP_DEFAULT},
+	{10, 2457, LBS_TX_PWR_JP_DEFAULT},
+	{11, 2462, LBS_TX_PWR_JP_DEFAULT},
+	{12, 2467, LBS_TX_PWR_JP_DEFAULT},
+	{13, 2472, LBS_TX_PWR_JP_DEFAULT},
+	{14, 2484, LBS_TX_PWR_JP_DEFAULT}
+};
+
+/**
+ * the structure for channel, frequency and power
+ */
+struct region_cfp_table {
+	u8 region;
+	struct chan_freq_power *cfp_BG;
+	int cfp_no_BG;
+};
+
+/**
+ * the structure for the mapping between region and CFP
+ */
+static struct region_cfp_table region_cfp_table[] = {
+	{0x10,			/*US FCC */
+	 channel_freq_power_US_BG,
+	 ARRAY_SIZE(channel_freq_power_US_BG),
+	 }
+	,
+	{0x20,			/*CANADA IC */
+	 channel_freq_power_US_BG,
+	 ARRAY_SIZE(channel_freq_power_US_BG),
+	 }
+	,
+	{0x30, /*EU*/ channel_freq_power_EU_BG,
+	 ARRAY_SIZE(channel_freq_power_EU_BG),
+	 }
+	,
+	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
+	 ARRAY_SIZE(channel_freq_power_SPN_BG),
+	 }
+	,
+	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
+	 ARRAY_SIZE(channel_freq_power_FR_BG),
+	 }
+	,
+	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
+	 ARRAY_SIZE(channel_freq_power_JPN_BG),
+	 }
+	,
+/*Add new region here */
+};
+
+/**
+ *  @brief This function finds the CFP in
+ *  region_cfp_table based on region and band parameter.
+ *
+ *  @param region  The region code
+ *  @param band	   The band
+ *  @param cfp_no  A pointer to CFP number
+ *  @return 	   A pointer to CFP
+ */
+static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
+{
+	int i, end;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	end = ARRAY_SIZE(region_cfp_table);
+
+	for (i = 0; i < end ; i++) {
+		lbs_deb_main("region_cfp_table[i].region=%d\n",
+			region_cfp_table[i].region);
+		if (region_cfp_table[i].region == region) {
+			*cfp_no = region_cfp_table[i].cfp_no_BG;
+			lbs_deb_leave(LBS_DEB_MAIN);
+			return region_cfp_table[i].cfp_BG;
+		}
+	}
+
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
+	return NULL;
+}
+
+int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
+{
+	int ret = 0;
+	int i = 0;
+
+	struct chan_freq_power *cfp;
+	int cfp_no;
+
+	lbs_deb_enter(LBS_DEB_MAIN);
+
+	memset(priv->region_channel, 0, sizeof(priv->region_channel));
+
+	cfp = lbs_get_region_cfp_table(region, &cfp_no);
+	if (cfp != NULL) {
+		priv->region_channel[i].nrcfp = cfp_no;
+		priv->region_channel[i].CFP = cfp;
+	} else {
+		lbs_deb_main("wrong region code %#x in band B/G\n",
+		       region);
+		ret = -1;
+		goto out;
+	}
+	priv->region_channel[i].valid = 1;
+	priv->region_channel[i].region = region;
+	priv->region_channel[i].band = band;
+	i++;
+out:
+	lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
+	return ret;
+}
+
+
+
 
 /*********************************************************************/
 /*                                                                   */
@@ -161,31 +345,15 @@ static int lbs_scan_create_channel_list(struct lbs_private *priv,
 	scantype = CMD_SCAN_TYPE_ACTIVE;
 
 	for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
-		if (priv->enable11d && (priv->connect_status != LBS_CONNECTED)
-		    && (priv->mesh_connect_status != LBS_CONNECTED)) {
-			/* Scan all the supported chan for the first scan */
-			if (!priv->universal_channel[rgnidx].valid)
-				continue;
-			scanregion = &priv->universal_channel[rgnidx];
-
-			/* clear the parsed_region_chan for the first scan */
-			memset(&priv->parsed_region_chan, 0x00,
-			       sizeof(priv->parsed_region_chan));
-		} else {
-			if (!priv->region_channel[rgnidx].valid)
-				continue;
-			scanregion = &priv->region_channel[rgnidx];
-		}
+		if (!priv->region_channel[rgnidx].valid)
+			continue;
+		scanregion = &priv->region_channel[rgnidx];
 
 		for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
 			struct chanscanparamset *chan = &scanchanlist[chanidx];
 
 			cfp = scanregion->CFP + nextchan;
 
-			if (priv->enable11d)
-				scantype = lbs_get_scan_type_11d(cfp->channel,
-								 &priv->parsed_region_chan);
-
 			if (scanregion->band == BAND_B || scanregion->band == BAND_G)
 				chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
 
@@ -519,7 +687,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
 	struct ieee_ie_cf_param_set *cf;
 	struct ieee_ie_ibss_param_set *ibss;
 	DECLARE_SSID_BUF(ssid);
-	struct ieee_ie_country_info_set *pcountryinfo;
 	uint8_t *pos, *end, *p;
 	uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
 	uint16_t beaconsize = 0;
@@ -642,26 +809,6 @@ static int lbs_process_bss(struct bss_descriptor *bss,
 			lbs_deb_scan("got IBSS IE\n");
 			break;
 
-		case WLAN_EID_COUNTRY:
-			pcountryinfo = (struct ieee_ie_country_info_set *) pos;
-			lbs_deb_scan("got COUNTRY IE\n");
-			if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode)
-			    || pcountryinfo->header.len > 254) {
-				lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n",
-					     __func__,
-					     pcountryinfo->header.len,
-					     sizeof(pcountryinfo->countrycode));
-				ret = -1;
-				goto done;
-			}
-
-			memcpy(&bss->countryinfo, pcountryinfo,
-				pcountryinfo->header.len + 2);
-			lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo",
-				    (uint8_t *) pcountryinfo,
-				    (int) (pcountryinfo->header.len + 2));
-			break;
-
 		case WLAN_EID_EXT_SUPP_RATES:
 			/* only process extended supported rate if data rate is
 			 * already found. Data rate IE should come before
@@ -812,7 +959,7 @@ static inline char *lbs_translate_scan(struct lbs_private *priv,
 	/* SSID */
 	iwe.cmd = SIOCGIWESSID;
 	iwe.u.data.flags = 1;
-	iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE);
+	iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
 	start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
 
 	/* Mode */
@@ -1022,9 +1169,12 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
 		return -EAGAIN;
 
 	/* Update RSSI if current BSS is a locally created ad-hoc BSS */
-	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate)
-		lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
-					     CMD_OPTION_WAITFORRSP, 0, NULL);
+	if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
+		err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+				CMD_OPTION_WAITFORRSP, 0, NULL);
+		if (err)
+			goto out;
+	}
 
 	mutex_lock(&priv->lock);
 	list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
@@ -1058,7 +1208,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
 
 	dwrq->length = (ev - extra);
 	dwrq->flags = 0;
-
+out:
 	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
 	return err;
 }
@@ -1141,11 +1291,11 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
 	/* The size of the TLV buffer is equal to the entire command response
 	 *   size (scanrespsize) minus the fixed fields (sizeof()'s), the
 	 *   BSS Descriptions (bssdescriptsize as bytesLef) and the command
-	 *   response header (S_DS_GEN)
+	 *   response header (sizeof(struct cmd_header))
 	 */
 	tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
 				     + sizeof(scanresp->nr_sets)
-				     + S_DS_GEN);
+				     + sizeof(struct cmd_header));
 
 	/*
 	 *  Process each scan response returned (scanresp->nr_sets). Save
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index fab7d5d097fc..8fb1706d7526 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -9,8 +9,36 @@
 
 #include <net/iw_handler.h>
 
+struct lbs_private;
+
 #define MAX_NETWORK_COUNT 128
 
+/** Chan-freq-TxPower mapping table*/
+struct chan_freq_power {
+	/** channel Number		*/
+	u16 channel;
+	/** frequency of this channel	*/
+	u32 freq;
+	/** Max allowed Tx power level	*/
+	u16 maxtxpower;
+	/** TRUE:channel unsupported;  FLASE:supported*/
+	u8 unsupported;
+};
+
+/** region-band mapping table*/
+struct region_channel {
+	/** TRUE if this entry is valid		     */
+	u8 valid;
+	/** region code for US, Japan ...	     */
+	u8 region;
+	/** band B/G/A, used for BAND_CONFIG cmd	     */
+	u8 band;
+	/** Actual No. of elements in the array below */
+	u8 nrcfp;
+	/** chan-freq-txpower mapping table*/
+	struct chan_freq_power *CFP;
+};
+
 /**
  *  @brief Maximum number of channels that can be sent in a setuserscan ioctl
  */
@@ -18,6 +46,8 @@
 
 int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
 
+int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
+
 int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
 				u8 ssid_len);
 
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index 8c3766a6e8e7..315d1ce286ca 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -5,7 +5,7 @@
 #include <linux/etherdevice.h>
 #include <linux/sched.h>
 
-#include "hostcmd.h"
+#include "host.h"
 #include "radiotap.h"
 #include "decl.h"
 #include "defs.h"
@@ -131,12 +131,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	txpd->tx_packet_length = cpu_to_le16(pkt_len);
 	txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
 
-	if (dev == priv->mesh_dev) {
-		if (priv->mesh_fw_ver == MESH_FW_OLD)
-			txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
-		else if (priv->mesh_fw_ver == MESH_FW_NEW)
-			txpd->u.bss.bss_num = MESH_IFACE_ID;
-	}
+	lbs_mesh_set_txpd(priv, dev, txpd);
 
 	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
 
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 99905df65b25..3e72c86ceca8 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -5,8 +5,8 @@
 #define _LBS_TYPES_H_
 
 #include <linux/if_ether.h>
+#include <linux/ieee80211.h>
 #include <asm/byteorder.h>
-#include <linux/wireless.h>
 
 struct ieee_ie_header {
 	u8 id;
@@ -247,7 +247,7 @@ struct mrvl_meshie_val {
 	uint8_t active_metric_id;
 	uint8_t mesh_capability;
 	uint8_t mesh_id_len;
-	uint8_t mesh_id[IW_ESSID_MAX_SIZE];
+	uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
 } __attribute__ ((packed));
 
 struct mrvl_meshie {
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index be837a0d2517..a8eb9e1fcf36 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -45,6 +45,63 @@ static inline void lbs_cancel_association_work(struct lbs_private *priv)
 	priv->pending_assoc_req = NULL;
 }
 
+void lbs_send_disconnect_notification(struct lbs_private *priv)
+{
+	union iwreq_data wrqu;
+
+	memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
+}
+
+static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
+{
+	union iwreq_data iwrq;
+	u8 buf[50];
+
+	lbs_deb_enter(LBS_DEB_WEXT);
+
+	memset(&iwrq, 0, sizeof(union iwreq_data));
+	memset(buf, 0, sizeof(buf));
+
+	snprintf(buf, sizeof(buf) - 1, "%s", str);
+
+	iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
+
+	/* Send Event to upper layer */
+	lbs_deb_wext("event indication string %s\n", (char *)buf);
+	lbs_deb_wext("event indication length %d\n", iwrq.data.length);
+	lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
+
+	wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
+
+	lbs_deb_leave(LBS_DEB_WEXT);
+}
+
+/**
+ *  @brief This function handles MIC failure event.
+ *
+ *  @param priv    A pointer to struct lbs_private structure
+ *  @para  event   the event id
+ *  @return 	   n/a
+ */
+void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
+{
+	char buf[50];
+
+	lbs_deb_enter(LBS_DEB_CMD);
+	memset(buf, 0, sizeof(buf));
+
+	sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
+
+	if (event == MACREG_INT_CODE_MIC_ERR_UNICAST)
+		strcat(buf, "unicast ");
+	else
+		strcat(buf, "multicast ");
+
+	lbs_send_iwevcustom_event(priv, buf);
+	lbs_deb_leave(LBS_DEB_CMD);
+}
 
 /**
  *  @brief Find the channel frequency power info with specific channel
@@ -66,8 +123,6 @@ struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
 	for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
 		rc = &priv->region_channel[j];
 
-		if (priv->enable11d)
-			rc = &priv->universal_channel[j];
 		if (!rc->valid || !rc->CFP)
 			continue;
 		if (rc->band != band)
@@ -107,8 +162,6 @@ static struct chan_freq_power *find_cfp_by_band_and_freq(
 	for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
 		rc = &priv->region_channel[j];
 
-		if (priv->enable11d)
-			rc = &priv->universal_channel[j];
 		if (!rc->valid || !rc->CFP)
 			continue;
 		if (rc->band != band)
@@ -169,12 +222,12 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
 	lbs_deb_enter(LBS_DEB_WEXT);
 
 	cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
-					   priv->curbssparams.channel);
+					   priv->channel);
 
 	if (!cfp) {
-		if (priv->curbssparams.channel)
+		if (priv->channel)
 			lbs_deb_wext("invalid channel %d\n",
-			       priv->curbssparams.channel);
+			       priv->channel);
 		return -EINVAL;
 	}
 
@@ -547,8 +600,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
 	struct chan_freq_power *cfp;
 	u8 rates[MAX_RATES + 1];
 
-	u8 flag = 0;
-
 	lbs_deb_enter(LBS_DEB_WEXT);
 
 	dwrq->length = sizeof(struct iw_range);
@@ -570,52 +621,21 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
 
 	range->scan_capa = IW_SCAN_CAPA_ESSID;
 
-	if (priv->enable11d &&
-	    (priv->connect_status == LBS_CONNECTED ||
-	    priv->mesh_connect_status == LBS_CONNECTED)) {
-		u8 chan_no;
-		u8 band;
-
-		struct parsed_region_chan_11d *parsed_region_chan =
-		    &priv->parsed_region_chan;
-
-		if (parsed_region_chan == NULL) {
-			lbs_deb_wext("11d: parsed_region_chan is NULL\n");
-			goto out;
-		}
-		band = parsed_region_chan->band;
-		lbs_deb_wext("band %d, nr_char %d\n", band,
-		       parsed_region_chan->nr_chan);
-
+	for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+	     && (j < ARRAY_SIZE(priv->region_channel)); j++) {
+		cfp = priv->region_channel[j].CFP;
 		for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-		     && (i < parsed_region_chan->nr_chan); i++) {
-			chan_no = parsed_region_chan->chanpwr[i].chan;
-			lbs_deb_wext("chan_no %d\n", chan_no);
-			range->freq[range->num_frequency].i = (long)chan_no;
+		     && priv->region_channel[j].valid
+		     && cfp
+		     && (i < priv->region_channel[j].nrcfp); i++) {
+			range->freq[range->num_frequency].i =
+			    (long)cfp->channel;
 			range->freq[range->num_frequency].m =
-			    (long)lbs_chan_2_freq(chan_no) * 100000;
+			    (long)cfp->freq * 100000;
 			range->freq[range->num_frequency].e = 1;
+			cfp++;
 			range->num_frequency++;
 		}
-		flag = 1;
-	}
-	if (!flag) {
-		for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-		     && (j < ARRAY_SIZE(priv->region_channel)); j++) {
-			cfp = priv->region_channel[j].CFP;
-			for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
-			     && priv->region_channel[j].valid
-			     && cfp
-			     && (i < priv->region_channel[j].nrcfp); i++) {
-				range->freq[range->num_frequency].i =
-				    (long)cfp->channel;
-				range->freq[range->num_frequency].m =
-				    (long)cfp->freq * 100000;
-				range->freq[range->num_frequency].e = 1;
-				cfp++;
-				range->num_frequency++;
-			}
-		}
 	}
 
 	lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
@@ -700,7 +720,6 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
 		                  | IW_ENC_CAPA_CIPHER_CCMP;
 	}
 
-out:
 	lbs_deb_leave(LBS_DEB_WEXT);
 	return 0;
 }
@@ -709,6 +728,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
 			  struct iw_param *vwrq, char *extra)
 {
 	struct lbs_private *priv = dev->ml_priv;
+	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -737,8 +757,54 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
 		       "setting power timeout is not supported\n");
 		return -EINVAL;
 	} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
-		lbs_deb_wext("setting power period not supported\n");
-		return -EINVAL;
+		vwrq->value = vwrq->value / 1000;
+		if (!priv->enter_deep_sleep) {
+			lbs_pr_err("deep sleep feature is not implemented "
+					"for this interface driver\n");
+			return -EINVAL;
+		}
+
+		if (priv->connect_status == LBS_CONNECTED) {
+			if ((priv->is_auto_deep_sleep_enabled) &&
+						(vwrq->value == -1000)) {
+				lbs_exit_auto_deep_sleep(priv);
+				return 0;
+			} else {
+				lbs_pr_err("can't use deep sleep cmd in "
+						"connected state\n");
+				return -EINVAL;
+			}
+		}
+
+		if ((vwrq->value < 0) && (vwrq->value != -1000)) {
+			lbs_pr_err("unknown option\n");
+			return -EINVAL;
+		}
+
+		if (vwrq->value > 0) {
+			if (!priv->is_auto_deep_sleep_enabled) {
+				priv->is_activity_detected = 0;
+				priv->auto_deep_sleep_timeout = vwrq->value;
+				lbs_enter_auto_deep_sleep(priv);
+			} else {
+				priv->auto_deep_sleep_timeout = vwrq->value;
+				lbs_deb_debugfs("auto deep sleep: "
+						"already enabled\n");
+			}
+			return 0;
+		} else {
+			if (priv->is_auto_deep_sleep_enabled) {
+				lbs_exit_auto_deep_sleep(priv);
+				/* Try to exit deep sleep if auto */
+				/*deep sleep disabled */
+				ret = lbs_set_deep_sleep(priv, 0);
+			}
+			if (vwrq->value == 0)
+				ret = lbs_set_deep_sleep(priv, 1);
+			else if (vwrq->value == -1000)
+				ret = lbs_set_deep_sleep(priv, 0);
+			return ret;
+		}
 	}
 
 	if (priv->psmode != LBS802_11POWERMODECAM) {
@@ -752,6 +818,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
 	}
 
 	lbs_deb_leave(LBS_DEB_WEXT);
+
 	return 0;
 }
 
@@ -785,7 +852,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	u32 rssi_qual;
 	u32 tx_qual;
 	u32 quality = 0;
-	int stats_valid = 0;
+	int ret, stats_valid = 0;
 	u8 rssi;
 	u32 tx_retries;
 	struct cmd_ds_802_11_get_log log;
@@ -834,7 +901,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 
 	memset(&log, 0, sizeof(log));
 	log.hdr.size = cpu_to_le16(sizeof(log));
-	lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+	ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
+	if (ret)
+		goto out;
 
 	tx_retries = le32_to_cpu(log.retry);
 
@@ -862,8 +931,10 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	stats_valid = 1;
 
 	/* update stats asynchronously for future calls */
-	lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
+	ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
 					0, 0, NULL);
+	if (ret)
+		lbs_pr_err("RSSI command failed\n");
 out:
 	if (!stats_valid) {
 		priv->wstats.miss.beacon = 0;
@@ -973,7 +1044,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
 		goto out;
 	}
 
-	if (fwrq->m != priv->curbssparams.channel) {
+	if (fwrq->m != priv->channel) {
 		lbs_deb_wext("mesh channel change forces eth disconnect\n");
 		if (priv->mode == IW_MODE_INFRA)
 			lbs_cmd_80211_deauthenticate(priv,
@@ -1000,6 +1071,7 @@ static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
 	u8 rates[MAX_RATES + 1];
 
 	lbs_deb_enter(LBS_DEB_WEXT);
+
 	lbs_deb_wext("vwrq->value %d\n", vwrq->value);
 	lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
 
@@ -1975,7 +2047,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
 {
 	struct lbs_private *priv = dev->ml_priv;
 	int ret = 0;
-	u8 ssid[IW_ESSID_MAX_SIZE];
+	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	u8 ssid_len = 0;
 	struct assoc_request * assoc_req;
 	int in_ssid_len = dwrq->length;
@@ -1989,7 +2061,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
 	}
 
 	/* Check the size of the string */
-	if (in_ssid_len > IW_ESSID_MAX_SIZE) {
+	if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
 		ret = -E2BIG;
 		goto out;
 	}
@@ -2020,7 +2092,7 @@ out:
 			ret = -ENOMEM;
 		} else {
 			/* Copy the SSID to the association request */
-			memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE);
+			memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
 			assoc_req->ssid_len = ssid_len;
 			set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
 			lbs_postpone_association_work(priv);
@@ -2071,7 +2143,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
 	}
 
 	/* Check the size of the string */
-	if (dwrq->length > IW_ESSID_MAX_SIZE) {
+	if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
 		ret = -E2BIG;
 		goto out;
 	}
@@ -2086,7 +2158,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
 	}
 
 	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-			priv->curbssparams.channel);
+			priv->channel);
  out:
 	lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
 	return ret;
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 4c08db497606..f3f19fe8c6c6 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -4,7 +4,14 @@
 #ifndef	_LBS_WEXT_H_
 #define	_LBS_WEXT_H_
 
+void lbs_send_disconnect_notification(struct lbs_private *priv);
+void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
+
+struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
+	struct lbs_private *priv,
+	u8 band,
+	u16 channel);
+
 extern struct iw_handler_def lbs_handler_def;
-extern struct iw_handler_def mesh_handler_def;
 
 #endif