Cumulative patch from commit f5728d0a82d5c5fb5347e41ce761fdf4a79772ec am: 58d12adcdf
am: f857d02690

Change-Id: I1b1b69290d7a868e424d8c0e162678288ee47191
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 62bef18..4e7b58e 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -2254,6 +2254,34 @@
 }
 
 
+static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf,
+				     size_t buflen)
+{
+	int ret, i;
+	char *pos, *end;
+
+	ret = os_snprintf(buf, buflen, "%016llX:\n",
+			  (long long unsigned) iface->drv_flags);
+	if (os_snprintf_error(buflen, ret))
+		return -1;
+
+	pos = buf + ret;
+	end = buf + buflen;
+
+	for (i = 0; i < 64; i++) {
+		if (iface->drv_flags & (1LLU << i)) {
+			ret = os_snprintf(pos, end - pos, "%s\n",
+					  driver_flag_to_string(1LLU << i));
+			if (os_snprintf_error(end - pos, ret))
+				return -1;
+			pos += ret;
+		}
+	}
+
+	return pos - buf;
+}
+
+
 static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
 					      char *buf, char *reply,
 					      int reply_size,
@@ -2510,6 +2538,9 @@
 	} else if (os_strncmp(buf, "REQ_RANGE ", 10) == 0) {
 		if (hostapd_ctrl_iface_req_range(hapd, buf + 10))
 			reply_len = -1;
+	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+		reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply,
+						      reply_size);
 	} else {
 		os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
 		reply_len = 16;
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index ff133f6..5c1f297 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1218,6 +1218,13 @@
 }
 
 
+static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+					char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
 struct hostapd_cli_cmd {
 	const char *cmd;
 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
@@ -1283,6 +1290,7 @@
 	{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
 	{ "req_lci", hostapd_cli_cmd_req_lci },
 	{ "req_range", hostapd_cli_cmd_req_range },
+	{ "driver_flags", hostapd_cli_cmd_driver_flags },
 	{ NULL, NULL }
 };
 
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 98601a8..11f12f9 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1385,6 +1385,9 @@
 		return 0;
 	}
 
+	if (TEST_FAIL())
+		return -1;
+
 	for (i = 0; i < AID_WORDS; i++) {
 		if (hapd->sta_aid[i] == (u32) -1)
 			continue;
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 5d4d0c8..cf3fbb1 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -80,6 +80,7 @@
 	enum mesh_plink_state plink_state;
 	u16 peer_lid;
 	u16 my_lid;
+	u16 peer_aid;
 	u16 mpm_close_reason;
 	int mpm_retries;
 	u8 my_nonce[WPA_NONCE_LEN];
diff --git a/src/common/defs.h b/src/common/defs.h
index 6ef929c..4f56794 100644
--- a/src/common/defs.h
+++ b/src/common/defs.h
@@ -320,13 +320,13 @@
 #define EAP_MAX_METHODS 8
 
 enum mesh_plink_state {
-	PLINK_LISTEN = 1,
-	PLINK_OPEN_SENT,
-	PLINK_OPEN_RCVD,
+	PLINK_IDLE = 1,
+	PLINK_OPN_SNT,
+	PLINK_OPN_RCVD,
 	PLINK_CNF_RCVD,
 	PLINK_ESTAB,
 	PLINK_HOLDING,
-	PLINK_BLOCKED,
+	PLINK_BLOCKED, /* not defined in the IEEE 802.11 standard */
 };
 
 enum set_band {
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index bac87ed..912d1e1 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -89,6 +89,32 @@
  * @QCA_NL80211_VENDOR_SUBCMD_DFS_OFFLOAD_RADAR_DETECTED: Event used by driver,
  *	which supports DFS offloading, to indicate a radar pattern has been
  *	detected. The channel is now unusable.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to
+ *	start the P2P Listen offload function in device and pass the listen
+ *	channel, period, interval, count, device types, and vendor specific
+ *	information elements to the device driver and firmware.
+ *	Uses the attributes defines in
+ *	enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP: Command/event used to
+ *	indicate stop request/response of the P2P Listen offload function in
+ *	device. As an event, it indicates either the feature stopped after it
+ *	was already running or feature has actually failed to start. Uses the
+ *	attributes defines in enum qca_wlan_vendor_attr_p2p_listen_offload.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH: After AP starts
+ *	beaconing, this sub command provides the driver, the frequencies on the
+ *	5 GHz band to check for any radar activity. Driver selects one channel
+ *	from this priority list provided through
+ *	@QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST and starts
+ *	to check for radar activity on it. If no radar activity is detected
+ *	during the channel availability check period, driver internally switches
+ *	to the selected frequency of operation. If the frequency is zero, driver
+ *	internally selects a channel. The status of this conditional switch is
+ *	indicated through an event using the same sub command through
+ *	@QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS. Attributes are
+ *	listed in qca_wlan_vendor_attr_sap_conditional_chan_switch.
  */
 enum qca_nl80211_vendor_subcmds {
 	QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -171,6 +197,9 @@
 	QCA_NL80211_VENDOR_SUBCMD_TSF = 119,
 	QCA_NL80211_VENDOR_SUBCMD_WISA = 120,
 	/* 121 - reserved for QCA */
+	QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START = 122,
+	QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP = 123,
+	QCA_NL80211_VENDOR_SUBCMD_SAP_CONDITIONAL_CHAN_SWITCH = 124,
 };
 
 
@@ -227,6 +256,43 @@
 	QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AFTER_LAST - 1
 };
 
+enum qca_wlan_vendor_attr_p2p_listen_offload {
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INVALID = 0,
+	/* A 32-bit unsigned value; the P2P listen frequency (MHz); must be one
+	 * of the social channels.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
+	/* A 32-bit unsigned value; the P2P listen offload period (ms).
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
+	/* A 32-bit unsigned value; the P2P listen interval duration (ms).
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
+	/* A 32-bit unsigned value; number of interval times the firmware needs
+	 * to run the offloaded P2P listen operation before it stops.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
+	/* An array of arbitrary binary data with one or more 8-byte values.
+	 * The device types include both primary and secondary device types.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
+	/* An array of unsigned 8-bit characters; vendor information elements.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
+	/* A 32-bit unsigned value; a control flag to indicate whether listen
+	 * results need to be flushed to wpa_supplicant.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CTRL_FLAG,
+	/* A 8-bit unsigned value; reason code for P2P listen offload stop
+	 * event.
+	 */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON,
+	/* keep last */
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX =
+	QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_AFTER_LAST - 1
+};
+
 enum qca_wlan_vendor_attr_acs_offload {
 	QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0,
 	QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL,
@@ -265,12 +331,19 @@
  *	band selection based on channel selection results.
  * @QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS: Device supports
  * 	simultaneous off-channel operations.
+ * @QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD: Device supports P2P
+ *	Listen offload; a mechanism where the station's firmware takes care of
+ *	responding to incoming Probe Request frames received from other P2P
+ *	Devices whilst in Listen state, rather than having the user space
+ *	wpa_supplicant do it. Information from received P2P requests are
+ *	forwarded from firmware to host whenever the host processor wakes up.
  * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits
  */
 enum qca_wlan_vendor_features {
 	QCA_WLAN_VENDOR_FEATURE_KEY_MGMT_OFFLOAD	= 0,
 	QCA_WLAN_VENDOR_FEATURE_SUPPORT_HW_MODE_ANY     = 1,
 	QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS = 2,
+	QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD	= 3,
 	NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */
 };
 
@@ -576,6 +649,25 @@
 	/* 8-bit unsigned value to configure the maximum RX MPDU for
 	 * aggregation. */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MPDU_AGGREGATION,
+	/* 8-bit unsigned value to configure the Non aggregrate/11g sw
+	 * retry threshold (0 disable, 31 max). */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_NON_AGG_RETRY,
+	/* 8-bit unsigned value to configure the aggregrate sw
+	 * retry threshold (0 disable, 31 max). */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_AGG_RETRY,
+	/* 8-bit unsigned value to configure the MGMT frame
+	 * retry threshold (0 disable, 31 max). */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_MGMT_RETRY,
+	/* 8-bit unsigned value to configure the CTRL frame
+	 * retry threshold (0 disable, 31 max). */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_CTRL_RETRY,
+	/* 8-bit unsigned value to configure the propagation delay for
+	 * 2G/5G band (0~63, units in us) */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_PROPAGATION_DELAY,
+	/* Unsigned 32-bit value to configure the number of unicast TX fail
+	 * packet count. The peer is disconnected once this threshold is
+	 * reached. */
+	QCA_WLAN_VENDOR_ATTR_CONFIG_TX_FAIL_COUNT,
 
 	/* keep last */
 	QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST,
@@ -602,4 +694,23 @@
 	QCA_WLAN_VENDOR_ATTR_SAP_CONFIG_AFTER_LAST - 1,
 };
 
+/**
+ * enum qca_wlan_vendor_attr_sap_conditional_chan_switch - Parameters for AP
+ *					conditional channel switch
+ */
+enum qca_wlan_vendor_attr_sap_conditional_chan_switch {
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_INVALID = 0,
+	/* Priority based frequency list (an array of u32 values in host byte
+	 * order) */
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_FREQ_LIST = 1,
+	/* Status of the conditional switch (u32).
+	 * 0: Success, Non-zero: Failure
+	 */
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_STATUS = 2,
+
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST,
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_MAX =
+	QCA_WLAN_VENDOR_ATTR_SAP_CONDITIONAL_CHAN_SWITCH_AFTER_LAST - 1,
+};
+
 #endif /* QCA_VENDOR_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index d6295b2..299b8bb 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1184,6 +1184,8 @@
 			"WPA2-PSK" : "WPA-PSK";
 	case WPA_KEY_MGMT_NONE:
 		return "NONE";
+	case WPA_KEY_MGMT_WPA_NONE:
+		return "WPA-NONE";
 	case WPA_KEY_MGMT_IEEE8021X_NO_WPA:
 		return "IEEE 802.1X (no WPA)";
 #ifdef CONFIG_IEEE80211R
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index df26c7b..4dcba81 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -228,6 +228,11 @@
 /* parameters: <addr> <result> */
 #define ANQP_QUERY_DONE "ANQP-QUERY-DONE "
 
+#define RX_ANQP "RX-ANQP "
+#define RX_HS20_ANQP "RX-HS20-ANQP "
+#define RX_HS20_ANQP_ICON "RX-HS20-ANQP-ICON "
+#define RX_HS20_ICON "RX-HS20-ICON "
+
 #define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION "
 #define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE "
 
@@ -271,6 +276,9 @@
 
 #define AP_CSA_FINISHED "AP-CSA-FINISHED "
 
+#define P2P_EVENT_LISTEN_OFFLOAD_STOP "P2P-LISTEN-OFFLOAD-STOPPED "
+#define P2P_LISTEN_OFFLOAD_STOP_REASON "P2P-LISTEN-OFFLOAD-STOP-REASON "
+
 /* BSS Transition Management Response frame received */
 #define BSS_TM_RESP "BSS-TM-RESP "
 
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index fde154f..7f33686 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -754,7 +754,7 @@
 
 	priv_key = BN_bin2bn(wpabuf_head(priv), wpabuf_len(priv), NULL);
 	pub_key = BN_bin2bn(wpabuf_head(publ), wpabuf_len(publ), NULL);
-	if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 0)
+	if (!priv_key || !pub_key || DH_set0_key(dh, pub_key, priv_key) != 1)
 		goto err;
 	pub_key = NULL;
 	priv_key = NULL;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index a9dbdef..a85ed32 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1135,6 +1135,7 @@
 	int ie_len;
 	struct hostapd_freq_params freq;
 	int beacon_int;
