diff --git a/src/common/defs.h b/src/common/defs.h
index fb289b0..92bc499 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -300,6 +300,17 @@ enum wpa_ctrl_req_type {
 /* Maximum number of EAP methods to store for EAP server user information */
 #define EAP_MAX_METHODS 8
 
+/**
+ *  enum ht_mode - channel width and offset
+ */
+enum ht_mode {
+	CHAN_UNDEFINED = 0,
+	CHAN_NO_HT,
+	CHAN_HT20,
+	CHAN_HT40PLUS,
+	CHAN_HT40MINUS,
+};
+
 #ifdef CONFIG_MESH
 enum mesh_plink_state {
 	PLINK_LISTEN = 1,
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index f48ff84..afcea45 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -911,6 +911,7 @@ struct wpa_driver_mesh_join_params {
 	u8 *ies;
 	int ie_len;
 	int freq;
+	enum ht_mode ht_mode;
 	struct wpa_driver_mesh_bss_params conf;
 #define WPA_DRIVER_MESH_FLAG_USER_MPM	0x00000001
 #define WPA_DRIVER_MESH_FLAG_DRIVER_MPM	0x00000002
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 42097e2..8b23342 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -9099,12 +9099,37 @@ wpa_driver_nl80211_join_mesh(void *priv,
 	nl80211_cmd(drv, msg, 0, NL80211_CMD_JOIN_MESH);
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, drv->ifindex);
-	/* XXX: need chtype too in case we want HT */
 	if (params->freq) {
 		wpa_printf(MSG_DEBUG, "  * freq=%d", params->freq);
 		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, params->freq);
 	}
 
+	if (params->ht_mode) {
+		unsigned int ht_value;
+		char *ht_mode = "";
+		switch (params->ht_mode) {
+		default:
+		case CHAN_NO_HT:
+			ht_value = NL80211_CHAN_NO_HT;
+			ht_mode = "NOHT";
+			break;
+		case CHAN_HT20:
+			ht_value = NL80211_CHAN_HT20;
+			ht_mode = "HT20";
+			break;
+		case CHAN_HT40PLUS:
+			ht_value = NL80211_CHAN_HT40PLUS;
+			ht_mode = "HT40+";
+			break;
+		case CHAN_HT40MINUS:
+			ht_value = NL80211_CHAN_HT40MINUS;
+			ht_mode = "HT40-";
+			break;
+		}
+		wpa_printf(MSG_DEBUG, "  * ht_mode=%s", ht_mode);
+		NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ht_value);
+	}
+
 	if (params->basic_rates) {
 		u8 rates[NL80211_MAX_SUPP_RATES];
 		u8 rates_len = 0;
diff --git a/tests/hwsim/p2p0.conf b/tests/hwsim/p2p0.conf
index 9482bdc..79804a6 100644
--- a/tests/hwsim/p2p0.conf
+++ b/tests/hwsim/p2p0.conf
@@ -1,3 +1,4 @@
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=admin
 device_name=Device A
 p2p_no_group_iface=1
+disable_scan_offload=1
diff --git a/tests/hwsim/p2p1.conf b/tests/hwsim/p2p1.conf
index 3622b15..7a713a8 100644
--- a/tests/hwsim/p2p1.conf
+++ b/tests/hwsim/p2p1.conf
@@ -1,3 +1,4 @@
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=admin
 device_name=Device B
 p2p_no_group_iface=1
+disable_scan_offload=1
diff --git a/tests/hwsim/p2p2.conf b/tests/hwsim/p2p2.conf
index eda52e1..1df136f 100644
--- a/tests/hwsim/p2p2.conf
+++ b/tests/hwsim/p2p2.conf
@@ -1,3 +1,4 @@
 ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=admin
 device_name=Device C
 p2p_no_group_iface=1
+disable_scan_offload=1
diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py
index f1eca36..84ef00d 100644
--- a/tests/hwsim/test_wpas_mesh.py
+++ b/tests/hwsim/test_wpas_mesh.py
@@ -43,7 +43,7 @@ def check_mesh_scan(dev, params, other_started=False):
 
     res = dev.request("SCAN_RESULTS")
 
-    if not res.find("[MESH]"):
+    if res.find("[MESH]") < 0:
         raise Exception("Scan did not contain a MESH network")
 
 
@@ -168,6 +168,7 @@ def test_wpas_mesh_mode_scan(dev):
     dev[0].set_network_quoted(id, "ssid", "wpas-mesh-open")
     dev[0].set_network(id, "key_mgmt", "NONE")
     dev[0].set_network(id, "frequency", "2412")
+    dev[0].set_network(id, "mesh_ht_mode", "HT40+")
     dev[0].mesh_group_add(id)
 
     id = dev[1].add_network()
@@ -175,6 +176,7 @@ def test_wpas_mesh_mode_scan(dev):
     dev[1].set_network_quoted(id, "ssid", "wpas-mesh-open")
     dev[1].set_network(id, "key_mgmt", "NONE")
     dev[1].set_network(id, "frequency", "2412")
+    dev[1].set_network(id, "mesh_ht_mode", "HT40+")
     dev[1].mesh_group_add(id)
 
     # Check for mesh joined
@@ -201,6 +203,7 @@ def _test_wpas_mesh_open(dev, apdev, test_connectivity):
     dev[0].set_network_quoted(id, "ssid", "wpas-mesh-open")
     dev[0].set_network(id, "key_mgmt", "NONE")
     dev[0].set_network(id, "frequency", "2412")
+    dev[0].set_network(id, "mesh_ht_mode", "HT40+")
     dev[0].mesh_group_add(id)
 
     id = dev[1].add_network()
@@ -208,6 +211,7 @@ def _test_wpas_mesh_open(dev, apdev, test_connectivity):
     dev[1].set_network_quoted(id, "ssid", "wpas-mesh-open")
     dev[1].set_network(id, "key_mgmt", "NONE")
     dev[1].set_network(id, "frequency", "2412")
+    dev[1].set_network(id, "mesh_ht_mode", "HT40+")
     dev[1].mesh_group_add(id)
 
     # Check for mesh joined
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index f9aa807..df95f51 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -74,25 +74,10 @@ no_vht:
 }
 #endif /* CONFIG_IEEE80211N */
 
-
-static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
-				  struct wpa_ssid *ssid,
-				  struct hostapd_config *conf)
+void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid,
+			       struct hostapd_config *conf)
 {
-	struct hostapd_bss_config *bss = conf->bss[0];
-
-	conf->driver = wpa_s->driver;
-
-	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
-
-	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
-					       &conf->channel);
-	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
-		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
-			   ssid->frequency);
-		return -1;
-	}
-
 	/* TODO: enable HT40 if driver supports it;
 	 * drop to 11b if driver does not support 11g */
 
