diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index b456a53b64b19b22aa3442b13ca1a2859ea622c6..63009c7eb2f1a0105795bc853f244d4d8810b9c1 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -19,6 +19,7 @@
 #include "decl.h"
 #include "cfg.h"
 #include "cmd.h"
+#include "mesh.h"
 
 
 #define CHAN2G(_channel, _freq, _flags) {        \
@@ -442,13 +443,16 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
 	struct lbs_private *priv = wiphy_priv(wiphy);
 	int ret = -ENOTSUPP;
 
-	lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
-			   channel->center_freq, channel_type);
+	lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
+			   netdev_name(netdev), channel->center_freq, channel_type);
 
 	if (channel_type != NL80211_CHAN_NO_HT)
 		goto out;
 
-	ret = lbs_set_channel(priv, channel->hw_value);
+	if (netdev == priv->mesh_dev)
+		ret = lbs_mesh_set_channel(priv, channel->hw_value);
+	else
+		ret = lbs_set_channel(priv, channel->hw_value);
 
  out:
 	lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -1292,6 +1296,9 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
 	int ret = 0;
 	u8 preamble = RADIO_PREAMBLE_SHORT;
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	if (!sme->bssid) {
@@ -1408,6 +1415,9 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
 	struct lbs_private *priv = wiphy_priv(wiphy);
 	struct cmd_ds_802_11_deauthenticate cmd;
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
 
 	/* store for lbs_cfg_ret_disconnect() */
@@ -1439,6 +1449,9 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
 {
 	struct lbs_private *priv = wiphy_priv(wiphy);
 
+	if (netdev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	if (key_index != priv->wep_tx_key) {
@@ -1460,6 +1473,9 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
 	u16 key_type;
 	int ret = 0;
 
+	if (netdev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
@@ -1603,6 +1619,9 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
 	s8 signal, noise;
 	int ret;
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	if (idx != 0)
 		ret = -ENOENT;
 
@@ -1636,6 +1655,9 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
 	struct lbs_private *priv = wiphy_priv(wiphy);
 	int ret = 0;
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	switch (type) {
@@ -1959,6 +1981,9 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	struct cfg80211_bss *bss;
 	DECLARE_SSID_BUF(ssid_buf);
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	if (!params->channel) {
@@ -1995,6 +2020,9 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 	struct cmd_ds_802_11_ad_hoc_stop cmd;
 	int ret = 0;
 
+	if (dev == priv->mesh_dev)
+		return -EOPNOTSUPP;
+
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	memset(&cmd, 0, sizeof(cmd));
@@ -2117,6 +2145,8 @@ int lbs_cfg_register(struct lbs_private *priv)
 			BIT(NL80211_IFTYPE_ADHOC);
 	if (lbs_rtap_supported(priv))
 		wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
+	if (lbs_mesh_activated(priv))
+		wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
 
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
 
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index adb3490e3cf52e427210d2c34eb1db2fd1ae247b..133ff1cac524e5a3471a8bfb873946e656f6b0f6 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,7 +6,6 @@
 #ifndef _LBS_DEV_H_
 #define _LBS_DEV_H_
 
-#include "mesh.h"
 #include "defs.h"
 #include "host.h"
 
@@ -22,6 +21,17 @@ 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 {
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 4dfb3bfd2cf3f923710939869cea359d503d3c1f..885ddc1c4fed70d8b6a2a47042cba18016069c00 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -5,6 +5,7 @@
 
 #include "decl.h"
 #include "cmd.h"
+#include "mesh.h"
 
 
 static void lbs_ethtool_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 94652c5a25de396ebe4fceeeb4ccd79663d4b862..ee28ae510935a41610179a9e98c16e3b0fc437f4 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -23,6 +23,7 @@
 #include "cfg.h"
 #include "debugfs.h"
 #include "cmd.h"
+#include "mesh.h"
 
 #define DRIVER_RELEASE_VERSION "323.p0"
 const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -950,17 +951,20 @@ int lbs_start_card(struct lbs_private *priv)
 	if (ret)
 		goto done;
 
+	if (!lbs_disablemesh)
+		lbs_init_mesh(priv);
+	else
+		pr_info("%s: mesh disabled\n", dev->name);
+
 	if (lbs_cfg_register(priv)) {
 		pr_err("cannot register device\n");
 		goto done;
 	}
 
-	lbs_update_channel(priv);
+	if (lbs_mesh_activated(priv))
+		lbs_start_mesh(priv);
 
-	if (!lbs_disablemesh)
-		lbs_init_mesh(priv);
-	else
-		pr_info("%s: mesh disabled\n", dev->name);
+	lbs_update_channel(priv);
 
 	lbs_debugfs_init_one(priv, dev);
 
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index be72c08ea2a79acf457c4ef3e5e7b82ae927cbfc..2a635d279ffebb4acc060de364acf23469640549 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -129,6 +129,19 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
 	return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
 }
 
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
+{
+	return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
+}
+
+static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
+{
+	struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
+	if (mesh_wdev->channel)
+		return mesh_wdev->channel->hw_value;
+	else
+		return 1;
+}
 
 /***************************************************************************
  * Mesh sysfs support
@@ -812,7 +825,6 @@ static void lbs_persist_config_remove(struct net_device *dev)
  */
 int lbs_init_mesh(struct lbs_private *priv)
 {
-	struct net_device *dev = priv->dev;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_MESH);
@@ -837,11 +849,9 @@ int lbs_init_mesh(struct lbs_private *priv)
 		   useful */
 
 		priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
-		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-				    priv->channel)) {
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
 			priv->mesh_tlv = TLV_TYPE_MESH_ID;
-			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
-					    priv->channel))
+			if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
 				priv->mesh_tlv = 0;
 		}
 	} else
@@ -851,23 +861,16 @@ int lbs_init_mesh(struct lbs_private *priv)
 		 * 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))