+	int dtim_period;
 	int max_peer_links;
 	struct wpa_driver_mesh_bss_params conf;
 #define WPA_DRIVER_MESH_FLAG_USER_MPM	0x00000001
@@ -1278,6 +1279,8 @@
 #define WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS	0x0000008000000000ULL
 /** Driver supports full AP client state */
 #define WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE	0x0000010000000000ULL
+/** Driver supports P2P Listen offload */
+#define WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD     0x0000020000000000ULL
 	u64 flags;
 
 #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -1423,6 +1426,7 @@
 	u32 flags_mask; /* unset bits in flags */
 #ifdef CONFIG_MESH
 	enum mesh_plink_state plink_state;
+	u16 peer_aid;
 #endif /* CONFIG_MESH */
 	int set; /* Set STA parameters instead of add */
 	u8 qosinfo;
@@ -3573,6 +3577,32 @@
 	int (*get_ext_capab)(void *priv, enum wpa_driver_if_type type,
 			     const u8 **ext_capab, const u8 **ext_capab_mask,
 			     unsigned int *ext_capab_len);
+
+	/**
+	 * p2p_lo_start - Start offloading P2P listen to device
+	 * @priv: Private driver interface data
+	 * @freq: Listening frequency (MHz) for P2P listen
+	 * @period: Length of the listen operation in milliseconds
+	 * @interval: Interval for running the listen operation in milliseconds
+	 * @count: Number of times to run the listen operation
+	 * @device_types: Device primary and secondary types
+	 * @dev_types_len: Number of bytes for device_types
+	 * @ies: P2P IE and WSC IE for Probe Response frames
+	 * @ies_len: Length of ies in bytes
+	 * Returns: 0 on success or -1 on failure
+	 */
+	int (*p2p_lo_start)(void *priv, unsigned int freq,
+			    unsigned int period, unsigned int interval,
+			    unsigned int count,
+			    const u8 *device_types, size_t dev_types_len,
+			    const u8 *ies, size_t ies_len);
+
+	/**
+	 * p2p_lo_stop - Stop P2P listen offload
+	 * @priv: Private driver interface data
+	 * Returns: 0 on success or -1 on failure
+	 */
+	int (*p2p_lo_stop)(void *priv);
 };
 
 
@@ -4057,6 +4087,11 @@
 	 * on a DFS frequency by a driver that supports DFS Offload.
 	 */
 	EVENT_DFS_CAC_STARTED,
+
+	/**
+	 * EVENT_P2P_LO_STOP - Notify that P2P listen offload is stopped
+	 */
+	EVENT_P2P_LO_STOP,
 };
 
 
@@ -4782,6 +4817,27 @@
 		u16 ch_width;
 		enum hostapd_hw_mode hw_mode;
 	} acs_selected_channels;
+
+	/**
+	 * struct p2p_lo_stop - Reason code for P2P Listen offload stop event
+	 * @reason_code: Reason for stopping offload
+	 *	P2P_LO_STOPPED_REASON_COMPLETE: Listen offload finished as
+	 *	scheduled.
+	 *	P2P_LO_STOPPED_REASON_RECV_STOP_CMD: Host requested offload to
+	 *	be stopped.
+	 *	P2P_LO_STOPPED_REASON_INVALID_PARAM: Invalid listen offload
+	 *	parameters.
+	 *	P2P_LO_STOPPED_REASON_NOT_SUPPORTED: Listen offload not
+	 *	supported by device.
+	 */
+	struct p2p_lo_stop {
+		enum {
+			P2P_LO_STOPPED_REASON_COMPLETE = 0,
+			P2P_LO_STOPPED_REASON_RECV_STOP_CMD,
+			P2P_LO_STOPPED_REASON_INVALID_PARAM,
+			P2P_LO_STOPPED_REASON_NOT_SUPPORTED,
+		} reason_code;
+	} p2p_lo_stop;
 };
 
 /**
@@ -4861,6 +4917,8 @@
 struct wowlan_triggers *
 wpa_get_wowlan_triggers(const char *wowlan_triggers,
 			const struct wpa_driver_capa *capa);
+/* Convert driver flag to string */
+const char * driver_flag_to_string(u64 flag);
 
 /* NULL terminated array of linked in driver wrappers */
 extern const struct wpa_driver_ops *const wpa_drivers[];
diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c
index b32d35f..c7107ba 100644
--- a/src/drivers/driver_common.c
+++ b/src/drivers/driver_common.c
@@ -80,6 +80,7 @@
 	E2S(NEW_PEER_CANDIDATE);
 	E2S(ACS_CHANNEL_SELECTED);
 	E2S(DFS_CAC_STARTED);
+	E2S(P2P_LO_STOP);
 	}
 
 	return "UNKNOWN";
@@ -218,3 +219,55 @@
 	os_free(buf);
 	return triggers;
 }
+
+
+const char * driver_flag_to_string(u64 flag)
+{
+#define DF2S(x) case WPA_DRIVER_FLAGS_ ## x: return #x
+	switch (flag) {
+	DF2S(DRIVER_IE);
+	DF2S(SET_KEYS_AFTER_ASSOC);
+	DF2S(DFS_OFFLOAD);
+	DF2S(4WAY_HANDSHAKE);
+	DF2S(WIRED);
+	DF2S(SME);
+	DF2S(AP);
+	DF2S(SET_KEYS_AFTER_ASSOC_DONE);
+	DF2S(HT_2040_COEX);
+	DF2S(P2P_CONCURRENT);
+	DF2S(P2P_DEDICATED_INTERFACE);
+	DF2S(P2P_CAPABLE);
+	DF2S(AP_TEARDOWN_SUPPORT);
+	DF2S(P2P_MGMT_AND_NON_P2P);
+	DF2S(SANE_ERROR_CODES);
+	DF2S(OFFCHANNEL_TX);
+	DF2S(EAPOL_TX_STATUS);
+	DF2S(DEAUTH_TX_STATUS);
+	DF2S(BSS_SELECTION);
+	DF2S(TDLS_SUPPORT);
+	DF2S(TDLS_EXTERNAL_SETUP);
+	DF2S(PROBE_RESP_OFFLOAD);
+	DF2S(AP_UAPSD);
+	DF2S(INACTIVITY_TIMER);
+	DF2S(AP_MLME);
+	DF2S(SAE);
+	DF2S(OBSS_SCAN);
+	DF2S(IBSS);
+	DF2S(RADAR);
+	DF2S(DEDICATED_P2P_DEVICE);
+	DF2S(QOS_MAPPING);
+	DF2S(AP_CSA);
+	DF2S(MESH);
+	DF2S(ACS_OFFLOAD);
+	DF2S(KEY_MGMT_OFFLOAD);
+	DF2S(TDLS_CHANNEL_SWITCH);
+	DF2S(HT_IBSS);
+	DF2S(VHT_IBSS);
+	DF2S(SUPPORT_HW_MODE_ANY);
+	DF2S(OFFCHANNEL_SIMULTANEOUS);
+	DF2S(FULL_AP_CLIENT_STATE);
+	DF2S(P2P_LISTEN_OFFLOAD);
+	}
+	return "UNKNOWN";
+#undef DF2S
+}
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index c89665b..ae40f42 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -3468,6 +3468,17 @@
 }
 
 
+static int nl80211_put_dtim_period(struct nl_msg *msg, int dtim_period)
+{
+	if (dtim_period > 0) {
+		wpa_printf(MSG_DEBUG, "  * dtim_period=%d", dtim_period);
+		return nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, dtim_period);
+	}
+
+	return 0;
+}
+
+
 static int wpa_driver_nl80211_set_ap(void *priv,
 				     struct wpa_driver_ap_params *params)
 {
@@ -3504,7 +3515,7 @@
 	    nla_put(msg, NL80211_ATTR_BEACON_TAIL, params->tail_len,
 		    params->tail) ||
 	    nl80211_put_beacon_int(msg, params->beacon_int) ||
-	    nla_put_u32(msg, NL80211_ATTR_DTIM_PERIOD, params->dtim_period) ||
+	    nl80211_put_dtim_period(msg, params->dtim_period) ||
 	    nla_put(msg, NL80211_ATTR_SSID, params->ssid_len, params->ssid))
 		goto fail;
 	if (params->proberesp && params->proberesp_len) {
@@ -3695,7 +3706,7 @@
 					   "nl80211: Frequency set succeeded for ht2040 coex");
 				bss->bandwidth = params->freq->bandwidth;
 			}
-		} else if (!beacon_set) {
+		} else if (!beacon_set && params->freq) {
 			/*
 			 * cfg80211 updates the driver on frequence change in AP
 			 * mode only at the point when beaconing is started, so
@@ -3777,6 +3788,12 @@
 		wpa_printf(MSG_DEBUG, "  * channel_type=%d", ct);
 		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, ct))
 			return -ENOBUFS;
+	} else {
+		wpa_printf(MSG_DEBUG, "  * channel_type=%d",
+			   NL80211_CHAN_NO_HT);
+		if (nla_put_u32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE,
+				NL80211_CHAN_NO_HT))
+			return -ENOBUFS;
 	}
 	return 0;
 }
@@ -3839,11 +3856,11 @@
 static u32 sta_plink_state_nl80211(enum mesh_plink_state state)
 {
 	switch (state) {
-	case PLINK_LISTEN:
+	case PLINK_IDLE:
 		return NL80211_PLINK_LISTEN;
-	case PLINK_OPEN_SENT:
+	case PLINK_OPN_SNT:
 		return NL80211_PLINK_OPN_SNT;
-	case PLINK_OPEN_RCVD:
+	case PLINK_OPN_RCVD:
 		return NL80211_PLINK_OPN_RCVD;
 	case PLINK_CNF_RCVD:
 		return NL80211_PLINK_CNF_RCVD;
@@ -4032,6 +4049,15 @@
 			if (!(params->flags & WPA_STA_ASSOCIATED))
 				upd.mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
 		}
+#ifdef CONFIG_MESH
+	} else {
+		if (params->plink_state == PLINK_ESTAB && params->peer_aid) {
+			ret = nla_put_u16(msg, NL80211_ATTR_MESH_PEER_AID,
+					  params->peer_aid);
+			if (ret)
+				goto fail;
+		}
+#endif /* CONFIG_MESH */
 	}
 
 	wpa_printf(MSG_DEBUG, "  * flags set=0x%x mask=0x%x",
@@ -8391,7 +8417,8 @@
 	    nl80211_put_freq_params(msg, &params->freq) ||
 	    nl80211_put_basic_rates(msg, params->basic_rates) ||
 	    nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
-	    nl80211_put_beacon_int(msg, params->beacon_int))
+	    nl80211_put_beacon_int(msg, params->beacon_int) ||
+	    nl80211_put_dtim_period(msg, params->dtim_period))
 		goto fail;
 
 	wpa_printf(MSG_DEBUG, "  * flags=%08X", params->flags);