@@ -155,6 +140,27 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
 		}
 	}
 #endif /* CONFIG_IEEE80211N */
+}
+
+static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s,
+				  struct wpa_ssid *ssid,
+				  struct hostapd_config *conf)
+{
+	struct hostapd_bss_config *bss = conf->bss[0];
+
+	conf->driver = wpa_s->driver;
+
+	os_strlcpy(bss->iface, wpa_s->ifname, sizeof(bss->iface));
+
+	conf->hw_mode = ieee80211_freq_to_chan(ssid->frequency,
+					       &conf->channel);
+	if (conf->hw_mode == NUM_HOSTAPD_MODES) {
+		wpa_printf(MSG_ERROR, "Unsupported AP mode frequency: %d MHz",
+			   ssid->frequency);
+		return -1;
+	}
+
+	wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
 
 #ifdef CONFIG_P2P
 	if (conf->hw_mode == HOSTAPD_MODE_IEEE80211G &&
diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h
index 8aa5ffa..4d80c7a 100644
--- a/wpa_supplicant/ap.h
+++ b/wpa_supplicant/ap.h
@@ -75,4 +75,9 @@ int wpas_ap_wps_nfc_report_handover(struct wpa_supplicant *wpa_s,
 int wpas_ap_wps_add_nfc_pw(struct wpa_supplicant *wpa_s, u16 pw_id,
 			   const struct wpabuf *pw, const u8 *pubkey_hash);
 
+struct hostapd_config;
+void wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
+			       struct wpa_ssid *ssid,
+			       struct hostapd_config *conf);
+
 #endif /* AP_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index b1069ce..efc0a96 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1543,7 +1543,6 @@ static int wpa_config_parse_psk_list(const struct parse_data *data,
 	return 0;
 }
 
-
 #ifndef NO_CONFIG_WRITE
 static char * wpa_config_write_psk_list(const struct parse_data *data,
 					struct wpa_ssid *ssid)
@@ -1554,6 +1553,60 @@ static char * wpa_config_write_psk_list(const struct parse_data *data,
 
 #endif /* CONFIG_P2P */
 
+#ifdef CONFIG_MESH
+static int wpa_config_parse_mesh_ht_mode(const struct parse_data *data,
+					 struct wpa_ssid *ssid, int line,
+					 const char *value)
+{
+	int htval = 0;
+
+	if (os_strcmp(value, "NOHT") == 0)
+		htval = CHAN_NO_HT;
+	else if (os_strcmp(value, "HT20") == 0)
+		htval = CHAN_HT20;
+	else if (os_strcmp(value, "HT40-") == 0)
+		htval = CHAN_HT40MINUS;
+	else if (os_strcmp(value, "HT40+") == 0)
+		htval = CHAN_HT40PLUS;
+	else {
+		wpa_printf(MSG_ERROR,
+			   "Line %d: no ht_mode configured.", line);
+		return -1;
+	}
+
+	wpa_printf(MSG_MSGDUMP, "mesh_ht_mode: 0x%x", htval);
+	ssid->mesh_ht_mode = htval;
+	return 0;
+}
+
+#ifndef NO_CONFIG_WRITE
+static char *wpa_config_write_mesh_ht_mode(const struct parse_data *data,
+					   struct wpa_ssid *ssid)
+{
+	char *val;
+	switch (ssid->mesh_ht_mode) {
+	default:
+		val = NULL;
+		break;
+	case CHAN_NO_HT:
+		val = "NOHT";
+		break;
+	case CHAN_HT20:
+		val = "HT20";
+		break;
+	case CHAN_HT40MINUS:
+		val = "HT40-";
+		break;
+	case CHAN_HT40PLUS:
+		val = "HT40+";
+		break;
+	}
+	return val ? os_strdup(val) : NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
+#endif /* CONFIG_MESH */
+
 /* Helper macros for network block parser */
 
 #ifdef OFFSET
@@ -1722,6 +1775,9 @@ static const struct parse_data ssid_fields[] = {
 	{ INT_RANGE(peerkey, 0, 1) },
 	{ INT_RANGE(mixed_cell, 0, 1) },
 	{ INT_RANGE(frequency, 0, 65000) },
+#ifdef CONFIG_MESH
+	{ FUNC(mesh_ht_mode) },
+#endif
 	{ INT(wpa_ptk_rekey) },
 	{ STR(bgscan) },
 	{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
@@ -2197,6 +2253,9 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid)
 	ssid->eap.fragment_size = DEFAULT_FRAGMENT_SIZE;
 	ssid->eap.sim_num = DEFAULT_USER_SELECTED_SIM;
 #endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_MESH
+	ssid->mesh_ht_mode = DEFAULT_MESH_HT_MODE;
+#endif
 #ifdef CONFIG_HT_OVERRIDES
 	ssid->disable_ht = DEFAULT_DISABLE_HT;
 	ssid->disable_ht40 = DEFAULT_DISABLE_HT40;
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index daa7ce3..6234f71 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -27,6 +27,7 @@
 #define DEFAULT_FRAGMENT_SIZE 1398
 
 #define DEFAULT_BG_SCAN_PERIOD -1
+#define DEFAULT_MESH_HT_MODE CHAN_UNDEFINED /* undefined */
 #define DEFAULT_DISABLE_HT 0
 #define DEFAULT_DISABLE_HT40 0
 #define DEFAULT_DISABLE_SGI 0
@@ -403,6 +404,15 @@ struct wpa_ssid {
 	 */
 	int frequency;
 
+	/**
+	 * mesh_ht_mode - definition of HT mode in mesh mode
+	 *
+	 * Use the given HT mode for mesh networks. The driver will
+	 * adapt to other stations if neccesary, but advertise the
+	 * configured HT mode (HT20/HT40-/HT40+/NOHT).
+	 */
+	int mesh_ht_mode;
+
 	int ht40;
 
 	int vht;
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index d8b648a..25b0eb6 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -6,6 +6,14 @@
  * See README for more details.
  */
 
+
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "config_ssid.h"
+#include "config.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "ap.h"
 #include "mesh.h"
 #include "mesh_mpm.h"
 #include "mesh_rsn.h"
@@ -205,6 +213,8 @@ wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s,
 			goto out_free;
 	}
 
+	wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf);
+
 	return 0;
 out_free:
 	wpa_supplicant_mesh_deinit(wpa_s);
@@ -256,6 +266,9 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s,
 	params.meshid = ssid->ssid;
 	params.meshid_len = ssid->ssid_len;
 	params.freq = ssid->frequency;
+#ifdef CONFIG_IEEE80211N
+	params.ht_mode = ssid->mesh_ht_mode;
+#endif /* CONFIG_IEEE80211N */
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
 		params.flags |= WPA_DRIVER_MESH_FLAG_SAE_AUTH;
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 69ffba8..af5b124 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -367,6 +367,12 @@ wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
 
 	mesh_mpm_init_link(wpa_s, sta);
 
+#ifdef CONFIG_IEEE80211N
+	copy_sta_ht_capab(data, sta, elems->ht_capabilities,
+			elems->ht_capabilities_len);
+	update_ht_state(data, sta);
+#endif
+
 	/* insert into driver */
 	os_memset(&params, 0, sizeof(params));
 	params.supp_rates = sta->supported_rates;
@@ -375,7 +381,7 @@ wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr,
 	params.plink_state = sta->plink_state;
 	params.aid = sta->peer_lid;
 	params.listen_interval = 100;
-	/* TODO: HT capabilities */
+	params.ht_capabilities = sta->ht_capabilities;
 	params.flags |= WPA_STA_WMM;
 	params.flags_mask |= WPA_STA_AUTHENTICATED;
 	if (conf->security == MESH_CONF_SEC_NONE) {
@@ -415,6 +421,9 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 	struct hostapd_data *bss = ifmsh->bss[0];
 	struct mesh_conf *conf = ifmsh->mconf;
 	u8 supp_rates[2 + 2 + 32];
+#ifdef CONFIG_IEEE80211N
+	u8 ht_capa_oper[2 + 26 + 2 + 22];
+#endif
 	u8 *pos, *cat;
 	u8 ie_len, add_plid = 0;
 	int ret;
@@ -445,6 +454,7 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 		else
 			wpabuf_put_le16(buf, 0);
 
+		/* aid */
 		if (type == PLINK_CONFIRM)
 			wpabuf_put_le16(buf, sta->peer_lid);
 
@@ -515,7 +525,14 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
 	if (ampe)
 		mesh_rsn_get_pmkid(sta, (u8 *) wpabuf_put(buf, PMKID_LEN));
 
-	/* TODO HT IEs */
+#ifdef CONFIG_IEEE80211N
+	if (type != PLINK_CLOSE &&
+	    wpa_s->current_ssid->mesh_ht_mode != CHAN_NO_HT) {
+		pos = hostapd_eid_ht_capabilities(bss, ht_capa_oper);
+		pos = hostapd_eid_ht_operation(bss, pos);
+		wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper);
+	}
+#endif /* CONFIG_IEEE80211N */
 
 	if (ampe && mesh_rsn_protect_frame(wpa_s->mesh_rsn, sta, cat, buf)) {
 		wpa_msg(wpa_s, MSG_INFO,