+		if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
 			priv->mesh_tlv = 0;
 	}
 
 	/* Stop meshing until interface is brought up */
-	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
 
 	if (priv->mesh_tlv) {
 		sprintf(priv->mesh_ssid, "mesh");
 		priv->mesh_ssid_len = 4;
-
-		lbs_add_mesh(priv);
-
-		if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
-			netdev_err(dev, "cannot register lbs_mesh attribute\n");
-
 		ret = 1;
 	}
 
@@ -875,6 +878,13 @@ int lbs_init_mesh(struct lbs_private *priv)
 	return ret;
 }
 
+void lbs_start_mesh(struct lbs_private *priv)
+{
+	lbs_add_mesh(priv);
+
+	if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
+		netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
+}
 
 int lbs_deinit_mesh(struct lbs_private *priv)
 {
@@ -904,7 +914,8 @@ static int lbs_mesh_stop(struct net_device *dev)
 	struct lbs_private *priv = dev->ml_priv;
 
 	lbs_deb_enter(LBS_DEB_MESH);
-	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel);
+	lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
+		lbs_mesh_get_channel(priv));
 
 	spin_lock_irq(&priv->driver_lock);
 
@@ -947,7 +958,8 @@ static int lbs_mesh_dev_open(struct net_device *dev)
 
 	spin_unlock_irq(&priv->driver_lock);
 