@@ -9117,6 +9144,89 @@
 	return 0;
 }
 
+
+static int nl80211_p2p_lo_start(void *priv, unsigned int freq,
+				unsigned int period, unsigned int interval,
+				unsigned int count, const u8 *device_types,
+				size_t dev_types_len,
+				const u8 *ies, size_t ies_len)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+	struct nlattr *container;
+	int ret;
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: Start P2P Listen offload: freq=%u, period=%u, interval=%u, count=%u",
+		   freq, period, interval, count);
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
+		return -1;
+
+	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START))
+		goto fail;
+
+	container = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA);
+	if (!container)
+		goto fail;
+
+	if (nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_CHANNEL,
+			freq) ||
+	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_PERIOD,
+			period) ||
+	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_INTERVAL,
+			interval) ||
+	    nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_COUNT,
+			count) ||
+	    nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_DEVICE_TYPES,
+		    dev_types_len, device_types) ||
+	    nla_put(msg, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_VENDOR_IE,
+		    ies_len, ies))
+		goto fail;
+
+	nla_nest_end(msg, container);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	msg = NULL;
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "nl80211: Failed to send P2P Listen offload vendor command");
+		goto fail;
+	}
+
+	return 0;
+
+fail:
+	nlmsg_free(msg);
+	return -1;
+}
+
+
+static int nl80211_p2p_lo_stop(void *priv)
+{
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+	struct nl_msg *msg;
+
+	wpa_printf(MSG_DEBUG, "nl80211: Stop P2P Listen offload");
+
+	if (!(drv->capa.flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD))
+		return -1;
+
+	if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) ||
+	    nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD,
+			QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP)) {
+		nlmsg_free(msg);
+		return -1;
+	}
+
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+}
+
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
 
@@ -9338,9 +9448,6 @@
 	.vendor_cmd = nl80211_vendor_cmd,
 	.set_qos_map = nl80211_set_qos_map,
 	.set_wowlan = nl80211_set_wowlan,
-#ifdef CONFIG_DRIVER_NL80211_QCA
-	.roaming = nl80211_roaming,
-#endif /* CONFIG_DRIVER_NL80211_QCA */
 	.set_mac_addr = nl80211_set_mac_addr,
 #ifdef CONFIG_MESH
 	.init_mesh = wpa_driver_nl80211_init_mesh,
@@ -9355,10 +9462,13 @@
 	.del_tx_ts = nl80211_del_ts,
 	.get_ifindex = nl80211_get_ifindex,
 #ifdef CONFIG_DRIVER_NL80211_QCA
+	.roaming = nl80211_roaming,
 	.do_acs = wpa_driver_do_acs,
 	.set_band = nl80211_set_band,
 	.get_pref_freq_list = nl80211_get_pref_freq_list,
 	.set_prob_oper_freq = nl80211_set_prob_oper_freq,
+	.p2p_lo_start = nl80211_p2p_lo_start,
+	.p2p_lo_stop = nl80211_p2p_lo_stop,
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 	.configure_data_frame_filters = nl80211_configure_data_frame_filters,
 	.get_ext_capab = nl80211_get_ext_capab,
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index 1ebbdaa..1134886 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -972,6 +972,8 @@
 	if (check_feature(QCA_WLAN_VENDOR_FEATURE_OFFCHANNEL_SIMULTANEOUS,
 			  &info))
 		drv->capa.flags |= WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS;
+	if (check_feature(QCA_WLAN_VENDOR_FEATURE_P2P_LISTEN_OFFLOAD, &info))
+		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD;
 	os_free(info.flags);
 }
 
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 961a2e4..762e3ac 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -916,6 +916,7 @@
 				 struct nlattr *tb[])
 {
 	unsigned int freq;
+	union wpa_event_data event;
 
 	if (tb[NL80211_ATTR_MAC] == NULL) {
 		wpa_printf(MSG_DEBUG, "nl80211: No address in IBSS joined "
@@ -935,7 +936,10 @@
 		drv->first_bss->freq = freq;
 	}
 
-	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, NULL);
+	os_memset(&event, 0, sizeof(event));
+	event.assoc_info.freq = freq;
+
+	wpa_supplicant_event(drv->ctx, EVENT_ASSOC, &event);
 }
 
 
@@ -1872,6 +1876,31 @@
 			       external_scan);
 }
 
+
+static void qca_nl80211_p2p_lo_stop_event(struct wpa_driver_nl80211_data *drv,
+					  u8 *data, size_t len)
+{
+	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX + 1];
+	union wpa_event_data event;
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: P2P listen offload stop vendor event received");
+
+	if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_MAX,
+		      (struct nlattr *) data, len, NULL) ||
+	    !tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON])
+		return;
+
+	os_memset(&event, 0, sizeof(event));
+	event.p2p_lo_stop.reason_code =
+		nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_P2P_LISTEN_OFFLOAD_STOP_REASON]);
+
+	wpa_printf(MSG_DEBUG,
+		   "nl80211: P2P Listen offload stop reason: %d",
+		   event.p2p_lo_stop.reason_code);
+	wpa_supplicant_event(drv->ctx, EVENT_P2P_LO_STOP, &event);
+}
+
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 
 
@@ -1905,6 +1934,9 @@
 	case QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE:
 		qca_nl80211_scan_done_event(drv, data, len);
 		break;
+	case QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_STOP:
+		qca_nl80211_p2p_lo_stop_event(drv, data, len);
+		break;
 #endif /* CONFIG_DRIVER_NL80211_QCA */
 	default:
 		wpa_printf(MSG_DEBUG,
diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h
index 53c8278..2206941 100644
--- a/src/drivers/nl80211_copy.h
+++ b/src/drivers/nl80211_copy.h
@@ -1829,6 +1829,44 @@
  *	%NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per
  *	interface type.
  *
+ * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO
+ *	groupID for monitor mode.
+ *	The first 8 bytes are a mask that defines the membership in each
+ *	group (there are 64 groups, group 0 and 63 are reserved),
+ *	each bit represents a group and set to 1 for being a member in
+ *	that group and 0 for not being a member.
+ *	The remaining 16 bytes define the position in each group: 2 bits for
+ *	each group.
+ *	(smaller group numbers represented on most significant bits and bigger
+ *	group numbers on least significant bits.)
+ *	This attribute is used only if all interfaces are in monitor mode.
+ *	Set this attribute in order to monitor packets using the given MU-MIMO
+ *	groupID data.
+ *	to turn off that feature set all the bits of the groupID to zero.
+ * @NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR: mac address for the sniffer to follow
+ *	when using MU-MIMO air sniffer.
+ *	to turn that feature off set an invalid mac address
+ *	(e.g. FF:FF:FF:FF:FF:FF)
+ *
+ * @NL80211_ATTR_SCAN_START_TIME_TSF: The time at which the scan was actually
+ *	started (u64). The time is the TSF of the BSS the interface that
+ *	requested the scan is connected to (if available, otherwise this
+ *	attribute must not be included).
+ * @NL80211_ATTR_SCAN_START_TIME_TSF_BSSID: The BSS according to which
+ *	%NL80211_ATTR_SCAN_START_TIME_TSF is set.
+ * @NL80211_ATTR_MEASUREMENT_DURATION: measurement duration in TUs (u16). If
+ *	%NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY is not set, this is the
+ *	maximum measurement duration allowed. This attribute is used with
+ *	measurement requests. It can also be used with %NL80211_CMD_TRIGGER_SCAN
+ *	if the scan is used for beacon report radio measurement.
+ * @NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY: flag attribute that indicates
+ *	that the duration specified with %NL80211_ATTR_MEASUREMENT_DURATION is
+ *	mandatory. If this flag is not set, the duration is the maximum duration
+ *	and the actual measurement duration may be shorter.
+ *
+ * @NL80211_ATTR_MESH_PEER_AID: Association ID for the mesh peer (u16). This is
+ *	used to pull the stored data for mesh peer in power save state.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2213,6 +2251,16 @@
 
 	NL80211_ATTR_IFTYPE_EXT_CAPA,
 
+	NL80211_ATTR_MU_MIMO_GROUP_DATA,
+	NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR,
+
+	NL80211_ATTR_SCAN_START_TIME_TSF,
+	NL80211_ATTR_SCAN_START_TIME_TSF_BSSID,
+	NL80211_ATTR_MEASUREMENT_DURATION,
+	NL80211_ATTR_MEASUREMENT_DURATION_MANDATORY,
+
+	NL80211_ATTR_MESH_PEER_AID,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -3474,6 +3522,12 @@
  *	was last updated by a received frame. The value is expected to be
  *	accurate to about 10ms. (u64, nanoseconds)
  * @NL80211_BSS_PAD: attribute used for padding for 64-bit alignment
+ * @NL80211_BSS_PARENT_TSF: the time at the start of reception of the first
+ *	octet of the timestamp field of the last beacon/probe received for
+ *	this BSS. The time is the TSF of the BSS specified by
+ *	@NL80211_BSS_PARENT_BSSID. (u64).
+ * @NL80211_BSS_PARENT_BSSID: the BSS according to which @NL80211_BSS_PARENT_TSF
+ *	is set.
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -3495,6 +3549,8 @@
 	NL80211_BSS_PRESP_DATA,
 	NL80211_BSS_LAST_SEEN_BOOTTIME,
 	NL80211_BSS_PAD,
+	NL80211_BSS_PARENT_TSF,
+	NL80211_BSS_PARENT_BSSID,
 
 	/* keep last */
 	__NL80211_BSS_AFTER_LAST,
@@ -4479,6 +4535,22 @@
  *	%NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set
  *	the ASSOC_REQ_USE_RRM flag in the association request even if
  *	NL80211_FEATURE_QUIET is not advertized.
+ * @NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER: This device supports MU-MIMO air
+ *	sniffer which means that it can be configured to hear packets from
+ *	certain groups which can be configured by the
+ *	%NL80211_ATTR_MU_MIMO_GROUP_DATA attribute,
+ *	or can be configured to follow a station by configuring the
+ *	%NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR attribute.
+ * @NL80211_EXT_FEATURE_SCAN_START_TIME: This driver includes the actual
+ *	time the scan started in scan results event. The time is the TSF of
+ *	the BSS that the interface that requested the scan is connected to
+ *	(if available).
+ * @NL80211_EXT_FEATURE_BSS_PARENT_TSF: Per BSS, this driver reports the
+ *	time the last beacon/probe was received. The time is the TSF of the
+ *	BSS that the interface that requested the scan is connected to
+ *	(if available).
+ * @NL80211_EXT_FEATURE_SET_SCAN_DWELL: This driver supports configuration of
+ *	channel dwell time.
  *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
@@ -4486,6 +4558,10 @@
 enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_VHT_IBSS,
 	NL80211_EXT_FEATURE_RRM,
+	NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER,
+	NL80211_EXT_FEATURE_SCAN_START_TIME,
+	NL80211_EXT_FEATURE_BSS_PARENT_TSF,
+	NL80211_EXT_FEATURE_SET_SCAN_DWELL,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index a209a56..996b4e8 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -788,11 +788,11 @@
 		dev->oper_ssid_len = msg.ssid[1];
 	}
 
-	if (msg.adv_service_instance && msg.adv_service_instance_len) {
-		wpabuf_free(dev->info.p2ps_instance);
+	wpabuf_free(dev->info.p2ps_instance);
+	dev->info.p2ps_instance = NULL;
+	if (msg.adv_service_instance && msg.adv_service_instance_len)
 		dev->info.p2ps_instance = wpabuf_alloc_copy(
 			msg.adv_service_instance, msg.adv_service_instance_len);
-	}
 
 	if (freq >= 2412 && freq <= 2484 && msg.ds_params &&
 	    *msg.ds_params >= 1 && *msg.ds_params <= 14) {
@@ -2234,6 +2234,58 @@
 	return buf;
 }
 
+static int p2p_build_probe_resp_buf(struct p2p_data *p2p, struct wpabuf *buf,
+				    struct wpabuf *ies,
+				    const u8 *addr, int rx_freq)
+{
+	struct ieee80211_mgmt *resp;
+	u8 channel, op_class;
+
+	resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
+					u.probe_resp.variable));
+
+	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+					   (WLAN_FC_STYPE_PROBE_RESP << 4));
+	os_memcpy(resp->da, addr, ETH_ALEN);
+	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
+	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
+	resp->u.probe_resp.beacon_int = host_to_le16(100);
+	/* hardware or low-level driver will setup seq_ctrl and timestamp */
+	resp->u.probe_resp.capab_info =
+	    host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
+		     WLAN_CAPABILITY_PRIVACY |
+		     WLAN_CAPABILITY_SHORT_SLOT_TIME);
+
+	wpabuf_put_u8(buf, WLAN_EID_SSID);
+	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
+	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
+
+	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
+	wpabuf_put_u8(buf, 8);
+	wpabuf_put_u8(buf, (60 / 5) | 0x80);
+	wpabuf_put_u8(buf, 90 / 5);
+	wpabuf_put_u8(buf, (120 / 5) | 0x80);
+	wpabuf_put_u8(buf, 180 / 5);
+	wpabuf_put_u8(buf, (240 / 5) | 0x80);
+	wpabuf_put_u8(buf, 360 / 5);
+	wpabuf_put_u8(buf, 480 / 5);
+	wpabuf_put_u8(buf, 540 / 5);
+
+	if (!rx_freq) {
+		channel = p2p->cfg->channel;
+	} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
+		p2p_err(p2p, "Failed to convert freq to channel");
+		return -1;
+	}
+
+	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
+	wpabuf_put_u8(buf, 1);
+	wpabuf_put_u8(buf, channel);
+
+	wpabuf_put_buf(buf, ies);
+
+	return 0;
+}
 
 static int p2p_service_find_asp(struct p2p_data *p2p, const u8 *hash)
 {
@@ -2267,10 +2319,8 @@
 {
 	struct ieee802_11_elems elems;
 	struct wpabuf *buf;
-	struct ieee80211_mgmt *resp;
 	struct p2p_message msg;
 	struct wpabuf *ies;
-	u8 channel, op_class;
 
 	if (ieee802_11_parse_elems((u8 *) ie, ie_len, &elems, 0) ==
 	    ParseFailed) {
@@ -2414,49 +2464,12 @@
 		return P2P_PREQ_NOT_PROCESSED;
 	}
 
-	resp = wpabuf_put(buf, offsetof(struct ieee80211_mgmt,
-					u.probe_resp.variable));
-
-	resp->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
-					   (WLAN_FC_STYPE_PROBE_RESP << 4));
-	os_memcpy(resp->da, addr, ETH_ALEN);
-	os_memcpy(resp->sa, p2p->cfg->dev_addr, ETH_ALEN);
-	os_memcpy(resp->bssid, p2p->cfg->dev_addr, ETH_ALEN);
-	resp->u.probe_resp.beacon_int = host_to_le16(100);
-	/* hardware or low-level driver will setup seq_ctrl and timestamp */
-	resp->u.probe_resp.capab_info =
-		host_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE |
-			     WLAN_CAPABILITY_PRIVACY |
-			     WLAN_CAPABILITY_SHORT_SLOT_TIME);
-
-	wpabuf_put_u8(buf, WLAN_EID_SSID);
-	wpabuf_put_u8(buf, P2P_WILDCARD_SSID_LEN);
-	wpabuf_put_data(buf, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN);
-
-	wpabuf_put_u8(buf, WLAN_EID_SUPP_RATES);
-	wpabuf_put_u8(buf, 8);
-	wpabuf_put_u8(buf, (60 / 5) | 0x80);
-	wpabuf_put_u8(buf, 90 / 5);
-	wpabuf_put_u8(buf, (120 / 5) | 0x80);
-	wpabuf_put_u8(buf, 180 / 5);
-	wpabuf_put_u8(buf, (240 / 5) | 0x80);
-	wpabuf_put_u8(buf, 360 / 5);
-	wpabuf_put_u8(buf, 480 / 5);
-	wpabuf_put_u8(buf, 540 / 5);
-
-	if (!rx_freq) {
-		channel = p2p->cfg->channel;
-	} else if (p2p_freq_to_channel(rx_freq, &op_class, &channel)) {
+	if (p2p_build_probe_resp_buf(p2p, buf, ies, addr, rx_freq)) {
 		wpabuf_free(ies);
 		wpabuf_free(buf);
 		return P2P_PREQ_NOT_PROCESSED;
 	}
 
-	wpabuf_put_u8(buf, WLAN_EID_DS_PARAMS);
-	wpabuf_put_u8(buf, 1);
-	wpabuf_put_u8(buf, channel);
-
-	wpabuf_put_buf(buf, ies);
 	wpabuf_free(ies);
 
 	p2p->cfg->send_probe_resp(p2p->cfg->cb_ctx, buf, rx_freq);
@@ -2470,12 +2483,18 @@
 enum p2p_probe_req_status
 p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
 		 const u8 *bssid, const u8 *ie, size_t ie_len,
-		 unsigned int rx_freq)
+		 unsigned int rx_freq, int p2p_lo_started)
 {
 	enum p2p_probe_req_status res;
 
 	p2p_add_dev_from_probe_req(p2p, addr, ie, ie_len);
 
+	if (p2p_lo_started) {
+		p2p_dbg(p2p,
+			"Probe Response is offloaded, do not reply Probe Request");
+		return P2P_PREQ_PROCESSED;
+	}
+
 	res = p2p_reply_probe(p2p, addr, dst, bssid, ie, ie_len, rx_freq);
 	if (res != P2P_PREQ_PROCESSED && res != P2P_PREQ_NOT_PROCESSED)
 		return res;
@@ -2980,7 +2999,6 @@
 	os_free(p2p->groups);
 	p2ps_prov_free(p2p);
 	wpabuf_free(p2p->sd_resp);
-	os_free(p2p->after_scan_tx);
 	p2p_remove_wps_vendor_extensions(p2p);
 	os_free(p2p->no_go_freq.range);
 	p2p_service_flush_asp(p2p);
@@ -5490,3 +5508,34 @@
 			i, p2p->pref_freq_list[i]);
 	}
 }
+
+
+struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
+					      unsigned int freq)
+{
+	struct wpabuf *ies, *buf;
+	u8 addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+	int ret;
+
+	ies = p2p_build_probe_resp_ies(p2p, NULL, 0);
+	if (!ies) {
+		wpa_printf(MSG_ERROR,
+			   "CTRL: Failed to build Probe Response IEs");
+		return NULL;
+	}
+
+	buf = wpabuf_alloc(200 + wpabuf_len(ies));
+	if (!buf) {
+		wpabuf_free(ies);
+		return NULL;
+	}
+
+	ret = p2p_build_probe_resp_buf(p2p, buf, ies, addr, freq);
+	wpabuf_free(ies);
+	if (ret) {
+		wpabuf_free(buf);
+		return NULL;
+	}
+
+	return buf;
+}
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 186af36..5b5a0bf 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1555,12 +1555,13 @@
  * @ie: Information elements from the Probe Request frame body
  * @ie_len: Length of ie buffer in octets
  * @rx_freq: Probe Request frame RX frequency
+ * @p2p_lo_started: Whether P2P Listen Offload is started
  * Returns: value indicating the type and status of the probe request
  */
 enum p2p_probe_req_status
 p2p_probe_req_rx(struct p2p_data *p2p, const u8 *addr, const u8 *dst,
 		 const u8 *bssid, const u8 *ie, size_t ie_len,
-		 unsigned int rx_freq);
+		 unsigned int rx_freq, int p2p_lo_started);
 
 /**
  * p2p_rx_action - Report received Action frame
@@ -2383,4 +2384,7 @@
 int p2p_group_get_common_freqs(struct p2p_group *group, int *common_freqs,
 			       unsigned int *num);
 
+struct wpabuf * p2p_build_probe_resp_template(struct p2p_data *p2p,
+					      unsigned int freq);
+
 #endif /* P2P_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 0571c23..ce631dd 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2669,9 +2669,8 @@
 	return props;
 
 err:
-	value = *props;
-	while (value)
-		os_free(value++);
+	for (i = 0; props[i]; i++)
+		os_free(props[i]);
 	os_free(props);
 	return NULL;
 #endif /* NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index e75323d..4aa0f24 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -6283,6 +6283,21 @@
 	return 0;
 }
 
+
+static int p2p_ctrl_iface_p2p_lo_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+	int freq = 0, period = 0, interval = 0, count = 0;
+
+	if (sscanf(cmd, "%d %d %d %d", &freq, &period, &interval, &count) != 4)
+	{
+		wpa_printf(MSG_DEBUG,
+			   "CTRL: Invalid P2P LO Start parameter: '%s'", cmd);
+		return -1;
+	}
+
+	return wpas_p2p_lo_start(wpa_s, freq, period, interval, count);
+}
+
 #endif /* CONFIG_P2P */
 
 
@@ -6983,6 +6998,34 @@
 }
 
 
+static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s,
+					char *buf, size_t buflen)
+{
+	int ret, i;
+	char *pos, *end;
+
+	ret = os_snprintf(buf, buflen, "%016llX:\n",
+			  (long long unsigned) wpa_s->drv_flags);
+	if (os_snprintf_error(buflen, ret))
+		return -1;
+
+	pos = buf + ret;
+	end = buf + buflen;
+
+	for (i = 0; i < 64; i++) {
+		if (wpa_s->drv_flags & (1LLU << i)) {
+			ret = os_snprintf(pos, end - pos, "%s\n",
+					  driver_flag_to_string(1LLU << i));
+			if (os_snprintf_error(end - pos, ret))
+				return -1;
+			pos += ret;
+		}
+	}
+
+	return pos - buf;
+}
+
+
 static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf,
 				      size_t buflen)
 {
@@ -7213,6 +7256,10 @@
 
 	eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
 	wpa_s->wnmsleep_used = 0;
+
+#ifdef CONFIG_SME
+	wpa_s->sme.last_unprot_disconnect.sec = 0;
+#endif /* CONFIG_SME */
 }
 
 
@@ -8968,6 +9015,12 @@
 	} else if (os_strncmp(buf, "P2P_REMOVE_CLIENT ", 18) == 0) {
 		if (p2p_ctrl_remove_client(wpa_s, buf + 18) < 0)
 			reply_len = -1;
+	} else if (os_strncmp(buf, "P2P_LO_START ", 13) == 0) {
+		if (p2p_ctrl_iface_p2p_lo_start(wpa_s, buf + 13))
+			reply_len = -1;
+	} else if (os_strcmp(buf, "P2P_LO_STOP") == 0) {
+		if (wpas_p2p_lo_stop(wpa_s))
+			reply_len = -1;
 #endif /* CONFIG_P2P */
 #ifdef CONFIG_WIFI_DISPLAY
 	} else if (os_strncmp(buf, "WFD_SUBELEM_SET ", 16) == 0) {
@@ -9032,7 +9085,10 @@
 		if (del_hs20_icon(wpa_s, buf + 14) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "FETCH_OSU") == 0) {
-		if (hs20_fetch_osu(wpa_s) < 0)
+		if (hs20_fetch_osu(wpa_s, 0) < 0)
+			reply_len = -1;
+	} else if (os_strcmp(buf, "FETCH_OSU no-scan") == 0) {
+		if (hs20_fetch_osu(wpa_s, 1) < 0)
 			reply_len = -1;
 	} else if (os_strcmp(buf, "CANCEL_FETCH_OSU") == 0) {
 		hs20_cancel_fetch_osu(wpa_s);
@@ -9243,6 +9299,9 @@
 		if (wpa_supplicant_ctrl_iface_autoscan(wpa_s, buf + 9))
 			reply_len = -1;
 #endif /* CONFIG_AUTOSCAN */
+	} else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) {
+		reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply,
+							 reply_size);
 #ifdef ANDROID
 	} else if (os_strncmp(buf, "DRIVER ", 7) == 0) {
 		reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 9f104f5..396a0dc 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -946,4 +946,27 @@
 					    &wpa_s->extended_capa_len);
 }
 
+static inline int wpa_drv_p2p_lo_start(struct wpa_supplicant *wpa_s,
+				       unsigned int channel,
+				       unsigned int period,
+				       unsigned int interval,
+				       unsigned int count,
+				       const u8 *device_types,
+				       size_t dev_types_len,
+				       const u8 *ies, size_t ies_len)
+{
+	if (!wpa_s->driver->p2p_lo_start)
+		return -1;
+	return wpa_s->driver->p2p_lo_start(wpa_s->drv_priv, channel, period,
+					   interval, count, device_types,
+					   dev_types_len, ies, ies_len);
+}
+
+static inline int wpa_drv_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s->driver->p2p_lo_stop)
+		return -1;
+	return wpa_s->driver->p2p_lo_stop(wpa_s->drv_priv);
+}
+
 #endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b7a3bc0..50461b6 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1014,8 +1014,10 @@
 			continue;
 		}
 
-		if (!bss_is_ess(bss) && !bss_is_pbss(bss)) {
-			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - neither ESS nor PBSS network");
+		if (ssid->mode != IEEE80211_MODE_MESH && !bss_is_ess(bss) &&
+		    !bss_is_pbss(bss)) {
+			wpa_dbg(wpa_s, MSG_DEBUG,
+				"   skip - not ESS, PBSS, or MBSS");
 			continue;
 		}
 
@@ -1031,6 +1033,14 @@
 			continue;
 		}
 
+#ifdef CONFIG_MESH
+		if (ssid->mode == IEEE80211_MODE_MESH && ssid->frequency > 0 &&
+		    ssid->frequency != bss->freq) {
+			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - frequency not allowed (mesh)");
+			continue;
+		}
+#endif /* CONFIG_MESH */
+
 		if (!rate_match(wpa_s, bss)) {
 			wpa_dbg(wpa_s, MSG_DEBUG, "   skip - rate sets do "
 				"not match");
@@ -1624,6 +1634,14 @@
 
 	selected = wpa_supplicant_pick_network(wpa_s, &ssid);
 
+#ifdef CONFIG_MESH
+	if (wpa_s->ifmsh) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Avoiding join because we already joined a mesh group");
+		return 0;
+	}
+#endif /* CONFIG_MESH */
+
 	if (selected) {
 		int skip;
 		skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid);
@@ -1652,13 +1670,6 @@
 		 */
 		return 1;
 	} else {
-#ifdef CONFIG_MESH
-		if (wpa_s->ifmsh) {
-			wpa_msg(wpa_s, MSG_INFO,
-				"Avoiding join because we already joined a mesh group");
-			return 0;
-		}
-#endif /* CONFIG_MESH */
 		wpa_dbg(wpa_s, MSG_DEBUG, "No suitable network found");
 		ssid = wpa_supplicant_pick_new_network(wpa_s);
 		if (ssid) {
@@ -4067,6 +4078,14 @@
 					     &data->acs_selected_channels);
 #endif /* CONFIG_ACS */
 		break;
+	case EVENT_P2P_LO_STOP:
+#ifdef CONFIG_P2P
+		wpa_s->p2p_lo_started = 0;
+		wpa_msg(wpa_s, MSG_INFO, P2P_EVENT_LISTEN_OFFLOAD_STOP
+			P2P_LISTEN_OFFLOAD_STOP_REASON "reason=%d",
+			data->p2p_lo_stop.reason_code);
+#endif /* CONFIG_P2P */
+		break;
 	default:
 		wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event);
 		break;
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index a62c1c3..e88f147 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -205,8 +205,8 @@
 }
 
 
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
-				    size_t payload_len)
+static struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
+					   size_t payload_len)
 {
 	struct wpabuf *buf;
 
@@ -320,7 +320,7 @@
 		return -1;
 
 	b64 = base64_encode(&icon->image[offset], size, &b64_size);
-	if (buf_len >= b64_size) {
+	if (b64 && buf_len >= b64_size) {
 		os_memcpy(reply, b64, b64_size);
 		reply_size = b64_size;
 	} else {
@@ -436,14 +436,14 @@
 			icon->image_len = slen;
 			hs20_remove_duplicate_icons(wpa_s, icon);
 			wpa_msg(wpa_s, MSG_INFO,
-				"RX-HS20-ICON " MACSTR " %s %u",
+				RX_HS20_ICON MACSTR " %s %u",
 				MAC2STR(sa), icon->file_name,
 				(unsigned int) icon->image_len);
 			return 0;
 		}
 	}
 
-	wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR " Icon Binary File",
+	wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Icon Binary File",
 		MAC2STR(sa));
 
 	if (slen < 4) {
@@ -506,7 +506,7 @@
 	}
 	fclose(f);
 
-	wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP-ICON %s", fname);
+	wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP_ICON "%s", fname);
 	return 0;
 }
 
@@ -570,7 +570,7 @@
 
 	switch (subtype) {
 	case HS20_STYPE_CAPABILITY_LIST:
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" HS Capability List", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
 		if (anqp) {
@@ -580,7 +580,7 @@
 		}
 		break;
 	case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" Operator Friendly Name", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
 		if (anqp) {
@@ -596,7 +596,7 @@
 				"Metrics value from " MACSTR, MAC2STR(sa));
 			break;
 		}
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa),
 			pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5),
 			pos[9], pos[10], WPA_GET_LE16(pos + 11));
@@ -606,7 +606,7 @@
 		}
 		break;
 	case HS20_STYPE_CONNECTION_CAPABILITY:
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" Connection Capability", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
 		if (anqp) {
@@ -616,7 +616,7 @@
 		}
 		break;
 	case HS20_STYPE_OPERATING_CLASS:
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" Operating Class", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
 		if (anqp) {
@@ -626,7 +626,7 @@
 		}
 		break;
 	case HS20_STYPE_OSU_PROVIDERS_LIST:
-		wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
 			" OSU Providers list", MAC2STR(sa));
 		wpa_s->num_prov_found++;
 		if (anqp) {
@@ -703,6 +703,8 @@
 		 wpa_s->conf->osu_dir);
 	f = fopen(fname, "w");
 	if (f == NULL) {
+		wpa_msg(wpa_s, MSG_INFO,
+			"Could not write OSU provider information");
 		hs20_free_osu_prov(wpa_s);
 		wpa_s->fetch_anqp_in_progress = 0;
 		return;
@@ -1076,7 +1078,7 @@
 }
 
 
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s)
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan)
 {
 	if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
 		wpa_printf(MSG_DEBUG, "HS 2.0: Cannot start fetch_osu - "
@@ -1107,7 +1109,16 @@
 	wpa_msg(wpa_s, MSG_INFO, "Starting OSU provisioning information fetch");
 	wpa_s->num_osu_scans = 0;
 	wpa_s->num_prov_found = 0;
-	hs20_start_osu_scan(wpa_s);
+	if (skip_scan) {
+		wpa_s->network_select = 0;
+		wpa_s->fetch_all_anqp = 1;
+		wpa_s->fetch_osu_info = 1;
+		wpa_s->fetch_osu_icon_in_progress = 0;
+
+		interworking_start_fetch_anqp(wpa_s);
+	} else {
+		hs20_start_osu_scan(wpa_s);
+	}
 
 	return 0;
 }
diff --git a/wpa_supplicant/hs20_supplicant.h b/wpa_supplicant/hs20_supplicant.h
index 89c47a5..0dd559f 100644
--- a/wpa_supplicant/hs20_supplicant.h
+++ b/wpa_supplicant/hs20_supplicant.h
@@ -13,8 +13,6 @@
 
 int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
 		       const u8 *payload, size_t payload_len, int inmem);
-struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
-				    size_t payload_len);
 void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
 		       struct wpabuf *buf);
 void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
@@ -33,7 +31,7 @@
 void hs20_free_osu_prov(struct wpa_supplicant *wpa_s);
 void hs20_next_osu_icon(struct wpa_supplicant *wpa_s);
 void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s);
-int hs20_fetch_osu(struct wpa_supplicant *wpa_s);
+int hs20_fetch_osu(struct wpa_supplicant *wpa_s, int skip_scan);
 void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s);
 void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s);
 void hs20_start_osu_scan(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 589ee57..697810e 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -950,11 +950,9 @@
 	if (!key_mgmt)
 		key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ?
 			"WPA-EAP WPA-EAP-SHA256" : "WPA-EAP";
-	if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0)
-		return -1;
-	if (wpa_config_set(ssid, "proto", "RSN", 0) < 0)
-		return -1;
-	if (wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
+	if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 ||
+	    wpa_config_set(ssid, "proto", "RSN", 0) < 0 ||
+	    wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0)
 		return -1;
 	return 0;
 }
@@ -1590,9 +1588,8 @@
 }
 
 
-static int interworking_connect_helper(struct wpa_supplicant *wpa_s,
-				       struct wpa_bss *bss, int allow_excluded,
-				       int only_add)
+int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
+			 int only_add)
 {
 	struct wpa_cred *cred, *cred_rc, *cred_3gpp;
 	struct wpa_ssid *ssid;
@@ -1600,7 +1597,7 @@
 	struct nai_realm_eap *eap = NULL;
 	u16 count, i;
 	char buf[100];
-	int excluded = 0, *excl = allow_excluded ? &excluded : NULL;
+	int excluded = 0, *excl = &excluded;
 	const char *name;
 
 	if (wpa_s->conf->cred == NULL || bss == NULL)
@@ -1614,8 +1611,8 @@
 	}
 
 	wpa_printf(MSG_DEBUG, "Interworking: Considering BSS " MACSTR
-		   " for connection (allow_excluded=%d)",
-		   MAC2STR(bss->bssid), allow_excluded);
+		   " for connection",
+		   MAC2STR(bss->bssid));
 
 	if (!wpa_bss_get_ie(bss, WLAN_EID_RSN)) {
 		/*
@@ -1633,7 +1630,7 @@
 		wpa_msg(wpa_s, MSG_DEBUG,
 			"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d",
 			cred_rc->priority, cred_rc->sp_priority);
-		if (allow_excluded && excl && !(*excl))
+		if (excl && !(*excl))
 			excl = NULL;
 	}
 
@@ -1642,7 +1639,7 @@
 		wpa_msg(wpa_s, MSG_DEBUG,
 			"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d",
 			cred->priority, cred->sp_priority);
-		if (allow_excluded && excl && !(*excl))
+		if (excl && !(*excl))
 			excl = NULL;
 	}
 
@@ -1652,7 +1649,7 @@
 		wpa_msg(wpa_s, MSG_DEBUG,
 			"Interworking: Highest 3GPP matching credential priority %d sp_priority %d",
 			cred_3gpp->priority, cred_3gpp->sp_priority);
-		if (allow_excluded && excl && !(*excl))
+		if (excl && !(*excl))
 			excl = NULL;
 	}
 
@@ -1665,7 +1662,7 @@
 			wpa_msg(wpa_s, MSG_DEBUG,
 				"Interworking: Highest roaming consortium matching credential priority %d sp_priority %d (ignore BW)",
 				cred_rc->priority, cred_rc->sp_priority);
-			if (allow_excluded && excl && !(*excl))
+			if (excl && !(*excl))
 				excl = NULL;
 		}
 
@@ -1675,7 +1672,7 @@
 			wpa_msg(wpa_s, MSG_DEBUG,
 				"Interworking: Highest NAI Realm list matching credential priority %d sp_priority %d (ignore BW)",
 				cred->priority, cred->sp_priority);
-			if (allow_excluded && excl && !(*excl))
+			if (excl && !(*excl))
 				excl = NULL;
 		}
 
@@ -1685,7 +1682,7 @@
 			wpa_msg(wpa_s, MSG_DEBUG,
 				"Interworking: Highest 3GPP matching credential priority %d sp_priority %d (ignore BW)",
 				cred_3gpp->priority, cred_3gpp->sp_priority);
-			if (allow_excluded && excl && !(*excl))
+			if (excl && !(*excl))
 				excl = NULL;
 		}
 	}
@@ -1850,13 +1847,6 @@
 }
 
 
-int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
-			 int only_add)
-{
-	return interworking_connect_helper(wpa_s, bss, 1, only_add);
-}
-
-
 #ifdef PCSC_FUNCS
 static int interworking_pcsc_read_imsi(struct wpa_supplicant *wpa_s)
 {
@@ -2806,7 +2796,7 @@
 
 	switch (info_id) {
 	case ANQP_CAPABILITY_LIST:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" ANQP Capability list", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Capability list",
 				  pos, slen);
@@ -2816,7 +2806,7 @@
 		}
 		break;
 	case ANQP_VENUE_NAME:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" Venue Name", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Venue Name", pos, slen);
 		if (anqp) {
@@ -2825,7 +2815,7 @@
 		}
 		break;
 	case ANQP_NETWORK_AUTH_TYPE:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" Network Authentication Type information",
 			MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Network Authentication "
@@ -2836,7 +2826,7 @@
 		}
 		break;
 	case ANQP_ROAMING_CONSORTIUM:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" Roaming Consortium list", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: Roaming Consortium",
 				  pos, slen);
@@ -2846,7 +2836,7 @@
 		}
 		break;
 	case ANQP_IP_ADDR_TYPE_AVAILABILITY:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" IP Address Type Availability information",
 			MAC2STR(sa));
 		wpa_hexdump(MSG_MSGDUMP, "ANQP: IP Address Availability",
@@ -2858,7 +2848,7 @@
 		}
 		break;
 	case ANQP_NAI_REALM:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" NAI Realm list", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: NAI Realm", pos, slen);
 		if (anqp) {
@@ -2867,7 +2857,7 @@
 		}
 		break;
 	case ANQP_3GPP_CELLULAR_NETWORK:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" 3GPP Cellular Network information", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_DEBUG, "ANQP: 3GPP Cellular Network",
 				  pos, slen);
@@ -2877,7 +2867,7 @@
 		}
 		break;
 	case ANQP_DOMAIN_NAME:
-		wpa_msg(wpa_s, MSG_INFO, "RX-ANQP " MACSTR
+		wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR
 			" Domain Name list", MAC2STR(sa));
 		wpa_hexdump_ascii(MSG_MSGDUMP, "ANQP: Domain Name", pos, slen);
 		if (anqp) {
diff --git a/wpa_supplicant/mbo.c b/wpa_supplicant/mbo.c
index c37d547..5b5c3e6 100644
--- a/wpa_supplicant/mbo.c
+++ b/wpa_supplicant/mbo.c
@@ -532,9 +532,26 @@
 			return NOT_ALLOWED;
 		res2 = allow_channel(mode, channel + 4, NULL);
 	} else if (bw == BW80) {
-		res2 = verify_80mhz(mode, channel);
+		/*
+		 * channel is a center channel and as such, not necessarily a
+		 * valid 20 MHz channels. Override earlier allow_channel()
+		 * result and use only the 80 MHz specific version.
+		 */
+		res2 = res = verify_80mhz(mode, channel);
 	} else if (bw == BW160) {
-		res2 = verify_160mhz(mode, channel);
+		/*
+		 * channel is a center channel and as such, not necessarily a
+		 * valid 20 MHz channels. Override earlier allow_channel()
+		 * result and use only the 160 MHz specific version.
+		 */
+		res2 = res = verify_160mhz(mode, channel);
+	} else if (bw == BW80P80) {
+		/*
+		 * channel is a center channel and as such, not necessarily a
+		 * valid 20 MHz channels. Override earlier allow_channel()
+		 * result and use only the 80 MHz specific version.
+		 */
+		res2 = res = verify_80mhz(mode, channel);
 	}
 
 	if (res == NOT_ALLOWED || res2 == NOT_ALLOWED)
@@ -550,38 +567,63 @@
 	int chan;
 	size_t i;
 	struct hostapd_hw_modes *mode;
+	int found;
 
 	mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, op_class->mode);
 	if (!mode)
 		return 0;
 
-	if (op_class->op_class == 128 || op_class->op_class == 130) {
+	if (op_class->op_class == 128) {
 		u8 channels[] = { 42, 58, 106, 122, 138, 155 };
 
 		for (i = 0; i < ARRAY_SIZE(channels); i++) {
 			if (verify_channel(mode, channels[i], op_class->bw) ==
-			    NOT_ALLOWED)
-				return 0;
+			    ALLOWED)
+				return 1;
 		}
 
-		return 1;
+		return 0;
 	}
 
 	if (op_class->op_class == 129) {
-		if (verify_channel(mode, 50, op_class->bw) == NOT_ALLOWED ||
-		    verify_channel(mode, 114, op_class->bw) == NOT_ALLOWED)
-			return 0;
-
-		return 1;
+		/* Check if either 160 MHz channels is allowed */
+		return verify_channel(mode, 50, op_class->bw) == ALLOWED ||
+			verify_channel(mode, 114, op_class->bw) == ALLOWED;
 	}
 
+	if (op_class->op_class == 130) {
+		/* Need at least two non-contiguous 80 MHz segments */
+		found = 0;
+
+		if (verify_channel(mode, 42, op_class->bw) == ALLOWED ||
+		    verify_channel(mode, 58, op_class->bw) == ALLOWED)
+			found++;
+		if (verify_channel(mode, 106, op_class->bw) == ALLOWED ||
+		    verify_channel(mode, 122, op_class->bw) == ALLOWED ||
+		    verify_channel(mode, 138, op_class->bw) == ALLOWED)
+			found++;
+		if (verify_channel(mode, 106, op_class->bw) == ALLOWED &&
+		    verify_channel(mode, 138, op_class->bw) == ALLOWED)
+			found++;
+		if (verify_channel(mode, 155, op_class->bw) == ALLOWED)
+			found++;
+
+		if (found >= 2)
+			return 1;
+
+		return 0;
+	}
+
+	found = 0;
 	for (chan = op_class->min_chan; chan <= op_class->max_chan;
 	     chan += op_class->inc) {
-		if (verify_channel(mode, chan, op_class->bw) == NOT_ALLOWED)
-			return 0;
+		if (verify_channel(mode, chan, op_class->bw) == ALLOWED) {
+			found = 1;
+			break;
+		}
 	}
 
-	return 1;
+	return found;
 }
 
 
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index dd534d4..cdfe51c 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -400,6 +400,10 @@
 		params.beacon_int = ssid->beacon_int;
 	else if (wpa_s->conf->beacon_int > 0)
 		params.beacon_int = wpa_s->conf->beacon_int;
+	if (ssid->dtim_period > 0)
+		params.dtim_period = ssid->dtim_period;
+	else if (wpa_s->conf->dtim_period > 0)
+		params.dtim_period = wpa_s->conf->dtim_period;
 	params.max_peer_links = wpa_s->conf->max_peer_links;
 
 	if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) {
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index 8f327d8..7ffdefe 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -35,19 +35,17 @@
 	PLINK_UNDEFINED,
 	OPN_ACPT,
 	OPN_RJCT,
-	OPN_IGNR,
 	CNF_ACPT,
 	CNF_RJCT,
-	CNF_IGNR,
 	CLS_ACPT,
-	CLS_IGNR
+	REQ_RJCT
 };
 
 static const char * const mplstate[] = {
 	[0] = "UNINITIALIZED",
-	[PLINK_LISTEN] = "LISTEN",
-	[PLINK_OPEN_SENT] = "OPEN_SENT",
-	[PLINK_OPEN_RCVD] = "OPEN_RCVD",
+	[PLINK_IDLE] = "IDLE",
+	[PLINK_OPN_SNT] = "OPN_SNT",
+	[PLINK_OPN_RCVD] = "OPN_RCVD",
 	[PLINK_CNF_RCVD] = "CNF_RCVD",
 	[PLINK_ESTAB] = "ESTAB",
 	[PLINK_HOLDING] = "HOLDING",
@@ -58,12 +56,10 @@
 	[PLINK_UNDEFINED] = "UNDEFINED",
 	[OPN_ACPT] = "OPN_ACPT",
 	[OPN_RJCT] = "OPN_RJCT",
-	[OPN_IGNR] = "OPN_IGNR",
 	[CNF_ACPT] = "CNF_ACPT",
 	[CNF_RJCT] = "CNF_RJCT",
-	[CNF_IGNR] = "CNF_IGNR",
 	[CLS_ACPT] = "CLS_ACPT",
-	[CLS_IGNR] = "CLS_IGNR"
+	[REQ_RJCT] = "REQ_RJCT",
 };
 
 
@@ -195,12 +191,13 @@
 
 	sta->my_lid = llid;
 	sta->peer_lid = 0;
+	sta->peer_aid = 0;
 
 	/*
 	 * We do not use wpa_mesh_set_plink_state() here because there is no
 	 * entry in kernel yet.
 	 */
-	sta->plink_state = PLINK_LISTEN;
+	sta->plink_state = PLINK_IDLE;
 }
 
 
@@ -394,6 +391,7 @@
 	os_memset(&params, 0, sizeof(params));
 	params.addr = sta->addr;
 	params.plink_state = state;
+	params.peer_aid = sta->peer_aid;
 	params.set = 1;
 
 	ret = wpa_drv_sta_add(wpa_s, &params);
@@ -424,8 +422,8 @@
 	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
 
 	switch (sta->plink_state) {
-	case PLINK_OPEN_RCVD:
-	case PLINK_OPEN_SENT:
+	case PLINK_OPN_RCVD:
+	case PLINK_OPN_SNT:
 		/* retry timer */
 		if (sta->mpm_retries < conf->dot11MeshMaxRetries) {
 			eloop_register_timeout(
@@ -559,7 +557,7 @@
 		return -1;
 	}
 
-	if ((PLINK_OPEN_SENT <= sta->plink_state &&
+	if ((PLINK_OPN_SNT <= sta->plink_state &&
 	    sta->plink_state <= PLINK_ESTAB) ||
 	    (sta->sae && sta->sae->state > SAE_NOTHING)) {
 		wpa_msg(wpa_s, MSG_INFO,
@@ -568,7 +566,7 @@
 	}
 
 	if (conf->security == MESH_CONF_SEC_NONE) {
-		mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+		mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
 	} else {
 		mesh_rsn_auth_sae_sta(wpa_s, sta);
 		os_memcpy(hapd->mesh_required_peer, addr, ETH_ALEN);
@@ -631,7 +629,7 @@
 	if (!sta->my_lid)
 		mesh_mpm_init_link(wpa_s, sta);
 
-	mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+	mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
 }
 
 /*
@@ -700,6 +698,7 @@
 	params.addr = addr;
 	params.plink_state = sta->plink_state;
 	params.aid = sta->aid;
+	params.peer_aid = sta->peer_aid;
 	params.listen_interval = 100;
 	params.ht_capabilities = sta->ht_capabilities;
 	params.vht_capabilities = sta->vht_capabilities;
@@ -770,9 +769,9 @@
 	}
 
 	if (conf->security == MESH_CONF_SEC_NONE) {
-		if (sta->plink_state < PLINK_OPEN_SENT ||
+		if (sta->plink_state < PLINK_OPN_SNT ||
 		    sta->plink_state > PLINK_ESTAB)
-			mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_SENT);
+			mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_SNT);
 	} else {
 		mesh_rsn_auth_sae_sta(wpa_s, sta);
 	}
@@ -847,36 +846,40 @@
 
 
 static void mesh_mpm_fsm(struct wpa_supplicant *wpa_s, struct sta_info *sta,
-			 enum plink_event event)
+			 enum plink_event event, u16 reason)
 {
 	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
 	struct mesh_conf *conf = wpa_s->ifmsh->mconf;
-	u16 reason = 0;
 
 	wpa_msg(wpa_s, MSG_DEBUG, "MPM " MACSTR " state %s event %s",
 		MAC2STR(sta->addr), mplstate[sta->plink_state],
 		mplevent[event]);
 
 	switch (sta->plink_state) {
-	case PLINK_LISTEN:
+	case PLINK_IDLE:
 		switch (event) {
 		case CLS_ACPT:
 			mesh_mpm_fsm_restart(wpa_s, sta);
 			break;
 		case OPN_ACPT:
-			mesh_mpm_plink_open(wpa_s, sta, PLINK_OPEN_RCVD);
+			mesh_mpm_plink_open(wpa_s, sta, PLINK_OPN_RCVD);
 			mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CONFIRM,
 						   0);
 			break;
+		case REQ_RJCT:
+			mesh_mpm_send_plink_action(wpa_s, sta,
+						   PLINK_CLOSE, reason);
+			break;
 		default:
 			break;
 		}
 		break;
-	case PLINK_OPEN_SENT:
+	case PLINK_OPN_SNT:
 		switch (event) {
 		case OPN_RJCT:
 		case CNF_RJCT:
-			reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+			if (!reason)
+				reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
 			/* fall-through */
 		case CLS_ACPT:
 			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
@@ -891,7 +894,7 @@
 			break;
 		case OPN_ACPT:
 			/* retry timer is left untouched */
-			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPEN_RCVD);
+			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_OPN_RCVD);
 			mesh_mpm_send_plink_action(wpa_s, sta,
 						   PLINK_CONFIRM, 0);
 			break;
@@ -907,11 +910,12 @@
 			break;
 		}
 		break;
-	case PLINK_OPEN_RCVD:
+	case PLINK_OPN_RCVD:
 		switch (event) {
 		case OPN_RJCT:
 		case CNF_RJCT:
-			reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+			if (!reason)
+				reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
 			/* fall-through */
 		case CLS_ACPT:
 			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
@@ -942,7 +946,8 @@
 		switch (event) {
 		case OPN_RJCT:
 		case CNF_RJCT:
-			reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
+			if (!reason)
+				reason = WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION;
 			/* fall-through */
 		case CLS_ACPT:
 			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
@@ -969,9 +974,12 @@
 		break;
 	case PLINK_ESTAB:
 		switch (event) {
+		case OPN_RJCT:
+		case CNF_RJCT:
 		case CLS_ACPT:
 			wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING);
-			reason = WLAN_REASON_MESH_CLOSE_RCVD;
+			if (!reason)
+				reason = WLAN_REASON_MESH_CLOSE_RCVD;
 
 			eloop_register_timeout(
 				conf->dot11MeshHoldingTimeout / 1000,
@@ -1032,13 +1040,14 @@
 	struct hostapd_data *hapd = wpa_s->ifmsh->bss[0];
 	struct mesh_conf *mconf = wpa_s->ifmsh->mconf;
 	struct sta_info *sta;
-	u16 plid = 0, llid = 0;
+	u16 plid = 0, llid = 0, aid = 0;
 	enum plink_event event;
 	struct ieee802_11_elems elems;
 	struct mesh_peer_mgmt_ie peer_mgmt_ie;
 	const u8 *ies;
 	size_t ie_len;
 	int ret;
+	u16 reason = 0;
 
 	if (mgmt->u.action.category != WLAN_ACTION_SELF_PROTECTED)
 		return;
@@ -1069,7 +1078,8 @@
 		ie_len -= 2;
 	}
 	if (action_field == PLINK_CONFIRM) {
-		wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", WPA_GET_LE16(ies));
+		aid = WPA_GET_LE16(ies);
+		wpa_printf(MSG_DEBUG, "MPM: AID 0x%x", aid);
 		ies += 2;	/* aid */
 		ie_len -= 2;
 	}
@@ -1113,6 +1123,10 @@
 		llid = WPA_GET_LE16(peer_mgmt_ie.plid);
 	wpa_printf(MSG_DEBUG, "MPM: plid=0x%x llid=0x%x", plid, llid);
 
+	if (action_field == PLINK_CLOSE)
+		wpa_printf(MSG_DEBUG, "MPM: close reason=%u",
+			   WPA_GET_LE16(peer_mgmt_ie.reason));
+
 	sta = ap_get_sta(hapd, mgmt->sa);
 
 	/*
@@ -1140,13 +1154,24 @@
 	if (!sta->my_lid)
 		mesh_mpm_init_link(wpa_s, sta);
 
-	if ((mconf->security & MESH_CONF_SEC_AMPE) &&
-	    mesh_rsn_process_ampe(wpa_s, sta, &elems,
-				  &mgmt->u.action.category,
-				  peer_mgmt_ie.chosen_pmk,
-				  ies, ie_len)) {
-		wpa_printf(MSG_DEBUG, "MPM: RSN process rejected frame");
-		return;
+	if (mconf->security & MESH_CONF_SEC_AMPE) {
+		int res;
+
+		res = mesh_rsn_process_ampe(wpa_s, sta, &elems,
+					    &mgmt->u.action.category,
+					    peer_mgmt_ie.chosen_pmk,
+					    ies, ie_len);
+		if (res) {
+			wpa_printf(MSG_DEBUG,
+				   "MPM: RSN process rejected frame (res=%d)",
+				   res);
+			if (action_field == PLINK_OPEN && res == -2) {
+				/* AES-SIV decryption failed */
+				mesh_mpm_fsm(wpa_s, sta, OPN_RJCT,
+					     WLAN_REASON_MESH_INVALID_GTK);
+			}
+			return;
+		}
 	}
 
 	if (sta->plink_state == PLINK_BLOCKED) {
@@ -1158,12 +1183,16 @@
 	switch (action_field) {
 	case PLINK_OPEN:
 		if (plink_free_count(hapd) == 0) {
-			event = OPN_IGNR;
+			event = REQ_RJCT;
+			reason = WLAN_REASON_MESH_MAX_PEERS;
 			wpa_printf(MSG_INFO,
 				   "MPM: Peer link num over quota(%d)",
 				   hapd->max_plinks);
 		} else if (sta->peer_lid && sta->peer_lid != plid) {
-			event = OPN_IGNR;
+			wpa_printf(MSG_DEBUG,
+				   "MPM: peer_lid mismatch: 0x%x != 0x%x",
+				   sta->peer_lid, plid);
+			return; /* no FSM event */
 		} else {
 			sta->peer_lid = plid;
 			event = OPN_ACPT;
@@ -1171,16 +1200,21 @@
 		break;
 	case PLINK_CONFIRM:
 		if (plink_free_count(hapd) == 0) {
-			event = CNF_IGNR;
+			event = REQ_RJCT;
+			reason = WLAN_REASON_MESH_MAX_PEERS;
 			wpa_printf(MSG_INFO,
 				   "MPM: Peer link num over quota(%d)",
 				   hapd->max_plinks);
 		} else if (sta->my_lid != llid ||
 			   (sta->peer_lid && sta->peer_lid != plid)) {
-			event = CNF_IGNR;
+			wpa_printf(MSG_DEBUG,
+				   "MPM: lid mismatch: my_lid: 0x%x != 0x%x or peer_lid: 0x%x != 0x%x",
+				   sta->my_lid, llid, sta->peer_lid, plid);
+			return; /* no FSM event */
 		} else {
 			if (!sta->peer_lid)
 				sta->peer_lid = plid;
+			sta->peer_aid = aid;
 			event = CNF_ACPT;
 		}
 		break;
@@ -1196,12 +1230,19 @@
 			 * restarted.
 			 */
 			event = CLS_ACPT;
-		else if (sta->peer_lid != plid)
-			event = CLS_IGNR;
-		else if (peer_mgmt_ie.plid && sta->my_lid != llid)
-			event = CLS_IGNR;
-		else
+		else if (sta->peer_lid != plid) {
+			wpa_printf(MSG_DEBUG,
+				   "MPM: peer_lid mismatch: 0x%x != 0x%x",
+				   sta->peer_lid, plid);
+			return; /* no FSM event */
+		} else if (peer_mgmt_ie.plid && sta->my_lid != llid) {
+			wpa_printf(MSG_DEBUG,
+				   "MPM: my_lid mismatch: 0x%x != 0x%x",
+				   sta->my_lid, llid);
+			return; /* no FSM event */
+		} else {
 			event = CLS_ACPT;
+		}
 		break;
 	default:
 		/*
@@ -1211,7 +1252,7 @@
 		 */
 		return;
 	}
-	mesh_mpm_fsm(wpa_s, sta, event);
+	mesh_mpm_fsm(wpa_s, sta, event, reason);
 }
 
 
diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
index 2eec227..27ab8cb 100644
--- a/wpa_supplicant/mesh_rsn.c
+++ b/wpa_supplicant/mesh_rsn.c
@@ -504,9 +504,11 @@
 	int ret = 0;
 	size_t len;
 
-	len = sizeof(*ampe) + rsn->mgtk_len + WPA_KEY_RSC_LEN + 4;
+	len = sizeof(*ampe);
+	if (cat[1] == PLINK_OPEN)
+		len += rsn->mgtk_len + WPA_KEY_RSC_LEN + 4;
 #ifdef CONFIG_IEEE80211W
-	if (rsn->igtk_len)
+	if (cat[1] == PLINK_OPEN && rsn->igtk_len)
 		len += 2 + 6 + rsn->igtk_len;
 #endif /* CONFIG_IEEE80211W */
 
@@ -532,6 +534,8 @@
 	os_memcpy(ampe->peer_nonce, sta->peer_nonce, WPA_NONCE_LEN);
 
 	pos = (u8 *) (ampe + 1);
+	if (cat[1] != PLINK_OPEN)
+		goto skip_keys;
 
 	/* TODO: Key Replay Counter[8] optionally for
 	 * Mesh Group Key Inform/Acknowledge frames */
@@ -563,6 +567,7 @@
 	}
 #endif /* CONFIG_IEEE80211W */
 
+skip_keys:
 	wpa_hexdump_key(MSG_DEBUG, "mesh: Plaintext AMPE element",
 			ampe_ie, 2 + len);
 
@@ -648,7 +653,7 @@
 	if (aes_siv_decrypt(sta->aek, crypt, crypt_len, 3,
 			    aad, aad_len, ampe_buf)) {
 		wpa_printf(MSG_ERROR, "Mesh RSN: frame verification failed!");
-		ret = -1;
+		ret = -2;
 		goto free;
 	}
 
@@ -683,6 +688,28 @@
 	 * frames */
 
 	/*
+	 * GTKdata shall not be included in Mesh Peering Confirm. While the
+	 * standard does not state the same about IGTKdata, that same constraint
+	 * needs to apply for it. It makes no sense to include the keys in Mesh
+	 * Peering Close frames either, so while the standard does not seem to
+	 * have a shall statement for these, they are described without
+	 * mentioning GTKdata.
+	 *
+	 * An earlier implementation used to add GTKdata to both Mesh Peering
+	 * Open and Mesh Peering Confirm frames, so ignore the possibly present
+	 * GTKdata frame without rejecting the frame as a backwards
+	 * compatibility mechanism.
+	 */
+	if (cat[1] != PLINK_OPEN) {
+		if (end > pos) {
+			wpa_hexdump_key(MSG_DEBUG,
+					"mesh: Ignore unexpected GTKdata(etc.) fields in the end of AMPE element in Mesh Peering Confirm/Close",
+					pos, end - pos);
+		}
+		goto free;
+	}
+
+	/*
 	 * GTKdata[variable]:
 	 * MGTK[variable] || Key RSC[8] || GTKExpirationTime[4]
 	 */
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 8c5af5e..cb8df66 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -6632,6 +6632,12 @@
 	if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
 		return -1;
 
+	if (wpa_s->p2p_lo_started) {
+		wpa_printf(MSG_DEBUG,
+			"P2P: Cannot start P2P listen, it is offloaded");
+		return -1;
+	}
+
 	wpa_supplicant_cancel_sched_scan(wpa_s);
 	wpas_p2p_clear_pending_action_tx(wpa_s);
 
@@ -6705,7 +6711,7 @@
 		return 0;
 
 	switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid,
-				 ie, ie_len, rx_freq)) {
+				 ie, ie_len, rx_freq, wpa_s->p2p_lo_started)) {
 	case P2P_PREQ_NOT_P2P:
 		wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len,
 				 ssi_signal);
@@ -9206,3 +9212,86 @@
 		wpa_s->ap_iface->bss[0]->p2p_group = NULL;
 	wpas_p2p_group_deinit(wpa_s);
 }
+
+
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+		      unsigned int period, unsigned int interval,
+		      unsigned int count)
+{
+	struct p2p_data *p2p = wpa_s->global->p2p;
+	u8 *device_types;
+	size_t dev_types_len;
+	struct wpabuf *buf;
+	int ret;
+
+	if (wpa_s->p2p_lo_started) {
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P Listen offload is already started");
+		return 0;
+	}
+
+	if (wpa_s->global->p2p == NULL ||
+	    !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) {
+		wpa_printf(MSG_DEBUG, "P2P: Listen offload not supported");
+		return -1;
+	}
+
+	if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+		wpa_printf(MSG_ERROR, "P2P: Input channel not supported: %u",
+			   freq);
+		return -1;
+	}
+
+	/* Get device type */
+	dev_types_len = (wpa_s->conf->num_sec_device_types + 1) *
+		WPS_DEV_TYPE_LEN;
+	device_types = os_malloc(dev_types_len);
+	if (!device_types)
+		return -1;
+	os_memcpy(device_types, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN);
+	os_memcpy(&device_types[WPS_DEV_TYPE_LEN], wpa_s->conf->sec_device_type,
+		  wpa_s->conf->num_sec_device_types * WPS_DEV_TYPE_LEN);
+
+	/* Get Probe Response IE(s) */
+	buf = p2p_build_probe_resp_template(p2p, freq);
+	if (!buf) {
+		os_free(device_types);
+		return -1;
+	}
+
+	ret = wpa_drv_p2p_lo_start(wpa_s, freq, period, interval, count,
+				   device_types, dev_types_len,
+				   wpabuf_mhead_u8(buf), wpabuf_len(buf));
+	if (ret < 0)
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P: Failed to start P2P listen offload");
+
+	os_free(device_types);
+	wpabuf_free(buf);
+
+	if (ret == 0) {
+		wpa_s->p2p_lo_started = 1;
+
+		/* Stop current P2P listen if any */
+		wpas_stop_listen(wpa_s);
+	}
+
+	return ret;
+}
+
+
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s)
+{
+	int ret;
+
+	if (!wpa_s->p2p_lo_started)
+		return 0;
+
+	ret = wpa_drv_p2p_lo_stop(wpa_s);
+	if (ret < 0)
+		wpa_dbg(wpa_s, MSG_DEBUG,
+			"P2P: Failed to stop P2P listen offload");
+
+	wpa_s->p2p_lo_started = 0;
+	return ret;
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index 6a770d2..63910d1 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -207,6 +207,10 @@
 void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s,
 			 struct wps_event_fail *fail);
 int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname);
+int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq,
+		      unsigned int period, unsigned int interval,
+		      unsigned int count);
+int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s);
 
 #else /* CONFIG_P2P */
 
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 6ade9af..119da28 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -588,6 +588,12 @@
 	unsigned int i;
 	struct wpa_ssid *ssid;
 
+	/*
+	 * For devices with max_ssids greater than 1, leave the last slot empty
+	 * for adding the wildcard scan entry.
+	 */
+	max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
+
 	for (i = 0; i < wpa_s->scan_id_count; i++) {
 		unsigned int j;
 
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 3a8f5b1..61fd3b2 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1585,8 +1585,10 @@
 	nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
 				wpa_s->sme.sa_query_count + 1,
 				WLAN_SA_QUERY_TR_ID_LEN);
-	if (nbuf == NULL)
+	if (nbuf == NULL) {
+		sme_stop_sa_query(wpa_s);
 		return;
+	}
 	if (wpa_s->sme.sa_query_count == 0) {
 		/* Starting a new SA Query procedure */
 		os_get_reltime(&wpa_s->sme.sa_query_start);
@@ -1597,6 +1599,7 @@
 
 	if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
 		wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
+		sme_stop_sa_query(wpa_s);
 		return;
 	}
 
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 53036ae..7012dfb 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -711,6 +711,13 @@
 }
 
 
+static int wpa_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
+				    char *argv[])
+{
+	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
+}
+
+
 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
 {
 	return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
@@ -2892,6 +2899,20 @@
 }
 
 
+static int wpa_cli_cmd_p2p_lo_start(struct wpa_ctrl *ctrl, int argc,
+				    char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "P2P_LO_START", 4, argc, argv);
+}
+
+
+static int wpa_cli_cmd_p2p_lo_stop(struct wpa_ctrl *ctrl, int argc,
+				   char *argv[])
+{
+	return wpa_cli_cmd(ctrl, "P2P_LO_STOP", 0, argc, argv);
+}
+
+
 enum wpa_cli_cmd_flags {
 	cli_cmd_flag_none		= 0x00,
 	cli_cmd_flag_sensitive		= 0x01
@@ -2949,6 +2970,9 @@
 	{ "get", wpa_cli_cmd_get, wpa_cli_complete_get,
 	  cli_cmd_flag_none,
 	  "<name> = get information" },
+	{ "driver_flags", wpa_cli_cmd_driver_flags, NULL,
+	  cli_cmd_flag_none,
+	  "= list driver flags" },
 	{ "logon", wpa_cli_cmd_logon, NULL,
 	  cli_cmd_flag_none,
 	  "= IEEE 802.1X EAPOL state machine logon" },
@@ -3477,6 +3501,12 @@
 	{ "get_pref_freq_list", wpa_cli_cmd_get_pref_freq_list, NULL,
 	  cli_cmd_flag_none,
 	  "<interface type> = retrieve preferred freq list for the specified interface type" },
+	{ "p2p_lo_start", wpa_cli_cmd_p2p_lo_start, NULL,
+	  cli_cmd_flag_none,
+	  "<freq> <period> <interval> <count> = start P2P listen offload" },
+	{ "p2p_lo_stop", wpa_cli_cmd_p2p_lo_stop, NULL,
+	  cli_cmd_flag_none,
+	  "= stop P2P listen offload" },
 	{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
 };
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6999bbb..7ed7efa 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1873,6 +1873,13 @@
 	if (!mode)
 		return;
 
+#ifdef CONFIG_HT_OVERRIDES
+	if (ssid->disable_ht) {
+		freq->ht_enabled = 0;
+		return;
+	}
+#endif /* CONFIG_HT_OVERRIDES */
+
 	freq->ht_enabled = ht_supported(mode);
 	if (!freq->ht_enabled)
 		return;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index e45f662..dd6a60d 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -893,6 +893,7 @@
 
 	unsigned int p2p_go_max_oper_chwidth;
 	unsigned int p2p_go_vht_center_freq2;
+	int p2p_lo_started;
 #endif /* CONFIG_P2P */
 
 	struct wpa_ssid *bgscan_ssid;