-	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel);
+	ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
+		lbs_mesh_get_channel(priv));
 
 out:
 	lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -971,18 +983,32 @@ static const struct net_device_ops mesh_netdev_ops = {
 static int lbs_add_mesh(struct lbs_private *priv)
 {
 	struct net_device *mesh_dev = NULL;
+	struct wireless_dev *mesh_wdev;
 	int ret = 0;
 
 	lbs_deb_enter(LBS_DEB_MESH);
 
 	/* Allocate a virtual mesh device */
+	mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+	if (!mesh_wdev) {
+		lbs_deb_mesh("init mshX wireless device failed\n");
+		ret = -ENOMEM;
+		goto done;
+	}
+
 	mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
 	if (!mesh_dev) {
 		lbs_deb_mesh("init mshX device failed\n");
 		ret = -ENOMEM;
-		goto done;
+		goto err_free_wdev;
 	}
+
+	mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
+	mesh_wdev->wiphy = priv->wdev->wiphy;
+	mesh_wdev->netdev = mesh_dev;
+
 	mesh_dev->ml_priv = priv;
+	mesh_dev->ieee80211_ptr = mesh_wdev;
 	priv->mesh_dev = mesh_dev;
 
 	mesh_dev->netdev_ops = &mesh_netdev_ops;
@@ -996,7 +1022,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
 	ret = register_netdev(mesh_dev);
 	if (ret) {
 		pr_err("cannot register mshX virtual interface\n");
-		goto err_free;
+		goto err_free_netdev;
 	}
 
 	ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
@@ -1012,9 +1038,12 @@ static int lbs_add_mesh(struct lbs_private *priv)
 err_unregister:
 	unregister_netdev(mesh_dev);
 
-err_free:
+err_free_netdev:
 	free_netdev(mesh_dev);
 
+err_free_wdev:
+	kfree(mesh_wdev);
+
 done:
 	lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
 	return ret;
@@ -1035,6 +1064,7 @@ void lbs_remove_mesh(struct lbs_private *priv)
 	lbs_persist_config_remove(mesh_dev);
 	unregister_netdev(mesh_dev);
 	priv->mesh_dev = NULL;
+	kfree(mesh_dev->ieee80211_ptr);
 	free_netdev(mesh_dev);
 	lbs_deb_leave(LBS_DEB_MESH);
 }
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index 50144913f2abefd8a86fe93f81e42ed7eeaedcde..6603f341c8746f0b6ed66078ac4d8d02b2ce4f53 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -9,30 +9,25 @@
 #include <net/lib80211.h>
 
 #include "host.h"
+#include "dev.h"
 
 #ifdef CONFIG_LIBERTAS_MESH
 
-/* 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);
+void lbs_start_mesh(struct lbs_private *priv);
 int lbs_deinit_mesh(struct lbs_private *priv);
 
 void lbs_remove_mesh(struct lbs_private *priv);
 
+static inline bool lbs_mesh_activated(struct lbs_private *priv)
+{
+	/* Mesh SSID is only programmed after successful init */
+	return priv->mesh_ssid_len != 0;
+}
+
+int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
 
 /* Sending / Receiving */
 
@@ -67,11 +62,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
 
 #define lbs_init_mesh(priv)
 #define lbs_deinit_mesh(priv)
+#define lbs_start_mesh(priv)
 #define lbs_add_mesh(priv)
 #define lbs_remove_mesh(priv)
 #define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
 #define lbs_mesh_set_txpd(priv, dev, txpd)
-#define lbs_mesh_config(priv, enable, chan)
+#define lbs_mesh_set_channel(priv, channel) (0)
+#define lbs_mesh_activated(priv) (false)
 
 #endif
 
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index bfb8898ae518908f8394ef94a6f158b74f1bb232..62e10eeadd7e11339ff4ee2b67cdf04d097a6bbf 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -15,6 +15,7 @@
 #include "radiotap.h"
 #include "decl.h"
 #include "dev.h"
+#include "mesh.h"
 
 struct eth803hdr {
 	u8 dest_addr[6];
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a6e85134cfe1c24e8bd0e3aa4f95e8178b2078ec..8f127520d7863f6ff5eb09b49272d7227b75c5ab 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -12,6 +12,7 @@
 #include "decl.h"
 #include "defs.h"
 #include "dev.h"
+#include "mesh.h"
 
 /**
  * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE